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