• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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