OSDN Git Service

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