Commit 848b49b2 authored by Christian Gmeiner's avatar Christian Gmeiner Committed by Emil Velikov

gallium: add renderonly library

This a very lightweight library to add basic support for renderonly
GPUs. A kms gallium driver must specify how a renderonly_scanout
objects gets created. Also it must provide file handles to the used
kms device and the used gpu device.

This could look like:
struct renderonly ro = {
   .create_for_resource = renderonly_create_gpu_import_for_resource,
   .kms_fd = fd,
   .gpu_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC)
};

The renderonly_scanout object exits for two reasons:
 - Do any special treatment for a scanout resource like importing the
   GPU resource into the scanout hw.
 - Make it easier for a gallium driver to detect if anything special
   needs to be done in flush_resource(..) like a resolve to linear.

A GPU gallium driver which gets used as renderonly GPU needs to be
aware of the renderonly library.

This library will likely break android support and hopefully will get
replaced with a better solution based on gbm2.

Changes from V1 -> V2:
 - reworked the lifecycle of renderonly object (suggested by Nicolai Hähnle)
 - killed the midlayer (suggested by Thierry Reding)
 - made the API more explicit regarding gpu and kms fd's
 - added some docs
Signed-off-by: Christian Gmeiner's avatarChristian Gmeiner <christian.gmeiner@gmail.com>
Acked-by: default avatarEmil Velikov <emil.velikov@collabora.com>
Tested-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
parent 27a1c7ff
......@@ -50,6 +50,11 @@ GALLIUM_COMMON_LIB_DEPS = \
$(PTHREAD_LIBS) \
$(DLOPEN_LIBS)
if HAVE_LIBDRM
GALLIUM_COMMON_LIB_DEPS += \
$(LIBDRM_LIBS)
endif
GALLIUM_WINSYS_CFLAGS = \
-I$(top_srcdir)/src \
-I$(top_srcdir)/include \
......
......@@ -20,6 +20,16 @@ libgallium_la_SOURCES = \
$(NIR_SOURCES) \
$(GENERATED_SOURCES)
if HAVE_LIBDRM
AM_CFLAGS += \
$(LIBDRM_CFLAGS)
libgallium_la_SOURCES += \
$(RENDERONLY_SOURCES)
endif
if HAVE_GALLIUM_LLVM
AM_CFLAGS += \
......
......@@ -435,3 +435,7 @@ GALLIVM_SOURCES := \
draw/draw_llvm_sample.c \
draw/draw_pt_fetch_shade_pipeline_llvm.c \
draw/draw_vs_llvm.c
RENDERONLY_SOURCES := \
renderonly/renderonly.c \
renderonly/renderonly.h
/*
* Copyright (C) 2016 Christian Gmeiner <christian.gmeiner@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Christian Gmeiner <christian.gmeiner@gmail.com>
*/
#include "renderonly/renderonly.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <xf86drm.h>
#include "state_tracker/drm_driver.h"
#include "pipe/p_screen.h"
#include "util/u_memory.h"
struct renderonly *
renderonly_dup(const struct renderonly *ro)
{
struct renderonly *copy;
copy = CALLOC_STRUCT(renderonly);
if (!copy)
return NULL;
memcpy(copy, ro, sizeof(*ro));
return copy;
}
struct renderonly_scanout *
renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro)
{
struct renderonly_scanout *scanout;
scanout = CALLOC_STRUCT(renderonly_scanout);
if (!scanout)
return NULL;
scanout->prime = rsc;
return scanout;
}
void
renderonly_scanout_destroy(struct renderonly_scanout *scanout)
{
FREE(scanout);
}
struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
struct renderonly *ro)
{
struct pipe_screen *screen = rsc->screen;
struct renderonly_scanout *scanout;
struct winsys_handle handle;
int prime_fd, err;
struct drm_mode_create_dumb create_dumb = {
.width = rsc->width0,
.height = rsc->height0,
.bpp = 32,
};
struct drm_mode_destroy_dumb destroy_dumb = { };
scanout = CALLOC_STRUCT(renderonly_scanout);
if (!scanout)
return NULL;
/* create dumb buffer at scanout GPU */
err = ioctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
if (err < 0) {
fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
strerror(errno));
goto free_scanout;
}
scanout->handle = create_dumb.handle;
scanout->stride = create_dumb.pitch;
/* export dumb buffer */
err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
&prime_fd);
if (err < 0) {
fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
goto free_dumb;
}
/* import dumb buffer */
handle.type = DRM_API_HANDLE_TYPE_FD;
handle.handle = prime_fd;
handle.stride = create_dumb.pitch;
scanout->prime = screen->resource_from_handle(screen, rsc,
&handle, PIPE_HANDLE_USAGE_READ_WRITE);
if (!scanout->prime) {
fprintf(stderr, "failed to create resource_from_handle: %s\n", strerror(errno));
goto free_dumb;
}
return scanout;
free_dumb:
destroy_dumb.handle = scanout->handle;
ioctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
free_scanout:
FREE(scanout);
return NULL;
}
struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
struct renderonly *ro)
{
struct pipe_screen *screen = rsc->screen;
struct renderonly_scanout *scanout;
boolean status;
int fd, err;
struct winsys_handle handle = {
.type = DRM_API_HANDLE_TYPE_FD
};
scanout = CALLOC_STRUCT(renderonly_scanout);
if (!scanout)
return NULL;
status = screen->resource_get_handle(screen, NULL, rsc, &handle,
PIPE_HANDLE_USAGE_READ_WRITE);
if (!status)
goto free_scanout;
scanout->stride = handle.stride;
fd = handle.handle;
err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
close(fd);
if (err < 0) {
fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
goto free_scanout;
}
return scanout;
free_scanout:
FREE(scanout);
return NULL;
}
/*
* Copyright (C) 2016 Christian Gmeiner <christian.gmeiner@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Christian Gmeiner <christian.gmeiner@gmail.com>
*/
#ifndef RENDERONLY_H
#define RENDERONLY_H
#include <stdint.h>
#include "state_tracker/drm_driver.h"
#include "pipe/p_state.h"
struct renderonly_scanout {
uint32_t handle;
uint32_t stride;
struct pipe_resource *prime;
};
struct renderonly {
/**
* Create a renderonly_scanout object for scanout resource.
*
* This function creates a renderonly_scanout object based on the provided
* resource. The library is designed that the driver specific pipe_resource
* struct holds a pointer to a renderonly_scanout struct.
*
* struct driver_resource {
* struct pipe_resource base;
* struct renderonly_scanout *scanout;
* ...
* };
*
* The renderonly_scanout object exits for two reasons:
* - Do any special treatment for a scanout resource like importing the GPU
* resource into the scanout hw.
* - Make it easier for a gallium driver to detect if anything special needs
* to be done in flush_resource(..) like a resolve to linear.
*/
struct renderonly_scanout *(*create_for_resource)(struct pipe_resource *rsc,
struct renderonly *ro);
int kms_fd;
int gpu_fd;
};
struct renderonly *
renderonly_dup(const struct renderonly *ro);
static inline struct renderonly_scanout *
renderonly_scanout_for_resource(struct pipe_resource *rsc, struct renderonly *ro)
{
return ro->create_for_resource(rsc, ro);
}
struct renderonly_scanout *
renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro);
void
renderonly_scanout_destroy(struct renderonly_scanout *scanout);
static inline boolean
renderonly_get_handle(struct renderonly_scanout *scanout,
struct winsys_handle *handle)
{
if (!scanout)
return FALSE;
handle->handle = scanout->handle;
handle->stride = scanout->stride;
return TRUE;
}
/**
* Create a dumb buffer object for a resource at scanout hw.
*/
struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
struct renderonly *ro);
/**
* Import GPU resource into scanout hw.
*/
struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
struct renderonly *ro);
#endif /* RENDERONLY_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment