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 "git_sha1.h"
33 #include "GL/mesa_glinterop.h"
34 #include "GL/internal/mesa_interface.h"
35 #include "util/disk_cache.h"
36 #include "util/u_memory.h"
37 #include "util/u_inlines.h"
38 #include "util/format/u_format.h"
39 #include "util/u_debug.h"
40 #include "util/libsync.h"
41 #include "util/os_file.h"
42 #include "frontend/drm_driver.h"
43 #include "state_tracker/st_format.h"
44 #include "state_tracker/st_cb_texture.h"
45 #include "state_tracker/st_texture.h"
46 #include "state_tracker/st_context.h"
47 #include "state_tracker/st_interop.h"
48 #include "pipe-loader/pipe_loader.h"
49 #include "main/bufferobj.h"
50 #include "main/texobj.h"
51
52 #include "dri_util.h"
53
54 #include "dri_helpers.h"
55 #include "dri_drawable.h"
56 #include "dri_query_renderer.h"
57 #include "loader_dri_helper.h"
58
59 #include "drm-uapi/drm_fourcc.h"
60
61 struct dri2_buffer
62 {
63 __DRIbuffer base;
64 struct pipe_resource *resource;
65 };
66
67 static inline struct dri2_buffer *
dri2_buffer(__DRIbuffer * driBufferPriv)68 dri2_buffer(__DRIbuffer * driBufferPriv)
69 {
70 return (struct dri2_buffer *) driBufferPriv;
71 }
72
73 /**
74 * Invalidate the drawable.
75 *
76 * How we get here is listed below.
77 *
78 * 1. Called by these SwapBuffers implementations where the context is known:
79 * loader_dri3_swap_buffers_msc
80 * EGL: droid_swap_buffers
81 * EGL: dri2_drm_swap_buffers
82 * EGL: dri2_wl_swap_buffers_with_damage
83 * EGL: dri2_x11_swap_buffers_msc
84 *
85 * 2. Other callers where the context is known:
86 * st_manager_flush_frontbuffer -> dri2_flush_frontbuffer
87 * -> EGL droid_display_shared_buffer
88 *
89 * 3. Other callers where the context is unknown:
90 * loader: dri3_handle_present_event - XCB_PRESENT_CONFIGURE_NOTIFY
91 * eglQuerySurface -> dri3_query_surface
92 * -> loader_dri3_update_drawable_geometry
93 * EGL: wl_egl_window::resize_callback (called outside Mesa)
94 */
95 static void
dri2_invalidate_drawable(__DRIdrawable * dPriv)96 dri2_invalidate_drawable(__DRIdrawable *dPriv)
97 {
98 struct dri_drawable *drawable = dri_drawable(dPriv);
99
100 drawable->lastStamp++;
101 drawable->texture_mask = 0; /* mark all attachments as invalid */
102
103 p_atomic_inc(&drawable->base.stamp);
104 }
105
106 static const __DRI2flushExtension dri2FlushExtension = {
107 .base = { __DRI2_FLUSH, 4 },
108
109 .flush = dri_flush_drawable,
110 .invalidate = dri2_invalidate_drawable,
111 .flush_with_flags = dri_flush,
112 };
113
114 /**
115 * Retrieve __DRIbuffer from the DRI loader.
116 */
117 static __DRIbuffer *
dri2_drawable_get_buffers(struct dri_drawable * drawable,const enum st_attachment_type * atts,unsigned * count)118 dri2_drawable_get_buffers(struct dri_drawable *drawable,
119 const enum st_attachment_type *atts,
120 unsigned *count)
121 {
122 const __DRIdri2LoaderExtension *loader = drawable->screen->dri2.loader;
123 bool with_format;
124 __DRIbuffer *buffers;
125 int num_buffers;
126 unsigned attachments[__DRI_BUFFER_COUNT];
127 unsigned num_attachments, i;
128
129 assert(loader);
130 assert(*count <= __DRI_BUFFER_COUNT);
131 with_format = dri_with_format(drawable->screen);
132
133 num_attachments = 0;
134
135 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
136 if (!with_format)
137 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
138
139 for (i = 0; i < *count; i++) {
140 enum pipe_format format;
141 unsigned bind;
142 int att, depth;
143
144 dri_drawable_get_format(drawable, atts[i], &format, &bind);
145 if (format == PIPE_FORMAT_NONE)
146 continue;
147
148 switch (atts[i]) {
149 case ST_ATTACHMENT_FRONT_LEFT:
150 /* already added */
151 if (!with_format)
152 continue;
153 att = __DRI_BUFFER_FRONT_LEFT;
154 break;
155 case ST_ATTACHMENT_BACK_LEFT:
156 att = __DRI_BUFFER_BACK_LEFT;
157 break;
158 case ST_ATTACHMENT_FRONT_RIGHT:
159 att = __DRI_BUFFER_FRONT_RIGHT;
160 break;
161 case ST_ATTACHMENT_BACK_RIGHT:
162 att = __DRI_BUFFER_BACK_RIGHT;
163 break;
164 default:
165 continue;
166 }
167
168 /*
169 * In this switch statement we must support all formats that
170 * may occur as the stvis->color_format.
171 */
172 switch(format) {
173 case PIPE_FORMAT_R16G16B16A16_FLOAT:
174 depth = 64;
175 break;
176 case PIPE_FORMAT_R16G16B16X16_FLOAT:
177 depth = 48;
178 break;
179 case PIPE_FORMAT_B10G10R10A2_UNORM:
180 case PIPE_FORMAT_R10G10B10A2_UNORM:
181 case PIPE_FORMAT_BGRA8888_UNORM:
182 case PIPE_FORMAT_RGBA8888_UNORM:
183 depth = 32;
184 break;
185 case PIPE_FORMAT_R10G10B10X2_UNORM:
186 case PIPE_FORMAT_B10G10R10X2_UNORM:
187 depth = 30;
188 break;
189 case PIPE_FORMAT_BGRX8888_UNORM:
190 case PIPE_FORMAT_RGBX8888_UNORM:
191 depth = 24;
192 break;
193 case PIPE_FORMAT_B5G6R5_UNORM:
194 depth = 16;
195 break;
196 default:
197 depth = util_format_get_blocksizebits(format);
198 assert(!"Unexpected format in dri2_drawable_get_buffers()");
199 }
200
201 attachments[num_attachments++] = att;
202 if (with_format) {
203 attachments[num_attachments++] = depth;
204 }
205 }
206
207 if (with_format) {
208 num_attachments /= 2;
209 buffers = loader->getBuffersWithFormat(opaque_dri_drawable(drawable),
210 &drawable->w, &drawable->h,
211 attachments, num_attachments,
212 &num_buffers, drawable->loaderPrivate);
213 }
214 else {
215 buffers = loader->getBuffers(opaque_dri_drawable(drawable),
216 &drawable->w, &drawable->h,
217 attachments, num_attachments,
218 &num_buffers, drawable->loaderPrivate);
219 }
220
221 if (buffers)
222 *count = num_buffers;
223
224 return buffers;
225 }
226
227 bool
228 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
229 struct __DRIimageList *images,
230 const enum st_attachment_type *statts,
231 unsigned statts_count);
232 bool
dri_image_drawable_get_buffers(struct dri_drawable * drawable,struct __DRIimageList * images,const enum st_attachment_type * statts,unsigned statts_count)233 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
234 struct __DRIimageList *images,
235 const enum st_attachment_type *statts,
236 unsigned statts_count)
237 {
238 enum pipe_format color_format = PIPE_FORMAT_NONE;
239 uint32_t buffer_mask = 0;
240 unsigned i;
241
242 for (i = 0; i < statts_count; i++) {
243 enum pipe_format pf;
244 unsigned bind;
245
246 dri_drawable_get_format(drawable, statts[i], &pf, &bind);
247 if (pf == PIPE_FORMAT_NONE)
248 continue;
249
250 switch (statts[i]) {
251 case ST_ATTACHMENT_FRONT_LEFT:
252 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
253 color_format = pf;
254 break;
255 case ST_ATTACHMENT_BACK_LEFT:
256 buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
257 color_format = pf;
258 break;
259 default:
260 break;
261 }
262 }
263
264 /* Stamp usage behavior in the getBuffers callback:
265 *
266 * 1. DRI3 (EGL and GLX):
267 * This calls loader_dri3_get_buffers, which saves the stamp pointer
268 * in loader_dri3_drawable::stamp, which is only changed (incremented)
269 * by loader_dri3_swap_buffers_msc.
270 *
271 * 2. EGL Android, Device, Surfaceless, Wayland:
272 * The stamp is unused.
273 *
274 * How do we get here:
275 * dri_set_tex_buffer2 (GLX_EXT_texture_from_pixmap)
276 * st_api_make_current
277 * st_manager_validate_framebuffers (part of st_validate_state)
278 */
279 return drawable->screen->image.loader->getBuffers(
280 opaque_dri_drawable(drawable),
281 color_format,
282 (uint32_t *)&drawable->base.stamp,
283 drawable->loaderPrivate, buffer_mask,
284 images);
285 }
286
287 static __DRIbuffer *
dri2_allocate_buffer(struct dri_screen * screen,unsigned attachment,unsigned format,int width,int height)288 dri2_allocate_buffer(struct dri_screen *screen,
289 unsigned attachment, unsigned format,
290 int width, int height)
291 {
292 struct dri2_buffer *buffer;
293 struct pipe_resource templ;
294 enum pipe_format pf;
295 unsigned bind = 0;
296 struct winsys_handle whandle;
297
298 /* struct pipe_resource height0 is 16-bit, avoid overflow */
299 if (height > 0xffff)
300 return NULL;
301
302 switch (attachment) {
303 case __DRI_BUFFER_FRONT_LEFT:
304 case __DRI_BUFFER_FAKE_FRONT_LEFT:
305 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
306 break;
307 case __DRI_BUFFER_BACK_LEFT:
308 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
309 break;
310 case __DRI_BUFFER_DEPTH:
311 case __DRI_BUFFER_DEPTH_STENCIL:
312 case __DRI_BUFFER_STENCIL:
313 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
314 break;
315 }
316
317 /* because we get the handle and stride */
318 bind |= PIPE_BIND_SHARED;
319
320 switch (format) {
321 case 64:
322 pf = PIPE_FORMAT_R16G16B16A16_FLOAT;
323 break;
324 case 48:
325 pf = PIPE_FORMAT_R16G16B16X16_FLOAT;
326 break;
327 case 32:
328 pf = PIPE_FORMAT_BGRA8888_UNORM;
329 break;
330 case 30:
331 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
332 break;
333 case 24:
334 pf = PIPE_FORMAT_BGRX8888_UNORM;
335 break;
336 case 16:
337 pf = PIPE_FORMAT_Z16_UNORM;
338 break;
339 default:
340 return NULL;
341 }
342
343 buffer = CALLOC_STRUCT(dri2_buffer);
344 if (!buffer)
345 return NULL;
346
347 memset(&templ, 0, sizeof(templ));
348 templ.bind = bind;
349 templ.format = pf;
350 templ.target = PIPE_TEXTURE_2D;
351 templ.last_level = 0;
352 templ.width0 = width;
353 templ.height0 = height;
354 templ.depth0 = 1;
355 templ.array_size = 1;
356
357 buffer->resource =
358 screen->base.screen->resource_create(screen->base.screen, &templ);
359 if (!buffer->resource) {
360 FREE(buffer);
361 return NULL;
362 }
363
364 memset(&whandle, 0, sizeof(whandle));
365 if (screen->can_share_buffer)
366 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
367 else
368 whandle.type = WINSYS_HANDLE_TYPE_KMS;
369
370 screen->base.screen->resource_get_handle(screen->base.screen, NULL,
371 buffer->resource, &whandle,
372 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
373
374 buffer->base.attachment = attachment;
375 buffer->base.name = whandle.handle;
376 buffer->base.cpp = util_format_get_blocksize(pf);
377 buffer->base.pitch = whandle.stride;
378
379 return &buffer->base;
380 }
381
382 static void
dri2_release_buffer(__DRIbuffer * bPriv)383 dri2_release_buffer(__DRIbuffer *bPriv)
384 {
385 struct dri2_buffer *buffer = dri2_buffer(bPriv);
386
387 pipe_resource_reference(&buffer->resource, NULL);
388 FREE(buffer);
389 }
390
391 static void
dri2_set_in_fence_fd(__DRIimage * img,int fd)392 dri2_set_in_fence_fd(__DRIimage *img, int fd)
393 {
394 validate_fence_fd(fd);
395 validate_fence_fd(img->in_fence_fd);
396 sync_accumulate("dri", &img->in_fence_fd, fd);
397 }
398
399 static void
handle_in_fence(struct dri_context * ctx,__DRIimage * img)400 handle_in_fence(struct dri_context *ctx, __DRIimage *img)
401 {
402 struct pipe_context *pipe = ctx->st->pipe;
403 struct pipe_fence_handle *fence;
404 int fd = img->in_fence_fd;
405
406 if (fd == -1)
407 return;
408
409 validate_fence_fd(fd);
410
411 img->in_fence_fd = -1;
412
413 pipe->create_fence_fd(pipe, &fence, fd, PIPE_FD_TYPE_NATIVE_SYNC);
414 pipe->fence_server_sync(pipe, fence);
415 pipe->screen->fence_reference(pipe->screen, &fence, NULL);
416
417 close(fd);
418 }
419
420 /*
421 * Backend functions for pipe_frontend_drawable.
422 */
423
424 static void
dri2_allocate_textures(struct dri_context * ctx,struct dri_drawable * drawable,const enum st_attachment_type * statts,unsigned statts_count)425 dri2_allocate_textures(struct dri_context *ctx,
426 struct dri_drawable *drawable,
427 const enum st_attachment_type *statts,
428 unsigned statts_count)
429 {
430 struct dri_screen *screen = drawable->screen;
431 struct pipe_resource templ;
432 bool alloc_depthstencil = false;
433 unsigned i, j, bind;
434 const __DRIimageLoaderExtension *image = screen->image.loader;
435 /* Image specific variables */
436 struct __DRIimageList images;
437 /* Dri2 specific variables */
438 __DRIbuffer *buffers = NULL;
439 struct winsys_handle whandle;
440 unsigned num_buffers = statts_count;
441
442 assert(num_buffers <= __DRI_BUFFER_COUNT);
443
444 /* Wait for glthread to finish because we can't use pipe_context from
445 * multiple threads.
446 */
447 _mesa_glthread_finish(ctx->st->ctx);
448
449 /* First get the buffers from the loader */
450 if (image) {
451 if (!dri_image_drawable_get_buffers(drawable, &images,
452 statts, statts_count))
453 return;
454 }
455 else {
456 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
457 if (!buffers || (drawable->old_num == num_buffers &&
458 drawable->old_w == drawable->w &&
459 drawable->old_h == drawable->h &&
460 memcmp(drawable->old, buffers,
461 sizeof(__DRIbuffer) * num_buffers) == 0))
462 return;
463 }
464
465 /* Second clean useless resources*/
466
467 /* See if we need a depth-stencil buffer. */
468 for (i = 0; i < statts_count; i++) {
469 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
470 alloc_depthstencil = true;
471 break;
472 }
473 }
474
475 /* Delete the resources we won't need. */
476 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
477 /* Don't delete the depth-stencil buffer, we can reuse it. */
478 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
479 continue;
480
481 /* Flush the texture before unreferencing, so that other clients can
482 * see what the driver has rendered.
483 */
484 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
485 struct pipe_context *pipe = ctx->st->pipe;
486 pipe->flush_resource(pipe, drawable->textures[i]);
487 }
488
489 pipe_resource_reference(&drawable->textures[i], NULL);
490 }
491
492 if (drawable->stvis.samples > 1) {
493 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
494 bool del = true;
495
496 /* Don't delete MSAA resources for the attachments which are enabled,
497 * we can reuse them. */
498 for (j = 0; j < statts_count; j++) {
499 if (i == statts[j]) {
500 del = false;
501 break;
502 }
503 }
504
505 if (del) {
506 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
507 }
508 }
509 }
510
511 /* Third use the buffers retrieved to fill the drawable info */
512
513 memset(&templ, 0, sizeof(templ));
514 templ.target = screen->target;
515 templ.last_level = 0;
516 templ.depth0 = 1;
517 templ.array_size = 1;
518
519 if (image) {
520 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
521 struct pipe_resource **buf =
522 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
523 struct pipe_resource *texture = images.front->texture;
524
525 drawable->w = texture->width0;
526 drawable->h = texture->height0;
527
528 pipe_resource_reference(buf, texture);
529 handle_in_fence(ctx, images.front);
530 }
531
532 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
533 struct pipe_resource **buf =
534 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
535 struct pipe_resource *texture = images.back->texture;
536
537 drawable->w = texture->width0;
538 drawable->h = texture->height0;
539
540 pipe_resource_reference(buf, texture);
541 handle_in_fence(ctx, images.back);
542 }
543
544 if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
545 struct pipe_resource **buf =
546 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
547 struct pipe_resource *texture = images.back->texture;
548
549 drawable->w = texture->width0;
550 drawable->h = texture->height0;
551
552 pipe_resource_reference(buf, texture);
553 handle_in_fence(ctx, images.back);
554
555 ctx->is_shared_buffer_bound = true;
556 } else {
557 ctx->is_shared_buffer_bound = false;
558 }
559
560 /* Note: if there is both a back and a front buffer,
561 * then they have the same size.
562 */
563 templ.width0 = drawable->w;
564 templ.height0 = drawable->h;
565 }
566 else {
567 memset(&whandle, 0, sizeof(whandle));
568
569 /* Process DRI-provided buffers and get pipe_resources. */
570 for (i = 0; i < num_buffers; i++) {
571 __DRIbuffer *buf = &buffers[i];
572 enum st_attachment_type statt;
573 enum pipe_format format;
574
575 switch (buf->attachment) {
576 case __DRI_BUFFER_FRONT_LEFT:
577 if (!screen->auto_fake_front) {
578 continue; /* invalid attachment */
579 }
580 FALLTHROUGH;
581 case __DRI_BUFFER_FAKE_FRONT_LEFT:
582 statt = ST_ATTACHMENT_FRONT_LEFT;
583 break;
584 case __DRI_BUFFER_BACK_LEFT:
585 statt = ST_ATTACHMENT_BACK_LEFT;
586 break;
587 default:
588 continue; /* invalid attachment */
589 }
590
591 dri_drawable_get_format(drawable, statt, &format, &bind);
592 if (format == PIPE_FORMAT_NONE)
593 continue;
594
595 /* dri2_drawable_get_buffers has already filled dri_drawable->w
596 * and dri_drawable->h */
597 templ.width0 = drawable->w;
598 templ.height0 = drawable->h;
599 templ.format = format;
600 templ.bind = bind;
601 whandle.handle = buf->name;
602 whandle.stride = buf->pitch;
603 whandle.offset = 0;
604 whandle.format = format;
605 whandle.modifier = DRM_FORMAT_MOD_INVALID;
606 if (screen->can_share_buffer)
607 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
608 else
609 whandle.type = WINSYS_HANDLE_TYPE_KMS;
610 drawable->textures[statt] =
611 screen->base.screen->resource_from_handle(screen->base.screen,
612 &templ, &whandle,
613 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
614 assert(drawable->textures[statt]);
615 }
616 }
617
618 /* Allocate private MSAA colorbuffers. */
619 if (drawable->stvis.samples > 1) {
620 for (i = 0; i < statts_count; i++) {
621 enum st_attachment_type statt = statts[i];
622
623 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
624 continue;
625
626 if (drawable->textures[statt]) {
627 templ.format = drawable->textures[statt]->format;
628 templ.bind = drawable->textures[statt]->bind &
629 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
630 templ.nr_samples = drawable->stvis.samples;
631 templ.nr_storage_samples = drawable->stvis.samples;
632
633 /* Try to reuse the resource.
634 * (the other resource parameters should be constant)
635 */
636 if (!drawable->msaa_textures[statt] ||
637 drawable->msaa_textures[statt]->width0 != templ.width0 ||
638 drawable->msaa_textures[statt]->height0 != templ.height0) {
639 /* Allocate a new one. */
640 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
641
642 drawable->msaa_textures[statt] =
643 screen->base.screen->resource_create(screen->base.screen,
644 &templ);
645 assert(drawable->msaa_textures[statt]);
646
647 /* If there are any MSAA resources, we should initialize them
648 * such that they contain the same data as the single-sample
649 * resources we just got from the X server.
650 *
651 * The reason for this is that the gallium frontend (and
652 * therefore the app) can access the MSAA resources only.
653 * The single-sample resources are not exposed
654 * to the gallium frontend.
655 *
656 */
657 dri_pipe_blit(ctx->st->pipe,
658 drawable->msaa_textures[statt],
659 drawable->textures[statt]);
660 }
661 }
662 else {
663 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
664 }
665 }
666 }
667
668 /* Allocate a private depth-stencil buffer. */
669 if (alloc_depthstencil) {
670 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
671 struct pipe_resource **zsbuf;
672 enum pipe_format format;
673 unsigned bind;
674
675 dri_drawable_get_format(drawable, statt, &format, &bind);
676
677 if (format) {
678 templ.format = format;
679 templ.bind = bind & ~PIPE_BIND_SHARED;
680
681 if (drawable->stvis.samples > 1) {
682 templ.nr_samples = drawable->stvis.samples;
683 templ.nr_storage_samples = drawable->stvis.samples;
684 zsbuf = &drawable->msaa_textures[statt];
685 }
686 else {
687 templ.nr_samples = 0;
688 templ.nr_storage_samples = 0;
689 zsbuf = &drawable->textures[statt];
690 }
691
692 /* Try to reuse the resource.
693 * (the other resource parameters should be constant)
694 */
695 if (!*zsbuf ||
696 (*zsbuf)->width0 != templ.width0 ||
697 (*zsbuf)->height0 != templ.height0) {
698 /* Allocate a new one. */
699 pipe_resource_reference(zsbuf, NULL);
700 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
701 &templ);
702 assert(*zsbuf);
703 }
704 }
705 else {
706 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
707 pipe_resource_reference(&drawable->textures[statt], NULL);
708 }
709 }
710
711 /* For DRI2, we may get the same buffers again from the server.
712 * To prevent useless imports of gem names, drawable->old* is used
713 * to bypass the import if we get the same buffers. This doesn't apply
714 * to DRI3/Wayland, users of image.loader, since the buffer is managed
715 * by the client (no import), and the back buffer is going to change
716 * at every redraw.
717 */
718 if (!image) {
719 drawable->old_num = num_buffers;
720 drawable->old_w = drawable->w;
721 drawable->old_h = drawable->h;
722 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
723 }
724 }
725
726 static bool
dri2_flush_frontbuffer(struct dri_context * ctx,struct dri_drawable * drawable,enum st_attachment_type statt)727 dri2_flush_frontbuffer(struct dri_context *ctx,
728 struct dri_drawable *drawable,
729 enum st_attachment_type statt)
730 {
731 const __DRIimageLoaderExtension *image = drawable->screen->image.loader;
732 const __DRIdri2LoaderExtension *loader = drawable->screen->dri2.loader;
733 const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader =
734 drawable->screen->mutableRenderBuffer.loader;
735 struct pipe_context *pipe = ctx->st->pipe;
736 struct pipe_fence_handle *fence = NULL;
737 int fence_fd = -1;
738
739 /* We need to flush for front buffer rendering when either we're using the
740 * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer
741 * has redirected GL_BACK to the front buffer.
742 */
743 if (statt != ST_ATTACHMENT_FRONT_LEFT &&
744 (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT))
745 return false;
746
747 /* Wait for glthread to finish because we can't use pipe_context from
748 * multiple threads.
749 */
750 _mesa_glthread_finish(ctx->st->ctx);
751
752 if (drawable->stvis.samples > 1) {
753 /* Resolve the buffer used for front rendering. */
754 dri_pipe_blit(ctx->st->pipe, drawable->textures[statt],
755 drawable->msaa_textures[statt]);
756 }
757
758 if (drawable->textures[statt]) {
759 pipe->flush_resource(pipe, drawable->textures[statt]);
760 }
761
762 if (ctx->is_shared_buffer_bound) {
763 /* is_shared_buffer_bound should only be true with image extension: */
764 assert(image);
765 pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD);
766 } else {
767 pipe->flush(pipe, NULL, 0);
768 }
769
770 if (image) {
771 image->flushFrontBuffer(opaque_dri_drawable(drawable),
772 drawable->loaderPrivate);
773 if (ctx->is_shared_buffer_bound) {
774 if (fence)
775 fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence);
776
777 shared_buffer_loader->displaySharedBuffer(opaque_dri_drawable(drawable),
778 fence_fd,
779 drawable->loaderPrivate);
780
781 pipe->screen->fence_reference(pipe->screen, &fence, NULL);
782 }
783 }
784 else if (loader->flushFrontBuffer) {
785 loader->flushFrontBuffer(opaque_dri_drawable(drawable),
786 drawable->loaderPrivate);
787 }
788
789 return true;
790 }
791
792 /**
793 * The struct dri_drawable flush_swapbuffers callback
794 */
795 static void
dri2_flush_swapbuffers(struct dri_context * ctx,struct dri_drawable * drawable)796 dri2_flush_swapbuffers(struct dri_context *ctx,
797 struct dri_drawable *drawable)
798 {
799 const __DRIimageLoaderExtension *image = drawable->screen->image.loader;
800
801 if (image && image->flushSwapBuffers) {
802 image->flushSwapBuffers(opaque_dri_drawable(drawable),
803 drawable->loaderPrivate);
804 }
805 }
806
807 static void
dri2_update_tex_buffer(struct dri_drawable * drawable,struct dri_context * ctx,struct pipe_resource * res)808 dri2_update_tex_buffer(struct dri_drawable *drawable,
809 struct dri_context *ctx,
810 struct pipe_resource *res)
811 {
812 /* no-op */
813 }
814
815 static const struct dri2_format_mapping r8_b8_g8_mapping = {
816 DRM_FORMAT_YVU420,
817 __DRI_IMAGE_FORMAT_NONE,
818 __DRI_IMAGE_COMPONENTS_Y_U_V,
819 PIPE_FORMAT_R8_B8_G8_420_UNORM,
820 3,
821 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
822 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 },
823 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 } }
824 };
825
826 static const struct dri2_format_mapping r8_g8_b8_mapping = {
827 DRM_FORMAT_YUV420,
828 __DRI_IMAGE_FORMAT_NONE,
829 __DRI_IMAGE_COMPONENTS_Y_U_V,
830 PIPE_FORMAT_R8_G8_B8_420_UNORM,
831 3,
832 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
833 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 },
834 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 } }
835 };
836
837 static const struct dri2_format_mapping r8_g8b8_mapping = {
838 DRM_FORMAT_NV12,
839 __DRI_IMAGE_FORMAT_NONE,
840 __DRI_IMAGE_COMPONENTS_Y_UV,
841 PIPE_FORMAT_R8_G8B8_420_UNORM,
842 2,
843 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
844 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }
845 };
846
847 static const struct dri2_format_mapping r8_b8g8_mapping = {
848 DRM_FORMAT_NV21,
849 __DRI_IMAGE_FORMAT_NONE,
850 __DRI_IMAGE_COMPONENTS_Y_UV,
851 PIPE_FORMAT_R8_B8G8_420_UNORM,
852 2,
853 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
854 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }
855 };
856
857 static const struct dri2_format_mapping r8g8_r8b8_mapping = {
858 DRM_FORMAT_YUYV,
859 __DRI_IMAGE_FORMAT_NONE,
860 __DRI_IMAGE_COMPONENTS_Y_XUXV,
861 PIPE_FORMAT_R8G8_R8B8_UNORM, 2,
862 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
863 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }
864 };
865
866 static const struct dri2_format_mapping r8b8_r8g8_mapping = {
867 DRM_FORMAT_YVYU,
868 __DRI_IMAGE_FORMAT_NONE,
869 __DRI_IMAGE_COMPONENTS_Y_XUXV,
870 PIPE_FORMAT_R8B8_R8G8_UNORM, 2,
871 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
872 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }
873 };
874
875 static const struct dri2_format_mapping b8r8_g8r8_mapping = {
876 DRM_FORMAT_VYUY,
877 __DRI_IMAGE_FORMAT_NONE,
878 __DRI_IMAGE_COMPONENTS_Y_XUXV,
879 PIPE_FORMAT_B8R8_G8R8_UNORM, 2,
880 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
881 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }
882 };
883
884 static const struct dri2_format_mapping g8r8_b8r8_mapping = {
885 DRM_FORMAT_UYVY,
886 __DRI_IMAGE_FORMAT_NONE,
887 __DRI_IMAGE_COMPONENTS_Y_XUXV,
888 PIPE_FORMAT_G8R8_B8R8_UNORM, 2,
889 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
890 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }
891 };
892
893 static __DRIimage *
dri2_create_image_from_winsys(__DRIscreen * _screen,int width,int height,const struct dri2_format_mapping * map,int num_handles,struct winsys_handle * whandle,unsigned bind,void * loaderPrivate)894 dri2_create_image_from_winsys(__DRIscreen *_screen,
895 int width, int height, const struct dri2_format_mapping *map,
896 int num_handles, struct winsys_handle *whandle,
897 unsigned bind,
898 void *loaderPrivate)
899 {
900 struct dri_screen *screen = dri_screen(_screen);
901 struct pipe_screen *pscreen = screen->base.screen;
902 __DRIimage *img;
903 struct pipe_resource templ;
904 unsigned tex_usage = 0;
905 int i;
906 bool use_lowered = false;
907 const unsigned format_planes = util_format_get_num_planes(map->pipe_format);
908
909 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
910 PIPE_BIND_RENDER_TARGET))
911 tex_usage |= PIPE_BIND_RENDER_TARGET;
912 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
913 PIPE_BIND_SAMPLER_VIEW))
914 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
915 if (is_protected_content)
916 tex_usage |= PIPE_BIND_PROTECTED;
917
918 /* For NV12, see if we have support for sampling r8_g8b8 */
919 if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 &&
920 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM,
921 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
922 map = &r8_g8b8_mapping;
923 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
924 }
925
926 /* For NV21, see if we have support for sampling r8_b8g8 */
927 if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV21 &&
928 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_B8G8_420_UNORM,
929 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
930 map = &r8_b8g8_mapping;
931 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
932 }
933
934 /* For YV12 and I420, see if we have support for sampling r8_b8_g8 or r8_g8_b8 */
935 if (!tex_usage && map->pipe_format == PIPE_FORMAT_IYUV) {
936 if (map->dri_fourcc == DRM_FORMAT_YUV420 &&
937 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8_B8_420_UNORM,
938 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
939 map = &r8_g8_b8_mapping;
940 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
941 } else if (map->dri_fourcc == DRM_FORMAT_YVU420 &&
942 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_B8_G8_420_UNORM,
943 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
944 map = &r8_b8_g8_mapping;
945 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
946 }
947 }
948
949 /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these
950 * can be used for YUYV and UYVY formats.
951 */
952 if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV &&
953 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM,
954 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
955 map = &r8g8_r8b8_mapping;
956 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
957 }
958
959 if (!tex_usage && map->pipe_format == PIPE_FORMAT_YVYU &&
960 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8B8_R8G8_UNORM,
961 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
962 map = &r8b8_r8g8_mapping;
963 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
964 }
965
966 if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY &&
967 pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM,
968 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
969 map = &g8r8_b8r8_mapping;
970 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
971 }
972
973 if (!tex_usage && map->pipe_format == PIPE_FORMAT_VYUY &&
974 pscreen->is_format_supported(pscreen, PIPE_FORMAT_B8R8_G8R8_UNORM,
975 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
976 map = &b8r8_g8r8_mapping;
977 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
978 }
979
980 if (!tex_usage && util_format_is_yuv(map->pipe_format)) {
981 /* YUV format sampling can be emulated by the GL gallium frontend by
982 * using multiple samplers of varying formats.
983 * If no tex_usage is set and we detect a YUV format,
984 * test for support of all planes' sampler formats and
985 * add sampler view usage.
986 */
987 use_lowered = true;
988 if (dri2_yuv_dma_buf_supported(screen, map))
989 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
990 }
991
992 if (!tex_usage)
993 return NULL;
994
995 img = CALLOC_STRUCT(__DRIimageRec);
996 if (!img)
997 return NULL;
998
999 memset(&templ, 0, sizeof(templ));
1000 templ.bind = tex_usage | bind;
1001 templ.target = screen->target;
1002 templ.last_level = 0;
1003 templ.depth0 = 1;
1004 templ.array_size = 1;
1005 templ.width0 = width;
1006 templ.height0 = height;
1007
1008 for (i = num_handles - 1; i >= format_planes; i--) {
1009 struct pipe_resource *tex;
1010
1011 templ.next = img->texture;
1012
1013 tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i],
1014 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
1015 if (!tex) {
1016 pipe_resource_reference(&img->texture, NULL);
1017 FREE(img);
1018 return NULL;
1019 }
1020
1021 img->texture = tex;
1022 }
1023
1024 for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) {
1025 struct pipe_resource *tex;
1026
1027 templ.next = img->texture;
1028 templ.width0 = width >> map->planes[i].width_shift;
1029 templ.height0 = height >> map->planes[i].height_shift;
1030 if (use_lowered)
1031 templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);
1032 else
1033 templ.format = map->pipe_format;
1034 assert(templ.format != PIPE_FORMAT_NONE);
1035
1036 tex = pscreen->resource_from_handle(pscreen,
1037 &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i],
1038 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
1039 if (!tex) {
1040 pipe_resource_reference(&img->texture, NULL);
1041 FREE(img);
1042 return NULL;
1043 }
1044
1045 /* Reject image creation if there's an inconsistency between
1046 * content protection status of tex and img.
1047 */
1048 const struct driOptionCache *optionCache = &screen->dev->option_cache;
1049 if (driQueryOptionb(optionCache, "force_protected_content_check") &&
1050 (tex->bind & PIPE_BIND_PROTECTED) != (bind & PIPE_BIND_PROTECTED)) {
1051 pipe_resource_reference(&img->texture, NULL);
1052 pipe_resource_reference(&tex, NULL);
1053 FREE(img);
1054 return NULL;
1055 }
1056
1057 img->texture = tex;
1058 }
1059
1060 img->level = 0;
1061 img->layer = 0;
1062 img->use = 0;
1063 img->in_fence_fd = -1;
1064 img->loader_private = loaderPrivate;
1065 img->screen = screen;
1066
1067 return img;
1068 }
1069
1070 static __DRIimage *
dri2_create_image_from_name(__DRIscreen * _screen,int width,int height,int format,int name,int pitch,void * loaderPrivate)1071 dri2_create_image_from_name(__DRIscreen *_screen,
1072 int width, int height, int format,
1073 int name, int pitch, void *loaderPrivate)
1074 {
1075 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1076 struct winsys_handle whandle;
1077 __DRIimage *img;
1078
1079 if (!map)
1080 return NULL;
1081
1082 memset(&whandle, 0, sizeof(whandle));
1083 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1084 whandle.handle = name;
1085 whandle.format = map->pipe_format;
1086 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1087
1088 whandle.stride = pitch * util_format_get_blocksize(map->pipe_format);
1089
1090 img = dri2_create_image_from_winsys(_screen, width, height, map,
1091 1, &whandle, 0, loaderPrivate);
1092
1093 if (!img)
1094 return NULL;
1095
1096 img->dri_components = map->dri_components;
1097 img->dri_fourcc = map->dri_fourcc;
1098 img->dri_format = map->dri_format;
1099
1100 return img;
1101 }
1102
1103 static unsigned
dri2_get_modifier_num_planes(__DRIscreen * _screen,uint64_t modifier,int fourcc)1104 dri2_get_modifier_num_planes(__DRIscreen *_screen,
1105 uint64_t modifier, int fourcc)
1106 {
1107 struct pipe_screen *pscreen = dri_screen(_screen)->base.screen;
1108 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1109
1110 if (!map)
1111 return 0;
1112
1113 switch (modifier) {
1114 case DRM_FORMAT_MOD_LINEAR:
1115 /* DRM_FORMAT_MOD_NONE is the same as LINEAR */
1116 case DRM_FORMAT_MOD_INVALID:
1117 return util_format_get_num_planes(map->pipe_format);
1118 default:
1119 if (!pscreen->is_dmabuf_modifier_supported ||
1120 !pscreen->is_dmabuf_modifier_supported(pscreen, modifier,
1121 map->pipe_format, NULL)) {
1122 return 0;
1123 }
1124
1125 if (pscreen->get_dmabuf_modifier_planes) {
1126 return pscreen->get_dmabuf_modifier_planes(pscreen, modifier,
1127 map->pipe_format);
1128 }
1129
1130 return map->nplanes;
1131 }
1132 }
1133
1134 static __DRIimage *
dri2_create_image_from_fd(__DRIscreen * _screen,int width,int height,int fourcc,uint64_t modifier,int * fds,int num_fds,int * strides,int * offsets,unsigned bind,unsigned * error,void * loaderPrivate)1135 dri2_create_image_from_fd(__DRIscreen *_screen,
1136 int width, int height, int fourcc,
1137 uint64_t modifier, int *fds, int num_fds,
1138 int *strides, int *offsets,
1139 unsigned bind, unsigned *error, void *loaderPrivate)
1140 {
1141 struct winsys_handle whandles[4];
1142 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1143 __DRIimage *img = NULL;
1144 unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
1145 int i;
1146 const int expected_num_fds = dri2_get_modifier_num_planes(_screen, modifier, fourcc);
1147
1148 if (!map || expected_num_fds == 0) {
1149 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1150 goto exit;
1151 }
1152
1153 if (num_fds != expected_num_fds) {
1154 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1155 goto exit;
1156 }
1157
1158 memset(whandles, 0, sizeof(whandles));
1159
1160 for (i = 0; i < num_fds; i++) {
1161 if (fds[i] < 0) {
1162 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1163 goto exit;
1164 }
1165
1166 whandles[i].type = WINSYS_HANDLE_TYPE_FD;
1167 whandles[i].handle = (unsigned)fds[i];
1168 whandles[i].stride = (unsigned)strides[i];
1169 whandles[i].offset = (unsigned)offsets[i];
1170 whandles[i].format = map->pipe_format;
1171 whandles[i].modifier = modifier;
1172 whandles[i].plane = i;
1173 }
1174
1175 img = dri2_create_image_from_winsys(_screen, width, height, map,
1176 num_fds, whandles, bind,
1177 loaderPrivate);
1178 if(img == NULL) {
1179 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1180 goto exit;
1181 }
1182
1183 img->dri_components = map->dri_components;
1184 img->dri_fourcc = fourcc;
1185 img->dri_format = map->dri_format;
1186 img->imported_dmabuf = true;
1187
1188 exit:
1189 if (error)
1190 *error = err;
1191
1192 return img;
1193 }
1194
1195 static __DRIimage *
dri2_create_image_common(__DRIscreen * _screen,int width,int height,int format,unsigned int use,const uint64_t * modifiers,const unsigned count,void * loaderPrivate)1196 dri2_create_image_common(__DRIscreen *_screen,
1197 int width, int height,
1198 int format, unsigned int use,
1199 const uint64_t *modifiers,
1200 const unsigned count,
1201 void *loaderPrivate)
1202 {
1203 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1204 struct dri_screen *screen = dri_screen(_screen);
1205 struct pipe_screen *pscreen = screen->base.screen;
1206 __DRIimage *img;
1207 struct pipe_resource templ;
1208 unsigned tex_usage = 0;
1209
1210 if (!map)
1211 return NULL;
1212
1213 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
1214 0, 0, PIPE_BIND_RENDER_TARGET))
1215 tex_usage |= PIPE_BIND_RENDER_TARGET;
1216 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
1217 0, 0, PIPE_BIND_SAMPLER_VIEW))
1218 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
1219
1220 if (!tex_usage)
1221 return NULL;
1222
1223 if (use & __DRI_IMAGE_USE_SCANOUT)
1224 tex_usage |= PIPE_BIND_SCANOUT;
1225 if (use & __DRI_IMAGE_USE_SHARE)
1226 tex_usage |= PIPE_BIND_SHARED;
1227 if (use & __DRI_IMAGE_USE_LINEAR)
1228 tex_usage |= PIPE_BIND_LINEAR;
1229 if (use & __DRI_IMAGE_USE_CURSOR) {
1230 if (width != 64 || height != 64)
1231 return NULL;
1232 tex_usage |= PIPE_BIND_CURSOR;
1233 }
1234 if (use & __DRI_IMAGE_USE_PROTECTED)
1235 tex_usage |= PIPE_BIND_PROTECTED;
1236 if (use & __DRI_IMAGE_USE_PRIME_BUFFER)
1237 tex_usage |= PIPE_BIND_PRIME_BLIT_DST;
1238 if (use & __DRI_IMAGE_USE_FRONT_RENDERING)
1239 tex_usage |= PIPE_BIND_USE_FRONT_RENDERING;
1240
1241 img = CALLOC_STRUCT(__DRIimageRec);
1242 if (!img)
1243 return NULL;
1244
1245 memset(&templ, 0, sizeof(templ));
1246 templ.bind = tex_usage;
1247 templ.format = map->pipe_format;
1248 templ.target = PIPE_TEXTURE_2D;
1249 templ.last_level = 0;
1250 templ.width0 = width;
1251 templ.height0 = height;
1252 templ.depth0 = 1;
1253 templ.array_size = 1;
1254
1255 if (modifiers)
1256 img->texture =
1257 screen->base.screen
1258 ->resource_create_with_modifiers(screen->base.screen,
1259 &templ,
1260 modifiers,
1261 count);
1262 else
1263 img->texture =
1264 screen->base.screen->resource_create(screen->base.screen, &templ);
1265 if (!img->texture) {
1266 FREE(img);
1267 return NULL;
1268 }
1269
1270 img->level = 0;
1271 img->layer = 0;
1272 img->dri_format = format;
1273 img->dri_fourcc = map->dri_fourcc;
1274 img->dri_components = 0;
1275 img->use = use;
1276 img->in_fence_fd = -1;
1277
1278 img->loader_private = loaderPrivate;
1279 img->screen = screen;
1280 return img;
1281 }
1282
1283 static __DRIimage *
dri2_create_image(__DRIscreen * _screen,int width,int height,int format,unsigned int use,void * loaderPrivate)1284 dri2_create_image(__DRIscreen *_screen,
1285 int width, int height, int format,
1286 unsigned int use, void *loaderPrivate)
1287 {
1288 return dri2_create_image_common(_screen, width, height, format, use,
1289 NULL /* modifiers */, 0 /* count */,
1290 loaderPrivate);
1291 }
1292
1293 static __DRIimage *
dri2_create_image_with_modifiers(__DRIscreen * dri_screen,int width,int height,int format,const uint64_t * modifiers,const unsigned count,void * loaderPrivate)1294 dri2_create_image_with_modifiers(__DRIscreen *dri_screen,
1295 int width, int height, int format,
1296 const uint64_t *modifiers,
1297 const unsigned count,
1298 void *loaderPrivate)
1299 {
1300 return dri2_create_image_common(dri_screen, width, height, format,
1301 __DRI_IMAGE_USE_SHARE, modifiers, count,
1302 loaderPrivate);
1303 }
1304
1305 static __DRIimage *
dri2_create_image_with_modifiers2(__DRIscreen * dri_screen,int width,int height,int format,const uint64_t * modifiers,const unsigned count,unsigned int use,void * loaderPrivate)1306 dri2_create_image_with_modifiers2(__DRIscreen *dri_screen,
1307 int width, int height, int format,
1308 const uint64_t *modifiers,
1309 const unsigned count, unsigned int use,
1310 void *loaderPrivate)
1311 {
1312 return dri2_create_image_common(dri_screen, width, height, format, use,
1313 modifiers, count, loaderPrivate);
1314 }
1315
1316 static bool
dri2_query_image_common(__DRIimage * image,int attrib,int * value)1317 dri2_query_image_common(__DRIimage *image, int attrib, int *value)
1318 {
1319 switch (attrib) {
1320 case __DRI_IMAGE_ATTRIB_FORMAT:
1321 *value = image->dri_format;
1322 return true;
1323 case __DRI_IMAGE_ATTRIB_WIDTH:
1324 *value = image->texture->width0;
1325 return true;
1326 case __DRI_IMAGE_ATTRIB_HEIGHT:
1327 *value = image->texture->height0;
1328 return true;
1329 case __DRI_IMAGE_ATTRIB_COMPONENTS:
1330 if (image->dri_components == 0)
1331 return false;
1332 *value = image->dri_components;
1333 return true;
1334 case __DRI_IMAGE_ATTRIB_FOURCC:
1335 if (image->dri_fourcc) {
1336 *value = image->dri_fourcc;
1337 } else {
1338 const struct dri2_format_mapping *map;
1339
1340 map = dri2_get_mapping_by_format(image->dri_format);
1341 if (!map)
1342 return false;
1343
1344 *value = map->dri_fourcc;
1345 }
1346 return true;
1347 default:
1348 return false;
1349 }
1350 }
1351
1352 static bool
dri2_query_image_by_resource_handle(__DRIimage * image,int attrib,int * value)1353 dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value)
1354 {
1355 struct pipe_screen *pscreen = image->texture->screen;
1356 struct winsys_handle whandle;
1357 struct pipe_resource *tex;
1358 unsigned usage;
1359 memset(&whandle, 0, sizeof(whandle));
1360 whandle.plane = image->plane;
1361 int i;
1362
1363 switch (attrib) {
1364 case __DRI_IMAGE_ATTRIB_STRIDE:
1365 case __DRI_IMAGE_ATTRIB_OFFSET:
1366 case __DRI_IMAGE_ATTRIB_HANDLE:
1367 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1368 break;
1369 case __DRI_IMAGE_ATTRIB_NAME:
1370 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1371 break;
1372 case __DRI_IMAGE_ATTRIB_FD:
1373 whandle.type = WINSYS_HANDLE_TYPE_FD;
1374 break;
1375 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1376 for (i = 0, tex = image->texture; tex; tex = tex->next)
1377 i++;
1378 *value = i;
1379 return true;
1380 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1381 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1382 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1383 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1384 break;
1385 default:
1386 return false;
1387 }
1388
1389 usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1390
1391 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1392 usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1393
1394 if (!pscreen->resource_get_handle(pscreen, NULL, image->texture,
1395 &whandle, usage))
1396 return false;
1397
1398 switch (attrib) {
1399 case __DRI_IMAGE_ATTRIB_STRIDE:
1400 *value = whandle.stride;
1401 return true;
1402 case __DRI_IMAGE_ATTRIB_OFFSET:
1403 *value = whandle.offset;
1404 return true;
1405 case __DRI_IMAGE_ATTRIB_HANDLE:
1406 case __DRI_IMAGE_ATTRIB_NAME:
1407 case __DRI_IMAGE_ATTRIB_FD:
1408 *value = whandle.handle;
1409 return true;
1410 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1411 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1412 return false;
1413 *value = (whandle.modifier >> 32) & 0xffffffff;
1414 return true;
1415 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1416 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1417 return false;
1418 *value = whandle.modifier & 0xffffffff;
1419 return true;
1420 default:
1421 return false;
1422 }
1423 }
1424
1425 static bool
dri2_resource_get_param(__DRIimage * image,enum pipe_resource_param param,unsigned handle_usage,uint64_t * value)1426 dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param,
1427 unsigned handle_usage, uint64_t *value)
1428 {
1429 struct pipe_screen *pscreen = image->texture->screen;
1430 if (!pscreen->resource_get_param)
1431 return false;
1432
1433 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1434 handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1435
1436 return pscreen->resource_get_param(pscreen, NULL, image->texture,
1437 image->plane, 0, 0, param, handle_usage,
1438 value);
1439 }
1440
1441 static bool
dri2_query_image_by_resource_param(__DRIimage * image,int attrib,int * value)1442 dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value)
1443 {
1444 enum pipe_resource_param param;
1445 uint64_t res_param;
1446 unsigned handle_usage;
1447
1448 if (!image->texture->screen->resource_get_param)
1449 return false;
1450
1451 switch (attrib) {
1452 case __DRI_IMAGE_ATTRIB_STRIDE:
1453 param = PIPE_RESOURCE_PARAM_STRIDE;
1454 break;
1455 case __DRI_IMAGE_ATTRIB_OFFSET:
1456 param = PIPE_RESOURCE_PARAM_OFFSET;
1457 break;
1458 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1459 param = PIPE_RESOURCE_PARAM_NPLANES;
1460 break;
1461 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1462 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1463 param = PIPE_RESOURCE_PARAM_MODIFIER;
1464 break;
1465 case __DRI_IMAGE_ATTRIB_HANDLE:
1466 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS;
1467 break;
1468 case __DRI_IMAGE_ATTRIB_NAME:
1469 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED;
1470 break;
1471 case __DRI_IMAGE_ATTRIB_FD:
1472 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD;
1473 break;
1474 default:
1475 return false;
1476 }
1477
1478 handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1479
1480 if (!dri2_resource_get_param(image, param, handle_usage, &res_param))
1481 return false;
1482
1483 switch (attrib) {
1484 case __DRI_IMAGE_ATTRIB_STRIDE:
1485 case __DRI_IMAGE_ATTRIB_OFFSET:
1486 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1487 if (res_param > INT_MAX)
1488 return false;
1489 *value = (int)res_param;
1490 return true;
1491 case __DRI_IMAGE_ATTRIB_HANDLE:
1492 case __DRI_IMAGE_ATTRIB_NAME:
1493 case __DRI_IMAGE_ATTRIB_FD:
1494 if (res_param > UINT_MAX)
1495 return false;
1496 *value = (int)res_param;
1497 return true;
1498 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1499 if (res_param == DRM_FORMAT_MOD_INVALID)
1500 return false;
1501 *value = (res_param >> 32) & 0xffffffff;
1502 return true;
1503 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1504 if (res_param == DRM_FORMAT_MOD_INVALID)
1505 return false;
1506 *value = res_param & 0xffffffff;
1507 return true;
1508 default:
1509 return false;
1510 }
1511 }
1512
1513 static GLboolean
dri2_query_image(__DRIimage * image,int attrib,int * value)1514 dri2_query_image(__DRIimage *image, int attrib, int *value)
1515 {
1516 if (dri2_query_image_common(image, attrib, value))
1517 return GL_TRUE;
1518 else if (dri2_query_image_by_resource_param(image, attrib, value))
1519 return GL_TRUE;
1520 else if (dri2_query_image_by_resource_handle(image, attrib, value))
1521 return GL_TRUE;
1522 else
1523 return GL_FALSE;
1524 }
1525
1526 static __DRIimage *
dri2_dup_image(__DRIimage * image,void * loaderPrivate)1527 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
1528 {
1529 __DRIimage *img;
1530
1531 img = CALLOC_STRUCT(__DRIimageRec);
1532 if (!img)
1533 return NULL;
1534
1535 img->texture = NULL;
1536 pipe_resource_reference(&img->texture, image->texture);
1537 img->level = image->level;
1538 img->layer = image->layer;
1539 img->dri_format = image->dri_format;
1540 img->internal_format = image->internal_format;
1541 /* This should be 0 for sub images, but dup is also used for base images. */
1542 img->dri_components = image->dri_components;
1543 img->use = image->use;
1544 img->in_fence_fd = (image->in_fence_fd > 0) ?
1545 os_dupfd_cloexec(image->in_fence_fd) : -1;
1546 img->loader_private = loaderPrivate;
1547 img->screen = image->screen;
1548
1549 return img;
1550 }
1551
1552 static GLboolean
dri2_validate_usage(__DRIimage * image,unsigned int use)1553 dri2_validate_usage(__DRIimage *image, unsigned int use)
1554 {
1555 if (!image || !image->texture)
1556 return false;
1557
1558 struct pipe_screen *screen = image->texture->screen;
1559 if (!screen->check_resource_capability)
1560 return true;
1561
1562 /* We don't want to check these:
1563 * __DRI_IMAGE_USE_SHARE (all images are shareable)
1564 * __DRI_IMAGE_USE_BACKBUFFER (all images support this)
1565 */
1566 unsigned bind = 0;
1567 if (use & __DRI_IMAGE_USE_SCANOUT)
1568 bind |= PIPE_BIND_SCANOUT;
1569 if (use & __DRI_IMAGE_USE_LINEAR)
1570 bind |= PIPE_BIND_LINEAR;
1571 if (use & __DRI_IMAGE_USE_CURSOR)
1572 bind |= PIPE_BIND_CURSOR;
1573
1574 if (!bind)
1575 return true;
1576
1577 return screen->check_resource_capability(screen, image->texture, bind);
1578 }
1579
1580 static __DRIimage *
dri2_from_names(__DRIscreen * screen,int width,int height,int fourcc,int * names,int num_names,int * strides,int * offsets,void * loaderPrivate)1581 dri2_from_names(__DRIscreen *screen, int width, int height, int fourcc,
1582 int *names, int num_names, int *strides, int *offsets,
1583 void *loaderPrivate)
1584 {
1585 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1586 __DRIimage *img;
1587 struct winsys_handle whandle;
1588
1589 if (!map)
1590 return NULL;
1591
1592 if (num_names != 1)
1593 return NULL;
1594
1595 memset(&whandle, 0, sizeof(whandle));
1596 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1597 whandle.handle = names[0];
1598 whandle.stride = strides[0];
1599 whandle.offset = offsets[0];
1600 whandle.format = map->pipe_format;
1601 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1602
1603 img = dri2_create_image_from_winsys(screen, width, height, map,
1604 1, &whandle, 0, loaderPrivate);
1605 if (img == NULL)
1606 return NULL;
1607
1608 img->dri_components = map->dri_components;
1609 img->dri_fourcc = map->dri_fourcc;
1610 img->dri_format = map->pipe_format;
1611
1612 return img;
1613 }
1614
1615 static __DRIimage *
dri2_from_planar(__DRIimage * image,int plane,void * loaderPrivate)1616 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1617 {
1618 __DRIimage *img;
1619
1620 if (plane < 0) {
1621 return NULL;
1622 } else if (plane > 0) {
1623 uint64_t planes;
1624 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0,
1625 &planes) ||
1626 plane >= planes) {
1627 return NULL;
1628 }
1629 }
1630
1631 if (image->dri_components == 0) {
1632 uint64_t modifier;
1633 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0,
1634 &modifier) ||
1635 modifier == DRM_FORMAT_MOD_INVALID) {
1636 return NULL;
1637 }
1638 }
1639
1640 img = dri2_dup_image(image, loaderPrivate);
1641 if (img == NULL)
1642 return NULL;
1643
1644 if (img->texture->screen->resource_changed)
1645 img->texture->screen->resource_changed(img->texture->screen,
1646 img->texture);
1647
1648 /* set this to 0 for sub images. */
1649 img->dri_components = 0;
1650 img->plane = plane;
1651 return img;
1652 }
1653
1654 static __DRIimage *
dri2_from_fds(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,int * strides,int * offsets,void * loaderPrivate)1655 dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1656 int *fds, int num_fds, int *strides, int *offsets,
1657 void *loaderPrivate)
1658 {
1659 return dri2_create_image_from_fd(screen, width, height, fourcc,
1660 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1661 strides, offsets, 0, NULL, loaderPrivate);
1662 }
1663
1664 static __DRIimage *
dri2_from_fds2(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,uint32_t flags,int * strides,int * offsets,void * loaderPrivate)1665 dri2_from_fds2(__DRIscreen *screen, int width, int height, int fourcc,
1666 int *fds, int num_fds, uint32_t flags, int *strides,
1667 int *offsets, void *loaderPrivate)
1668 {
1669 unsigned bind = 0;
1670 if (flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG)
1671 bind |= PIPE_BIND_PROTECTED;
1672 if (flags & __DRI_IMAGE_PRIME_LINEAR_BUFFER)
1673 bind |= PIPE_BIND_PRIME_BLIT_DST;
1674
1675 return dri2_create_image_from_fd(screen, width, height, fourcc,
1676 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1677 strides, offsets, bind, NULL, loaderPrivate);
1678 }
1679
1680 static bool
dri2_query_dma_buf_modifiers(__DRIscreen * _screen,int fourcc,int max,uint64_t * modifiers,unsigned int * external_only,int * count)1681 dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1682 uint64_t *modifiers, unsigned int *external_only,
1683 int *count)
1684 {
1685 struct dri_screen *screen = dri_screen(_screen);
1686 struct pipe_screen *pscreen = screen->base.screen;
1687 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1688 enum pipe_format format;
1689
1690 if (!map)
1691 return false;
1692
1693 format = map->pipe_format;
1694
1695 bool native_sampling = pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1696 PIPE_BIND_SAMPLER_VIEW);
1697 if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1698 PIPE_BIND_RENDER_TARGET) ||
1699 native_sampling ||
1700 dri2_yuv_dma_buf_supported(screen, map)) {
1701 if (pscreen->query_dmabuf_modifiers != NULL) {
1702 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1703 external_only, count);
1704 if (!native_sampling && external_only) {
1705 /* To support it using YUV lowering, we need it to be samplerExternalOES.
1706 */
1707 for (int i = 0; i < *count; i++)
1708 external_only[i] = true;
1709 }
1710 } else {
1711 *count = 0;
1712 }
1713 return true;
1714 }
1715 return false;
1716 }
1717
1718 static bool
dri2_query_dma_buf_format_modifier_attribs(__DRIscreen * _screen,uint32_t fourcc,uint64_t modifier,int attrib,uint64_t * value)1719 dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen,
1720 uint32_t fourcc, uint64_t modifier,
1721 int attrib, uint64_t *value)
1722 {
1723 struct dri_screen *screen = dri_screen(_screen);
1724 struct pipe_screen *pscreen = screen->base.screen;
1725
1726 if (!pscreen->query_dmabuf_modifiers)
1727 return false;
1728
1729 switch (attrib) {
1730 case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: {
1731 uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier,
1732 fourcc);
1733 if (mod_planes > 0)
1734 *value = mod_planes;
1735 return mod_planes > 0;
1736 }
1737 default:
1738 return false;
1739 }
1740 }
1741
1742 static __DRIimage *
dri2_from_dma_bufs(__DRIscreen * screen,int width,int height,int fourcc,int * fds,int num_fds,int * strides,int * offsets,enum __DRIYUVColorSpace yuv_color_space,enum __DRISampleRange sample_range,enum __DRIChromaSiting horizontal_siting,enum __DRIChromaSiting vertical_siting,unsigned * error,void * loaderPrivate)1743 dri2_from_dma_bufs(__DRIscreen *screen,
1744 int width, int height, int fourcc,
1745 int *fds, int num_fds,
1746 int *strides, int *offsets,
1747 enum __DRIYUVColorSpace yuv_color_space,
1748 enum __DRISampleRange sample_range,
1749 enum __DRIChromaSiting horizontal_siting,
1750 enum __DRIChromaSiting vertical_siting,
1751 unsigned *error,
1752 void *loaderPrivate)
1753 {
1754 __DRIimage *img;
1755
1756 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1757 DRM_FORMAT_MOD_INVALID, fds, num_fds,
1758 strides, offsets, 0, error, loaderPrivate);
1759 if (img == NULL)
1760 return NULL;
1761
1762 img->yuv_color_space = yuv_color_space;
1763 img->sample_range = sample_range;
1764 img->horizontal_siting = horizontal_siting;
1765 img->vertical_siting = vertical_siting;
1766
1767 *error = __DRI_IMAGE_ERROR_SUCCESS;
1768 return img;
1769 }
1770
1771 static __DRIimage *
dri2_from_dma_bufs2(__DRIscreen * screen,int width,int height,int fourcc,uint64_t modifier,int * fds,int num_fds,int * strides,int * offsets,enum __DRIYUVColorSpace yuv_color_space,enum __DRISampleRange sample_range,enum __DRIChromaSiting horizontal_siting,enum __DRIChromaSiting vertical_siting,unsigned * error,void * loaderPrivate)1772 dri2_from_dma_bufs2(__DRIscreen *screen,
1773 int width, int height, int fourcc,
1774 uint64_t modifier, int *fds, int num_fds,
1775 int *strides, int *offsets,
1776 enum __DRIYUVColorSpace yuv_color_space,
1777 enum __DRISampleRange sample_range,
1778 enum __DRIChromaSiting horizontal_siting,
1779 enum __DRIChromaSiting vertical_siting,
1780 unsigned *error,
1781 void *loaderPrivate)
1782 {
1783 __DRIimage *img;
1784
1785 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1786 modifier, fds, num_fds, strides, offsets,
1787 0, error, loaderPrivate);
1788 if (img == NULL)
1789 return NULL;
1790
1791 img->yuv_color_space = yuv_color_space;
1792 img->sample_range = sample_range;
1793 img->horizontal_siting = horizontal_siting;
1794 img->vertical_siting = vertical_siting;
1795
1796 *error = __DRI_IMAGE_ERROR_SUCCESS;
1797 return img;
1798 }
1799
1800 static __DRIimage *
dri2_from_dma_bufs3(__DRIscreen * screen,int width,int height,int fourcc,uint64_t modifier,int * fds,int num_fds,int * strides,int * offsets,enum __DRIYUVColorSpace yuv_color_space,enum __DRISampleRange sample_range,enum __DRIChromaSiting horizontal_siting,enum __DRIChromaSiting vertical_siting,uint32_t flags,unsigned * error,void * loaderPrivate)1801 dri2_from_dma_bufs3(__DRIscreen *screen,
1802 int width, int height, int fourcc,
1803 uint64_t modifier, int *fds, int num_fds,
1804 int *strides, int *offsets,
1805 enum __DRIYUVColorSpace yuv_color_space,
1806 enum __DRISampleRange sample_range,
1807 enum __DRIChromaSiting horizontal_siting,
1808 enum __DRIChromaSiting vertical_siting,
1809 uint32_t flags,
1810 unsigned *error,
1811 void *loaderPrivate)
1812 {
1813 unsigned bind = 0;
1814 __DRIimage *img;
1815
1816 if (flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG)
1817 bind |= PIPE_BIND_PROTECTED;
1818 if (flags & __DRI_IMAGE_PRIME_LINEAR_BUFFER)
1819 bind |= PIPE_BIND_PRIME_BLIT_DST;
1820
1821 img = dri2_create_image_from_fd(screen, width, height, fourcc,
1822 modifier, fds, num_fds, strides, offsets,
1823 bind, error, loaderPrivate);
1824 if (img == NULL)
1825 return NULL;
1826
1827 img->yuv_color_space = yuv_color_space;
1828 img->sample_range = sample_range;
1829 img->horizontal_siting = horizontal_siting;
1830 img->vertical_siting = vertical_siting;
1831
1832 *error = __DRI_IMAGE_ERROR_SUCCESS;
1833 return img;
1834 }
1835
1836 static void
dri2_blit_image(__DRIcontext * context,__DRIimage * dst,__DRIimage * src,int dstx0,int dsty0,int dstwidth,int dstheight,int srcx0,int srcy0,int srcwidth,int srcheight,int flush_flag)1837 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1838 int dstx0, int dsty0, int dstwidth, int dstheight,
1839 int srcx0, int srcy0, int srcwidth, int srcheight,
1840 int flush_flag)
1841 {
1842 struct dri_context *ctx = dri_context(context);
1843 struct pipe_context *pipe = ctx->st->pipe;
1844 struct pipe_screen *screen;
1845 struct pipe_fence_handle *fence;
1846 struct pipe_blit_info blit;
1847
1848 if (!dst || !src)
1849 return;
1850
1851 /* Wait for glthread to finish because we can't use pipe_context from
1852 * multiple threads.
1853 */
1854 _mesa_glthread_finish(ctx->st->ctx);
1855
1856 handle_in_fence(ctx, dst);
1857
1858 memset(&blit, 0, sizeof(blit));
1859 blit.dst.resource = dst->texture;
1860 blit.dst.box.x = dstx0;
1861 blit.dst.box.y = dsty0;
1862 blit.dst.box.width = dstwidth;
1863 blit.dst.box.height = dstheight;
1864 blit.dst.box.depth = 1;
1865 blit.dst.format = dst->texture->format;
1866 blit.src.resource = src->texture;
1867 blit.src.box.x = srcx0;
1868 blit.src.box.y = srcy0;
1869 blit.src.box.width = srcwidth;
1870 blit.src.box.height = srcheight;
1871 blit.src.box.depth = 1;
1872 blit.src.format = src->texture->format;
1873 blit.mask = PIPE_MASK_RGBA;
1874 blit.filter = PIPE_TEX_FILTER_NEAREST;
1875
1876 pipe->blit(pipe, &blit);
1877
1878 if (flush_flag == __BLIT_FLAG_FLUSH) {
1879 pipe->flush_resource(pipe, dst->texture);
1880 st_context_flush(ctx->st, 0, NULL, NULL, NULL);
1881 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1882 screen = ctx->screen->base.screen;
1883 pipe->flush_resource(pipe, dst->texture);
1884 st_context_flush(ctx->st, 0, &fence, NULL, NULL);
1885 (void) screen->fence_finish(screen, NULL, fence, OS_TIMEOUT_INFINITE);
1886 screen->fence_reference(screen, &fence, NULL);
1887 }
1888 }
1889
1890 static void *
dri2_map_image(__DRIcontext * context,__DRIimage * image,int x0,int y0,int width,int height,unsigned int flags,int * stride,void ** data)1891 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1892 int x0, int y0, int width, int height,
1893 unsigned int flags, int *stride, void **data)
1894 {
1895 struct dri_context *ctx = dri_context(context);
1896 struct pipe_context *pipe = ctx->st->pipe;
1897 enum pipe_map_flags pipe_access = 0;
1898 struct pipe_transfer *trans;
1899 void *map;
1900
1901 if (!image || !data || *data)
1902 return NULL;
1903
1904 unsigned plane = image->plane;
1905 if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes)
1906 return NULL;
1907
1908 /* Wait for glthread to finish because we can't use pipe_context from
1909 * multiple threads.
1910 */
1911 _mesa_glthread_finish(ctx->st->ctx);
1912
1913 handle_in_fence(ctx, image);
1914
1915 struct pipe_resource *resource = image->texture;
1916 while (plane--)
1917 resource = resource->next;
1918
1919 if (flags & __DRI_IMAGE_TRANSFER_READ)
1920 pipe_access |= PIPE_MAP_READ;
1921 if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1922 pipe_access |= PIPE_MAP_WRITE;
1923
1924 map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0,
1925 width, height, &trans);
1926 if (map) {
1927 *data = trans;
1928 *stride = trans->stride;
1929 }
1930
1931 return map;
1932 }
1933
1934 static void
dri2_unmap_image(__DRIcontext * context,__DRIimage * image,void * data)1935 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1936 {
1937 struct dri_context *ctx = dri_context(context);
1938 struct pipe_context *pipe = ctx->st->pipe;
1939
1940 /* Wait for glthread to finish because we can't use pipe_context from
1941 * multiple threads.
1942 */
1943 _mesa_glthread_finish(ctx->st->ctx);
1944
1945 pipe_texture_unmap(pipe, (struct pipe_transfer *)data);
1946 }
1947
1948 static int
dri2_get_capabilities(__DRIscreen * _screen)1949 dri2_get_capabilities(__DRIscreen *_screen)
1950 {
1951 struct dri_screen *screen = dri_screen(_screen);
1952
1953 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1954 }
1955
1956 /* The extension is modified during runtime if DRI_PRIME is detected */
1957 static const __DRIimageExtension dri2ImageExtensionTempl = {
1958 .base = { __DRI_IMAGE, 21 },
1959
1960 .createImageFromName = dri2_create_image_from_name,
1961 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1962 .destroyImage = dri2_destroy_image,
1963 .createImage = dri2_create_image,
1964 .queryImage = dri2_query_image,
1965 .dupImage = dri2_dup_image,
1966 .validateUsage = dri2_validate_usage,
1967 .createImageFromNames = dri2_from_names,
1968 .fromPlanar = dri2_from_planar,
1969 .createImageFromTexture = dri2_create_from_texture,
1970 .createImageFromFds = NULL,
1971 .createImageFromFds2 = NULL,
1972 .createImageFromDmaBufs = NULL,
1973 .blitImage = dri2_blit_image,
1974 .getCapabilities = dri2_get_capabilities,
1975 .mapImage = dri2_map_image,
1976 .unmapImage = dri2_unmap_image,
1977 .createImageWithModifiers = NULL,
1978 .createImageFromDmaBufs2 = NULL,
1979 .createImageFromDmaBufs3 = NULL,
1980 .queryDmaBufFormats = NULL,
1981 .queryDmaBufModifiers = NULL,
1982 .queryDmaBufFormatModifierAttribs = NULL,
1983 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
1984 .createImageWithModifiers2 = NULL,
1985 };
1986
1987 const __DRIimageExtension driVkImageExtension = {
1988 .base = { __DRI_IMAGE, 20 },
1989
1990 .createImageFromName = dri2_create_image_from_name,
1991 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
1992 .destroyImage = dri2_destroy_image,
1993 .createImage = dri2_create_image,
1994 .queryImage = dri2_query_image,
1995 .dupImage = dri2_dup_image,
1996 .validateUsage = dri2_validate_usage,
1997 .createImageFromNames = dri2_from_names,
1998 .fromPlanar = dri2_from_planar,
1999 .createImageFromTexture = dri2_create_from_texture,
2000 .createImageFromFds = dri2_from_fds,
2001 .createImageFromFds2 = dri2_from_fds2,
2002 .createImageFromDmaBufs = dri2_from_dma_bufs,
2003 .blitImage = dri2_blit_image,
2004 .getCapabilities = dri2_get_capabilities,
2005 .mapImage = dri2_map_image,
2006 .unmapImage = dri2_unmap_image,
2007 .createImageWithModifiers = dri2_create_image_with_modifiers,
2008 .createImageFromDmaBufs2 = dri2_from_dma_bufs2,
2009 .createImageFromDmaBufs3 = dri2_from_dma_bufs3,
2010 .queryDmaBufFormats = dri2_query_dma_buf_formats,
2011 .queryDmaBufModifiers = dri2_query_dma_buf_modifiers,
2012 .queryDmaBufFormatModifierAttribs = dri2_query_dma_buf_format_modifier_attribs,
2013 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
2014 .createImageWithModifiers2 = dri2_create_image_with_modifiers2,
2015 };
2016
2017 const __DRIimageExtension driVkImageExtensionSw = {
2018 .base = { __DRI_IMAGE, 20 },
2019
2020 .createImageFromName = dri2_create_image_from_name,
2021 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,
2022 .destroyImage = dri2_destroy_image,
2023 .createImage = dri2_create_image,
2024 .queryImage = dri2_query_image,
2025 .dupImage = dri2_dup_image,
2026 .validateUsage = dri2_validate_usage,
2027 .createImageFromNames = dri2_from_names,
2028 .fromPlanar = dri2_from_planar,
2029 .createImageFromTexture = dri2_create_from_texture,
2030 .createImageFromFds = dri2_from_fds,
2031 .createImageFromFds2 = dri2_from_fds2,
2032 .blitImage = dri2_blit_image,
2033 .getCapabilities = dri2_get_capabilities,
2034 .mapImage = dri2_map_image,
2035 .unmapImage = dri2_unmap_image,
2036 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
2037 };
2038
2039 static const __DRIrobustnessExtension dri2Robustness = {
2040 .base = { __DRI2_ROBUSTNESS, 1 }
2041 };
2042
2043 static int
dri2_interop_query_device_info(__DRIcontext * _ctx,struct mesa_glinterop_device_info * out)2044 dri2_interop_query_device_info(__DRIcontext *_ctx,
2045 struct mesa_glinterop_device_info *out)
2046 {
2047 return st_interop_query_device_info(dri_context(_ctx)->st, out);
2048 }
2049
2050 static int
dri2_interop_export_object(__DRIcontext * _ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)2051 dri2_interop_export_object(__DRIcontext *_ctx,
2052 struct mesa_glinterop_export_in *in,
2053 struct mesa_glinterop_export_out *out)
2054 {
2055 return st_interop_export_object(dri_context(_ctx)->st, in, out);
2056 }
2057
2058 static int
dri2_interop_flush_objects(__DRIcontext * _ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)2059 dri2_interop_flush_objects(__DRIcontext *_ctx,
2060 unsigned count, struct mesa_glinterop_export_in *objects,
2061 struct mesa_glinterop_flush_out *out)
2062 {
2063 return st_interop_flush_objects(dri_context(_ctx)->st, count, objects, out);
2064 }
2065
2066 static const __DRI2interopExtension dri2InteropExtension = {
2067 .base = { __DRI2_INTEROP, 2 },
2068 .query_device_info = dri2_interop_query_device_info,
2069 .export_object = dri2_interop_export_object,
2070 .flush_objects = dri2_interop_flush_objects
2071 };
2072
2073 /**
2074 * \brief the DRI2bufferDamageExtension set_damage_region method
2075 */
2076 static void
dri2_set_damage_region(__DRIdrawable * dPriv,unsigned int nrects,int * rects)2077 dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects)
2078 {
2079 struct dri_drawable *drawable = dri_drawable(dPriv);
2080 struct pipe_box *boxes = NULL;
2081
2082 if (nrects) {
2083 boxes = CALLOC(nrects, sizeof(*boxes));
2084 assert(boxes);
2085
2086 for (unsigned int i = 0; i < nrects; i++) {
2087 int *rect = &rects[i * 4];
2088
2089 u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]);
2090 }
2091 }
2092
2093 FREE(drawable->damage_rects);
2094 drawable->damage_rects = boxes;
2095 drawable->num_damage_rects = nrects;
2096
2097 /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */
2098 if (drawable->texture_stamp == drawable->lastStamp &&
2099 (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) {
2100 struct pipe_screen *screen = drawable->screen->base.screen;
2101 struct pipe_resource *resource;
2102
2103 if (drawable->stvis.samples > 1)
2104 resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT];
2105 else
2106 resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
2107
2108 screen->set_damage_region(screen, resource,
2109 drawable->num_damage_rects,
2110 drawable->damage_rects);
2111 }
2112 }
2113
2114 static const __DRI2bufferDamageExtension dri2BufferDamageExtensionTempl = {
2115 .base = { __DRI2_BUFFER_DAMAGE, 1 },
2116 };
2117
2118 /**
2119 * \brief the DRI2ConfigQueryExtension configQueryb method
2120 */
2121 static int
dri2GalliumConfigQueryb(__DRIscreen * sPriv,const char * var,unsigned char * val)2122 dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
2123 unsigned char *val)
2124 {
2125 struct dri_screen *screen = dri_screen(sPriv);
2126
2127 if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))
2128 return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
2129
2130 *val = driQueryOptionb(&screen->dev->option_cache, var);
2131
2132 return 0;
2133 }
2134
2135 /**
2136 * \brief the DRI2ConfigQueryExtension configQueryi method
2137 */
2138 static int
dri2GalliumConfigQueryi(__DRIscreen * sPriv,const char * var,int * val)2139 dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
2140 {
2141 struct dri_screen *screen = dri_screen(sPriv);
2142
2143 if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&
2144 !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))
2145 return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
2146
2147 *val = driQueryOptioni(&screen->dev->option_cache, var);
2148
2149 return 0;
2150 }
2151
2152 /**
2153 * \brief the DRI2ConfigQueryExtension configQueryf method
2154 */
2155 static int
dri2GalliumConfigQueryf(__DRIscreen * sPriv,const char * var,float * val)2156 dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
2157 {
2158 struct dri_screen *screen = dri_screen(sPriv);
2159
2160 if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))
2161 return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
2162
2163 *val = driQueryOptionf(&screen->dev->option_cache, var);
2164
2165 return 0;
2166 }
2167
2168 /**
2169 * \brief the DRI2ConfigQueryExtension configQuerys method
2170 */
2171 static int
dri2GalliumConfigQuerys(__DRIscreen * sPriv,const char * var,char ** val)2172 dri2GalliumConfigQuerys(__DRIscreen *sPriv, const char *var, char **val)
2173 {
2174 struct dri_screen *screen = dri_screen(sPriv);
2175
2176 if (!driCheckOption(&screen->dev->option_cache, var, DRI_STRING))
2177 return dri2ConfigQueryExtension.configQuerys(sPriv, var, val);
2178
2179 *val = driQueryOptionstr(&screen->dev->option_cache, var);
2180
2181 return 0;
2182 }
2183
2184 /**
2185 * \brief the DRI2ConfigQueryExtension struct.
2186 *
2187 * We first query the driver option cache. Then the dri2 option cache.
2188 */
2189 static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
2190 .base = { __DRI2_CONFIG_QUERY, 2 },
2191
2192 .configQueryb = dri2GalliumConfigQueryb,
2193 .configQueryi = dri2GalliumConfigQueryi,
2194 .configQueryf = dri2GalliumConfigQueryf,
2195 .configQuerys = dri2GalliumConfigQuerys,
2196 };
2197
2198 /**
2199 * \brief the DRI2blobExtension set_cache_funcs method
2200 */
2201 static void
set_blob_cache_funcs(__DRIscreen * sPriv,__DRIblobCacheSet set,__DRIblobCacheGet get)2202 set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set,
2203 __DRIblobCacheGet get)
2204 {
2205 struct dri_screen *screen = dri_screen(sPriv);
2206 struct pipe_screen *pscreen = screen->base.screen;
2207
2208 if (!pscreen->get_disk_shader_cache)
2209 return;
2210
2211 struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen);
2212
2213 if (!cache)
2214 return;
2215
2216 disk_cache_set_callbacks(cache, set, get);
2217 }
2218
2219 static const __DRI2blobExtension driBlobExtension = {
2220 .base = { __DRI2_BLOB, 1 },
2221 .set_cache_funcs = set_blob_cache_funcs
2222 };
2223
2224 static const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = {
2225 .base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 },
2226 };
2227
2228 /*
2229 * Backend function init_screen.
2230 */
2231
2232 static const __DRIextension *dri_screen_extensions_base[] = {
2233 &driTexBufferExtension.base,
2234 &dri2FlushExtension.base,
2235 &dri2RendererQueryExtension.base,
2236 &dri2GalliumConfigQueryExtension.base,
2237 &dri2ThrottleExtension.base,
2238 &dri2FenceExtension.base,
2239 &dri2InteropExtension.base,
2240 &driBlobExtension.base,
2241 &driMutableRenderBufferExtension.base,
2242 &dri2FlushControlExtension.base,
2243 };
2244
2245 /**
2246 * Set up the DRI extension list for this screen based on its underlying
2247 * gallium screen's capabilities.
2248 */
2249 static void
dri2_init_screen_extensions(struct dri_screen * screen,struct pipe_screen * pscreen,bool is_kms_screen)2250 dri2_init_screen_extensions(struct dri_screen *screen,
2251 struct pipe_screen *pscreen,
2252 bool is_kms_screen)
2253 {
2254 const __DRIextension **nExt;
2255
2256 STATIC_ASSERT(sizeof(screen->screen_extensions) >=
2257 sizeof(dri_screen_extensions_base));
2258 memcpy(&screen->screen_extensions, dri_screen_extensions_base,
2259 sizeof(dri_screen_extensions_base));
2260 screen->extensions = screen->screen_extensions;
2261
2262 /* Point nExt at the end of the extension list */
2263 nExt = &screen->screen_extensions[ARRAY_SIZE(dri_screen_extensions_base)];
2264
2265 screen->image_extension = dri2ImageExtensionTempl;
2266 if (pscreen->resource_create_with_modifiers) {
2267 screen->image_extension.createImageWithModifiers =
2268 dri2_create_image_with_modifiers;
2269 screen->image_extension.createImageWithModifiers2 =
2270 dri2_create_image_with_modifiers2;
2271 }
2272
2273 if (pscreen->get_param(pscreen, PIPE_CAP_NATIVE_FENCE_FD)) {
2274 screen->image_extension.setInFenceFd = dri2_set_in_fence_fd;
2275 }
2276
2277 if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF) & DRM_PRIME_CAP_IMPORT) {
2278 screen->image_extension.createImageFromFds = dri2_from_fds;
2279 screen->image_extension.createImageFromFds2 = dri2_from_fds2;
2280 screen->image_extension.createImageFromDmaBufs = dri2_from_dma_bufs;
2281 screen->image_extension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2282 screen->image_extension.createImageFromDmaBufs3 = dri2_from_dma_bufs3;
2283 screen->image_extension.queryDmaBufFormats =
2284 dri2_query_dma_buf_formats;
2285 screen->image_extension.queryDmaBufModifiers =
2286 dri2_query_dma_buf_modifiers;
2287 if (!is_kms_screen) {
2288 screen->image_extension.queryDmaBufFormatModifierAttribs =
2289 dri2_query_dma_buf_format_modifier_attribs;
2290 }
2291 }
2292 *nExt++ = &screen->image_extension.base;
2293
2294 if (!is_kms_screen) {
2295 screen->buffer_damage_extension = dri2BufferDamageExtensionTempl;
2296 if (pscreen->set_damage_region)
2297 screen->buffer_damage_extension.set_damage_region =
2298 dri2_set_damage_region;
2299 *nExt++ = &screen->buffer_damage_extension.base;
2300 }
2301
2302 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
2303 *nExt++ = &dri2Robustness.base;
2304 screen->has_reset_status_query = true;
2305 }
2306
2307 /* Ensure the extension list didn't overrun its buffer and is still
2308 * NULL-terminated */
2309 assert(nExt - screen->screen_extensions <=
2310 ARRAY_SIZE(screen->screen_extensions) - 1);
2311 assert(!*nExt);
2312 }
2313
2314 static struct dri_drawable *
dri2_create_drawable(struct dri_screen * screen,const struct gl_config * visual,bool isPixmap,void * loaderPrivate)2315 dri2_create_drawable(struct dri_screen *screen, const struct gl_config *visual,
2316 bool isPixmap, void *loaderPrivate)
2317 {
2318 struct dri_drawable *drawable = dri_create_drawable(screen, visual, isPixmap,
2319 loaderPrivate);
2320 if (!drawable)
2321 return NULL;
2322
2323 drawable->allocate_textures = dri2_allocate_textures;
2324 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2325 drawable->update_tex_buffer = dri2_update_tex_buffer;
2326 drawable->flush_swapbuffers = dri2_flush_swapbuffers;
2327
2328 return drawable;
2329 }
2330
2331 /**
2332 * This is the driver specific part of the createNewScreen entry point.
2333 *
2334 * Returns the struct gl_config supported by this driver.
2335 */
2336 static const __DRIconfig **
dri2_init_screen(struct dri_screen * screen)2337 dri2_init_screen(struct dri_screen *screen)
2338 {
2339 const __DRIconfig **configs;
2340 struct pipe_screen *pscreen = NULL;
2341
2342 (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
2343
2344 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, false))
2345 pscreen = pipe_loader_create_screen(screen->dev);
2346
2347 if (!pscreen)
2348 goto fail;
2349
2350 dri_init_options(screen);
2351 screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE);
2352
2353 dri2_init_screen_extensions(screen, pscreen, false);
2354
2355 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_PROTECTED_CONTEXT))
2356 screen->has_protected_context = true;
2357
2358 configs = dri_init_screen(screen, pscreen);
2359 if (!configs)
2360 goto fail;
2361
2362 screen->can_share_buffer = true;
2363 screen->auto_fake_front = dri_with_format(screen);
2364 screen->lookup_egl_image = dri2_lookup_egl_image;
2365
2366 const __DRIimageLookupExtension *loader = screen->dri2.image;
2367 if (loader &&
2368 loader->base.version >= 2 &&
2369 loader->validateEGLImage &&
2370 loader->lookupEGLImageValidated) {
2371 screen->validate_egl_image = dri2_validate_egl_image;
2372 screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated;
2373 }
2374
2375 screen->create_drawable = dri2_create_drawable;
2376 screen->allocate_buffer = dri2_allocate_buffer;
2377 screen->release_buffer = dri2_release_buffer;
2378
2379 return configs;
2380
2381 fail:
2382 dri_release_screen(screen);
2383
2384 return NULL;
2385 }
2386
2387 /**
2388 * This is the driver specific part of the createNewScreen entry point.
2389 *
2390 * Returns the struct gl_config supported by this driver.
2391 */
2392 static const __DRIconfig **
dri_swrast_kms_init_screen(struct dri_screen * screen)2393 dri_swrast_kms_init_screen(struct dri_screen *screen)
2394 {
2395 #if defined(GALLIUM_SOFTPIPE)
2396 const __DRIconfig **configs;
2397 struct pipe_screen *pscreen = NULL;
2398
2399 #ifdef HAVE_DRISW_KMS
2400 if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd))
2401 pscreen = pipe_loader_create_screen(screen->dev);
2402 #endif
2403
2404 if (!pscreen)
2405 goto fail;
2406
2407 dri_init_options(screen);
2408 dri2_init_screen_extensions(screen, pscreen, true);
2409
2410 configs = dri_init_screen(screen, pscreen);
2411 if (!configs)
2412 goto fail;
2413
2414 screen->can_share_buffer = false;
2415 screen->auto_fake_front = dri_with_format(screen);
2416 screen->lookup_egl_image = dri2_lookup_egl_image;
2417
2418 const __DRIimageLookupExtension *loader = screen->dri2.image;
2419 if (loader &&
2420 loader->base.version >= 2 &&
2421 loader->validateEGLImage &&
2422 loader->lookupEGLImageValidated) {
2423 screen->validate_egl_image = dri2_validate_egl_image;
2424 screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated;
2425 }
2426
2427 screen->create_drawable = dri2_create_drawable;
2428 screen->allocate_buffer = dri2_allocate_buffer;
2429 screen->release_buffer = dri2_release_buffer;
2430
2431 return configs;
2432
2433 fail:
2434 dri_release_screen(screen);
2435
2436 #endif // GALLIUM_SOFTPIPE
2437 return NULL;
2438 }
2439
2440 static int
dri_query_compatible_render_only_device_fd(int kms_only_fd)2441 dri_query_compatible_render_only_device_fd(int kms_only_fd)
2442 {
2443 return pipe_loader_get_compatible_render_capable_device_fd(kms_only_fd);
2444 }
2445
2446 static const struct __DRImesaCoreExtensionRec mesaCoreExtension = {
2447 .base = { __DRI_MESA, 1 },
2448 .version_string = MESA_INTERFACE_VERSION_STRING,
2449 .createNewScreen = driCreateNewScreen2,
2450 .createContext = driCreateContextAttribs,
2451 .initScreen = dri2_init_screen,
2452 .queryCompatibleRenderOnlyDeviceFd = dri_query_compatible_render_only_device_fd,
2453 };
2454
2455 /* This is the table of extensions that the loader will dlsym() for. */
2456 const __DRIextension *galliumdrm_driver_extensions[] = {
2457 &driCoreExtension.base,
2458 &mesaCoreExtension.base,
2459 &driImageDriverExtension.base,
2460 &driDRI2Extension.base,
2461 &gallium_config_options.base,
2462 NULL
2463 };
2464
2465 static const struct __DRImesaCoreExtensionRec swkmsMesaCoreExtension = {
2466 .base = { __DRI_MESA, 1 },
2467 .version_string = MESA_INTERFACE_VERSION_STRING,
2468 .createNewScreen = driCreateNewScreen2,
2469 .createContext = driCreateContextAttribs,
2470 .initScreen = dri_swrast_kms_init_screen,
2471 };
2472
2473 const __DRIextension *dri_swrast_kms_driver_extensions[] = {
2474 &driCoreExtension.base,
2475 &swkmsMesaCoreExtension.base,
2476 &driImageDriverExtension.base,
2477 &swkmsDRI2Extension.base,
2478 &gallium_config_options.base,
2479 NULL
2480 };
2481
2482 /* vim: set sw=3 ts=8 sts=3 expandtab: */
2483