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