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