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