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