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