renderonly: use drmIoctl
[mesa.git] / src / gallium / auxiliary / renderonly / renderonly.c
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 <xf86drm.h>
33
34 #include "state_tracker/drm_driver.h"
35 #include "pipe/p_screen.h"
36 #include "util/u_inlines.h"
37 #include "util/u_memory.h"
38
39 struct renderonly *
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 *
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
68 renderonly_scanout_destroy(struct renderonly_scanout *scanout,
69 struct renderonly *ro)
70 {
71 struct drm_mode_destroy_dumb destroy_dumb = { };
72
73 pipe_resource_reference(&scanout->prime, NULL);
74 if (ro->kms_fd != -1) {
75 destroy_dumb.handle = scanout->handle;
76 drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
77 }
78 FREE(scanout);
79 }
80
81 struct renderonly_scanout *
82 renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
83 struct renderonly *ro)
84 {
85 struct pipe_screen *screen = rsc->screen;
86 struct renderonly_scanout *scanout;
87 struct winsys_handle handle;
88 int prime_fd, err;
89 struct drm_mode_create_dumb create_dumb = {
90 .width = rsc->width0,
91 .height = rsc->height0,
92 .bpp = 32,
93 };
94 struct drm_mode_destroy_dumb destroy_dumb = { };
95
96 scanout = CALLOC_STRUCT(renderonly_scanout);
97 if (!scanout)
98 return NULL;
99
100 /* create dumb buffer at scanout GPU */
101 err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
102 if (err < 0) {
103 fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
104 strerror(errno));
105 goto free_scanout;
106 }
107
108 scanout->handle = create_dumb.handle;
109 scanout->stride = create_dumb.pitch;
110
111 /* export dumb buffer */
112 err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
113 &prime_fd);
114 if (err < 0) {
115 fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
116 goto free_dumb;
117 }
118
119 /* import dumb buffer */
120 handle.type = DRM_API_HANDLE_TYPE_FD;
121 handle.handle = prime_fd;
122 handle.stride = create_dumb.pitch;
123
124 scanout->prime = screen->resource_from_handle(screen, rsc,
125 &handle, PIPE_HANDLE_USAGE_READ_WRITE);
126
127 close(prime_fd);
128
129 if (!scanout->prime) {
130 fprintf(stderr, "failed to create resource_from_handle: %s\n", strerror(errno));
131 goto free_dumb;
132 }
133
134 return scanout;
135
136 free_dumb:
137 destroy_dumb.handle = scanout->handle;
138 drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
139
140 free_scanout:
141 FREE(scanout);
142
143 return NULL;
144 }
145
146 struct renderonly_scanout *
147 renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
148 struct renderonly *ro)
149 {
150 struct pipe_screen *screen = rsc->screen;
151 struct renderonly_scanout *scanout;
152 boolean status;
153 int fd, err;
154 struct winsys_handle handle = {
155 .type = DRM_API_HANDLE_TYPE_FD
156 };
157
158 scanout = CALLOC_STRUCT(renderonly_scanout);
159 if (!scanout)
160 return NULL;
161
162 status = screen->resource_get_handle(screen, NULL, rsc, &handle,
163 PIPE_HANDLE_USAGE_READ_WRITE);
164 if (!status)
165 goto free_scanout;
166
167 scanout->stride = handle.stride;
168 fd = handle.handle;
169
170 err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
171 close(fd);
172
173 if (err < 0) {
174 fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
175 goto free_scanout;
176 }
177
178 return scanout;
179
180 free_scanout:
181 FREE(scanout);
182
183 return NULL;
184 }
185