gallium: allow passing 'unsigned flags' to create_screen()
[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_HANDLE:
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.handle;
1187 return GL_TRUE;
1188 case __DRI_IMAGE_ATTRIB_NAME:
1189 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
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_FD:
1195 whandle.type= DRM_API_HANDLE_TYPE_FD;
1196 if (!image->texture->screen->resource_get_handle(image->texture->screen,
1197 NULL, image->texture, &whandle, usage))
1198 return GL_FALSE;
1199
1200 *value = whandle.handle;
1201 return GL_TRUE;
1202 case __DRI_IMAGE_ATTRIB_FORMAT:
1203 *value = image->dri_format;
1204 return GL_TRUE;
1205 case __DRI_IMAGE_ATTRIB_WIDTH:
1206 *value = image->texture->width0;
1207 return GL_TRUE;
1208 case __DRI_IMAGE_ATTRIB_HEIGHT:
1209 *value = image->texture->height0;
1210 return GL_TRUE;
1211 case __DRI_IMAGE_ATTRIB_COMPONENTS:
1212 if (image->dri_components == 0)
1213 return GL_FALSE;
1214 *value = image->dri_components;
1215 return GL_TRUE;
1216 case __DRI_IMAGE_ATTRIB_FOURCC:
1217 *value = convert_to_fourcc(image->dri_format);
1218 return GL_TRUE;
1219 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1220 *value = 1;
1221 return GL_TRUE;
1222 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1223 whandle.type = DRM_API_HANDLE_TYPE_KMS;
1224 image->texture->screen->resource_get_handle(image->texture->screen,
1225 NULL, image->texture, &whandle, usage);
1226 *value = (whandle.modifier >> 32) & 0xffffffff;
1227 return GL_TRUE;
1228 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
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 & 0xffffffff;
1233 return GL_TRUE;
1234 default:
1235 return GL_FALSE;
1236 }
1237 }
1238
1239 static __DRIimage *
1240 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
1241 {
1242 __DRIimage *img;
1243
1244 img = CALLOC_STRUCT(__DRIimageRec);
1245 if (!img)
1246 return NULL;
1247
1248 img->texture = NULL;
1249 pipe_resource_reference(&img->texture, image->texture);
1250 img->level = image->level;
1251 img->layer = image->layer;
1252 img->dri_format = image->dri_format;
1253 /* This should be 0 for sub images, but dup is also used for base images. */
1254 img->dri_components = image->dri_components;
1255 img->loader_private = loaderPrivate;
1256
1257 return img;
1258 }
1259
1260 static GLboolean
1261 dri2_validate_usage(__DRIimage *image, unsigned int use)
1262 {
1263 /*
1264 * Gallium drivers are bad at adding usages to the resources
1265 * once opened again in another process, which is the main use
1266 * case for this, so we have to lie.
1267 */
1268 if (image != NULL)
1269 return GL_TRUE;
1270 else
1271 return GL_FALSE;
1272 }
1273
1274 static __DRIimage *
1275 dri2_from_names(__DRIscreen *screen, int width, int height, int format,
1276 int *names, int num_names, int *strides, int *offsets,
1277 void *loaderPrivate)
1278 {
1279 __DRIimage *img;
1280 int dri_components;
1281 struct winsys_handle whandle;
1282
1283 if (num_names != 1)
1284 return NULL;
1285
1286 format = convert_fourcc(format, &dri_components);
1287 if (format == -1)
1288 return NULL;
1289
1290 memset(&whandle, 0, sizeof(whandle));
1291 whandle.type = DRM_API_HANDLE_TYPE_SHARED;
1292 whandle.handle = names[0];
1293 whandle.stride = strides[0];
1294 whandle.offset = offsets[0];
1295 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1296
1297 img = dri2_create_image_from_winsys(screen, width, height, format,
1298 1, &whandle, loaderPrivate);
1299 if (img == NULL)
1300 return NULL;
1301
1302 img->dri_components = dri_components;
1303 return img;
1304 }
1305
1306 static __DRIimage *
1307 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1308 {
1309 __DRIimage *img;
1310
1311 if (plane != 0)
1312 return NULL;
1313
1314 if (image->dri_components == 0)
1315 return NULL;
1316
1317 img = dri2_dup_image(image, loaderPrivate);
1318 if (img == NULL)
1319 return NULL;
1320
1321 if (img->texture->screen->resource_changed)
1322 img->texture->screen->resource_changed(img->texture->screen,
1323 img->texture);
1324
1325 /* set this to 0 for sub images. */
1326 img->dri_components = 0;
1327 return img;
1328 }
1329
1330 static __DRIimage *
1331 dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture,
1332 int depth, int level, unsigned *error,
1333 void *loaderPrivate)
1334 {
1335 __DRIimage *img;
1336 struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx;
1337 struct gl_texture_object *obj;
1338 struct pipe_resource *tex;
1339 GLuint face = 0;
1340
1341 obj = _mesa_lookup_texture(ctx, texture);
1342 if (!obj || obj->Target != target) {
1343 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1344 return NULL;
1345 }
1346
1347 tex = st_get_texobj_resource(obj);
1348 if (!tex) {
1349 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1350 return NULL;
1351 }
1352
1353 if (target == GL_TEXTURE_CUBE_MAP)
1354 face = depth;
1355
1356 _mesa_test_texobj_completeness(ctx, obj);
1357 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) {
1358 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1359 return NULL;
1360 }
1361
1362 if (level < obj->BaseLevel || level > obj->_MaxLevel) {
1363 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1364 return NULL;
1365 }
1366
1367 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) {
1368 *error = __DRI_IMAGE_ERROR_BAD_MATCH;
1369 return NULL;
1370 }
1371
1372 img = CALLOC_STRUCT(__DRIimageRec);
1373 if (!img) {
1374 *error = __DRI_IMAGE_ERROR_BAD_ALLOC;
1375 return NULL;
1376 }
1377
1378 img->level = level;
1379 img->layer = depth;
1380 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat);
1381
1382 img->loader_private = loaderPrivate;
1383
1384 if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) {
1385 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1386 free(img);
1387 return NULL;
1388 }
1389
1390 pipe_resource_reference(&img->texture, tex);
1391
1392 *error = __DRI_IMAGE_ERROR_SUCCESS;
1393 return img;
1394 }
1395
1396 static __DRIimage *
1397 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1398 int *fds, int num_fds, int *strides, int *offsets,
1399 void *loaderPrivate)
1400 {
1401 __DRIimage *img;
1402 int dri_components;
1403
1404 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1405 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1406 strides, offsets, NULL,
1407 &dri_components, loaderPrivate);
1408 if (img == NULL)
1409 return NULL;
1410
1411 img->dri_components = dri_components;
1412 return img;
1413 }
1414
1415 static boolean
1416 dri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
1417 int *count)
1418 {
1419 struct dri_screen *screen = dri_screen(_screen);
1420 struct pipe_screen *pscreen = screen->base.screen;
1421 const unsigned bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1422 int i, j;
1423
1424 for (i = 0, j = 0; (i < ARRAY_SIZE(fourcc_formats)) &&
1425 (j < max || max == 0); i++) {
1426 if (pscreen->is_format_supported(pscreen,
1427 fourcc_to_pipe_format(
1428 fourcc_formats[i]),
1429 screen->target,
1430 0, bind)) {
1431 if (j < max)
1432 formats[j] = fourcc_formats[i];
1433 j++;
1434 }
1435 }
1436 *count = j;
1437 return true;
1438 }
1439
1440 static boolean
1441 dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1442 uint64_t *modifiers, unsigned int *external_only,
1443 int *count)
1444 {
1445 struct dri_screen *screen = dri_screen(_screen);
1446 struct pipe_screen *pscreen = screen->base.screen;
1447 enum pipe_format format = fourcc_to_pipe_format(fourcc);
1448 const unsigned usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
1449
1450 if (pscreen->query_dmabuf_modifiers != NULL &&
1451 pscreen->is_format_supported(pscreen, format, screen->target, 0, usage)) {
1452 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1453 external_only, count);
1454 return true;
1455 }
1456 return false;
1457 }
1458
1459 static __DRIimage *
1460 dri2_from_dma_bufs(__DRIscreen *screen,
1461 int width, int height, int fourcc,
1462 int *fds, int num_fds,
1463 int *strides, int *offsets,
1464 enum __DRIYUVColorSpace yuv_color_space,
1465 enum __DRISampleRange sample_range,
1466 enum __DRIChromaSiting horizontal_siting,
1467 enum __DRIChromaSiting vertical_siting,
1468 unsigned *error,
1469 void *loaderPrivate)
1470 {
1471 __DRIimage *img;
1472 int dri_components;
1473
1474 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1475 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1476 strides, offsets, error,
1477 &dri_components, loaderPrivate);
1478 if (img == NULL)
1479 return NULL;
1480
1481 img->yuv_color_space = yuv_color_space;
1482 img->sample_range = sample_range;
1483 img->horizontal_siting = horizontal_siting;
1484 img->vertical_siting = vertical_siting;
1485 img->dri_components = dri_components;
1486
1487 *error = __DRI_IMAGE_ERROR_SUCCESS;
1488 return img;
1489 }
1490
1491 static __DRIimage *
1492 dri2_from_dma_bufs2(__DRIscreen *screen,
1493 int width, int height, int fourcc,
1494 uint64_t modifier, int *fds, int num_fds,
1495 int *strides, int *offsets,
1496 enum __DRIYUVColorSpace yuv_color_space,
1497 enum __DRISampleRange sample_range,
1498 enum __DRIChromaSiting horizontal_siting,
1499 enum __DRIChromaSiting vertical_siting,
1500 unsigned *error,
1501 void *loaderPrivate)
1502 {
1503 __DRIimage *img;
1504 int dri_components;
1505
1506 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1507 modifier, fds, num_fds, strides, offsets,
1508 error, &dri_components, loaderPrivate);
1509 if (img == NULL)
1510 return NULL;
1511
1512 img->yuv_color_space = yuv_color_space;
1513 img->sample_range = sample_range;
1514 img->horizontal_siting = horizontal_siting;
1515 img->vertical_siting = vertical_siting;
1516 img->dri_components = dri_components;
1517
1518 *error = __DRI_IMAGE_ERROR_SUCCESS;
1519 return img;
1520 }
1521
1522 static void
1523 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1524 int dstx0, int dsty0, int dstwidth, int dstheight,
1525 int srcx0, int srcy0, int srcwidth, int srcheight,
1526 int flush_flag)
1527 {
1528 struct dri_context *ctx = dri_context(context);
1529 struct pipe_context *pipe = ctx->st->pipe;
1530 struct pipe_screen *screen;
1531 struct pipe_fence_handle *fence;
1532 struct pipe_blit_info blit;
1533
1534 if (!dst || !src)
1535 return;
1536
1537 memset(&blit, 0, sizeof(blit));
1538 blit.dst.resource = dst->texture;
1539 blit.dst.box.x = dstx0;
1540 blit.dst.box.y = dsty0;
1541 blit.dst.box.width = dstwidth;
1542 blit.dst.box.height = dstheight;
1543 blit.dst.box.depth = 1;
1544 blit.dst.format = dst->texture->format;
1545 blit.src.resource = src->texture;
1546 blit.src.box.x = srcx0;
1547 blit.src.box.y = srcy0;
1548 blit.src.box.width = srcwidth;
1549 blit.src.box.height = srcheight;
1550 blit.src.box.depth = 1;
1551 blit.src.format = src->texture->format;
1552 blit.mask = PIPE_MASK_RGBA;
1553 blit.filter = PIPE_TEX_FILTER_NEAREST;
1554
1555 pipe->blit(pipe, &blit);
1556
1557 if (flush_flag == __BLIT_FLAG_FLUSH) {
1558 pipe->flush_resource(pipe, dst->texture);
1559 ctx->st->flush(ctx->st, 0, NULL);
1560 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1561 screen = dri_screen(ctx->sPriv)->base.screen;
1562 pipe->flush_resource(pipe, dst->texture);
1563 ctx->st->flush(ctx->st, 0, &fence);
1564 (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
1565 screen->fence_reference(screen, &fence, NULL);
1566 }
1567 }
1568
1569 static void *
1570 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1571 int x0, int y0, int width, int height,
1572 unsigned int flags, int *stride, void **data)
1573 {
1574 struct dri_context *ctx = dri_context(context);
1575 struct pipe_context *pipe = ctx->st->pipe;
1576 enum pipe_transfer_usage pipe_access = 0;
1577 struct pipe_transfer *trans;
1578 void *map;
1579
1580 if (!image || !data || *data)
1581 return NULL;
1582
1583 if (flags & __DRI_IMAGE_TRANSFER_READ)
1584 pipe_access |= PIPE_TRANSFER_READ;
1585 if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1586 pipe_access |= PIPE_TRANSFER_WRITE;
1587
1588 map = pipe_transfer_map(pipe, image->texture,
1589 0, 0, pipe_access, x0, y0, width, height,
1590 &trans);
1591 if (map) {
1592 *data = trans;
1593 *stride = trans->stride;
1594 }
1595
1596 return map;
1597 }
1598
1599 static void
1600 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1601 {
1602 struct dri_context *ctx = dri_context(context);
1603 struct pipe_context *pipe = ctx->st->pipe;
1604
1605 pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
1606 }
1607
1608 static void
1609 dri2_destroy_image(__DRIimage *img)
1610 {
1611 pipe_resource_reference(&img->texture, NULL);
1612 FREE(img);
1613 }
1614
1615 static int
1616 dri2_get_capabilities(__DRIscreen *_screen)
1617 {
1618 struct dri_screen *screen = dri_screen(_screen);
1619
1620 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1621 }
1622
1623 /* The extension is modified during runtime if DRI_PRIME is detected */
1624 static __DRIimageExtension dri2ImageExtension = {
1625 .base = { __DRI_IMAGE, 15 },
1626
1627 .createImageFromName = dri2_create_image_from_name,
1628 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1629 .destroyImage = dri2_destroy_image,
1630 .createImage = dri2_create_image,
1631 .queryImage = dri2_query_image,
1632 .dupImage = dri2_dup_image,
1633 .validateUsage = dri2_validate_usage,
1634 .createImageFromNames = dri2_from_names,
1635 .fromPlanar = dri2_from_planar,
1636 .createImageFromTexture = dri2_create_from_texture,
1637 .createImageFromFds = NULL,
1638 .createImageFromDmaBufs = NULL,
1639 .blitImage = dri2_blit_image,
1640 .getCapabilities = dri2_get_capabilities,
1641 .mapImage = dri2_map_image,
1642 .unmapImage = dri2_unmap_image,
1643 };
1644
1645 static const __DRIrobustnessExtension dri2Robustness = {
1646 .base = { __DRI2_ROBUSTNESS, 1 }
1647 };
1648
1649 static int
1650 dri2_interop_query_device_info(__DRIcontext *_ctx,
1651 struct mesa_glinterop_device_info *out)
1652 {
1653 struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
1654
1655 /* There is no version 0, thus we do not support it */
1656 if (out->version == 0)
1657 return MESA_GLINTEROP_INVALID_VERSION;
1658
1659 out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
1660 out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
1661 out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
1662 out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
1663
1664 out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
1665 out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
1666
1667 /* Instruct the caller that we support up-to version one of the interface */
1668 out->version = 1;
1669
1670 return MESA_GLINTEROP_SUCCESS;
1671 }
1672
1673 static int
1674 dri2_interop_export_object(__DRIcontext *_ctx,
1675 struct mesa_glinterop_export_in *in,
1676 struct mesa_glinterop_export_out *out)
1677 {
1678 struct st_context_iface *st = dri_context(_ctx)->st;
1679 struct pipe_screen *screen = st->pipe->screen;
1680 struct gl_context *ctx = ((struct st_context *)st)->ctx;
1681 struct pipe_resource *res = NULL;
1682 struct winsys_handle whandle;
1683 unsigned target, usage;
1684 boolean success;
1685
1686 /* There is no version 0, thus we do not support it */
1687 if (in->version == 0 || out->version == 0)
1688 return MESA_GLINTEROP_INVALID_VERSION;
1689
1690 /* Validate the target. */
1691 switch (in->target) {
1692 case GL_TEXTURE_BUFFER:
1693 case GL_TEXTURE_1D:
1694 case GL_TEXTURE_2D:
1695 case GL_TEXTURE_3D:
1696 case GL_TEXTURE_RECTANGLE:
1697 case GL_TEXTURE_1D_ARRAY:
1698 case GL_TEXTURE_2D_ARRAY:
1699 case GL_TEXTURE_CUBE_MAP_ARRAY:
1700 case GL_TEXTURE_CUBE_MAP:
1701 case GL_TEXTURE_2D_MULTISAMPLE:
1702 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1703 case GL_TEXTURE_EXTERNAL_OES:
1704 case GL_RENDERBUFFER:
1705 case GL_ARRAY_BUFFER:
1706 target = in->target;
1707 break;
1708 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1709 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1710 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1711 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1712 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1713 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1714 target = GL_TEXTURE_CUBE_MAP;
1715 break;
1716 default:
1717 return MESA_GLINTEROP_INVALID_TARGET;
1718 }
1719
1720 /* Validate the simple case of miplevel. */
1721 if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
1722 in->miplevel != 0)
1723 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1724
1725 /* Validate the OpenGL object and get pipe_resource. */
1726 mtx_lock(&ctx->Shared->Mutex);
1727
1728 if (target == GL_ARRAY_BUFFER) {
1729 /* Buffer objects.
1730 *
1731 * The error checking is based on the documentation of
1732 * clCreateFromGLBuffer from OpenCL 2.0 SDK.
1733 */
1734 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
1735
1736 /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
1737 * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
1738 * a GL buffer object but does not have an existing data store or
1739 * the size of the buffer is 0."
1740 */
1741 if (!buf || buf->Size == 0) {
1742 mtx_unlock(&ctx->Shared->Mutex);
1743 return MESA_GLINTEROP_INVALID_OBJECT;
1744 }
1745
1746 res = st_buffer_object(buf)->buffer;
1747 if (!res) {
1748 /* this shouldn't happen */
1749 mtx_unlock(&ctx->Shared->Mutex);
1750 return MESA_GLINTEROP_INVALID_OBJECT;
1751 }
1752
1753 out->buf_offset = 0;
1754 out->buf_size = buf->Size;
1755
1756 buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1757 } else if (target == GL_RENDERBUFFER) {
1758 /* Renderbuffers.
1759 *
1760 * The error checking is based on the documentation of
1761 * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
1762 */
1763 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
1764
1765 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1766 * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
1767 * object or if the width or height of renderbuffer is zero."
1768 */
1769 if (!rb || rb->Width == 0 || rb->Height == 0) {
1770 mtx_unlock(&ctx->Shared->Mutex);
1771 return MESA_GLINTEROP_INVALID_OBJECT;
1772 }
1773
1774 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1775 * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
1776 * renderbuffer object."
1777 */
1778 if (rb->NumSamples > 1) {
1779 mtx_unlock(&ctx->Shared->Mutex);
1780 return MESA_GLINTEROP_INVALID_OPERATION;
1781 }
1782
1783 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1784 * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
1785 * required by the OpenCL implementation on the device."
1786 */
1787 res = st_renderbuffer(rb)->texture;
1788 if (!res) {
1789 mtx_unlock(&ctx->Shared->Mutex);
1790 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1791 }
1792
1793 out->internal_format = rb->InternalFormat;
1794 out->view_minlevel = 0;
1795 out->view_numlevels = 1;
1796 out->view_minlayer = 0;
1797 out->view_numlayers = 1;
1798 } else {
1799 /* Texture objects.
1800 *
1801 * The error checking is based on the documentation of
1802 * clCreateFromGLTexture from OpenCL 2.0 SDK.
1803 */
1804 struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
1805
1806 if (obj)
1807 _mesa_test_texobj_completeness(ctx, obj);
1808
1809 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1810 * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
1811 * type matches texture_target, if the specified miplevel of texture
1812 * is not defined, or if the width or height of the specified
1813 * miplevel is zero or if the GL texture object is incomplete."
1814 */
1815 if (!obj ||
1816 obj->Target != target ||
1817 !obj->_BaseComplete ||
1818 (in->miplevel > 0 && !obj->_MipmapComplete)) {
1819 mtx_unlock(&ctx->Shared->Mutex);
1820 return MESA_GLINTEROP_INVALID_OBJECT;
1821 }
1822
1823 /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1824 * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
1825 * levelbase (for OpenGL implementations) or zero (for OpenGL ES
1826 * implementations); or greater than the value of q (for both OpenGL
1827 * and OpenGL ES). levelbase and q are defined for the texture in
1828 * section 3.8.10 (Texture Completeness) of the OpenGL 2.1
1829 * specification and section 3.7.10 of the OpenGL ES 2.0."
1830 */
1831 if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
1832 mtx_unlock(&ctx->Shared->Mutex);
1833 return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1834 }
1835
1836 if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
1837 mtx_unlock(&ctx->Shared->Mutex);
1838 return MESA_GLINTEROP_OUT_OF_RESOURCES;
1839 }
1840
1841 res = st_get_texobj_resource(obj);
1842 if (!res) {
1843 /* Incomplete texture buffer object? This shouldn't really occur. */
1844 mtx_unlock(&ctx->Shared->Mutex);
1845 return MESA_GLINTEROP_INVALID_OBJECT;
1846 }
1847
1848 if (target == GL_TEXTURE_BUFFER) {
1849 out->internal_format = obj->BufferObjectFormat;
1850 out->buf_offset = obj->BufferOffset;
1851 out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
1852 obj->BufferSize;
1853
1854 obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1855 } else {
1856 out->internal_format = obj->Image[0][0]->InternalFormat;
1857 out->view_minlevel = obj->MinLevel;
1858 out->view_numlevels = obj->NumLevels;
1859 out->view_minlayer = obj->MinLayer;
1860 out->view_numlayers = obj->NumLayers;
1861 }
1862 }
1863
1864 /* Get the handle. */
1865 switch (in->access) {
1866 case MESA_GLINTEROP_ACCESS_READ_WRITE:
1867 usage = PIPE_HANDLE_USAGE_READ_WRITE;
1868 break;
1869 case MESA_GLINTEROP_ACCESS_READ_ONLY:
1870 usage = PIPE_HANDLE_USAGE_READ;
1871 break;
1872 case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
1873 usage = PIPE_HANDLE_USAGE_WRITE;
1874 break;
1875 default:
1876 usage = 0;
1877 }
1878
1879 memset(&whandle, 0, sizeof(whandle));
1880 whandle.type = DRM_API_HANDLE_TYPE_FD;
1881
1882 success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
1883 usage);
1884 mtx_unlock(&ctx->Shared->Mutex);
1885
1886 if (!success)
1887 return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
1888
1889 out->dmabuf_fd = whandle.handle;
1890 out->out_driver_data_written = 0;
1891
1892 if (res->target == PIPE_BUFFER)
1893 out->buf_offset += whandle.offset;
1894
1895 /* Instruct the caller that we support up-to version one of the interface */
1896 in->version = 1;
1897 out->version = 1;
1898
1899 return MESA_GLINTEROP_SUCCESS;
1900 }
1901
1902 static const __DRI2interopExtension dri2InteropExtension = {
1903 .base = { __DRI2_INTEROP, 1 },
1904 .query_device_info = dri2_interop_query_device_info,
1905 .export_object = dri2_interop_export_object
1906 };
1907
1908 /**
1909 * \brief the DRI2ConfigQueryExtension configQueryb method
1910 */
1911 static int
1912 dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
1913 unsigned char *val)
1914 {
1915 struct dri_screen *screen = dri_screen(sPriv);
1916
1917 if (!driCheckOption(&screen->optionCache, var, DRI_BOOL))
1918 return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
1919
1920 *val = driQueryOptionb(&screen->optionCache, var);
1921
1922 return 0;
1923 }
1924
1925 /**
1926 * \brief the DRI2ConfigQueryExtension configQueryi method
1927 */
1928 static int
1929 dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
1930 {
1931 struct dri_screen *screen = dri_screen(sPriv);
1932
1933 if (!driCheckOption(&screen->optionCache, var, DRI_INT) &&
1934 !driCheckOption(&screen->optionCache, var, DRI_ENUM))
1935 return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
1936
1937 *val = driQueryOptioni(&screen->optionCache, var);
1938
1939 return 0;
1940 }
1941
1942 /**
1943 * \brief the DRI2ConfigQueryExtension configQueryf method
1944 */
1945 static int
1946 dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
1947 {
1948 struct dri_screen *screen = dri_screen(sPriv);
1949
1950 if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT))
1951 return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
1952
1953 *val = driQueryOptionf(&screen->optionCache, var);
1954
1955 return 0;
1956 }
1957
1958 /**
1959 * \brief the DRI2ConfigQueryExtension struct.
1960 *
1961 * We first query the driver option cache. Then the dri2 option cache.
1962 */
1963 static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
1964 .base = { __DRI2_CONFIG_QUERY, 1 },
1965
1966 .configQueryb = dri2GalliumConfigQueryb,
1967 .configQueryi = dri2GalliumConfigQueryi,
1968 .configQueryf = dri2GalliumConfigQueryf,
1969 };
1970
1971 /*
1972 * Backend function init_screen.
1973 */
1974
1975 static const __DRIextension *dri_screen_extensions[] = {
1976 &driTexBufferExtension.base,
1977 &dri2FlushExtension.base,
1978 &dri2ImageExtension.base,
1979 &dri2RendererQueryExtension.base,
1980 &dri2GalliumConfigQueryExtension.base,
1981 &dri2ThrottleExtension.base,
1982 &dri2FenceExtension.base,
1983 &dri2InteropExtension.base,
1984 NULL
1985 };
1986
1987 static const __DRIextension *dri_robust_screen_extensions[] = {
1988 &driTexBufferExtension.base,
1989 &dri2FlushExtension.base,
1990 &dri2ImageExtension.base,
1991 &dri2RendererQueryExtension.base,
1992 &dri2ConfigQueryExtension.base,
1993 &dri2ThrottleExtension.base,
1994 &dri2FenceExtension.base,
1995 &dri2InteropExtension.base,
1996 &dri2Robustness.base,
1997 NULL
1998 };
1999
2000 /**
2001 * This is the driver specific part of the createNewScreen entry point.
2002 *
2003 * Returns the struct gl_config supported by this driver.
2004 */
2005 static const __DRIconfig **
2006 dri2_init_screen(__DRIscreen * sPriv)
2007 {
2008 const __DRIconfig **configs;
2009 struct dri_screen *screen;
2010 struct pipe_screen *pscreen = NULL;
2011 const struct drm_conf_ret *throttle_ret;
2012 const struct drm_conf_ret *dmabuf_ret;
2013 int fd;
2014
2015 screen = CALLOC_STRUCT(dri_screen);
2016 if (!screen)
2017 return NULL;
2018
2019 screen->sPriv = sPriv;
2020 screen->fd = sPriv->fd;
2021 (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
2022
2023 sPriv->driverPrivate = (void *)screen;
2024
2025 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
2026 goto free_screen;
2027
2028 if (pipe_loader_drm_probe_fd(&screen->dev, fd))
2029 pscreen = pipe_loader_create_screen(screen->dev, 0);
2030
2031 if (!pscreen)
2032 goto release_pipe;
2033
2034 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
2035 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
2036
2037 if (throttle_ret && throttle_ret->val.val_int != -1) {
2038 screen->throttling_enabled = TRUE;
2039 screen->default_throttle_frames = throttle_ret->val.val_int;
2040 }
2041
2042 if (pscreen->resource_create_with_modifiers)
2043 dri2ImageExtension.createImageWithModifiers =
2044 dri2_create_image_with_modifiers;
2045
2046 if (dmabuf_ret && dmabuf_ret->val.val_bool) {
2047 uint64_t cap;
2048
2049 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2050 (cap & DRM_PRIME_CAP_IMPORT)) {
2051 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2052 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2053 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2054 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2055 dri2ImageExtension.queryDmaBufModifiers =
2056 dri2_query_dma_buf_modifiers;
2057 }
2058 }
2059
2060 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
2061 sPriv->extensions = dri_robust_screen_extensions;
2062 screen->has_reset_status_query = true;
2063 }
2064 else
2065 sPriv->extensions = dri_screen_extensions;
2066
2067 configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
2068 if (!configs)
2069 goto destroy_screen;
2070
2071 screen->can_share_buffer = true;
2072 screen->auto_fake_front = dri_with_format(sPriv);
2073 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2074 screen->lookup_egl_image = dri2_lookup_egl_image;
2075
2076 return configs;
2077
2078 destroy_screen:
2079 dri_destroy_screen_helper(screen);
2080
2081 release_pipe:
2082 if (screen->dev)
2083 pipe_loader_release(&screen->dev, 1);
2084 else
2085 close(fd);
2086
2087 free_screen:
2088 FREE(screen);
2089 return NULL;
2090 }
2091
2092 /**
2093 * This is the driver specific part of the createNewScreen entry point.
2094 *
2095 * Returns the struct gl_config supported by this driver.
2096 */
2097 static const __DRIconfig **
2098 dri_kms_init_screen(__DRIscreen * sPriv)
2099 {
2100 #if defined(GALLIUM_SOFTPIPE)
2101 const __DRIconfig **configs;
2102 struct dri_screen *screen;
2103 struct pipe_screen *pscreen = NULL;
2104 uint64_t cap;
2105 int fd;
2106
2107 screen = CALLOC_STRUCT(dri_screen);
2108 if (!screen)
2109 return NULL;
2110
2111 screen->sPriv = sPriv;
2112 screen->fd = sPriv->fd;
2113
2114 sPriv->driverPrivate = (void *)screen;
2115
2116 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
2117 goto free_screen;
2118
2119 if (pipe_loader_sw_probe_kms(&screen->dev, fd))
2120 pscreen = pipe_loader_create_screen(screen->dev, 0);
2121
2122 if (!pscreen)
2123 goto release_pipe;
2124
2125 if (pscreen->resource_create_with_modifiers)
2126 dri2ImageExtension.createImageWithModifiers =
2127 dri2_create_image_with_modifiers;
2128
2129 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2130 (cap & DRM_PRIME_CAP_IMPORT)) {
2131 dri2ImageExtension.createImageFromFds = dri2_from_fds;
2132 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2133 dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2134 dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2135 dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
2136 }
2137
2138 sPriv->extensions = dri_screen_extensions;
2139
2140 configs = dri_init_screen_helper(screen, pscreen, "swrast");
2141 if (!configs)
2142 goto destroy_screen;
2143
2144 screen->can_share_buffer = false;
2145 screen->auto_fake_front = dri_with_format(sPriv);
2146 screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2147 screen->lookup_egl_image = dri2_lookup_egl_image;
2148
2149 return configs;
2150
2151 destroy_screen:
2152 dri_destroy_screen_helper(screen);
2153
2154 release_pipe:
2155 if (screen->dev)
2156 pipe_loader_release(&screen->dev, 1);
2157 else
2158 close(fd);
2159
2160 free_screen:
2161 FREE(screen);
2162 #endif // GALLIUM_SOFTPIPE
2163 return NULL;
2164 }
2165
2166 static boolean
2167 dri2_create_buffer(__DRIscreen * sPriv,
2168 __DRIdrawable * dPriv,
2169 const struct gl_config * visual, boolean isPixmap)
2170 {
2171 struct dri_drawable *drawable = NULL;
2172
2173 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
2174 return FALSE;
2175
2176 drawable = dPriv->driverPrivate;
2177
2178 drawable->allocate_textures = dri2_allocate_textures;
2179 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2180 drawable->update_tex_buffer = dri2_update_tex_buffer;
2181
2182 return TRUE;
2183 }
2184
2185 /**
2186 * DRI driver virtual function table.
2187 *
2188 * DRI versions differ in their implementation of init_screen and swap_buffers.
2189 */
2190 const struct __DriverAPIRec galliumdrm_driver_api = {
2191 .InitScreen = dri2_init_screen,
2192 .DestroyScreen = dri_destroy_screen,
2193 .CreateContext = dri_create_context,
2194 .DestroyContext = dri_destroy_context,
2195 .CreateBuffer = dri2_create_buffer,
2196 .DestroyBuffer = dri_destroy_buffer,
2197 .MakeCurrent = dri_make_current,
2198 .UnbindContext = dri_unbind_context,
2199
2200 .AllocateBuffer = dri2_allocate_buffer,
2201 .ReleaseBuffer = dri2_release_buffer,
2202 };
2203
2204 /**
2205 * DRI driver virtual function table.
2206 *
2207 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
2208 * hook. The latter is used to explicitly initialise the kms_swrast driver
2209 * rather than selecting the approapriate driver as suggested by the loader.
2210 */
2211 const struct __DriverAPIRec dri_kms_driver_api = {
2212 .InitScreen = dri_kms_init_screen,
2213 .DestroyScreen = dri_destroy_screen,
2214 .CreateContext = dri_create_context,
2215 .DestroyContext = dri_destroy_context,
2216 .CreateBuffer = dri2_create_buffer,
2217 .DestroyBuffer = dri_destroy_buffer,
2218 .MakeCurrent = dri_make_current,
2219 .UnbindContext = dri_unbind_context,
2220
2221 .AllocateBuffer = dri2_allocate_buffer,
2222 .ReleaseBuffer = dri2_release_buffer,
2223 };
2224
2225 /* This is the table of extensions that the loader will dlsym() for. */
2226 const __DRIextension *galliumdrm_driver_extensions[] = {
2227 &driCoreExtension.base,
2228 &driImageDriverExtension.base,
2229 &driDRI2Extension.base,
2230 &gallium_config_options.base,
2231 &dri2FenceExtension.base,
2232 NULL
2233 };
2234
2235 /* vim: set sw=3 ts=8 sts=3 expandtab: */