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