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