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