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