wayland: Don't rely on static variable for identifying wl_drm buffers
[mesa.git] / src / gallium / state_trackers / egl / common / native_wayland_drm_bufmgr.c
1 #include <stdint.h>
2 #include <string.h>
3
4 #include "native.h"
5 #include "util/u_inlines.h"
6 #include "state_tracker/drm_driver.h"
7
8 #ifdef HAVE_WAYLAND_BACKEND
9
10 #include <wayland-server.h>
11 #include <wayland-drm-server-protocol.h>
12
13 #include "native_wayland_drm_bufmgr.h"
14
15 #include "wayland-drm.h"
16
17 struct wayland_drm_bufmgr {
18 struct native_display_wayland_bufmgr base;
19
20 struct wl_drm *wl_server_drm;
21 char *device_name;
22
23 void *user_data;
24
25 wayland_drm_bufmgr_authenticate_func authenticate;
26 };
27
28 static INLINE struct wayland_drm_bufmgr *
29 wayland_drm_bufmgr(const struct native_display_wayland_bufmgr *base)
30 {
31 return (struct wayland_drm_bufmgr *) base;
32 }
33
34 static int
35 wayland_drm_bufmgr_authenticate(void *user_data, uint32_t magic)
36 {
37 struct native_display *ndpy = user_data;
38 struct wayland_drm_bufmgr *bufmgr;
39
40 bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
41
42 return bufmgr->authenticate(user_data, magic);
43 }
44
45 static void
46 wayland_drm_bufmgr_reference_buffer(void *user_data, uint32_t name, int fd,
47 struct wl_drm_buffer *buffer)
48 {
49 struct native_display *ndpy = user_data;
50 struct pipe_resource templ;
51 struct winsys_handle wsh;
52 enum pipe_format pf;
53
54 switch (buffer->format) {
55 case WL_DRM_FORMAT_ARGB8888:
56 pf = PIPE_FORMAT_B8G8R8A8_UNORM;
57 break;
58 case WL_DRM_FORMAT_XRGB8888:
59 pf = PIPE_FORMAT_B8G8R8X8_UNORM;
60 break;
61 default:
62 pf = PIPE_FORMAT_NONE;
63 break;
64 }
65
66 if (pf == PIPE_FORMAT_NONE)
67 return;
68
69 memset(&templ, 0, sizeof(templ));
70 templ.target = PIPE_TEXTURE_2D;
71 templ.format = pf;
72 templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
73 templ.width0 = buffer->width;
74 templ.height0 = buffer->height;
75 templ.depth0 = 1;
76 templ.array_size = 1;
77
78 memset(&wsh, 0, sizeof(wsh));
79 wsh.handle = name;
80 wsh.stride = buffer->stride[0];
81
82 buffer->driver_buffer =
83 ndpy->screen->resource_from_handle(ndpy->screen, &templ, &wsh);
84 }
85
86 static void
87 wayland_drm_bufmgr_unreference_buffer(void *user_data,
88 struct wl_drm_buffer *buffer)
89 {
90 struct pipe_resource *resource = buffer->driver_buffer;
91
92 pipe_resource_reference(&resource, NULL);
93 }
94
95 static struct wayland_drm_callbacks wl_drm_callbacks = {
96 wayland_drm_bufmgr_authenticate,
97 wayland_drm_bufmgr_reference_buffer,
98 wayland_drm_bufmgr_unreference_buffer
99 };
100
101 static boolean
102 wayland_drm_bufmgr_bind_display(struct native_display *ndpy,
103 struct wl_display *wl_dpy)
104 {
105 struct wayland_drm_bufmgr *bufmgr;
106
107 bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
108
109 if (bufmgr->wl_server_drm)
110 return FALSE;
111
112 bufmgr->wl_server_drm = wayland_drm_init(wl_dpy, bufmgr->device_name,
113 &wl_drm_callbacks, ndpy, 0);
114
115 if (!bufmgr->wl_server_drm)
116 return FALSE;
117
118 return TRUE;
119 }
120
121 static boolean
122 wayland_drm_bufmgr_unbind_display(struct native_display *ndpy,
123 struct wl_display *wl_dpy)
124 {
125 struct wayland_drm_bufmgr *bufmgr;
126
127 bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
128
129 if (!bufmgr->wl_server_drm)
130 return FALSE;
131
132 wayland_drm_uninit(bufmgr->wl_server_drm);
133 bufmgr->wl_server_drm = NULL;
134
135 return TRUE;
136 }
137
138 static struct pipe_resource *
139 wayland_drm_bufmgr_wl_buffer_get_resource(struct native_display *ndpy,
140 struct wl_resource *buffer_resource)
141 {
142 struct wayland_drm_bufmgr *bufmgr;
143 struct wl_drm_buffer *buffer;
144
145 bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
146 buffer = wayland_drm_buffer_get(bufmgr->wl_server_drm, buffer_resource);
147
148 if (!buffer)
149 return NULL;
150
151 return wayland_drm_buffer_get_buffer(buffer);
152 }
153
154 static boolean
155 wayland_drm_bufmgr_query_buffer(struct native_display *ndpy,
156 struct wl_resource *buffer_resource,
157 int attribute, int *value)
158 {
159 struct wayland_drm_bufmgr *bufmgr;
160 struct wl_drm_buffer *buffer;
161 struct pipe_resource *resource;
162
163 bufmgr = wayland_drm_bufmgr(ndpy->wayland_bufmgr);
164 buffer = wayland_drm_buffer_get(bufmgr->wl_server_drm, buffer_resource);
165 if (!buffer)
166 return FALSE;
167
168 resource = buffer->driver_buffer;
169
170 switch (attribute) {
171 case EGL_TEXTURE_FORMAT:
172 switch (resource->format) {
173 case PIPE_FORMAT_B8G8R8A8_UNORM:
174 *value = EGL_TEXTURE_RGBA;
175 return TRUE;
176 case PIPE_FORMAT_B8G8R8X8_UNORM:
177 *value = EGL_TEXTURE_RGB;
178 return TRUE;
179 default:
180 return FALSE;
181 }
182 case EGL_WIDTH:
183 *value = buffer->width;
184 return TRUE;
185 case EGL_HEIGHT:
186 *value = buffer->height;
187 return TRUE;
188 default:
189 return FALSE;
190 }
191 }
192
193
194 struct native_display_wayland_bufmgr *
195 wayland_drm_bufmgr_create(wayland_drm_bufmgr_authenticate_func authenticate,
196 void *user_data, char *device_name)
197 {
198 struct wayland_drm_bufmgr *bufmgr;
199
200 bufmgr = calloc(1, sizeof *bufmgr);
201 if (!bufmgr)
202 return NULL;
203
204 bufmgr->user_data = user_data;
205 bufmgr->authenticate = authenticate;
206 bufmgr->device_name = strdup(device_name);
207
208 bufmgr->base.bind_display = wayland_drm_bufmgr_bind_display;
209 bufmgr->base.unbind_display = wayland_drm_bufmgr_unbind_display;
210 bufmgr->base.buffer_get_resource = wayland_drm_bufmgr_wl_buffer_get_resource;
211 bufmgr->base.query_buffer = wayland_drm_bufmgr_query_buffer;
212
213 return &bufmgr->base;
214 }
215
216 void
217 wayland_drm_bufmgr_destroy(struct native_display_wayland_bufmgr *_bufmgr)
218 {
219 struct wayland_drm_bufmgr *bufmgr = wayland_drm_bufmgr(_bufmgr);
220
221 if (!bufmgr)
222 return;
223
224 free(bufmgr->device_name);
225 free(bufmgr);
226 }
227
228 #endif