da91f12b2ea160394c0b4d55f4b5cf8c947a1498
[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 void
54 renderonly_scanout_destroy(struct renderonly_scanout *scanout,
55 struct renderonly *ro)
56 {
57 struct drm_mode_destroy_dumb destroy_dumb = { };
58
59 if (ro->kms_fd != -1) {
60 destroy_dumb.handle = scanout->handle;
61 drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
62 }
63 FREE(scanout);
64 }
65
66 struct renderonly_scanout *
67 renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
68 struct renderonly *ro,
69 struct winsys_handle *out_handle)
70 {
71 struct renderonly_scanout *scanout;
72 int err;
73 struct drm_mode_create_dumb create_dumb = {
74 .width = rsc->width0,
75 .height = rsc->height0,
76 .bpp = 32,
77 };
78 struct drm_mode_destroy_dumb destroy_dumb = { };
79
80 scanout = CALLOC_STRUCT(renderonly_scanout);
81 if (!scanout)
82 return NULL;
83
84 /* create dumb buffer at scanout GPU */
85 err = drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
86 if (err < 0) {
87 fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
88 strerror(errno));
89 goto free_scanout;
90 }
91
92 scanout->handle = create_dumb.handle;
93 scanout->stride = create_dumb.pitch;
94
95 if (!out_handle)
96 return scanout;
97
98 /* fill in winsys handle */
99 memset(out_handle, 0, sizeof(*out_handle));
100 out_handle->type = DRM_API_HANDLE_TYPE_FD;
101 out_handle->stride = create_dumb.pitch;
102
103 err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
104 (int *)&out_handle->handle);
105 if (err < 0) {
106 fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
107 goto free_dumb;
108 }
109
110 return scanout;
111
112 free_dumb:
113 destroy_dumb.handle = scanout->handle;
114 drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
115
116 free_scanout:
117 FREE(scanout);
118
119 return NULL;
120 }
121
122 struct renderonly_scanout *
123 renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
124 struct renderonly *ro,
125 struct winsys_handle *out_handle)
126 {
127 struct pipe_screen *screen = rsc->screen;
128 struct renderonly_scanout *scanout;
129 boolean status;
130 int fd, err;
131 struct winsys_handle handle = {
132 .type = DRM_API_HANDLE_TYPE_FD
133 };
134
135 scanout = CALLOC_STRUCT(renderonly_scanout);
136 if (!scanout)
137 return NULL;
138
139 status = screen->resource_get_handle(screen, NULL, rsc, &handle,
140 PIPE_HANDLE_USAGE_READ_WRITE);
141 if (!status)
142 goto free_scanout;
143
144 scanout->stride = handle.stride;
145 fd = handle.handle;
146
147 err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
148 close(fd);
149
150 if (err < 0) {
151 fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
152 goto free_scanout;
153 }
154
155 return scanout;
156
157 free_scanout:
158 FREE(scanout);
159
160 return NULL;
161 }
162