diff options
author | Christian Gmeiner <[email protected]> | 2016-12-23 20:33:10 +0100 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2017-01-12 19:27:11 +0000 |
commit | 848b49b288fc2fa942418d12829db2e559ad4916 (patch) | |
tree | 7de7214bec98a0e275bb18399902984b8a5b9847 /src/gallium/auxiliary/renderonly/renderonly.c | |
parent | 27a1c7ffbdd7d7a8fd1240413446c1172752d93b (diff) |
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 <[email protected]>
Acked-by: Emil Velikov <[email protected]>
Tested-by: Alexandre Courbot <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/renderonly/renderonly.c')
-rw-r--r-- | src/gallium/auxiliary/renderonly/renderonly.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/renderonly/renderonly.c b/src/gallium/auxiliary/renderonly/renderonly.c new file mode 100644 index 00000000000..7e23769159d --- /dev/null +++ b/src/gallium/auxiliary/renderonly/renderonly.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 Christian Gmeiner <[email protected]> + * + * 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 <[email protected]> + */ + +#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; +} + |