st/dri: simplify dri_get_egl_image by reusing dri2_format_table
[mesa.git] / src / gallium / state_trackers / dri / dri2.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright 2009, VMware, Inc.
5 * All Rights Reserved.
6 * Copyright (C) 2010 LunarG Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz
28 * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
29 */
30
31 #include <xf86drm.h>
32 #include "GL/mesa_glinterop.h"
33 #include "util/disk_cache.h"
34 #include "util/u_memory.h"
35 #include "util/u_inlines.h"
36 #include "util/u_format.h"
37 #include "util/u_debug.h"
38 #include "state_tracker/drm_driver.h"
39 #include "state_tracker/st_cb_bufferobjects.h"
40 #include "state_tracker/st_cb_fbo.h"
41 #include "state_tracker/st_cb_texture.h"
42 #include "state_tracker/st_texture.h"
43 #include "state_tracker/st_context.h"
44 #include "pipe-loader/pipe_loader.h"
45 #include "main/bufferobj.h"
46 #include "main/texobj.h"
47
48 #include "dri_util.h"
49
50 #include "dri_helpers.h"
51 #include "dri_drawable.h"
52 #include "dri_query_renderer.h"
53
54 #include "drm-uapi/drm_fourcc.h"
55
56 struct dri2_buffer
57 {
58 __DRIbuffer base;
59 struct pipe_resource *resource;
60 };
61
62 static inline struct dri2_buffer *
63 dri2_buffer(__DRIbuffer * driBufferPriv)
64 {
65 return (struct dri2_buffer *) driBufferPriv;
66 }
67
68 static const struct dri2_format_mapping dri2_format_table[] = {
69 { __DRI_IMAGE_FOURCC_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010,
70 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B10G10R10A2_UNORM, 1,
71 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB2101010, 4 } } },
72 { __DRI_IMAGE_FOURCC_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010,
73 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B10G10R10X2_UNORM, 1,
74 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB2101010, 4 } } },
75 { __DRI_IMAGE_FOURCC_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010,
76 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_R10G10B10A2_UNORM, 1,
77 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR2101010, 4 } } },
78 { __DRI_IMAGE_FOURCC_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010,
79 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_R10G10B10X2_UNORM, 1,
80 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR2101010, 4 } } },
81 { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888,
82 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_UNORM, 1,
83 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
84 { __DRI_IMAGE_FOURCC_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888,
85 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_RGBA8888_UNORM, 1,
86 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
87 { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_FORMAT_SARGB8,
88 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_BGRA8888_SRGB, 1,
89 { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
90 { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888,
91 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_BGRX8888_UNORM, 1,
92 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
93 { __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888,
94 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_RGBX8888_UNORM, 1,
95 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } },
96 { __DRI_IMAGE_FOURCC_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555,
97 __DRI_IMAGE_COMPONENTS_RGBA, PIPE_FORMAT_B5G5R5A1_UNORM, 1,
98 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } },
99 { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_FORMAT_RGB565,
100 __DRI_IMAGE_COMPONENTS_RGB, PIPE_FORMAT_B5G6R5_UNORM, 1,
101 { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
102 { __DRI_IMAGE_FOURCC_R8, __DRI_IMAGE_FORMAT_R8,
103 __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R8_UNORM, 1,
104 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } },
105 { __DRI_IMAGE_FOURCC_R16, __DRI_IMAGE_FORMAT_R16,
106 __DRI_IMAGE_COMPONENTS_R, PIPE_FORMAT_R16_UNORM, 1,
107 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } },
108 { __DRI_IMAGE_FOURCC_GR88, __DRI_IMAGE_FORMAT_GR88,
109 __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG88_UNORM, 1,
110 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } },
111 { __DRI_IMAGE_FOURCC_GR1616, __DRI_IMAGE_FORMAT_GR1616,
112 __DRI_IMAGE_COMPONENTS_RG, PIPE_FORMAT_RG1616_UNORM, 1,
113 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } },
114
115 { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_FORMAT_NONE,
116 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
117 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
118 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
119 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
120 { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_FORMAT_NONE,
121 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
122 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
123 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
124 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
125 { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_FORMAT_NONE,
126 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
127 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
128 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
129 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
130 { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_FORMAT_NONE,
131 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
132 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
133 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
134 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
135 { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_FORMAT_NONE,
136 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_IYUV, 3,
137 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
138 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
139 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
140
141 { __DRI_IMAGE_FOURCC_YVU410, __DRI_IMAGE_FORMAT_NONE,
142 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
143 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
144 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
145 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
146 { __DRI_IMAGE_FOURCC_YVU411, __DRI_IMAGE_FORMAT_NONE,
147 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
148 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
149 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
150 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
151 { __DRI_IMAGE_FOURCC_YVU420, __DRI_IMAGE_FORMAT_NONE,
152 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
153 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
154 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
155 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
156 { __DRI_IMAGE_FOURCC_YVU422, __DRI_IMAGE_FORMAT_NONE,
157 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
158 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
159 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
160 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
161 { __DRI_IMAGE_FOURCC_YVU444, __DRI_IMAGE_FORMAT_NONE,
162 __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_YV12, 3,
163 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
164 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
165 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
166
167 { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_FORMAT_NONE,
168 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,
169 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
170 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
171
172 { __DRI_IMAGE_FOURCC_P010, __DRI_IMAGE_FORMAT_NONE,
173 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
174 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
175 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
176 { __DRI_IMAGE_FOURCC_P012, __DRI_IMAGE_FORMAT_NONE,
177 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
178 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
179 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
180 { __DRI_IMAGE_FOURCC_P016, __DRI_IMAGE_FORMAT_NONE,
181 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_P016, 2,
182 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 2 },
183 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR1616, 4 } } },
184
185 { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_FORMAT_NONE,
186 __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2,
187 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
188 { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
189
190 { __DRI_IMAGE_FOURCC_AYUV, __DRI_IMAGE_FORMAT_ABGR8888,
191 __DRI_IMAGE_COMPONENTS_AYUV, PIPE_FORMAT_AYUV, 1,
192 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
193 { __DRI_IMAGE_FOURCC_XYUV8888, __DRI_IMAGE_FORMAT_XBGR8888,
194 __DRI_IMAGE_COMPONENTS_XYUV, PIPE_FORMAT_XYUV, 1,
195 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 } } },
196
197 /* For YUYV and UYVY buffers, we set up two overlapping DRI images
198 * and treat them as planar buffers in the compositors.
199 * Plane 0 is GR88 and samples YU or YV pairs and places Y into
200 * the R component, while plane 1 is ARGB/ABGR and samples YUYV/UYVY
201 * clusters and places pairs and places U into the G component and
202 * V into A. This lets the texture sampler interpolate the Y
203 * components correctly when sampling from plane 0, and interpolate
204 * U and V correctly when sampling from plane 1. */
205 { __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_FORMAT_NONE,
206 __DRI_IMAGE_COMPONENTS_Y_XUXV, PIPE_FORMAT_YUYV, 2,
207 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
208 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
209 { __DRI_IMAGE_FOURCC_UYVY, __DRI_IMAGE_FORMAT_NONE,
210 __DRI_IMAGE_COMPONENTS_Y_UXVX, PIPE_FORMAT_UYVY, 2,
211 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
212 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } }
213 };
214
215 const struct dri2_format_mapping *
216 dri2_get_mapping_by_fourcc(int fourcc)
217 {
218 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
219 if (dri2_format_table[i].dri_fourcc == fourcc)
220 return &dri2_format_table[i];
221 }
222
223 return NULL;
224 }
225
226 static const struct dri2_format_mapping *
227 dri2_get_mapping_by_format(int format)
228 {
229 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
230 if (dri2_format_table[i].dri_format == format)
231 return &dri2_format_table[i];
232 }
233
234 return NULL;
235 }
236
237 static enum pipe_format
238 dri2_get_pipe_format_for_dri_format(int format)
239 {
240 for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
241 if (dri2_format_table[i].dri_format == format)
242 return dri2_format_table[i].pipe_format;
243 }
244
245 return PIPE_FORMAT_NONE;
246 }
247
248 /**
249 * DRI2 flush extension.
250 */
251 static void
252 dri2_flush_drawable(__DRIdrawable *dPriv)
253 {
254 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
255 }
256
257 static void
258 dri2_invalidate_drawable(__DRIdrawable *dPriv)
259 {
260 struct dri_drawable *drawable = dri_drawable(dPriv);
261
262 dri2InvalidateDrawable(dPriv);
263 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
264 drawable->texture_mask = 0;
265
266 p_atomic_inc(&drawable->base.stamp);
267 }
268
269 static const __DRI2flushExtension dri2FlushExtension = {
270 .base = { __DRI2_FLUSH, 4 },
271
272 .flush = dri2_flush_drawable,
273 .invalidate = dri2_invalidate_drawable,
274 .flush_with_flags = dri_flush,
275 };
276
277 /**
278 * Retrieve __DRIbuffer from the DRI loader.
279 */
280 static __DRIbuffer *
281 dri2_drawable_get_buffers(struct dri_drawable *drawable,
282 const enum st_attachment_type *atts,
283 unsigned *count)
284 {
285 __DRIdrawable *dri_drawable = drawable->dPriv;
286 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
287 boolean with_format;
288 __DRIbuffer *buffers;
289 int num_buffers;
290 unsigned attachments[10];
291 unsigned num_attachments, i;
292
293 assert(loader);
294 with_format = dri_with_format(drawable->sPriv);
295
296 num_attachments = 0;
297
298 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
299 if (!with_format)
300 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
301
302 for (i = 0; i < *count; i++) {
303 enum pipe_format format;
304 unsigned bind;
305 int att, depth;
306
307 dri_drawable_get_format(drawable, atts[i], &format, &bind);
308 if (format == PIPE_FORMAT_NONE)
309 continue;
310
311 switch (atts[i]) {
312 case ST_ATTACHMENT_FRONT_LEFT:
313 /* already added */
314 if (!with_format)
315 continue;
316 att = __DRI_BUFFER_FRONT_LEFT;
317 break;
318 case ST_ATTACHMENT_BACK_LEFT:
319 att = __DRI_BUFFER_BACK_LEFT;
320 break;
321 case ST_ATTACHMENT_FRONT_RIGHT:
322 att = __DRI_BUFFER_FRONT_RIGHT;
323 break;
324 case ST_ATTACHMENT_BACK_RIGHT:
325 att = __DRI_BUFFER_BACK_RIGHT;
326 break;
327 default:
328 continue;
329 }
330
331 /*
332 * In this switch statement we must support all formats that
333 * may occur as the stvis->color_format.
334 */
335 switch(format) {
336 case PIPE_FORMAT_B10G10R10A2_UNORM:
337 case PIPE_FORMAT_R10G10B10A2_UNORM:
338 case PIPE_FORMAT_BGRA8888_UNORM:
339 case PIPE_FORMAT_RGBA8888_UNORM:
340 depth = 32;
341 break;
342 case PIPE_FORMAT_R10G10B10X2_UNORM:
343 case PIPE_FORMAT_B10G10R10X2_UNORM:
344 depth = 30;
345 break;
346 case PIPE_FORMAT_BGRX8888_UNORM:
347 case PIPE_FORMAT_RGBX8888_UNORM:
348 depth = 24;
349 break;
350 case PIPE_FORMAT_B5G6R5_UNORM:
351 depth = 16;
352 break;
353 default:
354 depth = util_format_get_blocksizebits(format);
355 assert(!"Unexpected format in dri2_drawable_get_buffers()");
356 }
357
358 attachments[num_attachments++] = att;
359 if (with_format) {
360 attachments[num_attachments++] = depth;
361 }
362 }
363
364 if (with_format) {
365 num_attachments /= 2;
366 buffers = loader->getBuffersWithFormat(dri_drawable,
367 &dri_drawable->w, &dri_drawable->h,
368 attachments, num_attachments,
369 &num_buffers, dri_drawable->loaderPrivate);
370 }
371 else {
372 buffers = loader->getBuffers(dri_drawable,
373 &dri_drawable->w, &dri_drawable->h,
374 attachments, num_attachments,
375 &num_buffers, dri_drawable->loaderPrivate);
376 }
377
378 if (buffers)
379 *count = num_buffers;
380
381 return buffers;
382 }
383
384 static bool
385 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
386 struct __DRIimageList *images,
387 const enum st_attachment_type *statts,
388 unsigned statts_count)
389 {
390 __DRIdrawable *dPriv = drawable->dPriv;
391 __DRIscreen *sPriv = drawable->sPriv;
392 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
393 enum pipe_format pf;
394 uint32_t buffer_mask = 0;
395 unsigned i, bind;
396
397 for (i = 0; i < statts_count; i++) {
398 dri_drawable_get_format(drawable, statts[i], &pf, &bind);
399 if (pf == PIPE_FORMAT_NONE)
400 continue;
401
402 switch (statts[i]) {
403 case ST_ATTACHMENT_FRONT_LEFT:
404 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
405 break;
406 case ST_ATTACHMENT_BACK_LEFT:
407 buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
408 break;
409 default:
410 continue;
411 }
412
413 switch (pf) {
414 case PIPE_FORMAT_B5G5R5A1_UNORM:
415 image_format = __DRI_IMAGE_FORMAT_ARGB1555;
416 break;
417 case PIPE_FORMAT_B5G6R5_UNORM:
418 image_format = __DRI_IMAGE_FORMAT_RGB565;
419 break;
420 case PIPE_FORMAT_BGRX8888_UNORM:
421 image_format = __DRI_IMAGE_FORMAT_XRGB8888;
422 break;
423 case PIPE_FORMAT_BGRA8888_UNORM:
424 image_format = __DRI_IMAGE_FORMAT_ARGB8888;
425 break;
426 case PIPE_FORMAT_RGBX8888_UNORM:
427 image_format = __DRI_IMAGE_FORMAT_XBGR8888;
428 break;
429 case PIPE_FORMAT_RGBA8888_UNORM:
430 image_format = __DRI_IMAGE_FORMAT_ABGR8888;
431 break;
432 case PIPE_FORMAT_B10G10R10X2_UNORM:
433 image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
434 break;
435 case PIPE_FORMAT_B10G10R10A2_UNORM:
436 image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
437 break;
438 case PIPE_FORMAT_R10G10B10X2_UNORM:
439 image_format = __DRI_IMAGE_FORMAT_XBGR2101010;
440 break;
441 case PIPE_FORMAT_R10G10B10A2_UNORM:
442 image_format = __DRI_IMAGE_FORMAT_ABGR2101010;
443 break;
444 default:
445 image_format = __DRI_IMAGE_FORMAT_NONE;
446 break;
447 }
448 }
449
450 return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
451 (uint32_t *) &drawable->base.stamp,
452 dPriv->loaderPrivate, buffer_mask,
453 images);
454 }
455
456 static __DRIbuffer *
457 dri2_allocate_buffer(__DRIscreen *sPriv,
458 unsigned attachment, unsigned format,
459 int width, int height)
460 {
461 struct dri_screen *screen = dri_screen(sPriv);
462 struct dri2_buffer *buffer;
463 struct pipe_resource templ;
464 enum pipe_format pf;
465 unsigned bind = 0;
466 struct winsys_handle whandle;
467
468 switch (attachment) {
469 case __DRI_BUFFER_FRONT_LEFT:
470 case __DRI_BUFFER_FAKE_FRONT_LEFT:
471 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
472 break;
473 case __DRI_BUFFER_BACK_LEFT:
474 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
475 break;
476 case __DRI_BUFFER_DEPTH:
477 case __DRI_BUFFER_DEPTH_STENCIL:
478 case __DRI_BUFFER_STENCIL:
479 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
480 break;
481 }
482
483 /* because we get the handle and stride */
484 bind |= PIPE_BIND_SHARED;
485
486 switch (format) {
487 case 32:
488 pf = PIPE_FORMAT_BGRA8888_UNORM;
489 break;
490 case 30:
491 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
492 break;
493 case 24:
494 pf = PIPE_FORMAT_BGRX8888_UNORM;
495 break;
496 case 16:
497 pf = PIPE_FORMAT_Z16_UNORM;
498 break;
499 default:
500 return NULL;
501 }
502
503 buffer = CALLOC_STRUCT(dri2_buffer);
504 if (!buffer)
505 return NULL;
506
507 memset(&templ, 0, sizeof(templ));
508 templ.bind = bind;
509 templ.format = pf;
510 templ.target = PIPE_TEXTURE_2D;
511 templ.last_level = 0;
512 templ.width0 = width;
513 templ.height0 = height;
514 templ.depth0 = 1;
515 templ.array_size = 1;
516
517 buffer->resource =
518 screen->base.screen->resource_create(screen->base.screen, &templ);
519 if (!buffer->resource) {
520 FREE(buffer);
521 return NULL;
522 }
523
524 memset(&whandle, 0, sizeof(whandle));
525 if (screen->can_share_buffer)
526 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
527 else
528 whandle.type = WINSYS_HANDLE_TYPE_KMS;
529
530 screen->base.screen->resource_get_handle(screen->base.screen, NULL,
531 buffer->resource, &whandle,
532 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
533
534 buffer->base.attachment = attachment;
535 buffer->base.name = whandle.handle;
536 buffer->base.cpp = util_format_get_blocksize(pf);
537 buffer->base.pitch = whandle.stride;
538
539 return &buffer->base;
540 }
541
542 static void
543 dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
544 {
545 struct dri2_buffer *buffer = dri2_buffer(bPriv);
546
547 pipe_resource_reference(&buffer->resource, NULL);
548 FREE(buffer);
549 }
550
551 /*
552 * Backend functions for st_framebuffer interface.
553 */
554
555 static void
556 dri2_allocate_textures(struct dri_context *ctx,
557 struct dri_drawable *drawable,
558 const enum st_attachment_type *statts,
559 unsigned statts_count)
560 {
561 __DRIscreen *sPriv = drawable->sPriv;
562 __DRIdrawable *dri_drawable = drawable->dPriv;
563 struct dri_screen *screen = dri_screen(sPriv);
564 struct pipe_resource templ;
565 boolean alloc_depthstencil = FALSE;
566 unsigned i, j, bind;
567 const __DRIimageLoaderExtension *image = sPriv->image.loader;
568 /* Image specific variables */
569 struct __DRIimageList images;
570 /* Dri2 specific variables */
571 __DRIbuffer *buffers = NULL;
572 struct winsys_handle whandle;
573 unsigned num_buffers = statts_count;
574
575 /* First get the buffers from the loader */
576 if (image) {
577 if (!dri_image_drawable_get_buffers(drawable, &images,
578 statts, statts_count))
579 return;
580 }
581 else {
582 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
583 if (!buffers || (drawable->old_num == num_buffers &&
584 drawable->old_w == dri_drawable->w &&
585 drawable->old_h == dri_drawable->h &&
586 memcmp(drawable->old, buffers,
587 sizeof(__DRIbuffer) * num_buffers) == 0))
588 return;
589 }
590
591 /* Second clean useless resources*/
592
593 /* See if we need a depth-stencil buffer. */
594 for (i = 0; i < statts_count; i++) {
595 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
596 alloc_depthstencil = TRUE;
597 break;
598 }
599 }
600
601 /* Delete the resources we won't need. */
602 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
603 /* Don't delete the depth-stencil buffer, we can reuse it. */
604 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
605 continue;
606
607 /* Flush the texture before unreferencing, so that other clients can
608 * see what the driver has rendered.
609 */
610 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
611 struct pipe_context *pipe = ctx->st->pipe;
612 pipe->flush_resource(pipe, drawable->textures[i]);
613 }
614
615 pipe_resource_reference(&drawable->textures[i], NULL);
616 }
617
618 if (drawable->stvis.samples > 1) {
619 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
620 boolean del = TRUE;
621
622 /* Don't delete MSAA resources for the attachments which are enabled,
623 * we can reuse them. */
624 for (j = 0; j < statts_count; j++) {
625 if (i == statts[j]) {
626 del = FALSE;
627 break;
628 }
629 }
630
631 if (del) {
632 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
633 }
634 }
635 }
636
637 /* Third use the buffers retrieved to fill the drawable info */
638
639 memset(&templ, 0, sizeof(templ));
640 templ.target = screen->target;
641 templ.last_level = 0;
642 templ.depth0 = 1;
643 templ.array_size = 1;
644
645 if (image) {
646 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
647 struct pipe_resource **buf =
648 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
649 struct pipe_resource *texture = images.front->texture;
650
651 dri_drawable->w = texture->width0;
652 dri_drawable->h = texture->height0;
653
654 pipe_resource_reference(buf, texture);
655 }
656
657 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
658 struct pipe_resource **buf =
659 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
660 struct pipe_resource *texture = images.back->texture;
661
662 dri_drawable->w = texture->width0;
663 dri_drawable->h = texture->height0;
664
665 pipe_resource_reference(buf, texture);
666 }
667
668 /* Note: if there is both a back and a front buffer,
669 * then they have the same size.
670 */
671 templ.width0 = dri_drawable->w;
672 templ.height0 = dri_drawable->h;
673 }
674 else {
675 memset(&whandle, 0, sizeof(whandle));
676
677 /* Process DRI-provided buffers and get pipe_resources. */
678 for (i = 0; i < num_buffers; i++) {
679 __DRIbuffer *buf = &buffers[i];
680 enum st_attachment_type statt;
681 enum pipe_format format;
682
683 switch (buf->attachment) {
684 case __DRI_BUFFER_FRONT_LEFT:
685 if (!screen->auto_fake_front) {
686 continue; /* invalid attachment */
687 }
688 /* fallthrough */
689 case __DRI_BUFFER_FAKE_FRONT_LEFT:
690 statt = ST_ATTACHMENT_FRONT_LEFT;
691 break;
692 case __DRI_BUFFER_BACK_LEFT:
693 statt = ST_ATTACHMENT_BACK_LEFT;
694 break;
695 default:
696 continue; /* invalid attachment */
697 }
698
699 dri_drawable_get_format(drawable, statt, &format, &bind);
700 if (format == PIPE_FORMAT_NONE)
701 continue;
702
703 /* dri2_drawable_get_buffers has already filled dri_drawable->w
704 * and dri_drawable->h */
705 templ.width0 = dri_drawable->w;
706 templ.height0 = dri_drawable->h;
707 templ.format = format;
708 templ.bind = bind;
709 whandle.handle = buf->name;
710 whandle.stride = buf->pitch;
711 whandle.offset = 0;
712 whandle.modifier = DRM_FORMAT_MOD_INVALID;
713 if (screen->can_share_buffer)
714 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
715 else
716 whandle.type = WINSYS_HANDLE_TYPE_KMS;
717 drawable->textures[statt] =
718 screen->base.screen->resource_from_handle(screen->base.screen,
719 &templ, &whandle,
720 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
721 assert(drawable->textures[statt]);
722 }
723 }
724
725 /* Allocate private MSAA colorbuffers. */
726 if (drawable->stvis.samples > 1) {
727 for (i = 0; i < statts_count; i++) {
728 enum st_attachment_type statt = statts[i];
729
730 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
731 continue;
732
733 if (drawable->textures[statt]) {
734 templ.format = drawable->textures[statt]->format;
735 templ.bind = drawable->textures[statt]->bind &
736 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
737 templ.nr_samples = drawable->stvis.samples;
738 templ.nr_storage_samples = drawable->stvis.samples;
739
740 /* Try to reuse the resource.
741 * (the other resource parameters should be constant)
742 */
743 if (!drawable->msaa_textures[statt] ||
744 drawable->msaa_textures[statt]->width0 != templ.width0 ||
745 drawable->msaa_textures[statt]->height0 != templ.height0) {
746 /* Allocate a new one. */
747 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
748
749 drawable->msaa_textures[statt] =
750 screen->base.screen->resource_create(screen->base.screen,
751 &templ);
752 assert(drawable->msaa_textures[statt]);
753
754 /* If there are any MSAA resources, we should initialize them
755 * such that they contain the same data as the single-sample
756 * resources we just got from the X server.
757 *
758 * The reason for this is that the state tracker (and
759 * therefore the app) can access the MSAA resources only.
760 * The single-sample resources are not exposed
761 * to the state tracker.
762 *
763 */
764 dri_pipe_blit(ctx->st->pipe,
765 drawable->msaa_textures[statt],
766 drawable->textures[statt]);
767 }
768 }
769 else {
770 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
771 }
772 }
773 }
774
775 /* Allocate a private depth-stencil buffer. */
776 if (alloc_depthstencil) {
777 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
778 struct pipe_resource **zsbuf;
779 enum pipe_format format;
780 unsigned bind;
781
782 dri_drawable_get_format(drawable, statt, &format, &bind);
783
784 if (format) {
785 templ.format = format;
786 templ.bind = bind & ~PIPE_BIND_SHARED;
787
788 if (drawable->stvis.samples > 1) {
789 templ.nr_samples = drawable->stvis.samples;
790 templ.nr_storage_samples = drawable->stvis.samples;
791 zsbuf = &drawable->msaa_textures[statt];
792 }
793 else {
794 templ.nr_samples = 0;
795 templ.nr_storage_samples = 0;
796 zsbuf = &drawable->textures[statt];
797 }
798
799 /* Try to reuse the resource.
800 * (the other resource parameters should be constant)
801 */
802 if (!*zsbuf ||
803 (*zsbuf)->width0 != templ.width0 ||
804 (*zsbuf)->height0 != templ.height0) {
805 /* Allocate a new one. */
806 pipe_resource_reference(zsbuf, NULL);
807 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
808 &templ);
809 assert(*zsbuf);
810 }
811 }
812 else {
813 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
814 pipe_resource_reference(&drawable->textures[statt], NULL);
815 }
816 }
817
818 /* For DRI2, we may get the same buffers again from the server.
819 * To prevent useless imports of gem names, drawable->old* is used
820 * to bypass the import if we get the same buffers. This doesn't apply
821 * to DRI3/Wayland, users of image.loader, since the buffer is managed
822 * by the client (no import), and the back buffer is going to change
823 * at every redraw.
824 */
825 if (!image) {
826 drawable->old_num = num_buffers;
827 drawable->old_w = dri_drawable->w;
828 drawable->old_h = dri_drawable->h;
829 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
830 }
831 }
832
833 static void
834 dri2_flush_frontbuffer(struct dri_context *ctx,
835 struct dri_drawable *drawable,
836 enum st_attachment_type statt)
837 {
838 __DRIdrawable *dri_drawable = drawable->dPriv;
839 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
840 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
841 struct pipe_context *pipe = ctx->st->pipe;
842
843 if (statt != ST_ATTACHMENT_FRONT_LEFT)
844 return;
845
846 if (drawable->stvis.samples > 1) {
847 /* Resolve the front buffer. */
848 dri_pipe_blit(ctx->st->pipe,
849 drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
850 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
851 }
852
853 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
854 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
855 }
856
857 pipe->flush(pipe, NULL, 0);
858
859 if (image) {
860 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
861 }
862 else if (loader->flushFrontBuffer) {
863 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
864 }
865 }
866
867 /**
868 * The struct dri_drawable flush_swapbuffers callback
869 */
870 static void
871 dri2_flush_swapbuffers(struct dri_context *ctx,
872 struct dri_drawable *drawable)
873 {
874 __DRIdrawable *dri_drawable = drawable->dPriv;
875 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
876
877 if (image && image->base.version >= 3 && image->flushSwapBuffers) {
878 image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate);
879 }
880 }
881
882 static void
883 dri2_update_tex_buffer(struct dri_drawable *drawable,
884 struct dri_context *ctx,
885 struct pipe_resource *res)
886 {
887 /* no-op */
888 }
889
890 static __DRIimage *
891 dri2_create_image_from_winsys(__DRIscreen *_screen,
892 int width, int height, const struct dri2_format_mapping *map,
893 int num_handles, struct winsys_handle *whandle,
894 void *loaderPrivate)
895 {
896 struct dri_screen *screen = dri_screen(_screen);
897 struct pipe_screen *pscreen = screen->base.screen;
898 __DRIimage *img;
899 struct pipe_resource templ;
900 unsigned tex_usage = 0;
901 int i;
902 bool is_yuv = util_format_is_yuv(map->pipe_format);
903
904 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
905 PIPE_BIND_RENDER_TARGET))
906 tex_usage |= PIPE_BIND_RENDER_TARGET;
907 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
908 PIPE_BIND_SAMPLER_VIEW))
909 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
910
911 if (!tex_usage && is_yuv) {
912 /* YUV format sampling can be emulated by the Mesa state tracker by
913 * using multiple samplers of varying formats.
914 * If no tex_usage is set and we detect a YUV format,
915 * test for support of the first plane's sampler format and
916 * add sampler view usage.
917 */
918 if (pscreen->is_format_supported(pscreen,
919 dri2_get_pipe_format_for_dri_format(map->planes[0].dri_format),
920 screen->target, 0, 0,
921 PIPE_BIND_SAMPLER_VIEW))
922 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
923 }
924
925 if (!tex_usage)
926 return NULL;
927
928 img = CALLOC_STRUCT(__DRIimageRec);
929 if (!img)
930 return NULL;
931
932 memset(&templ, 0, sizeof(templ));
933 templ.bind = tex_usage;
934 templ.target = screen->target;
935 templ.last_level = 0;
936 templ.depth0 = 1;
937 templ.array_size = 1;
938
939 for (i = num_handles - 1; i >= 0; i--) {
940 struct pipe_resource *tex;
941
942 templ.width0 = width >> map->planes[i].width_shift;
943 templ.height0 = height >> map->planes[i].height_shift;
944 if (is_yuv)
945 templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);
946 else
947 templ.format = map->pipe_format;
948 assert(templ.format != PIPE_FORMAT_NONE);
949
950 tex = pscreen->resource_from_handle(pscreen,
951 &templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
952 if (!tex) {
953 pipe_resource_reference(&img->texture, NULL);
954 FREE(img);
955 return NULL;
956 }
957
958 tex->next = img->texture;
959 img->texture = tex;
960 }
961
962 img->level = 0;
963 img->layer = 0;
964 img->use = 0;
965 img->loader_private = loaderPrivate;
966
967 return img;
968 }
969
970 static __DRIimage *
971 dri2_create_image_from_name(__DRIscreen *_screen,
972 int width, int height, int format,
973 int name, int pitch, void *loaderPrivate)
974 {
975 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
976 struct winsys_handle whandle;
977 __DRIimage *img;
978
979 if (!map)
980 return NULL;
981
982 memset(&whandle, 0, sizeof(whandle));
983 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
984 whandle.handle = name;
985 whandle.modifier = DRM_FORMAT_MOD_INVALID;
986
987 whandle.stride = pitch * util_format_get_blocksize(map->pipe_format);
988
989 img = dri2_create_image_from_winsys(_screen, width, height, map,
990 1, &whandle, loaderPrivate);
991
992 if (!img)
993 return NULL;
994
995 img->dri_components = map->dri_components;
996 img->dri_fourcc = map->dri_fourcc;
997 img->dri_format = map->dri_format;
998
999 return img;
1000 }
1001
1002 static __DRIimage *
1003 dri2_create_image_from_fd(__DRIscreen *_screen,
1004 int width, int height, int fourcc,
1005 uint64_t modifier, int *fds, int num_fds,
1006 int *strides, int *offsets, unsigned *error,
1007 void *loaderPrivate)
1008 {
1009 struct winsys_handle whandles[3];
1010 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1011 __DRIimage *img = NULL;
1012 unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
1013 int i, expected_num_fds;
1014
1015 if (!map) {
1016 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1017 goto exit;
1018 }
1019
1020 switch (fourcc) {
1021 case __DRI_IMAGE_FOURCC_YUYV:
1022 case __DRI_IMAGE_FOURCC_UYVY:
1023 expected_num_fds = 1;
1024 break;
1025 default:
1026 expected_num_fds = map->nplanes;
1027 break;
1028 }
1029
1030 if (num_fds != expected_num_fds) {
1031 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1032 goto exit;
1033 }
1034
1035 memset(whandles, 0, sizeof(whandles));
1036
1037 for (i = 0; i < map->nplanes; i++) {
1038 int fdnum = i >= num_fds ? 0 : i;
1039 int index = map->planes[i].buffer_index;
1040 if (fds[fdnum] < 0) {
1041 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1042 goto exit;
1043 }
1044
1045 whandles[i].type = WINSYS_HANDLE_TYPE_FD;
1046 whandles[i].handle = (unsigned)fds[fdnum];
1047 whandles[i].stride = (unsigned)strides[index];
1048 whandles[i].offset = (unsigned)offsets[index];
1049 whandles[i].modifier = modifier;
1050 }
1051
1052 img = dri2_create_image_from_winsys(_screen, width, height, map,
1053 map->nplanes, whandles, loaderPrivate);
1054 if(img == NULL) {
1055 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1056 goto exit;
1057 }
1058
1059 img->dri_components = map->dri_components;
1060 img->dri_fourcc = fourcc;
1061 img->dri_format = map->dri_format;
1062
1063 exit:
1064 if (error)
1065 *error = err;
1066
1067 return img;
1068 }
1069
1070 static __DRIimage *
1071 dri2_create_image_common(__DRIscreen *_screen,
1072 int width, int height,
1073 int format, unsigned int use,
1074 const uint64_t *modifiers,
1075 const unsigned count,
1076 void *loaderPrivate)
1077 {
1078 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1079 struct dri_screen *screen = dri_screen(_screen);
1080 __DRIimage *img;
1081 struct pipe_resource templ;
1082 unsigned tex_usage;
1083
1084 if (!map)
1085 return NULL;
1086
1087 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1088
1089 if (use & __DRI_IMAGE_USE_SCANOUT)
1090 tex_usage |= PIPE_BIND_SCANOUT;
1091 if (use & __DRI_IMAGE_USE_SHARE)
1092 tex_usage |= PIPE_BIND_SHARED;
1093 if (use & __DRI_IMAGE_USE_LINEAR)
1094 tex_usage |= PIPE_BIND_LINEAR;
1095 if (use & __DRI_IMAGE_USE_CURSOR) {
1096 if (width != 64 || height != 64)
1097 return NULL;
1098 tex_usage |= PIPE_BIND_CURSOR;
1099 }
1100
1101 img = CALLOC_STRUCT(__DRIimageRec);
1102 if (!img)
1103 return NULL;
1104
1105 memset(&templ, 0, sizeof(templ));
1106 templ.bind = tex_usage;
1107 templ.format = map->pipe_format;
1108 templ.target = PIPE_TEXTURE_2D;
1109 templ.last_level = 0;
1110 templ.width0 = width;
1111 templ.height0 = height;
1112 templ.depth0 = 1;
1113 templ.array_size = 1;
1114
1115 if (modifiers)
1116 img->texture =
1117 screen->base.screen
1118 ->resource_create_with_modifiers(screen->base.screen,
1119 &templ,
1120 modifiers,
1121 count);
1122 else
1123 img->texture =
1124 screen->base.screen->resource_create(screen->base.screen, &templ);
1125 if (!img->texture) {
1126 FREE(img);
1127 return NULL;
1128 }
1129
1130 img->level = 0;
1131 img->layer = 0;
1132 img->dri_format = format;
1133 img->dri_fourcc = map->dri_fourcc;
1134 img->dri_components = 0;
1135 img->use = use;
1136
1137 img->loader_private = loaderPrivate;
1138 return img;
1139 }
1140
1141 static __DRIimage *
1142 dri2_create_image(__DRIscreen *_screen,
1143 int width, int height, int format,
1144 unsigned int use, void *loaderPrivate)
1145 {
1146 return dri2_create_image_common(_screen, width, height, format, use,
1147 NULL /* modifiers */, 0 /* count */,
1148 loaderPrivate);
1149 }
1150
1151 static __DRIimage *
1152 dri2_create_image_with_modifiers(__DRIscreen *dri_screen,
1153 int width, int height, int format,
1154 const uint64_t *modifiers,
1155 const unsigned count,
1156 void *loaderPrivate)
1157 {
1158 return dri2_create_image_common(dri_screen, width, height, format,
1159 __DRI_IMAGE_USE_SHARE, modifiers, count,
1160 loaderPrivate);
1161 }
1162
1163 static GLboolean
1164 dri2_query_image(__DRIimage *image, int attrib, int *value)
1165 {
1166 struct winsys_handle whandle;
1167 unsigned usage;
1168
1169 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1170 usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1171 else
1172 usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1173
1174 memset(&whandle, 0, sizeof(whandle));
1175
1176 switch (attrib) {
1177 case __DRI_IMAGE_ATTRIB_STRIDE:
1178 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1179 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1180 NULL, image->texture, &whandle, usage))
1181 return GL_FALSE;
1182 *value = whandle.stride;
1183 return GL_TRUE;
1184 case __DRI_IMAGE_ATTRIB_OFFSET:
1185 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1186 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1187 NULL, image->texture, &whandle, usage))
1188 return GL_FALSE;
1189 *value = whandle.offset;
1190 return GL_TRUE;
1191 case __DRI_IMAGE_ATTRIB_HANDLE:
1192 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1193 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1194 NULL, image->texture, &whandle, usage))
1195 return GL_FALSE;
1196 *value = whandle.handle;
1197 return GL_TRUE;
1198 case __DRI_IMAGE_ATTRIB_NAME:
1199 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1200 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1201 NULL, image->texture, &whandle, usage))
1202 return GL_FALSE;
1203 *value = whandle.handle;
1204 return GL_TRUE;
1205 case __DRI_IMAGE_ATTRIB_FD:
1206 whandle.type= WINSYS_HANDLE_TYPE_FD;
1207 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1208 NULL, image->texture, &whandle, usage))
1209 return GL_FALSE;
1210
1211 *value = whandle.handle;
1212 return GL_TRUE;
1213 case __DRI_IMAGE_ATTRIB_FORMAT:
1214 *value = image->dri_format;
1215 return GL_TRUE;
1216 case __DRI_IMAGE_ATTRIB_WIDTH:
1217 *value = image->texture->width0;
1218 return GL_TRUE;
1219 case __DRI_IMAGE_ATTRIB_HEIGHT:
1220 *value = image->texture->height0;
1221 return GL_TRUE;
1222 case __DRI_IMAGE_ATTRIB_COMPONENTS:
1223 if (image->dri_components == 0)
1224 return GL_FALSE;
1225 *value = image->dri_components;
1226 return GL_TRUE;
1227 case __DRI_IMAGE_ATTRIB_FOURCC:
1228 if (image->dri_fourcc) {
1229 *value = image->dri_fourcc;
1230 } else {
1231 const struct dri2_format_mapping *map;
1232
1233 map = dri2_get_mapping_by_format(image->dri_format);
1234 if (!map)
1235 return GL_FALSE;
1236
1237 *value = map->dri_fourcc;
1238 }
1239 return GL_TRUE;
1240 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1241 *value = 1;
1242 return GL_TRUE;
1243 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1244 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1245 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1246 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1247 NULL, image->texture, &whandle, usage))
1248 return GL_FALSE;
1249 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1250 return GL_FALSE;
1251 *value = (whandle.modifier >> 32) & 0xffffffff;
1252 return GL_TRUE;
1253 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1254 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1255 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1256 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1257 NULL, image->texture, &whandle, usage))
1258 return GL_FALSE;
1259 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1260 return GL_FALSE;
1261 *value = whandle.modifier & 0xffffffff;
1262 return GL_TRUE;
1263 default:
1264 return GL_FALSE;
1265 }
1266 }
1267
1268 static __DRIimage *
1269 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
1270 {
1271 __DRIimage *img;
1272
1273 img = CALLOC_STRUCT(__DRIimageRec);
1274 if (!img)
1275 return NULL;
1276
1277 img->texture = NULL;
1278 pipe_resource_reference(&img->texture, image->texture);
1279 img->level = image->level;
1280 img->layer = image->layer;
1281 img->dri_format = image->dri_format;
1282 /* This should be 0 for sub images, but dup is also used for base images. */
1283 img->dri_components = image->dri_components;
1284 img->loader_private = loaderPrivate;
1285
1286 return img;
1287 }
1288
1289 static GLboolean
1290 dri2_validate_usage(__DRIimage *image, unsigned int use)
1291 {
1292 if (!image || !image->texture)
1293 return false;
1294
1295 struct pipe_screen *screen = image->texture->screen;
1296 if (!screen->check_resource_capability)
1297 return true;
1298
1299 /* We don't want to check these:
1300 * __DRI_IMAGE_USE_SHARE (all images are shareable)
1301 * __DRI_IMAGE_USE_BACKBUFFER (all images support this)
1302 */
1303 unsigned bind = 0;
1304 if (use & __DRI_IMAGE_USE_SCANOUT)
1305 bind |= PIPE_BIND_SCANOUT;
1306 if (use & __DRI_IMAGE_USE_LINEAR)
1307 bind |= PIPE_BIND_LINEAR;
1308 if (use & __DRI_IMAGE_USE_CURSOR)
1309 bind |= PIPE_BIND_CURSOR;
1310
1311 if (!bind)
1312 return true;
1313
1314 return screen->check_resource_capability(screen, image->texture, bind);
1315 }
1316
1317 static __DRIimage *
1318 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
1319 int *names, int num_names, int *strides, int *offsets,
1320 void *loaderPrivate)
1321 {
1322 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1323 __DRIimage *img;
1324 struct winsys_handle whandle;
1325
1326 if (!map)
1327 return NULL;
1328
1329 if (num_names != 1)
1330 return NULL;
1331
1332 memset(&whandle, 0, sizeof(whandle));
1333 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1334 whandle.handle = names[0];
1335 whandle.stride = strides[0];
1336 whandle.offset = offsets[0];
1337 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1338
1339 img = dri2_create_image_from_winsys(screen, width, height, map,
1340 1, &whandle, loaderPrivate);
1341 if (img == NULL)
1342 return NULL;
1343
1344 img->dri_components = map->dri_components;
1345 img->dri_fourcc = map->dri_fourcc;
1346 img->dri_format = map->pipe_format;
1347
1348 return img;
1349 }
1350
1351 static __DRIimage *
1352 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1353 {
1354 __DRIimage *img;
1355
1356 if (plane != 0)
1357 return NULL;
1358
1359 if (image->dri_components == 0)
1360 return NULL;
1361
1362 img = dri2_dup_image(image, loaderPrivate);
1363 if (img == NULL)
1364 return NULL;
1365
1366 if (img->texture->screen->resource_changed)
1367 img->texture->screen->resource_changed(img->texture->screen,
1368 img->texture);
1369
1370 /* set this to 0 for sub images. */
1371 img->dri_components = 0;
1372 return img;
1373 }
1374
1375 static __DRIimage *
1376 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1377 int *fds, int num_fds, int *strides, int *offsets,
1378 void *loaderPrivate)
1379 {
1380 return dri2_create_image_from_fd(screen, width, height, fourcc,
1381 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1382 strides, offsets, NULL, loaderPrivate);
1383 }
1384
1385 static boolean
1386 dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
1387 int *count)
1388 {
1389 struct dri_screen *screen = dri_screen(_screen);
1390 struct pipe_screen *pscreen = screen->base.screen;
1391 int i, j;
1392
1393 for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) &&
1394 (j < max || max == 0); i++) {
1395 const struct dri2_format_mapping *map = &dri2_format_table[i];
1396
1397 /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we
1398 * must not leak it out to clients.
1399 */
1400 if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888)
1401 continue;
1402
1403 if (pscreen->is_format_supported(pscreen, map->pipe_format,
1404 screen->target, 0, 0,
1405 PIPE_BIND_RENDER_TARGET) ||
1406 pscreen->is_format_supported(pscreen, map->pipe_format,
1407 screen->target, 0, 0,
1408 PIPE_BIND_SAMPLER_VIEW)) {
1409 if (j < max)
1410 formats[j] = map->dri_fourcc;
1411 j++;
1412 }
1413 }
1414 *count = j;
1415 return true;
1416 }
1417
1418 static boolean
1419 dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1420 uint64_t *modifiers, unsigned int *external_only,
1421 int *count)
1422 {
1423 struct dri_screen *screen = dri_screen(_screen);
1424 struct pipe_screen *pscreen = screen->base.screen;
1425 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1426 enum pipe_format format;
1427
1428 if (!map)
1429 return false;
1430
1431 format = map->pipe_format;
1432
1433 if (pscreen->query_dmabuf_modifiers != NULL &&
1434 (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1435 PIPE_BIND_RENDER_TARGET) ||
1436 pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1437 PIPE_BIND_SAMPLER_VIEW))) {
1438 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1439 external_only, count);
1440 return true;
1441 }
1442 return false;
1443 }
1444
1445 static __DRIimage *
1446 dri2_from_dma_bufs(__DRIscreen *screen,
1447 int width, int height, int fourcc,
1448 int *fds, int num_fds,
1449 int *strides, int *offsets,
1450 enum __DRIYUVColorSpace yuv_color_space,
1451 enum __DRISampleRange sample_range,
1452 enum __DRIChromaSiting horizontal_siting,
1453 enum __DRIChromaSiting vertical_siting,
1454 unsigned *error,
1455 void *loaderPrivate)
1456 {
1457 __DRIimage *img;
1458
1459 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1460 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1461 strides, offsets, error, loaderPrivate);
1462 if (img == NULL)
1463 return NULL;
1464
1465 img->yuv_color_space = yuv_color_space;
1466 img->sample_range = sample_range;
1467 img->horizontal_siting = horizontal_siting;
1468 img->vertical_siting = vertical_siting;
1469
1470 *error = __DRI_IMAGE_ERROR_SUCCESS;
1471 return img;
1472 }
1473
1474 static __DRIimage *
1475 dri2_from_dma_bufs2(__DRIscreen *screen,
1476 int width, int height, int fourcc,
1477 uint64_t modifier, int *fds, int num_fds,
1478 int *strides, int *offsets,
1479 enum __DRIYUVColorSpace yuv_color_space,
1480 enum __DRISampleRange sample_range,
1481 enum __DRIChromaSiting horizontal_siting,
1482 enum __DRIChromaSiting vertical_siting,
1483 unsigned *error,
1484 void *loaderPrivate)
1485 {
1486 __DRIimage *img;
1487
1488 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1489 modifier, fds, num_fds, strides, offsets,
1490 error, loaderPrivate);
1491 if (img == NULL)
1492 return NULL;
1493
1494 img->yuv_color_space = yuv_color_space;
1495 img->sample_range = sample_range;
1496 img->horizontal_siting = horizontal_siting;
1497 img->vertical_siting = vertical_siting;
1498
1499 *error = __DRI_IMAGE_ERROR_SUCCESS;
1500 return img;
1501 }
1502
1503 static void
1504 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1505 int dstx0, int dsty0, int dstwidth, int dstheight,
1506 int srcx0, int srcy0, int srcwidth, int srcheight,
1507 int flush_flag)
1508 {
1509 struct dri_context *ctx = dri_context(context);
1510 struct pipe_context *pipe = ctx->st->pipe;
1511 struct pipe_screen *screen;
1512 struct pipe_fence_handle *fence;
1513 struct pipe_blit_info blit;
1514
1515 if (!dst || !src)
1516 return;
1517
1518 memset(&blit, 0, sizeof(blit));
1519 blit.dst.resource = dst->texture;
1520 blit.dst.box.x = dstx0;
1521 blit.dst.box.y = dsty0;
1522 blit.dst.box.width = dstwidth;
1523 blit.dst.box.height = dstheight;
1524 blit.dst.box.depth = 1;
1525 blit.dst.format = dst->texture->format;
1526 blit.src.resource = src->texture;
1527 blit.src.box.x = srcx0;
1528 blit.src.box.y = srcy0;
1529 blit.src.box.width = srcwidth;
1530 blit.src.box.height = srcheight;
1531 blit.src.box.depth = 1;
1532 blit.src.format = src->texture->format;
1533 blit.mask = PIPE_MASK_RGBA;
1534 blit.filter = PIPE_TEX_FILTER_NEAREST;
1535
1536 pipe->blit(pipe, &blit);
1537
1538 if (flush_flag == __BLIT_FLAG_FLUSH) {
1539 pipe->flush_resource(pipe, dst->texture);
1540 ctx->st->flush(ctx->st, 0, NULL);
1541 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1542 screen = dri_screen(ctx->sPriv)->base.screen;
1543 pipe->flush_resource(pipe, dst->texture);
1544 ctx->st->flush(ctx->st, 0, &fence);
1545 (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
1546 screen->fence_reference(screen, &fence, NULL);
1547 }
1548 }
1549
1550 static void *
1551 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1552 int x0, int y0, int width, int height,
1553 unsigned int flags, int *stride, void **data)
1554 {
1555 struct dri_context *ctx = dri_context(context);
1556 struct pipe_context *pipe = ctx->st->pipe;
1557 enum pipe_transfer_usage pipe_access = 0;
1558 struct pipe_transfer *trans;
1559 void *map;
1560
1561 if (!image || !data || *data)
1562 return NULL;
1563
1564 if (flags & __DRI_IMAGE_TRANSFER_READ)
1565 pipe_access |= PIPE_TRANSFER_READ;
1566 if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1567 pipe_access |= PIPE_TRANSFER_WRITE;
1568
1569 map = pipe_transfer_map(pipe, image->texture,
1570 0, 0, pipe_access, x0, y0, width, height,
1571 &trans);
1572 if (map) {
1573 *data = trans;
1574 *stride = trans->stride;
1575 }
1576
1577 return map;
1578 }
1579
1580 static void
1581 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1582 {
1583 struct dri_context *ctx = dri_context(context);
1584 struct pipe_context *pipe = ctx->st->pipe;
1585
1586 pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
1587 }
1588
1589 static int
1590 dri2_get_capabilities(__DRIscreen *_screen)
1591 {
1592 struct dri_screen *screen = dri_screen(_screen);
1593
1594 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1595 }
1596
1597 /* The extension is modified during runtime if DRI_PRIME is detected */
1598 static __DRIimageExtension dri2ImageExtension = {
1599 .base = { __DRI_IMAGE, 17 },
1600
1601 .createImageFromName = dri2_create_image_from_name,
1602 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1603 .destroyImage = dri2_destroy_image,
1604 .createImage = dri2_create_image,
1605 .queryImage = dri2_query_image,
1606 .dupImage = dri2_dup_image,
1607 .validateUsage = dri2_validate_usage,
1608 .createImageFromNames = dri2_from_names,
1609 .fromPlanar = dri2_from_planar,
1610 .createImageFromTexture = dri2_create_from_texture,
1611 .createImageFromFds = NULL,
1612 .createImageFromDmaBufs = NULL,
1613 .blitImage = dri2_blit_image,
1614 .getCapabilities = dri2_get_capabilities,
1615 .mapImage = dri2_map_image,
1616 .unmapImage = dri2_unmap_image,
1617 .createImageWithModifiers = NULL,
1618 .createImageFromDmaBufs2 = NULL,
1619 .queryDmaBufFormats = NULL,
1620 .queryDmaBufModifiers = NULL,
1621 .queryDmaBufFormatModifierAttribs = NULL,
1622 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
1623 };
1624
1625 static const __DRIrobustnessExtension dri2Robustness = {
1626 .base = { __DRI2_ROBUSTNESS, 1 }
1627 };
1628
1629 static int
1630 dri2_interop_query_device_info(__DRIcontext *_ctx,
1631 struct mesa_glinterop_device_info *out)
1632 {
1633 struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
1634
1635 /* There is no version 0, thus we do not support it */
1636 if (out->version == 0)
1637 return MESA_GLINTEROP_INVALID_VERSION;
1638
1639 out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
1640 out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
1641 out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
1642 out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
1643
1644 out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
1645 out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
1646
1647 /* Instruct the caller that we support up-to version one of the interface */
1648 out->version = 1;
1649
1650 return MESA_GLINTEROP_SUCCESS;
1651 }
1652
1653 static int
1654 dri2_interop_export_object(__DRIcontext *_ctx,
1655 struct mesa_glinterop_export_in *in,
1656 struct mesa_glinterop_export_out *out)
1657 {
1658 struct st_context_iface *st = dri_context(_ctx)->st;
1659 struct pipe_screen *screen = st->pipe->screen;
1660 struct gl_context *ctx = ((struct st_context *)st)->ctx;
1661 struct pipe_resource *res = NULL;
1662 struct winsys_handle whandle;
1663 unsigned target, usage;
1664 boolean success;
1665
1666 /* There is no version 0, thus we do not support it */
1667 if (in->version == 0 || out->version == 0)
1668 return MESA_GLINTEROP_INVALID_VERSION;
1669
1670 /* Validate the target. */
1671 switch (in->target) {
1672 case GL_TEXTURE_BUFFER:
1673 case GL_TEXTURE_1D:
1674 case GL_TEXTURE_2D:
1675 case GL_TEXTURE_3D:
1676 case GL_TEXTURE_RECTANGLE:
1677 case GL_TEXTURE_1D_ARRAY:
1678 case GL_TEXTURE_2D_ARRAY:
1679 case GL_TEXTURE_CUBE_MAP_ARRAY:
1680 case GL_TEXTURE_CUBE_MAP:
1681 case GL_TEXTURE_2D_MULTISAMPLE:
1682 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1683 case GL_TEXTURE_EXTERNAL_OES:
1684 case GL_RENDERBUFFER:
1685 case GL_ARRAY_BUFFER:
1686 target = in->target;
1687 break;
1688 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1690 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1691 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1692 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1693 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1694 target = GL_TEXTURE_CUBE_MAP;
1695 break;
1696 default:
1697 return MESA_GLINTEROP_INVALID_TARGET;
1698 }
1699
1700 /* Validate the simple case of miplevel. */
1701 if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
1702 in->miplevel != 0)
1703 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1704
1705 /* Validate the OpenGL object and get pipe_resource. */
1706 simple_mtx_lock(&ctx->Shared->Mutex);
1707
1708 if (target == GL_ARRAY_BUFFER) {
1709 /* Buffer objects.
1710 *
1711 * The error checking is based on the documentation of
1712 * clCreateFromGLBuffer from OpenCL 2.0 SDK.
1713 */
1714 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
1715
1716 /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
1717 * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
1718 * a GL buffer object but does not have an existing data store or
1719 * the size of the buffer is 0."
1720 */
1721 if (!buf || buf->Size == 0) {
1722 simple_mtx_unlock(&ctx->Shared->Mutex);
1723 return MESA_GLINTEROP_INVALID_OBJECT;
1724 }
1725
1726 res = st_buffer_object(buf)->buffer;
1727 if (!res) {
1728 /* this shouldn't happen */
1729 simple_mtx_unlock(&ctx->Shared->Mutex);
1730 return MESA_GLINTEROP_INVALID_OBJECT;
1731 }
1732
1733 out->buf_offset = 0;
1734 out->buf_size = buf->Size;
1735
1736 buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1737 } else if (target == GL_RENDERBUFFER) {
1738 /* Renderbuffers.
1739 *
1740 * The error checking is based on the documentation of
1741 * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
1742 */
1743 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
1744
1745 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1746 * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
1747 * object or if the width or height of renderbuffer is zero."
1748 */
1749 if (!rb || rb->Width == 0 || rb->Height == 0) {
1750 simple_mtx_unlock(&ctx->Shared->Mutex);
1751 return MESA_GLINTEROP_INVALID_OBJECT;
1752 }
1753
1754 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1755 * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
1756 * renderbuffer object."
1757 */
1758 if (rb->NumSamples > 1) {
1759 simple_mtx_unlock(&ctx->Shared->Mutex);
1760 return MESA_GLINTEROP_INVALID_OPERATION;
1761 }
1762
1763 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1764 * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
1765 * required by the OpenCL implementation on the device."
1766 */
1767 res = st_renderbuffer(rb)->texture;
1768 if (!res) {
1769 simple_mtx_unlock(&ctx->Shared->Mutex);
1770 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1771 }
1772
1773 out->internal_format = rb->InternalFormat;
1774 out->view_minlevel = 0;
1775 out->view_numlevels = 1;
1776 out->view_minlayer = 0;
1777 out->view_numlayers = 1;
1778 } else {
1779 /* Texture objects.
1780 *
1781 * The error checking is based on the documentation of
1782 * clCreateFromGLTexture from OpenCL 2.0 SDK.
1783 */
1784 struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
1785
1786 if (obj)
1787 _mesa_test_texobj_completeness(ctx, obj);
1788
1789 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1790 * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
1791 * type matches texture_target, if the specified miplevel of texture
1792 * is not defined, or if the width or height of the specified
1793 * miplevel is zero or if the GL texture object is incomplete."
1794 */
1795 if (!obj ||
1796 obj->Target != target ||
1797 !obj->_BaseComplete ||
1798 (in->miplevel > 0 && !obj->_MipmapComplete)) {
1799 simple_mtx_unlock(&ctx->Shared->Mutex);
1800 return MESA_GLINTEROP_INVALID_OBJECT;
1801 }
1802
1803 if (target == GL_TEXTURE_BUFFER) {
1804 struct st_buffer_object *stBuf =
1805 st_buffer_object(obj->BufferObject);
1806
1807 if (!stBuf || !stBuf->buffer) {
1808 /* this shouldn't happen */
1809 simple_mtx_unlock(&ctx->Shared->Mutex);
1810 return MESA_GLINTEROP_INVALID_OBJECT;
1811 }
1812 res = stBuf->buffer;
1813
1814 out->internal_format = obj->BufferObjectFormat;
1815 out->buf_offset = obj->BufferOffset;
1816 out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
1817 obj->BufferSize;
1818
1819 obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1820 } else {
1821 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1822 * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
1823 * levelbase (for OpenGL implementations) or zero (for OpenGL ES
1824 * implementations); or greater than the value of q (for both OpenGL
1825 * and OpenGL ES). levelbase and q are defined for the texture in
1826 * section 3.8.10 (Texture Completeness) of the OpenGL 2.1
1827 * specification and section 3.7.10 of the OpenGL ES 2.0."
1828 */
1829 if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
1830 simple_mtx_unlock(&ctx->Shared->Mutex);
1831 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1832 }
1833
1834 if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
1835 simple_mtx_unlock(&ctx->Shared->Mutex);
1836 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1837 }
1838
1839 res = st_get_texobj_resource(obj);
1840 if (!res) {
1841 /* Incomplete texture buffer object? This shouldn't really occur. */
1842 simple_mtx_unlock(&ctx->Shared->Mutex);
1843 return MESA_GLINTEROP_INVALID_OBJECT;
1844 }
1845
1846 out->internal_format = obj->Image[0][0]->InternalFormat;
1847 out->view_minlevel = obj->MinLevel;
1848 out->view_numlevels = obj->NumLevels;
1849 out->view_minlayer = obj->MinLayer;
1850 out->view_numlayers = obj->NumLayers;
1851 }
1852 }
1853
1854 /* Get the handle. */
1855 switch (in->access) {
1856 case MESA_GLINTEROP_ACCESS_READ_ONLY:
1857 usage = 0;
1858 break;
1859 case MESA_GLINTEROP_ACCESS_READ_WRITE:
1860 case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
1861 usage = PIPE_HANDLE_USAGE_SHADER_WRITE;
1862 break;
1863 default:
1864 usage = 0;
1865 }
1866
1867 memset(&whandle, 0, sizeof(whandle));
1868 whandle.type = WINSYS_HANDLE_TYPE_FD;
1869
1870 success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
1871 usage);
1872 simple_mtx_unlock(&ctx->Shared->Mutex);
1873
1874 if (!success)
1875 return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
1876
1877 out->dmabuf_fd = whandle.handle;
1878 out->out_driver_data_written = 0;
1879
1880 if (res->target == PIPE_BUFFER)
1881 out->buf_offset += whandle.offset;
1882
1883 /* Instruct the caller that we support up-to version one of the interface */
1884 in->version = 1;
1885 out->version = 1;
1886
1887 return MESA_GLINTEROP_SUCCESS;
1888 }
1889
1890 static const __DRI2interopExtension dri2InteropExtension = {
1891 .base = { __DRI2_INTEROP, 1 },
1892 .query_device_info = dri2_interop_query_device_info,
1893 .export_object = dri2_interop_export_object
1894 };
1895
1896 /**
1897 * \brief the DRI2ConfigQueryExtension configQueryb method
1898 */
1899 static int
1900 dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
1901 unsigned char *val)
1902 {
1903 struct dri_screen *screen = dri_screen(sPriv);
1904
1905 if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))
1906 return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
1907
1908 *val = driQueryOptionb(&screen->dev->option_cache, var);
1909
1910 return 0;
1911 }
1912
1913 /**
1914 * \brief the DRI2ConfigQueryExtension configQueryi method
1915 */
1916 static int
1917 dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
1918 {
1919 struct dri_screen *screen = dri_screen(sPriv);
1920
1921 if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&
1922 !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))
1923 return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
1924
1925 *val = driQueryOptioni(&screen->dev->option_cache, var);
1926
1927 return 0;
1928 }
1929
1930 /**
1931 * \brief the DRI2ConfigQueryExtension configQueryf method
1932 */
1933 static int
1934 dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
1935 {
1936 struct dri_screen *screen = dri_screen(sPriv);
1937
1938 if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))
1939 return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
1940
1941 *val = driQueryOptionf(&screen->dev->option_cache, var);
1942
1943 return 0;
1944 }
1945
1946 /**
1947 * \brief the DRI2ConfigQueryExtension struct.
1948 *
1949 * We first query the driver option cache. Then the dri2 option cache.
1950 */
1951 static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
1952 .base = { __DRI2_CONFIG_QUERY, 1 },
1953
1954 .configQueryb = dri2GalliumConfigQueryb,
1955 .configQueryi = dri2GalliumConfigQueryi,
1956 .configQueryf = dri2GalliumConfigQueryf,
1957 };
1958
1959 /**
1960 * \brief the DRI2blobExtension set_cache_funcs method
1961 */
1962 static void
1963 set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set,
1964 __DRIblobCacheGet get)
1965 {
1966 struct dri_screen *screen = dri_screen(sPriv);
1967 struct pipe_screen *pscreen = screen->base.screen;
1968
1969 if (!pscreen->get_disk_shader_cache)
1970 return;
1971
1972 struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen);
1973
1974 if (!cache)
1975 return;
1976
1977 disk_cache_set_callbacks(cache, set, get);
1978 }
1979
1980 static const __DRI2blobExtension driBlobExtension = {
1981 .base = { __DRI2_BLOB, 1 },
1982 .set_cache_funcs = set_blob_cache_funcs
1983 };
1984
1985 /*
1986 * Backend function init_screen.
1987 */
1988
1989 static const __DRIextension *dri_screen_extensions[] = {
1990 &driTexBufferExtension.base,
1991 &dri2FlushExtension.base,
1992 &dri2ImageExtension.base,
1993 &dri2RendererQueryExtension.base,
1994 &dri2GalliumConfigQueryExtension.base,
1995 &dri2ThrottleExtension.base,
1996 &dri2FenceExtension.base,
1997 &dri2InteropExtension.base,
1998 &dri2NoErrorExtension.base,
1999 &driBlobExtension.base,
2000 NULL
2001 };
2002
2003 static const __DRIextension *dri_robust_screen_extensions[] = {
2004 &driTexBufferExtension.base,
2005 &dri2FlushExtension.base,
2006 &dri2ImageExtension.base,
2007 &dri2RendererQueryExtension.base,
2008 &dri2GalliumConfigQueryExtension.base,
2009 &dri2ThrottleExtension.base,
2010 &dri2FenceExtension.base,
2011 &dri2InteropExtension.base,
2012 &dri2Robustness.base,
2013 &dri2NoErrorExtension.base,
2014 &driBlobExtension.base,
2015 NULL
2016 };
2017
2018 /**
2019 * This is the driver specific part of the createNewScreen entry point.
2020 *
2021 * Returns the struct gl_config supported by this driver.
2022 */
2023 static const __DRIconfig **
2024 dri2_init_screen(__DRIscreen * sPriv)
2025 {
2026 const __DRIconfig **configs;
2027 struct dri_screen *screen;
2028 struct pipe_screen *pscreen = NULL;
2029
2030 screen = CALLOC_STRUCT(dri_screen);
2031 if (!screen)
2032 return NULL;
2033
2034 screen->sPriv = sPriv;
2035 screen->fd = sPriv->fd;
2036 (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
2037
2038 sPriv->driverPrivate = (void *)screen;
2039
2040 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) {
2041 dri_init_options(screen);
2042
2043 pscreen = pipe_loader_create_screen(screen->dev);
2044 }
2045
2046 if (!pscreen)
2047 goto release_pipe;
2048
2049 screen->default_throttle_frames =
2050 pscreen->get_param(pscreen, PIPE_CAP_MAX_FRAMES_IN_FLIGHT);
2051
2052 if (pscreen->resource_create_with_modifiers)
2053 dri2ImageExtension.createImageWithModifiers =
2054 dri2_create_image_with_modifiers;
2055
2056 if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) {
2057 uint64_t cap;
2058
2059 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2060 (cap & DRM_PRIME_CAP_IMPORT)) {
2061 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2062 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2063 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2064 if (pscreen->query_dmabuf_modifiers) {
2065 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2066 dri2ImageExtension.queryDmaBufModifiers =
2067 dri2_query_dma_buf_modifiers;
2068 }
2069 }
2070 }
2071
2072 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
2073 sPriv->extensions = dri_robust_screen_extensions;
2074 screen->has_reset_status_query = true;
2075 }
2076 else
2077 sPriv->extensions = dri_screen_extensions;
2078
2079 configs = dri_init_screen_helper(screen, pscreen);
2080 if (!configs)
2081 goto destroy_screen;
2082
2083 screen->can_share_buffer = true;
2084 screen->auto_fake_front = dri_with_format(sPriv);
2085 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2086 screen->lookup_egl_image = dri2_lookup_egl_image;
2087
2088 return configs;
2089
2090 destroy_screen:
2091 dri_destroy_screen_helper(screen);
2092
2093 release_pipe:
2094 if (screen->dev)
2095 pipe_loader_release(&screen->dev, 1);
2096
2097 FREE(screen);
2098 return NULL;
2099 }
2100
2101 /**
2102 * This is the driver specific part of the createNewScreen entry point.
2103 *
2104 * Returns the struct gl_config supported by this driver.
2105 */
2106 static const __DRIconfig **
2107 dri_kms_init_screen(__DRIscreen * sPriv)
2108 {
2109 #if defined(GALLIUM_SOFTPIPE)
2110 const __DRIconfig **configs;
2111 struct dri_screen *screen;
2112 struct pipe_screen *pscreen = NULL;
2113 uint64_t cap;
2114
2115 screen = CALLOC_STRUCT(dri_screen);
2116 if (!screen)
2117 return NULL;
2118
2119 screen->sPriv = sPriv;
2120 screen->fd = sPriv->fd;
2121
2122 sPriv->driverPrivate = (void *)screen;
2123
2124 if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) {
2125 dri_init_options(screen);
2126 pscreen = pipe_loader_create_screen(screen->dev);
2127 }
2128
2129 if (!pscreen)
2130 goto release_pipe;
2131
2132 if (pscreen->resource_create_with_modifiers)
2133 dri2ImageExtension.createImageWithModifiers =
2134 dri2_create_image_with_modifiers;
2135
2136 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2137 (cap & DRM_PRIME_CAP_IMPORT)) {
2138 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2139 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2140 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2141 if (pscreen->query_dmabuf_modifiers) {
2142 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2143 dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
2144 }
2145 }
2146
2147 sPriv->extensions = dri_screen_extensions;
2148
2149 configs = dri_init_screen_helper(screen, pscreen);
2150 if (!configs)
2151 goto destroy_screen;
2152
2153 screen->can_share_buffer = false;
2154 screen->auto_fake_front = dri_with_format(sPriv);
2155 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2156 screen->lookup_egl_image = dri2_lookup_egl_image;
2157
2158 return configs;
2159
2160 destroy_screen:
2161 dri_destroy_screen_helper(screen);
2162
2163 release_pipe:
2164 if (screen->dev)
2165 pipe_loader_release(&screen->dev, 1);
2166
2167 FREE(screen);
2168 #endif // GALLIUM_SOFTPIPE
2169 return NULL;
2170 }
2171
2172 static boolean
2173 dri2_create_buffer(__DRIscreen * sPriv,
2174 __DRIdrawable * dPriv,
2175 const struct gl_config * visual, boolean isPixmap)
2176 {
2177 struct dri_drawable *drawable = NULL;
2178
2179 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
2180 return FALSE;
2181
2182 drawable = dPriv->driverPrivate;
2183
2184 drawable->allocate_textures = dri2_allocate_textures;
2185 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2186 drawable->update_tex_buffer = dri2_update_tex_buffer;
2187 drawable->flush_swapbuffers = dri2_flush_swapbuffers;
2188
2189 return TRUE;
2190 }
2191
2192 /**
2193 * DRI driver virtual function table.
2194 *
2195 * DRI versions differ in their implementation of init_screen and swap_buffers.
2196 */
2197 const struct __DriverAPIRec galliumdrm_driver_api = {
2198 .InitScreen = dri2_init_screen,
2199 .DestroyScreen = dri_destroy_screen,
2200 .CreateContext = dri_create_context,
2201 .DestroyContext = dri_destroy_context,
2202 .CreateBuffer = dri2_create_buffer,
2203 .DestroyBuffer = dri_destroy_buffer,
2204 .MakeCurrent = dri_make_current,
2205 .UnbindContext = dri_unbind_context,
2206
2207 .AllocateBuffer = dri2_allocate_buffer,
2208 .ReleaseBuffer = dri2_release_buffer,
2209 };
2210
2211 /**
2212 * DRI driver virtual function table.
2213 *
2214 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
2215 * hook. The latter is used to explicitly initialise the kms_swrast driver
2216 * rather than selecting the approapriate driver as suggested by the loader.
2217 */
2218 const struct __DriverAPIRec dri_kms_driver_api = {
2219 .InitScreen = dri_kms_init_screen,
2220 .DestroyScreen = dri_destroy_screen,
2221 .CreateContext = dri_create_context,
2222 .DestroyContext = dri_destroy_context,
2223 .CreateBuffer = dri2_create_buffer,
2224 .DestroyBuffer = dri_destroy_buffer,
2225 .MakeCurrent = dri_make_current,
2226 .UnbindContext = dri_unbind_context,
2227
2228 .AllocateBuffer = dri2_allocate_buffer,
2229 .ReleaseBuffer = dri2_release_buffer,
2230 };
2231
2232 /* This is the table of extensions that the loader will dlsym() for. */
2233 const __DRIextension *galliumdrm_driver_extensions[] = {
2234 &driCoreExtension.base,
2235 &driImageDriverExtension.base,
2236 &driDRI2Extension.base,
2237 &gallium_config_options.base,
2238 NULL
2239 };
2240
2241 /* vim: set sw=3 ts=8 sts=3 expandtab: */