• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 Christian Gmeiner <christian.gmeiner@gmail.com>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Christian Gmeiner <christian.gmeiner@gmail.com>
25  */
26 
27 #include "renderonly/renderonly.h"
28 
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <sys/ioctl.h>
33 #include <xf86drm.h>
34 
35 #include "state_tracker/drm_driver.h"
36 #include "pipe/p_screen.h"
37 #include "util/u_memory.h"
38 
39 struct renderonly *
renderonly_dup(const struct renderonly * ro)40 renderonly_dup(const struct renderonly *ro)
41 {
42    struct renderonly *copy;
43 
44    copy = CALLOC_STRUCT(renderonly);
45    if (!copy)
46       return NULL;
47 
48    memcpy(copy, ro, sizeof(*ro));
49 
50    return copy;
51 }
52 
53 struct renderonly_scanout *
renderonly_scanout_for_prime(struct pipe_resource * rsc,struct renderonly * ro)54 renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro)
55 {
56    struct renderonly_scanout *scanout;
57 
58    scanout = CALLOC_STRUCT(renderonly_scanout);
59    if (!scanout)
60       return NULL;
61 
62    scanout->prime = rsc;
63 
64    return scanout;
65 }
66 
67 void
renderonly_scanout_destroy(struct renderonly_scanout * scanout)68 renderonly_scanout_destroy(struct renderonly_scanout *scanout)
69 {
70    FREE(scanout);
71 }
72 
73 struct renderonly_scanout *
renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource * rsc,struct renderonly * ro)74 renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
75                                                struct renderonly *ro)
76 {
77    struct pipe_screen *screen = rsc->screen;
78    struct renderonly_scanout *scanout;
79    struct winsys_handle handle;
80    int prime_fd, err;
81    struct drm_mode_create_dumb create_dumb = {
82       .width = rsc->width0,
83       .height = rsc->height0,
84       .bpp = 32,
85    };
86    struct drm_mode_destroy_dumb destroy_dumb = { };
87 
88    scanout = CALLOC_STRUCT(renderonly_scanout);
89    if (!scanout)
90       return NULL;
91 
92    /* create dumb buffer at scanout GPU */
93    err = ioctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
94    if (err < 0) {
95       fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
96             strerror(errno));
97       goto free_scanout;
98    }
99 
100    scanout->handle = create_dumb.handle;
101    scanout->stride = create_dumb.pitch;
102 
103    /* export dumb buffer */
104    err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
105          &prime_fd);
106    if (err < 0) {
107       fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
108       goto free_dumb;
109    }
110 
111    /* import dumb buffer */
112    handle.type = DRM_API_HANDLE_TYPE_FD;
113    handle.handle = prime_fd;
114    handle.stride = create_dumb.pitch;
115 
116    scanout->prime = screen->resource_from_handle(screen, rsc,
117          &handle, PIPE_HANDLE_USAGE_READ_WRITE);
118 
119    if (!scanout->prime) {
120       fprintf(stderr, "failed to create resource_from_handle: %s\n", strerror(errno));
121       goto free_dumb;
122    }
123 
124    return scanout;
125 
126 free_dumb:
127    destroy_dumb.handle = scanout->handle;
128    ioctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
129 
130 free_scanout:
131    FREE(scanout);
132 
133    return NULL;
134 }
135 
136 struct renderonly_scanout *
renderonly_create_gpu_import_for_resource(struct pipe_resource * rsc,struct renderonly * ro)137 renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
138                                           struct renderonly *ro)
139 {
140    struct pipe_screen *screen = rsc->screen;
141    struct renderonly_scanout *scanout;
142    boolean status;
143    int fd, err;
144    struct winsys_handle handle = {
145       .type = DRM_API_HANDLE_TYPE_FD
146    };
147 
148    scanout = CALLOC_STRUCT(renderonly_scanout);
149    if (!scanout)
150       return NULL;
151 
152    status = screen->resource_get_handle(screen, NULL, rsc, &handle,
153          PIPE_HANDLE_USAGE_READ_WRITE);
154    if (!status)
155       goto free_scanout;
156 
157    scanout->stride = handle.stride;
158    fd = handle.handle;
159 
160    err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
161    close(fd);
162 
163    if (err < 0) {
164       fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
165       goto free_scanout;
166    }
167 
168    return scanout;
169 
170 free_scanout:
171    FREE(scanout);
172 
173    return NULL;
174 }
175 
176