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