OSDN Git Service

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