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