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 <[email protected]> Jakob Bornecrantz
28 * <[email protected]> Chia-I Wu <[email protected]>
29 */
30
31 #include "util/libdrm.h"
32 #include "git_sha1.h"
33 #include "GL/mesa_glinterop.h"
34 #include "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 "util/log.h"
43 #include "frontend/drm_driver.h"
44 #include "state_tracker/st_format.h"
45 #include "state_tracker/st_cb_texture.h"
46 #include "state_tracker/st_texture.h"
47 #include "state_tracker/st_context.h"
48 #include "state_tracker/st_interop.h"
49 #include "pipe-loader/pipe_loader.h"
50 #include "main/bufferobj.h"
51 #include "main/texobj.h"
52
53 #include "dri_util.h"
54
55 #include "dri_helpers.h"
56 #include "dri_drawable.h"
57 #include "dri_query_renderer.h"
58 #include "loader_dri_helper.h"
59
60 #include "drm-uapi/drm_fourcc.h"
61
62 struct dri2_buffer
63 {
64 __DRIbuffer base;
65 struct pipe_resource *resource;
66 };
67
68 static inline struct dri2_buffer *
dri2_buffer(__DRIbuffer * driBufferPriv)69 dri2_buffer(__DRIbuffer * driBufferPriv)
70 {
71 return (struct dri2_buffer *) driBufferPriv;
72 }
73
74 /**
75 * Invalidate the drawable.
76 *
77 * How we get here is listed below.
78 *
79 * 1. Called by these SwapBuffers implementations where the context is known:
80 * loader_dri3_swap_buffers_msc
81 * EGL: droid_swap_buffers
82 * EGL: dri2_drm_swap_buffers
83 * EGL: dri2_wl_swap_buffers_with_damage
84 * EGL: dri2_x11_swap_buffers_msc
85 *
86 * 2. Other callers where the context is known:
87 * st_manager_flush_frontbuffer -> dri2_flush_frontbuffer
88 * -> EGL droid_display_shared_buffer
89 *
90 * 3. Other callers where the context is unknown:
91 * loader: dri3_handle_present_event - XCB_PRESENT_CONFIGURE_NOTIFY
92 * eglQuerySurface -> dri3_query_surface
93 * -> loader_dri3_update_drawable_geometry
94 * EGL: wl_egl_window::resize_callback (called outside Mesa)
95 */
96 void
dri_invalidate_drawable(__DRIdrawable * dPriv)97 dri_invalidate_drawable(__DRIdrawable *dPriv)
98 {
99 struct dri_drawable *drawable = dri_drawable(dPriv);
100
101 drawable->lastStamp++;
102 drawable->texture_mask = 0; /* mark all attachments as invalid */
103
104 p_atomic_inc(&drawable->base.stamp);
105 }
106
107 /**
108 * Retrieve __DRIbuffer from the DRI loader.
109 */
110 static __DRIbuffer *
dri2_drawable_get_buffers(struct dri_drawable * drawable,const enum st_attachment_type * atts,unsigned * count)111 dri2_drawable_get_buffers(struct dri_drawable *drawable,
112 const enum st_attachment_type *atts,
113 unsigned *count)
114 {
115 const __DRIdri2LoaderExtension *loader = drawable->screen->dri2.loader;
116 bool with_format;
117 __DRIbuffer *buffers;
118 int num_buffers;
119 unsigned attachments[__DRI_BUFFER_COUNT];
120 unsigned num_attachments, i;
121
122 assert(loader);
123 assert(*count <= __DRI_BUFFER_COUNT);
124 with_format = dri_with_format(drawable->screen);
125
126 num_attachments = 0;
127
128 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
129 if (!with_format)
130 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
131
132 for (i = 0; i < *count; i++) {
133 enum pipe_format format;
134 unsigned bind;
135 int att, depth;
136
137 dri_drawable_get_format(drawable, atts[i], &format, &bind);
138 if (format == PIPE_FORMAT_NONE)
139 continue;
140
141 switch (atts[i]) {
142 case ST_ATTACHMENT_FRONT_LEFT:
143 /* already added */
144 if (!with_format)
145 continue;
146 att = __DRI_BUFFER_FRONT_LEFT;
147 break;
148 case ST_ATTACHMENT_BACK_LEFT:
149 att = __DRI_BUFFER_BACK_LEFT;
150 break;
151 case ST_ATTACHMENT_FRONT_RIGHT:
152 att = __DRI_BUFFER_FRONT_RIGHT;
153 break;
154 case ST_ATTACHMENT_BACK_RIGHT:
155 att = __DRI_BUFFER_BACK_RIGHT;
156 break;
157 default:
158 continue;
159 }
160
161 /*
162 * In this switch statement we must support all formats that
163 * may occur as the stvis->color_format.
164 */
165 switch(format) {
166 case PIPE_FORMAT_R16G16B16A16_FLOAT:
167 depth = 64;
168 break;
169 case PIPE_FORMAT_R16G16B16X16_FLOAT:
170 depth = 48;
171 break;
172 case PIPE_FORMAT_B10G10R10A2_UNORM:
173 case PIPE_FORMAT_R10G10B10A2_UNORM:
174 case PIPE_FORMAT_BGRA8888_UNORM:
175 case PIPE_FORMAT_RGBA8888_UNORM:
176 depth = 32;
177 break;
178 case PIPE_FORMAT_R10G10B10X2_UNORM:
179 case PIPE_FORMAT_B10G10R10X2_UNORM:
180 depth = 30;
181 break;
182 case PIPE_FORMAT_BGRX8888_UNORM:
183 case PIPE_FORMAT_RGBX8888_UNORM:
184 depth = 24;
185 break;
186 case PIPE_FORMAT_B5G6R5_UNORM:
187 depth = 16;
188 break;
189 default:
190 depth = util_format_get_blocksizebits(format);
191 assert(!"Unexpected format in dri2_drawable_get_buffers()");
192 }
193
194 attachments[num_attachments++] = att;
195 if (with_format) {
196 attachments[num_attachments++] = depth;
197 }
198 }
199
200 if (with_format) {
201 num_attachments /= 2;
202 buffers = loader->getBuffersWithFormat(opaque_dri_drawable(drawable),
203 &drawable->w, &drawable->h,
204 attachments, num_attachments,
205 &num_buffers, drawable->loaderPrivate);
206 }
207 else {
208 buffers = loader->getBuffers(opaque_dri_drawable(drawable),
209 &drawable->w, &drawable->h,
210 attachments, num_attachments,
211 &num_buffers, drawable->loaderPrivate);
212 }
213
214 if (buffers)
215 *count = num_buffers;
216
217 return buffers;
218 }
219
220 bool
221 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
222 struct __DRIimageList *images,
223 const enum st_attachment_type *statts,
224 unsigned statts_count);
225 bool
dri_image_drawable_get_buffers(struct dri_drawable * drawable,struct __DRIimageList * images,const enum st_attachment_type * statts,unsigned statts_count)226 dri_image_drawable_get_buffers(struct dri_drawable *drawable,
227 struct __DRIimageList *images,
228 const enum st_attachment_type *statts,
229 unsigned statts_count)
230 {
231 enum pipe_format color_format = PIPE_FORMAT_NONE;
232 uint32_t buffer_mask = 0;
233 unsigned i;
234
235 for (i = 0; i < statts_count; i++) {
236 enum pipe_format pf;
237 unsigned bind;
238
239 dri_drawable_get_format(drawable, statts[i], &pf, &bind);
240 if (pf == PIPE_FORMAT_NONE)
241 continue;
242
243 switch (statts[i]) {
244 case ST_ATTACHMENT_FRONT_LEFT:
245 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
246 color_format = pf;
247 break;
248 case ST_ATTACHMENT_BACK_LEFT:
249 buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
250 color_format = pf;
251 break;
252 default:
253 break;
254 }
255 }
256
257 /* Stamp usage behavior in the getBuffers callback:
258 *
259 * 1. DRI3 (EGL and GLX):
260 * This calls loader_dri3_get_buffers, which saves the stamp pointer
261 * in loader_dri3_drawable::stamp, which is only changed (incremented)
262 * by loader_dri3_swap_buffers_msc.
263 *
264 * 2. EGL Android, Device, Surfaceless, Wayland:
265 * The stamp is unused.
266 *
267 * How do we get here:
268 * dri_set_tex_buffer2 (GLX_EXT_texture_from_pixmap)
269 * st_api_make_current
270 * st_manager_validate_framebuffers (part of st_validate_state)
271 */
272 return drawable->screen->image.loader->getBuffers(
273 opaque_dri_drawable(drawable),
274 color_format,
275 (uint32_t *)&drawable->base.stamp,
276 drawable->loaderPrivate, buffer_mask,
277 images);
278 }
279
280 static __DRIbuffer *
dri2_allocate_buffer(struct dri_screen * screen,unsigned attachment,unsigned format,int width,int height)281 dri2_allocate_buffer(struct dri_screen *screen,
282 unsigned attachment, unsigned format,
283 int width, int height)
284 {
285 struct dri2_buffer *buffer;
286 struct pipe_resource templ;
287 enum pipe_format pf;
288 unsigned bind = 0;
289 struct winsys_handle whandle;
290
291 /* struct pipe_resource height0 is 16-bit, avoid overflow */
292 if (height > 0xffff)
293 return NULL;
294
295 switch (attachment) {
296 case __DRI_BUFFER_FRONT_LEFT:
297 case __DRI_BUFFER_FAKE_FRONT_LEFT:
298 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
299 break;
300 case __DRI_BUFFER_BACK_LEFT:
301 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
302 break;
303 case __DRI_BUFFER_DEPTH:
304 case __DRI_BUFFER_DEPTH_STENCIL:
305 case __DRI_BUFFER_STENCIL:
306 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
307 break;
308 }
309
310 /* because we get the handle and stride */
311 bind |= PIPE_BIND_SHARED;
312
313 switch (format) {
314 case 64:
315 pf = PIPE_FORMAT_R16G16B16A16_FLOAT;
316 break;
317 case 48:
318 pf = PIPE_FORMAT_R16G16B16X16_FLOAT;
319 break;
320 case 32:
321 pf = PIPE_FORMAT_BGRA8888_UNORM;
322 break;
323 case 30:
324 pf = PIPE_FORMAT_B10G10R10X2_UNORM;
325 break;
326 case 24:
327 pf = PIPE_FORMAT_BGRX8888_UNORM;
328 break;
329 case 16:
330 pf = PIPE_FORMAT_Z16_UNORM;
331 break;
332 default:
333 return NULL;
334 }
335
336 buffer = CALLOC_STRUCT(dri2_buffer);
337 if (!buffer)
338 return NULL;
339
340 memset(&templ, 0, sizeof(templ));
341 templ.bind = bind;
342 templ.format = pf;
343 templ.target = PIPE_TEXTURE_2D;
344 templ.last_level = 0;
345 templ.width0 = width;
346 templ.height0 = height;
347 templ.depth0 = 1;
348 templ.array_size = 1;
349
350 buffer->resource =
351 screen->base.screen->resource_create(screen->base.screen, &templ);
352 if (!buffer->resource) {
353 FREE(buffer);
354 return NULL;
355 }
356
357 memset(&whandle, 0, sizeof(whandle));
358 if (screen->can_share_buffer)
359 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
360 else
361 whandle.type = WINSYS_HANDLE_TYPE_KMS;
362
363 screen->base.screen->resource_get_handle(screen->base.screen, NULL,
364 buffer->resource, &whandle,
365 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
366
367 buffer->base.attachment = attachment;
368 buffer->base.name = whandle.handle;
369 buffer->base.cpp = util_format_get_blocksize(pf);
370 buffer->base.pitch = whandle.stride;
371
372 return &buffer->base;
373 }
374
375 static void
dri2_release_buffer(__DRIbuffer * bPriv)376 dri2_release_buffer(__DRIbuffer *bPriv)
377 {
378 struct dri2_buffer *buffer = dri2_buffer(bPriv);
379
380 pipe_resource_reference(&buffer->resource, NULL);
381 FREE(buffer);
382 }
383
384 void
dri2_set_in_fence_fd(__DRIimage * img,int fd)385 dri2_set_in_fence_fd(__DRIimage *img, int fd)
386 {
387 validate_fence_fd(fd);
388 validate_fence_fd(img->in_fence_fd);
389 sync_accumulate("dri", &img->in_fence_fd, fd);
390 }
391
392 /*
393 * Backend functions for pipe_frontend_drawable.
394 */
395
396 static void
dri2_allocate_textures(struct dri_context * ctx,struct dri_drawable * drawable,const enum st_attachment_type * statts,unsigned statts_count)397 dri2_allocate_textures(struct dri_context *ctx,
398 struct dri_drawable *drawable,
399 const enum st_attachment_type *statts,
400 unsigned statts_count)
401 {
402 struct dri_screen *screen = drawable->screen;
403 struct pipe_resource templ;
404 bool alloc_depthstencil = false;
405 unsigned i, j, bind;
406 const __DRIimageLoaderExtension *image = screen->image.loader;
407 /* Image specific variables */
408 struct __DRIimageList images;
409 /* Dri2 specific variables */
410 __DRIbuffer *buffers = NULL;
411 struct winsys_handle whandle;
412 unsigned num_buffers = statts_count;
413
414 assert(num_buffers <= __DRI_BUFFER_COUNT);
415
416 /* Wait for glthread to finish because we can't use pipe_context from
417 * multiple threads.
418 */
419 _mesa_glthread_finish(ctx->st->ctx);
420
421 /* First get the buffers from the loader */
422 if (image) {
423 if (!dri_image_drawable_get_buffers(drawable, &images,
424 statts, statts_count))
425 return;
426 }
427 else {
428 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
429 if (!buffers || (drawable->old_num == num_buffers &&
430 drawable->old_w == drawable->w &&
431 drawable->old_h == drawable->h &&
432 memcmp(drawable->old, buffers,
433 sizeof(__DRIbuffer) * num_buffers) == 0))
434 return;
435 }
436
437 /* Second clean useless resources*/
438
439 /* See if we need a depth-stencil buffer. */
440 for (i = 0; i < statts_count; i++) {
441 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
442 alloc_depthstencil = true;
443 break;
444 }
445 }
446
447 /* Delete the resources we won't need. */
448 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
449 /* Don't delete the depth-stencil buffer, we can reuse it. */
450 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
451 continue;
452
453 /* Flush the texture before unreferencing, so that other clients can
454 * see what the driver has rendered.
455 */
456 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
457 struct pipe_context *pipe = ctx->st->pipe;
458 pipe->flush_resource(pipe, drawable->textures[i]);
459 }
460
461 pipe_resource_reference(&drawable->textures[i], NULL);
462 }
463
464 if (drawable->stvis.samples > 1) {
465 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
466 bool del = true;
467
468 /* Don't delete MSAA resources for the attachments which are enabled,
469 * we can reuse them. */
470 for (j = 0; j < statts_count; j++) {
471 if (i == statts[j]) {
472 del = false;
473 break;
474 }
475 }
476
477 if (del) {
478 pipe_resource_reference(&drawable->msaa_textures[i], NULL);
479 }
480 }
481 }
482
483 /* Third use the buffers retrieved to fill the drawable info */
484
485 memset(&templ, 0, sizeof(templ));
486 templ.target = screen->target;
487 templ.last_level = 0;
488 templ.depth0 = 1;
489 templ.array_size = 1;
490
491 if (image) {
492 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
493 struct pipe_resource **buf =
494 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
495 struct pipe_resource *texture = images.front->texture;
496
497 drawable->w = texture->width0;
498 drawable->h = texture->height0;
499
500 pipe_resource_reference(buf, texture);
501 dri_image_fence_sync(ctx, images.front);
502 }
503
504 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
505 struct pipe_resource **buf =
506 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
507 struct pipe_resource *texture = images.back->texture;
508
509 drawable->w = texture->width0;
510 drawable->h = texture->height0;
511
512 pipe_resource_reference(buf, texture);
513 dri_image_fence_sync(ctx, images.back);
514 }
515
516 if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
517 struct pipe_resource **buf =
518 &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
519 struct pipe_resource *texture = images.back->texture;
520
521 drawable->w = texture->width0;
522 drawable->h = texture->height0;
523
524 pipe_resource_reference(buf, texture);
525 dri_image_fence_sync(ctx, images.back);
526
527 ctx->is_shared_buffer_bound = true;
528 } else {
529 ctx->is_shared_buffer_bound = false;
530 }
531
532 /* Note: if there is both a back and a front buffer,
533 * then they have the same size.
534 */
535 templ.width0 = drawable->w;
536 templ.height0 = drawable->h;
537 }
538 else {
539 memset(&whandle, 0, sizeof(whandle));
540
541 /* Process DRI-provided buffers and get pipe_resources. */
542 for (i = 0; i < num_buffers; i++) {
543 __DRIbuffer *buf = &buffers[i];
544 enum st_attachment_type statt;
545 enum pipe_format format;
546
547 switch (buf->attachment) {
548 case __DRI_BUFFER_FRONT_LEFT:
549 if (!screen->auto_fake_front) {
550 continue; /* invalid attachment */
551 }
552 FALLTHROUGH;
553 case __DRI_BUFFER_FAKE_FRONT_LEFT:
554 statt = ST_ATTACHMENT_FRONT_LEFT;
555 break;
556 case __DRI_BUFFER_BACK_LEFT:
557 statt = ST_ATTACHMENT_BACK_LEFT;
558 break;
559 default:
560 continue; /* invalid attachment */
561 }
562
563 dri_drawable_get_format(drawable, statt, &format, &bind);
564 if (format == PIPE_FORMAT_NONE)
565 continue;
566
567 /* dri2_drawable_get_buffers has already filled dri_drawable->w
568 * and dri_drawable->h */
569 templ.width0 = drawable->w;
570 templ.height0 = drawable->h;
571 templ.format = format;
572 templ.bind = bind;
573 whandle.handle = buf->name;
574 whandle.stride = buf->pitch;
575 whandle.offset = 0;
576 whandle.format = format;
577 whandle.modifier = DRM_FORMAT_MOD_INVALID;
578 if (screen->can_share_buffer)
579 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
580 else
581 whandle.type = WINSYS_HANDLE_TYPE_KMS;
582 drawable->textures[statt] =
583 screen->base.screen->resource_from_handle(screen->base.screen,
584 &templ, &whandle,
585 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
586 assert(drawable->textures[statt]);
587 }
588 }
589
590 /* Allocate private MSAA colorbuffers. */
591 if (drawable->stvis.samples > 1) {
592 for (i = 0; i < statts_count; i++) {
593 enum st_attachment_type statt = statts[i];
594
595 if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
596 continue;
597
598 if (drawable->textures[statt]) {
599 templ.format = drawable->textures[statt]->format;
600 templ.bind = drawable->textures[statt]->bind &
601 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
602 templ.nr_samples = drawable->stvis.samples;
603 templ.nr_storage_samples = drawable->stvis.samples;
604
605 /* Try to reuse the resource.
606 * (the other resource parameters should be constant)
607 */
608 if (!drawable->msaa_textures[statt] ||
609 drawable->msaa_textures[statt]->width0 != templ.width0 ||
610 drawable->msaa_textures[statt]->height0 != templ.height0) {
611 /* Allocate a new one. */
612 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
613
614 drawable->msaa_textures[statt] =
615 screen->base.screen->resource_create(screen->base.screen,
616 &templ);
617 assert(drawable->msaa_textures[statt]);
618
619 /* If there are any MSAA resources, we should initialize them
620 * such that they contain the same data as the single-sample
621 * resources we just got from the X server.
622 *
623 * The reason for this is that the gallium frontend (and
624 * therefore the app) can access the MSAA resources only.
625 * The single-sample resources are not exposed
626 * to the gallium frontend.
627 *
628 */
629 dri_pipe_blit(ctx->st->pipe,
630 drawable->msaa_textures[statt],
631 drawable->textures[statt]);
632 }
633 }
634 else {
635 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
636 }
637 }
638 }
639
640 /* Allocate a private depth-stencil buffer. */
641 if (alloc_depthstencil) {
642 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
643 struct pipe_resource **zsbuf;
644 enum pipe_format format;
645 unsigned bind;
646
647 dri_drawable_get_format(drawable, statt, &format, &bind);
648
649 if (format) {
650 templ.format = format;
651 templ.bind = bind & ~PIPE_BIND_SHARED;
652
653 if (drawable->stvis.samples > 1) {
654 templ.nr_samples = drawable->stvis.samples;
655 templ.nr_storage_samples = drawable->stvis.samples;
656 zsbuf = &drawable->msaa_textures[statt];
657 }
658 else {
659 templ.nr_samples = 0;
660 templ.nr_storage_samples = 0;
661 zsbuf = &drawable->textures[statt];
662 }
663
664 /* Try to reuse the resource.
665 * (the other resource parameters should be constant)
666 */
667 if (!*zsbuf ||
668 (*zsbuf)->width0 != templ.width0 ||
669 (*zsbuf)->height0 != templ.height0) {
670 /* Allocate a new one. */
671 pipe_resource_reference(zsbuf, NULL);
672 *zsbuf = screen->base.screen->resource_create(screen->base.screen,
673 &templ);
674 assert(*zsbuf);
675 }
676 }
677 else {
678 pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
679 pipe_resource_reference(&drawable->textures[statt], NULL);
680 }
681 }
682
683 /* For DRI2, we may get the same buffers again from the server.
684 * To prevent useless imports of gem names, drawable->old* is used
685 * to bypass the import if we get the same buffers. This doesn't apply
686 * to DRI3/Wayland, users of image.loader, since the buffer is managed
687 * by the client (no import), and the back buffer is going to change
688 * at every redraw.
689 */
690 if (!image) {
691 drawable->old_num = num_buffers;
692 drawable->old_w = drawable->w;
693 drawable->old_h = drawable->h;
694 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
695 }
696 }
697
698 static bool
dri2_flush_frontbuffer(struct dri_context * ctx,struct dri_drawable * drawable,enum st_attachment_type statt)699 dri2_flush_frontbuffer(struct dri_context *ctx,
700 struct dri_drawable *drawable,
701 enum st_attachment_type statt)
702 {
703 const __DRIimageLoaderExtension *image = drawable->screen->image.loader;
704 const __DRIdri2LoaderExtension *loader = drawable->screen->dri2.loader;
705 const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader =
706 drawable->screen->mutableRenderBuffer.loader;
707 struct pipe_context *pipe = ctx->st->pipe;
708 struct pipe_fence_handle *fence = NULL;
709 int fence_fd = -1;
710
711 /* We need to flush for front buffer rendering when either we're using the
712 * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer
713 * has redirected GL_BACK to the front buffer.
714 */
715 if (statt != ST_ATTACHMENT_FRONT_LEFT &&
716 (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT))
717 return false;
718
719 /* Wait for glthread to finish because we can't use pipe_context from
720 * multiple threads.
721 */
722 _mesa_glthread_finish(ctx->st->ctx);
723
724 if (drawable->stvis.samples > 1) {
725 /* Resolve the buffer used for front rendering. */
726 dri_pipe_blit(ctx->st->pipe, drawable->textures[statt],
727 drawable->msaa_textures[statt]);
728 }
729
730 if (drawable->textures[statt]) {
731 pipe->flush_resource(pipe, drawable->textures[statt]);
732 }
733
734 if (ctx->is_shared_buffer_bound) {
735 /* is_shared_buffer_bound should only be true with image extension: */
736 assert(image);
737 pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD);
738 } else {
739 pipe->flush(pipe, NULL, 0);
740 }
741
742 if (image) {
743 image->flushFrontBuffer(opaque_dri_drawable(drawable),
744 drawable->loaderPrivate);
745 if (ctx->is_shared_buffer_bound) {
746 if (fence)
747 fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence);
748
749 shared_buffer_loader->displaySharedBuffer(opaque_dri_drawable(drawable),
750 fence_fd,
751 drawable->loaderPrivate);
752
753 pipe->screen->fence_reference(pipe->screen, &fence, NULL);
754 }
755 }
756 else if (loader->flushFrontBuffer) {
757 loader->flushFrontBuffer(opaque_dri_drawable(drawable),
758 drawable->loaderPrivate);
759 }
760
761 return true;
762 }
763
764 /**
765 * The struct dri_drawable flush_swapbuffers callback
766 */
767 static void
dri2_flush_swapbuffers(struct dri_context * ctx,struct dri_drawable * drawable)768 dri2_flush_swapbuffers(struct dri_context *ctx,
769 struct dri_drawable *drawable)
770 {
771 const __DRIimageLoaderExtension *image = drawable->screen->image.loader;
772
773 if (image && image->flushSwapBuffers) {
774 image->flushSwapBuffers(opaque_dri_drawable(drawable),
775 drawable->loaderPrivate);
776 }
777 }
778
779 static void
dri2_update_tex_buffer(struct dri_drawable * drawable,struct dri_context * ctx,struct pipe_resource * res)780 dri2_update_tex_buffer(struct dri_drawable *drawable,
781 struct dri_context *ctx,
782 struct pipe_resource *res)
783 {
784 /* no-op */
785 }
786
787 static const struct dri2_format_mapping r8_b8_g8_mapping = {
788 DRM_FORMAT_YVU420,
789 __DRI_IMAGE_FORMAT_NONE,
790 __DRI_IMAGE_COMPONENTS_Y_U_V,
791 PIPE_FORMAT_R8_B8_G8_420_UNORM,
792 3,
793 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
794 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 },
795 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 } }
796 };
797
798 static const struct dri2_format_mapping r8_g8_b8_mapping = {
799 DRM_FORMAT_YUV420,
800 __DRI_IMAGE_FORMAT_NONE,
801 __DRI_IMAGE_COMPONENTS_Y_U_V,
802 PIPE_FORMAT_R8_G8_B8_420_UNORM,
803 3,
804 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
805 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 },
806 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 } }
807 };
808
809 static const struct dri2_format_mapping r8_g8b8_mapping = {
810 DRM_FORMAT_NV12,
811 __DRI_IMAGE_FORMAT_NONE,
812 __DRI_IMAGE_COMPONENTS_Y_UV,
813 PIPE_FORMAT_R8_G8B8_420_UNORM,
814 2,
815 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
816 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }
817 };
818
819 static const struct dri2_format_mapping r8_b8g8_mapping = {
820 DRM_FORMAT_NV21,
821 __DRI_IMAGE_FORMAT_NONE,
822 __DRI_IMAGE_COMPONENTS_Y_UV,
823 PIPE_FORMAT_R8_B8G8_420_UNORM,
824 2,
825 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
826 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }
827 };
828
829 static const struct dri2_format_mapping r8g8_r8b8_mapping = {
830 DRM_FORMAT_YUYV,
831 __DRI_IMAGE_FORMAT_NONE,
832 __DRI_IMAGE_COMPONENTS_Y_XUXV,
833 PIPE_FORMAT_R8G8_R8B8_UNORM, 2,
834 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
835 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }
836 };
837
838 static const struct dri2_format_mapping r8b8_r8g8_mapping = {
839 DRM_FORMAT_YVYU,
840 __DRI_IMAGE_FORMAT_NONE,
841 __DRI_IMAGE_COMPONENTS_Y_XUXV,
842 PIPE_FORMAT_R8B8_R8G8_UNORM, 2,
843 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
844 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }
845 };
846
847 static const struct dri2_format_mapping b8r8_g8r8_mapping = {
848 DRM_FORMAT_VYUY,
849 __DRI_IMAGE_FORMAT_NONE,
850 __DRI_IMAGE_COMPONENTS_Y_XUXV,
851 PIPE_FORMAT_B8R8_G8R8_UNORM, 2,
852 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
853 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }
854 };
855
856 static const struct dri2_format_mapping g8r8_b8r8_mapping = {
857 DRM_FORMAT_UYVY,
858 __DRI_IMAGE_FORMAT_NONE,
859 __DRI_IMAGE_COMPONENTS_Y_XUXV,
860 PIPE_FORMAT_G8R8_B8R8_UNORM, 2,
861 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
862 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }
863 };
864
865 static enum __DRIFixedRateCompression
to_dri_compression_rate(uint32_t rate)866 to_dri_compression_rate(uint32_t rate)
867 {
868 switch (rate) {
869 case PIPE_COMPRESSION_FIXED_RATE_NONE:
870 return __DRI_FIXED_RATE_COMPRESSION_NONE;
871 case PIPE_COMPRESSION_FIXED_RATE_DEFAULT:
872 return __DRI_FIXED_RATE_COMPRESSION_DEFAULT;
873 case 1: return __DRI_FIXED_RATE_COMPRESSION_1BPC;
874 case 2: return __DRI_FIXED_RATE_COMPRESSION_2BPC;
875 case 3: return __DRI_FIXED_RATE_COMPRESSION_3BPC;
876 case 4: return __DRI_FIXED_RATE_COMPRESSION_4BPC;
877 case 5: return __DRI_FIXED_RATE_COMPRESSION_5BPC;
878 case 6: return __DRI_FIXED_RATE_COMPRESSION_6BPC;
879 case 7: return __DRI_FIXED_RATE_COMPRESSION_7BPC;
880 case 8: return __DRI_FIXED_RATE_COMPRESSION_8BPC;
881 case 9: return __DRI_FIXED_RATE_COMPRESSION_9BPC;
882 case 10: return __DRI_FIXED_RATE_COMPRESSION_10BPC;
883 case 11: return __DRI_FIXED_RATE_COMPRESSION_11BPC;
884 case 12: return __DRI_FIXED_RATE_COMPRESSION_12BPC;
885 default:
886 unreachable("invalid compression fixed-rate value");
887 }
888 }
889
890 static uint32_t
from_dri_compression_rate(enum __DRIFixedRateCompression rate)891 from_dri_compression_rate(enum __DRIFixedRateCompression rate)
892 {
893 switch (rate) {
894 case __DRI_FIXED_RATE_COMPRESSION_NONE:
895 return PIPE_COMPRESSION_FIXED_RATE_NONE;
896 case __DRI_FIXED_RATE_COMPRESSION_DEFAULT:
897 return PIPE_COMPRESSION_FIXED_RATE_DEFAULT;
898 case __DRI_FIXED_RATE_COMPRESSION_1BPC: return 1;
899 case __DRI_FIXED_RATE_COMPRESSION_2BPC: return 2;
900 case __DRI_FIXED_RATE_COMPRESSION_3BPC: return 3;
901 case __DRI_FIXED_RATE_COMPRESSION_4BPC: return 4;
902 case __DRI_FIXED_RATE_COMPRESSION_5BPC: return 5;
903 case __DRI_FIXED_RATE_COMPRESSION_6BPC: return 6;
904 case __DRI_FIXED_RATE_COMPRESSION_7BPC: return 7;
905 case __DRI_FIXED_RATE_COMPRESSION_8BPC: return 8;
906 case __DRI_FIXED_RATE_COMPRESSION_9BPC: return 9;
907 case __DRI_FIXED_RATE_COMPRESSION_10BPC: return 10;
908 case __DRI_FIXED_RATE_COMPRESSION_11BPC: return 11;
909 case __DRI_FIXED_RATE_COMPRESSION_12BPC: return 12;
910 default:
911 unreachable("invalid compression fixed-rate value");
912 }
913 }
914
915 static __DRIimage *
dri_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)916 dri_create_image_from_winsys(__DRIscreen *_screen,
917 int width, int height, const struct dri2_format_mapping *map,
918 int num_handles, struct winsys_handle *whandle,
919 unsigned bind,
920 void *loaderPrivate)
921 {
922 struct dri_screen *screen = dri_screen(_screen);
923 struct pipe_screen *pscreen = screen->base.screen;
924 __DRIimage *img;
925 struct pipe_resource templ;
926 unsigned tex_usage = 0;
927 int i;
928 bool use_lowered = false;
929 const unsigned format_planes = util_format_get_num_planes(map->pipe_format);
930
931 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
932 PIPE_BIND_RENDER_TARGET))
933 tex_usage |= PIPE_BIND_RENDER_TARGET;
934 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
935 PIPE_BIND_SAMPLER_VIEW))
936 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
937
938 /* For NV12, see if we have support for sampling r8_g8b8 */
939 if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 &&
940 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM,
941 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
942 map = &r8_g8b8_mapping;
943 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
944 }
945
946 /* For NV21, see if we have support for sampling r8_b8g8 */
947 if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV21 &&
948 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_B8G8_420_UNORM,
949 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
950 map = &r8_b8g8_mapping;
951 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
952 }
953
954 /* For YV12 and I420, see if we have support for sampling r8_b8_g8 or r8_g8_b8 */
955 if (!tex_usage && map->pipe_format == PIPE_FORMAT_IYUV) {
956 if (map->dri_fourcc == DRM_FORMAT_YUV420 &&
957 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8_B8_420_UNORM,
958 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
959 map = &r8_g8_b8_mapping;
960 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
961 } else if (map->dri_fourcc == DRM_FORMAT_YVU420 &&
962 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_B8_G8_420_UNORM,
963 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
964 map = &r8_b8_g8_mapping;
965 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
966 }
967 }
968
969 /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these
970 * can be used for YUYV and UYVY formats.
971 */
972 if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV &&
973 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM,
974 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
975 map = &r8g8_r8b8_mapping;
976 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
977 }
978
979 if (!tex_usage && map->pipe_format == PIPE_FORMAT_YVYU &&
980 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8B8_R8G8_UNORM,
981 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
982 map = &r8b8_r8g8_mapping;
983 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
984 }
985
986 if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY &&
987 pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM,
988 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
989 map = &g8r8_b8r8_mapping;
990 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
991 }
992
993 if (!tex_usage && map->pipe_format == PIPE_FORMAT_VYUY &&
994 pscreen->is_format_supported(pscreen, PIPE_FORMAT_B8R8_G8R8_UNORM,
995 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
996 map = &b8r8_g8r8_mapping;
997 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
998 }
999
1000 if (!tex_usage && util_format_is_yuv(map->pipe_format)) {
1001 /* YUV format sampling can be emulated by the GL gallium frontend by
1002 * using multiple samplers of varying formats.
1003 * If no tex_usage is set and we detect a YUV format,
1004 * test for support of all planes' sampler formats and
1005 * add sampler view usage.
1006 */
1007 use_lowered = true;
1008 if (dri2_yuv_dma_buf_supported(screen, map))
1009 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
1010 }
1011
1012 if (!tex_usage)
1013 return NULL;
1014
1015 img = CALLOC_STRUCT(__DRIimageRec);
1016 if (!img)
1017 return NULL;
1018
1019 memset(&templ, 0, sizeof(templ));
1020 templ.bind = tex_usage | bind;
1021 templ.target = screen->target;
1022 templ.last_level = 0;
1023 templ.depth0 = 1;
1024 templ.array_size = 1;
1025 templ.width0 = width;
1026 templ.height0 = height;
1027
1028 for (i = num_handles - 1; i >= format_planes; i--) {
1029 struct pipe_resource *tex;
1030
1031 templ.next = img->texture;
1032
1033 tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i],
1034 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
1035 if (!tex) {
1036 pipe_resource_reference(&img->texture, NULL);
1037 FREE(img);
1038 return NULL;
1039 }
1040
1041 img->texture = tex;
1042 }
1043
1044 for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) {
1045 struct pipe_resource *tex;
1046
1047 templ.next = img->texture;
1048 templ.width0 = width >> map->planes[i].width_shift;
1049 templ.height0 = height >> map->planes[i].height_shift;
1050 if (use_lowered)
1051 templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);
1052 else
1053 templ.format = map->pipe_format;
1054 assert(templ.format != PIPE_FORMAT_NONE);
1055
1056 tex = pscreen->resource_from_handle(pscreen,
1057 &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i],
1058 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
1059 if (!tex) {
1060 pipe_resource_reference(&img->texture, NULL);
1061 FREE(img);
1062 return NULL;
1063 }
1064
1065 /* Reject image creation if there's an inconsistency between
1066 * content protection status of tex and img.
1067 */
1068 const struct driOptionCache *optionCache = &screen->dev->option_cache;
1069 if (driQueryOptionb(optionCache, "force_protected_content_check") &&
1070 (tex->bind & PIPE_BIND_PROTECTED) != (bind & PIPE_BIND_PROTECTED)) {
1071 pipe_resource_reference(&img->texture, NULL);
1072 pipe_resource_reference(&tex, NULL);
1073 FREE(img);
1074 return NULL;
1075 }
1076
1077 img->texture = tex;
1078 }
1079
1080 img->level = 0;
1081 img->layer = 0;
1082 img->use = 0;
1083 img->in_fence_fd = -1;
1084 img->loader_private = loaderPrivate;
1085 img->screen = screen;
1086
1087 return img;
1088 }
1089
1090 static unsigned
dri2_get_modifier_num_planes(__DRIscreen * _screen,uint64_t modifier,int fourcc)1091 dri2_get_modifier_num_planes(__DRIscreen *_screen,
1092 uint64_t modifier, int fourcc)
1093 {
1094 struct pipe_screen *pscreen = dri_screen(_screen)->base.screen;
1095 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1096
1097 if (!map)
1098 return 0;
1099
1100 switch (modifier) {
1101 case DRM_FORMAT_MOD_LINEAR:
1102 /* DRM_FORMAT_MOD_NONE is the same as LINEAR */
1103 case DRM_FORMAT_MOD_INVALID:
1104 return util_format_get_num_planes(map->pipe_format);
1105 default:
1106 if (!pscreen->is_dmabuf_modifier_supported ||
1107 !pscreen->is_dmabuf_modifier_supported(pscreen, modifier,
1108 map->pipe_format, NULL)) {
1109 return 0;
1110 }
1111
1112 if (pscreen->get_dmabuf_modifier_planes) {
1113 return pscreen->get_dmabuf_modifier_planes(pscreen, modifier,
1114 map->pipe_format);
1115 }
1116
1117 return map->nplanes;
1118 }
1119 }
1120
1121 __DRIimage *
dri_create_image(__DRIscreen * _screen,int width,int height,int format,const uint64_t * modifiers,const unsigned _count,unsigned int use,void * loaderPrivate)1122 dri_create_image(__DRIscreen *_screen,
1123 int width, int height,
1124 int format,
1125 const uint64_t *modifiers,
1126 const unsigned _count,
1127 unsigned int use,
1128 void *loaderPrivate)
1129 {
1130 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1131 struct dri_screen *screen = dri_screen(_screen);
1132 struct pipe_screen *pscreen = screen->base.screen;
1133 __DRIimage *img;
1134 struct pipe_resource templ;
1135 unsigned tex_usage = 0;
1136 unsigned count = _count;
1137
1138 if (!map)
1139 return NULL;
1140
1141 if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) {
1142 count = 0;
1143 modifiers = NULL;
1144 }
1145
1146 if (!pscreen->resource_create_with_modifiers && count > 0) {
1147 bool invalid_ok = false;
1148 bool linear_ok = false;
1149
1150 for (unsigned i = 0; i < _count; i++) {
1151 if (modifiers[i] == DRM_FORMAT_MOD_LINEAR)
1152 linear_ok = true;
1153 else if (modifiers[i] == DRM_FORMAT_MOD_INVALID)
1154 invalid_ok = true;
1155 }
1156
1157 if (invalid_ok) {
1158 count = 0;
1159 modifiers = NULL;
1160 } else if (linear_ok) {
1161 count = 0;
1162 modifiers = NULL;
1163 use |= __DRI_IMAGE_USE_LINEAR;
1164 } else {
1165 return NULL;
1166 }
1167 }
1168
1169 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
1170 0, 0, PIPE_BIND_RENDER_TARGET))
1171 tex_usage |= PIPE_BIND_RENDER_TARGET;
1172 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
1173 0, 0, PIPE_BIND_SAMPLER_VIEW))
1174 tex_usage |= PIPE_BIND_SAMPLER_VIEW;
1175
1176 if (!tex_usage)
1177 return NULL;
1178
1179 if (use & __DRI_IMAGE_USE_SCANOUT)
1180 tex_usage |= PIPE_BIND_SCANOUT;
1181 if (use & __DRI_IMAGE_USE_SHARE)
1182 tex_usage |= PIPE_BIND_SHARED;
1183 if (use & __DRI_IMAGE_USE_LINEAR)
1184 tex_usage |= PIPE_BIND_LINEAR;
1185 if (use & __DRI_IMAGE_USE_CURSOR) {
1186 if (width != 64 || height != 64)
1187 return NULL;
1188 tex_usage |= PIPE_BIND_CURSOR;
1189 }
1190 if (use & __DRI_IMAGE_USE_PROTECTED)
1191 tex_usage |= PIPE_BIND_PROTECTED;
1192 if (use & __DRI_IMAGE_USE_PRIME_BUFFER)
1193 tex_usage |= PIPE_BIND_PRIME_BLIT_DST;
1194 if (use & __DRI_IMAGE_USE_FRONT_RENDERING)
1195 tex_usage |= PIPE_BIND_USE_FRONT_RENDERING;
1196
1197 img = CALLOC_STRUCT(__DRIimageRec);
1198 if (!img)
1199 return NULL;
1200
1201 memset(&templ, 0, sizeof(templ));
1202 templ.bind = tex_usage;
1203 templ.format = map->pipe_format;
1204 templ.target = PIPE_TEXTURE_2D;
1205 templ.last_level = 0;
1206 templ.width0 = width;
1207 templ.height0 = height;
1208 templ.depth0 = 1;
1209 templ.array_size = 1;
1210
1211 if (modifiers)
1212 img->texture =
1213 screen->base.screen
1214 ->resource_create_with_modifiers(screen->base.screen,
1215 &templ,
1216 modifiers,
1217 count);
1218 else
1219 img->texture =
1220 screen->base.screen->resource_create(screen->base.screen, &templ);
1221 if (!img->texture) {
1222 FREE(img);
1223 return NULL;
1224 }
1225
1226 img->level = 0;
1227 img->layer = 0;
1228 img->dri_format = format;
1229 img->dri_fourcc = map->dri_fourcc;
1230 img->dri_components = 0;
1231 img->use = use;
1232 img->in_fence_fd = -1;
1233
1234 img->loader_private = loaderPrivate;
1235 img->screen = screen;
1236 return img;
1237 }
1238
1239 static bool
dri2_query_image_common(__DRIimage * image,int attrib,int * value)1240 dri2_query_image_common(__DRIimage *image, int attrib, int *value)
1241 {
1242 switch (attrib) {
1243 case __DRI_IMAGE_ATTRIB_WIDTH:
1244 *value = image->texture->width0;
1245 return true;
1246 case __DRI_IMAGE_ATTRIB_HEIGHT:
1247 *value = image->texture->height0;
1248 return true;
1249 case __DRI_IMAGE_ATTRIB_COMPONENTS:
1250 if (image->dri_components == 0)
1251 return false;
1252 *value = image->dri_components;
1253 return true;
1254 case __DRI_IMAGE_ATTRIB_FOURCC:
1255 if (image->dri_fourcc) {
1256 *value = image->dri_fourcc;
1257 } else {
1258 const struct dri2_format_mapping *map;
1259
1260 map = dri2_get_mapping_by_format(image->dri_format);
1261 if (!map)
1262 return false;
1263
1264 *value = map->dri_fourcc;
1265 }
1266 return true;
1267 case __DRI_IMAGE_ATTRIB_COMPRESSION_RATE:
1268 if (!image->texture)
1269 *value = __DRI_FIXED_RATE_COMPRESSION_NONE;
1270 else
1271 *value = to_dri_compression_rate(image->texture->compression_rate);
1272 return true;
1273
1274 default:
1275 return false;
1276 }
1277 }
1278
1279 static bool
dri2_query_image_by_resource_handle(__DRIimage * image,int attrib,int * value)1280 dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value)
1281 {
1282 struct pipe_screen *pscreen = image->texture->screen;
1283 struct winsys_handle whandle;
1284 struct pipe_resource *tex;
1285 unsigned usage;
1286 memset(&whandle, 0, sizeof(whandle));
1287 whandle.plane = image->plane;
1288 int i;
1289
1290 switch (attrib) {
1291 case __DRI_IMAGE_ATTRIB_STRIDE:
1292 case __DRI_IMAGE_ATTRIB_OFFSET:
1293 case __DRI_IMAGE_ATTRIB_HANDLE:
1294 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1295 break;
1296 case __DRI_IMAGE_ATTRIB_NAME:
1297 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1298 break;
1299 case __DRI_IMAGE_ATTRIB_FD:
1300 whandle.type = WINSYS_HANDLE_TYPE_FD;
1301 break;
1302 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1303 for (i = 0, tex = image->texture; tex; tex = tex->next)
1304 i++;
1305 *value = i;
1306 return true;
1307 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1308 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1309 whandle.type = WINSYS_HANDLE_TYPE_KMS;
1310 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1311 break;
1312 default:
1313 return false;
1314 }
1315
1316 usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1317
1318 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1319 usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1320
1321 if (!pscreen->resource_get_handle(pscreen, NULL, image->texture,
1322 &whandle, usage))
1323 return false;
1324
1325 switch (attrib) {
1326 case __DRI_IMAGE_ATTRIB_STRIDE:
1327 *value = whandle.stride;
1328 return true;
1329 case __DRI_IMAGE_ATTRIB_OFFSET:
1330 *value = whandle.offset;
1331 return true;
1332 case __DRI_IMAGE_ATTRIB_HANDLE:
1333 case __DRI_IMAGE_ATTRIB_NAME:
1334 case __DRI_IMAGE_ATTRIB_FD:
1335 *value = whandle.handle;
1336 return true;
1337 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1338 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1339 return false;
1340 *value = (whandle.modifier >> 32) & 0xffffffff;
1341 return true;
1342 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1343 if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1344 return false;
1345 *value = whandle.modifier & 0xffffffff;
1346 return true;
1347 default:
1348 return false;
1349 }
1350 }
1351
1352 static bool
dri2_resource_get_param(__DRIimage * image,enum pipe_resource_param param,unsigned handle_usage,uint64_t * value)1353 dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param,
1354 unsigned handle_usage, uint64_t *value)
1355 {
1356 struct pipe_screen *pscreen = image->texture->screen;
1357 if (!pscreen->resource_get_param)
1358 return false;
1359
1360 if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1361 handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1362
1363 return pscreen->resource_get_param(pscreen, NULL, image->texture,
1364 image->plane, 0, 0, param, handle_usage,
1365 value);
1366 }
1367
1368 static bool
dri2_query_image_by_resource_param(__DRIimage * image,int attrib,int * value)1369 dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value)
1370 {
1371 enum pipe_resource_param param;
1372 uint64_t res_param;
1373 unsigned handle_usage;
1374
1375 if (!image->texture->screen->resource_get_param)
1376 return false;
1377
1378 switch (attrib) {
1379 case __DRI_IMAGE_ATTRIB_STRIDE:
1380 param = PIPE_RESOURCE_PARAM_STRIDE;
1381 break;
1382 case __DRI_IMAGE_ATTRIB_OFFSET:
1383 param = PIPE_RESOURCE_PARAM_OFFSET;
1384 break;
1385 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1386 param = PIPE_RESOURCE_PARAM_NPLANES;
1387 break;
1388 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1389 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1390 param = PIPE_RESOURCE_PARAM_MODIFIER;
1391 break;
1392 case __DRI_IMAGE_ATTRIB_HANDLE:
1393 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS;
1394 break;
1395 case __DRI_IMAGE_ATTRIB_NAME:
1396 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED;
1397 break;
1398 case __DRI_IMAGE_ATTRIB_FD:
1399 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD;
1400 break;
1401 default:
1402 return false;
1403 }
1404
1405 handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1406
1407 if (!dri2_resource_get_param(image, param, handle_usage, &res_param))
1408 return false;
1409
1410 switch (attrib) {
1411 case __DRI_IMAGE_ATTRIB_STRIDE:
1412 case __DRI_IMAGE_ATTRIB_OFFSET:
1413 case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1414 if (res_param > INT_MAX)
1415 return false;
1416 *value = (int)res_param;
1417 return true;
1418 case __DRI_IMAGE_ATTRIB_HANDLE:
1419 case __DRI_IMAGE_ATTRIB_NAME:
1420 case __DRI_IMAGE_ATTRIB_FD:
1421 if (res_param > UINT_MAX)
1422 return false;
1423 *value = (int)res_param;
1424 return true;
1425 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1426 if (res_param == DRM_FORMAT_MOD_INVALID)
1427 return false;
1428 *value = (res_param >> 32) & 0xffffffff;
1429 return true;
1430 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1431 if (res_param == DRM_FORMAT_MOD_INVALID)
1432 return false;
1433 *value = res_param & 0xffffffff;
1434 return true;
1435 default:
1436 return false;
1437 }
1438 }
1439
1440 GLboolean
dri2_query_image(__DRIimage * image,int attrib,int * value)1441 dri2_query_image(__DRIimage *image, int attrib, int *value)
1442 {
1443 if (dri2_query_image_common(image, attrib, value))
1444 return GL_TRUE;
1445 else if (dri2_query_image_by_resource_param(image, attrib, value))
1446 return GL_TRUE;
1447 else if (dri2_query_image_by_resource_handle(image, attrib, value))
1448 return GL_TRUE;
1449 else
1450 return GL_FALSE;
1451 }
1452
1453 __DRIimage *
dri2_dup_image(__DRIimage * image,void * loaderPrivate)1454 dri2_dup_image(__DRIimage *image, void *loaderPrivate)
1455 {
1456 __DRIimage *img;
1457
1458 img = CALLOC_STRUCT(__DRIimageRec);
1459 if (!img)
1460 return NULL;
1461
1462 img->texture = NULL;
1463 pipe_resource_reference(&img->texture, image->texture);
1464 img->level = image->level;
1465 img->layer = image->layer;
1466 img->dri_format = image->dri_format;
1467 img->internal_format = image->internal_format;
1468 /* This should be 0 for sub images, but dup is also used for base images. */
1469 img->dri_components = image->dri_components;
1470 img->use = image->use;
1471 img->in_fence_fd = (image->in_fence_fd > 0) ?
1472 os_dupfd_cloexec(image->in_fence_fd) : -1;
1473 img->loader_private = loaderPrivate;
1474 img->screen = image->screen;
1475
1476 return img;
1477 }
1478
1479 GLboolean
dri2_validate_usage(__DRIimage * image,unsigned int use)1480 dri2_validate_usage(__DRIimage *image, unsigned int use)
1481 {
1482 if (!image || !image->texture)
1483 return false;
1484
1485 struct pipe_screen *screen = image->texture->screen;
1486 if (!screen->check_resource_capability)
1487 return true;
1488
1489 /* We don't want to check these:
1490 * __DRI_IMAGE_USE_SHARE (all images are shareable)
1491 * __DRI_IMAGE_USE_BACKBUFFER (all images support this)
1492 */
1493 unsigned bind = 0;
1494 if (use & __DRI_IMAGE_USE_SCANOUT)
1495 bind |= PIPE_BIND_SCANOUT;
1496 if (use & __DRI_IMAGE_USE_LINEAR)
1497 bind |= PIPE_BIND_LINEAR;
1498 if (use & __DRI_IMAGE_USE_CURSOR)
1499 bind |= PIPE_BIND_CURSOR;
1500
1501 if (!bind)
1502 return true;
1503
1504 return screen->check_resource_capability(screen, image->texture, bind);
1505 }
1506
1507 __DRIimage *
dri2_from_names(__DRIscreen * screen,int width,int height,int fourcc,int * names,int num_names,int * strides,int * offsets,void * loaderPrivate)1508 dri2_from_names(__DRIscreen *screen, int width, int height, int fourcc,
1509 int *names, int num_names, int *strides, int *offsets,
1510 void *loaderPrivate)
1511 {
1512 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1513 __DRIimage *img;
1514 struct winsys_handle whandle;
1515
1516 if (!map)
1517 return NULL;
1518
1519 if (num_names != 1)
1520 return NULL;
1521
1522 memset(&whandle, 0, sizeof(whandle));
1523 whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1524 whandle.handle = names[0];
1525 whandle.stride = strides[0];
1526 whandle.offset = offsets[0];
1527 whandle.format = map->pipe_format;
1528 whandle.modifier = DRM_FORMAT_MOD_INVALID;
1529
1530 img = dri_create_image_from_winsys(screen, width, height, map,
1531 1, &whandle, 0, loaderPrivate);
1532 if (img == NULL)
1533 return NULL;
1534
1535 img->dri_components = map->dri_components;
1536 img->dri_fourcc = map->dri_fourcc;
1537 img->dri_format = map->dri_format;
1538
1539 return img;
1540 }
1541
1542 __DRIimage *
dri2_from_planar(__DRIimage * image,int plane,void * loaderPrivate)1543 dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1544 {
1545 __DRIimage *img;
1546
1547 if (plane < 0) {
1548 return NULL;
1549 } else if (plane > 0) {
1550 uint64_t planes;
1551 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0,
1552 &planes) ||
1553 plane >= planes) {
1554 return NULL;
1555 }
1556 }
1557
1558 if (image->dri_components == 0) {
1559 uint64_t modifier;
1560 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0,
1561 &modifier) ||
1562 modifier == DRM_FORMAT_MOD_INVALID) {
1563 return NULL;
1564 }
1565 }
1566
1567 img = dri2_dup_image(image, loaderPrivate);
1568 if (img == NULL)
1569 return NULL;
1570
1571 if (img->texture->screen->resource_changed)
1572 img->texture->screen->resource_changed(img->texture->screen,
1573 img->texture);
1574
1575 /* set this to 0 for sub images. */
1576 img->dri_components = 0;
1577 img->plane = plane;
1578 return img;
1579 }
1580
1581 bool
dri_query_dma_buf_modifiers(__DRIscreen * _screen,int fourcc,int max,uint64_t * modifiers,unsigned int * external_only,int * count)1582 dri_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1583 uint64_t *modifiers, unsigned int *external_only,
1584 int *count)
1585 {
1586 struct dri_screen *screen = dri_screen(_screen);
1587 struct pipe_screen *pscreen = screen->base.screen;
1588 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1589 enum pipe_format format;
1590
1591 if (!map)
1592 return false;
1593
1594 format = map->pipe_format;
1595
1596 bool native_sampling = pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1597 PIPE_BIND_SAMPLER_VIEW);
1598 if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1599 PIPE_BIND_RENDER_TARGET) ||
1600 native_sampling ||
1601 dri2_yuv_dma_buf_supported(screen, map)) {
1602 if (pscreen->query_dmabuf_modifiers != NULL) {
1603 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1604 external_only, count);
1605 if (!native_sampling && external_only) {
1606 /* To support it using YUV lowering, we need it to be samplerExternalOES.
1607 */
1608 for (int i = 0; i < *count; i++)
1609 external_only[i] = true;
1610 }
1611 } else {
1612 *count = 0;
1613 }
1614 return true;
1615 }
1616 return false;
1617 }
1618
1619 bool
dri2_query_dma_buf_format_modifier_attribs(__DRIscreen * _screen,uint32_t fourcc,uint64_t modifier,int attrib,uint64_t * value)1620 dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen,
1621 uint32_t fourcc, uint64_t modifier,
1622 int attrib, uint64_t *value)
1623 {
1624 struct dri_screen *screen = dri_screen(_screen);
1625 struct pipe_screen *pscreen = screen->base.screen;
1626
1627 if (!pscreen->query_dmabuf_modifiers)
1628 return false;
1629
1630 switch (attrib) {
1631 case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: {
1632 uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier,
1633 fourcc);
1634 if (mod_planes > 0)
1635 *value = mod_planes;
1636 return mod_planes > 0;
1637 }
1638 default:
1639 return false;
1640 }
1641 }
1642
1643 __DRIimage *
dri2_from_dma_bufs(__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 dri_flags,unsigned * error,void * loaderPrivate)1644 dri2_from_dma_bufs(__DRIscreen *screen,
1645 int width, int height, int fourcc,
1646 uint64_t modifier, int *fds, int num_fds,
1647 int *strides, int *offsets,
1648 enum __DRIYUVColorSpace yuv_color_space,
1649 enum __DRISampleRange sample_range,
1650 enum __DRIChromaSiting horizontal_siting,
1651 enum __DRIChromaSiting vertical_siting,
1652 uint32_t dri_flags,
1653 unsigned *error,
1654 void *loaderPrivate)
1655 {
1656 __DRIimage *img;
1657 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1658
1659 if (!dri_screen(screen)->dmabuf_import) {
1660 if (error)
1661 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER;
1662 return NULL;
1663 }
1664
1665 unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
1666 /* Allow a NULL error arg since many callers don't care. */
1667 unsigned unused_error;
1668 if (!error)
1669 error = &unused_error;
1670
1671 uint32_t flags = 0;
1672 if (dri_flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG)
1673 flags |= PIPE_BIND_PROTECTED;
1674 if (dri_flags & __DRI_IMAGE_PRIME_LINEAR_BUFFER)
1675 flags |= PIPE_BIND_PRIME_BLIT_DST;
1676
1677 const int expected_num_fds = dri2_get_modifier_num_planes(screen, modifier, fourcc);
1678 if (!map || expected_num_fds == 0) {
1679 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1680 goto exit;
1681 }
1682
1683 if (num_fds != expected_num_fds) {
1684 err = __DRI_IMAGE_ERROR_BAD_MATCH;
1685 goto exit;
1686 }
1687
1688 struct winsys_handle whandles[4];
1689 memset(whandles, 0, sizeof(whandles));
1690
1691 for (int i = 0; i < num_fds; i++) {
1692 if (fds[i] < 0) {
1693 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1694 goto exit;
1695 }
1696
1697 whandles[i].type = WINSYS_HANDLE_TYPE_FD;
1698 whandles[i].handle = (unsigned)fds[i];
1699 whandles[i].stride = (unsigned)strides[i];
1700 whandles[i].offset = (unsigned)offsets[i];
1701 whandles[i].format = map->pipe_format;
1702 whandles[i].modifier = modifier;
1703 whandles[i].plane = i;
1704 }
1705
1706 img = dri_create_image_from_winsys(screen, width, height, map,
1707 num_fds, whandles, flags,
1708 loaderPrivate);
1709 if (img == NULL) {
1710 err = __DRI_IMAGE_ERROR_BAD_ALLOC;
1711 goto exit;
1712 }
1713
1714 img->dri_components = map->dri_components;
1715 img->dri_fourcc = fourcc;
1716 img->dri_format = map->dri_format;
1717 img->imported_dmabuf = true;
1718 img->yuv_color_space = yuv_color_space;
1719 img->sample_range = sample_range;
1720 img->horizontal_siting = horizontal_siting;
1721 img->vertical_siting = vertical_siting;
1722
1723 *error = __DRI_IMAGE_ERROR_SUCCESS;
1724 return img;
1725
1726 exit:
1727 *error = err;
1728 return NULL;
1729 }
1730
1731 bool
dri2_query_compression_rates(__DRIscreen * _screen,const __DRIconfig * config,int max,enum __DRIFixedRateCompression * rates,int * count)1732 dri2_query_compression_rates(__DRIscreen *_screen, const __DRIconfig *config, int max,
1733 enum __DRIFixedRateCompression *rates, int *count)
1734 {
1735 struct dri_screen *screen = dri_screen(_screen);
1736 struct pipe_screen *pscreen = screen->base.screen;
1737 struct gl_config *gl_config = (struct gl_config *) config;
1738 enum pipe_format format = gl_config->color_format;
1739 uint32_t pipe_rates[max];
1740
1741 if (!pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1742 PIPE_BIND_RENDER_TARGET))
1743 return false;
1744
1745 if (pscreen->query_compression_rates != NULL) {
1746 pscreen->query_compression_rates(pscreen, format, max, pipe_rates, count);
1747 for (int i = 0; i < *count && i < max; ++i)
1748 rates[i] = to_dri_compression_rate(pipe_rates[i]);
1749 } else {
1750 *count = 0;
1751 }
1752
1753 return true;
1754 }
1755
1756 bool
dri2_query_compression_modifiers(__DRIscreen * _screen,uint32_t fourcc,enum __DRIFixedRateCompression rate,int max,uint64_t * modifiers,int * count)1757 dri2_query_compression_modifiers(__DRIscreen *_screen, uint32_t fourcc,
1758 enum __DRIFixedRateCompression rate, int max,
1759 uint64_t *modifiers, int *count)
1760 {
1761 struct dri_screen *screen = dri_screen(_screen);
1762 struct pipe_screen *pscreen = screen->base.screen;
1763 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1764 uint32_t pipe_rate = from_dri_compression_rate(rate);
1765
1766 if (!map)
1767 return false;
1768
1769 if (!pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
1770 0, 0, PIPE_BIND_RENDER_TARGET))
1771 return false;
1772
1773 if (pscreen->query_compression_modifiers != NULL) {
1774 pscreen->query_compression_modifiers(pscreen, map->pipe_format, pipe_rate,
1775 max, modifiers, count);
1776 } else {
1777 *count = 0;
1778 }
1779
1780 return true;
1781 }
1782
1783 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)1784 dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1785 int dstx0, int dsty0, int dstwidth, int dstheight,
1786 int srcx0, int srcy0, int srcwidth, int srcheight,
1787 int flush_flag)
1788 {
1789 struct dri_context *ctx = dri_context(context);
1790 struct pipe_context *pipe = ctx->st->pipe;
1791 struct pipe_screen *screen;
1792 struct pipe_fence_handle *fence;
1793 struct pipe_blit_info blit;
1794
1795 if (!dst || !src)
1796 return;
1797
1798 /* Wait for glthread to finish because we can't use pipe_context from
1799 * multiple threads.
1800 */
1801 _mesa_glthread_finish(ctx->st->ctx);
1802
1803 dri_image_fence_sync(ctx, dst);
1804
1805 memset(&blit, 0, sizeof(blit));
1806 blit.dst.resource = dst->texture;
1807 blit.dst.box.x = dstx0;
1808 blit.dst.box.y = dsty0;
1809 blit.dst.box.width = dstwidth;
1810 blit.dst.box.height = dstheight;
1811 blit.dst.box.depth = 1;
1812 blit.dst.format = dst->texture->format;
1813 blit.src.resource = src->texture;
1814 blit.src.box.x = srcx0;
1815 blit.src.box.y = srcy0;
1816 blit.src.box.width = srcwidth;
1817 blit.src.box.height = srcheight;
1818 blit.src.box.depth = 1;
1819 blit.src.format = src->texture->format;
1820 blit.mask = PIPE_MASK_RGBA;
1821 blit.filter = PIPE_TEX_FILTER_NEAREST;
1822
1823 pipe->blit(pipe, &blit);
1824
1825 if (flush_flag == __BLIT_FLAG_FLUSH) {
1826 pipe->flush_resource(pipe, dst->texture);
1827 st_context_flush(ctx->st, 0, NULL, NULL, NULL);
1828 } else if (flush_flag == __BLIT_FLAG_FINISH) {
1829 screen = ctx->screen->base.screen;
1830 pipe->flush_resource(pipe, dst->texture);
1831 st_context_flush(ctx->st, 0, &fence, NULL, NULL);
1832 (void) screen->fence_finish(screen, NULL, fence, OS_TIMEOUT_INFINITE);
1833 screen->fence_reference(screen, &fence, NULL);
1834 }
1835 }
1836
1837 void *
dri2_map_image(__DRIcontext * context,__DRIimage * image,int x0,int y0,int width,int height,unsigned int flags,int * stride,void ** data)1838 dri2_map_image(__DRIcontext *context, __DRIimage *image,
1839 int x0, int y0, int width, int height,
1840 unsigned int flags, int *stride, void **data)
1841 {
1842 struct dri_context *ctx = dri_context(context);
1843 struct pipe_context *pipe = ctx->st->pipe;
1844 enum pipe_map_flags pipe_access = 0;
1845 struct pipe_transfer *trans;
1846 void *map;
1847
1848 if (!image || !data || *data)
1849 return NULL;
1850
1851 unsigned plane = image->plane;
1852 if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes)
1853 return NULL;
1854
1855 /* Wait for glthread to finish because we can't use pipe_context from
1856 * multiple threads.
1857 */
1858 _mesa_glthread_finish(ctx->st->ctx);
1859
1860 dri_image_fence_sync(ctx, image);
1861
1862 struct pipe_resource *resource = image->texture;
1863 while (plane--)
1864 resource = resource->next;
1865
1866 if (flags & __DRI_IMAGE_TRANSFER_READ)
1867 pipe_access |= PIPE_MAP_READ;
1868 if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1869 pipe_access |= PIPE_MAP_WRITE;
1870
1871 map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0,
1872 width, height, &trans);
1873 if (map) {
1874 *data = trans;
1875 *stride = trans->stride;
1876 }
1877
1878 return map;
1879 }
1880
1881 void
dri2_unmap_image(__DRIcontext * context,__DRIimage * image,void * data)1882 dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1883 {
1884 struct dri_context *ctx = dri_context(context);
1885 struct pipe_context *pipe = ctx->st->pipe;
1886
1887 /* Wait for glthread to finish because we can't use pipe_context from
1888 * multiple threads.
1889 */
1890 _mesa_glthread_finish(ctx->st->ctx);
1891
1892 pipe_texture_unmap(pipe, (struct pipe_transfer *)data);
1893 }
1894
1895 int
dri2_get_capabilities(__DRIscreen * _screen)1896 dri2_get_capabilities(__DRIscreen *_screen)
1897 {
1898 struct dri_screen *screen = dri_screen(_screen);
1899
1900 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1901 }
1902
1903 int
dri_interop_query_device_info(__DRIcontext * _ctx,struct mesa_glinterop_device_info * out)1904 dri_interop_query_device_info(__DRIcontext *_ctx,
1905 struct mesa_glinterop_device_info *out)
1906 {
1907 return st_interop_query_device_info(dri_context(_ctx)->st, out);
1908 }
1909
1910 int
dri_interop_export_object(__DRIcontext * _ctx,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)1911 dri_interop_export_object(__DRIcontext *_ctx,
1912 struct mesa_glinterop_export_in *in,
1913 struct mesa_glinterop_export_out *out)
1914 {
1915 return st_interop_export_object(dri_context(_ctx)->st, in, out);
1916 }
1917
1918 int
dri_interop_flush_objects(__DRIcontext * _ctx,unsigned count,struct mesa_glinterop_export_in * objects,struct mesa_glinterop_flush_out * out)1919 dri_interop_flush_objects(__DRIcontext *_ctx,
1920 unsigned count, struct mesa_glinterop_export_in *objects,
1921 struct mesa_glinterop_flush_out *out)
1922 {
1923 return st_interop_flush_objects(dri_context(_ctx)->st, count, objects, out);
1924 }
1925
1926 /**
1927 * \brief the DRI2bufferDamageExtension set_damage_region method
1928 */
1929 void
dri_set_damage_region(__DRIdrawable * dPriv,unsigned int nrects,int * rects)1930 dri_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects)
1931 {
1932 struct dri_drawable *drawable = dri_drawable(dPriv);
1933 struct pipe_box *boxes = NULL;
1934
1935 if (nrects) {
1936 boxes = CALLOC(nrects, sizeof(*boxes));
1937 assert(boxes);
1938
1939 for (unsigned int i = 0; i < nrects; i++) {
1940 int *rect = &rects[i * 4];
1941
1942 u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]);
1943 }
1944 }
1945
1946 FREE(drawable->damage_rects);
1947 drawable->damage_rects = boxes;
1948 drawable->num_damage_rects = nrects;
1949
1950 /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */
1951 if (drawable->texture_stamp == drawable->lastStamp &&
1952 (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) {
1953 struct pipe_screen *screen = drawable->screen->base.screen;
1954 struct pipe_resource *resource;
1955
1956 if (drawable->stvis.samples > 1)
1957 resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT];
1958 else
1959 resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
1960
1961 screen->set_damage_region(screen, resource,
1962 drawable->num_damage_rects,
1963 drawable->damage_rects);
1964 }
1965 }
1966
1967 /**
1968 * \brief the DRI2blobExtension set_cache_funcs method
1969 */
1970 void
dri_set_blob_cache_funcs(__DRIscreen * sPriv,__DRIblobCacheSet set,__DRIblobCacheGet get)1971 dri_set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set,
1972 __DRIblobCacheGet get)
1973 {
1974 struct dri_screen *screen = dri_screen(sPriv);
1975 struct pipe_screen *pscreen = screen->base.screen;
1976
1977 if (!pscreen->get_disk_shader_cache)
1978 return;
1979
1980 struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen);
1981
1982 if (!cache)
1983 return;
1984
1985 disk_cache_set_callbacks(cache, set, get);
1986 }
1987
1988 /*
1989 * Backend function init_screen.
1990 */
1991
1992 void
dri2_init_drawable(struct dri_drawable * drawable,bool isPixmap,int alphaBits)1993 dri2_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits)
1994 {
1995 drawable->allocate_textures = dri2_allocate_textures;
1996 drawable->flush_frontbuffer = dri2_flush_frontbuffer;
1997 drawable->update_tex_buffer = dri2_update_tex_buffer;
1998 drawable->flush_swapbuffers = dri2_flush_swapbuffers;
1999 }
2000
2001 /**
2002 * This is the driver specific part of the createNewScreen entry point.
2003 *
2004 * Returns the struct gl_config supported by this driver.
2005 */
2006 struct pipe_screen *
dri2_init_screen(struct dri_screen * screen,bool driver_name_is_inferred)2007 dri2_init_screen(struct dri_screen *screen, bool driver_name_is_inferred)
2008 {
2009 struct pipe_screen *pscreen = NULL;
2010
2011 screen->can_share_buffer = true;
2012 screen->auto_fake_front = dri_with_format(screen);
2013
2014 #ifdef HAVE_LIBDRM
2015 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, false))
2016 pscreen = pipe_loader_create_screen(screen->dev, driver_name_is_inferred);
2017 #endif
2018
2019 return pscreen;
2020 }
2021
2022 /**
2023 * This is the driver specific part of the createNewScreen entry point.
2024 *
2025 * Returns the struct gl_config supported by this driver.
2026 */
2027 struct pipe_screen *
dri_swrast_kms_init_screen(struct dri_screen * screen,bool driver_name_is_inferred)2028 dri_swrast_kms_init_screen(struct dri_screen *screen, bool driver_name_is_inferred)
2029 {
2030 struct pipe_screen *pscreen = NULL;
2031 screen->can_share_buffer = false;
2032 screen->auto_fake_front = dri_with_format(screen);
2033
2034 #if defined(HAVE_DRISW_KMS) && defined(HAVE_SWRAST)
2035 if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd))
2036 pscreen = pipe_loader_create_screen(screen->dev, driver_name_is_inferred);
2037 #endif
2038
2039 return pscreen;
2040 }
2041
2042 int
dri_query_compatible_render_only_device_fd(int kms_only_fd)2043 dri_query_compatible_render_only_device_fd(int kms_only_fd)
2044 {
2045 #ifdef HAVE_LIBDRM
2046 return pipe_loader_get_compatible_render_capable_device_fd(kms_only_fd);
2047 #else
2048 return -1;
2049 #endif
2050 }
2051 /* vim: set sw=3 ts=8 sts=3 expandtab: */
2052