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
55static 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 */
114static 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
144static 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 */
178static void
179dri2_flush_drawable(__DRIdrawable *dPriv)
180{
181   dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
182}
183
184static void
185dri2_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
196static 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 */
207static __DRIbuffer *
208dri2_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
303static bool
304dri_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
357static __DRIbuffer *
358dri2_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
440static void
441dri2_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
453static void
454dri2_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
726static void
727dri2_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
760static void
761dri2_update_tex_buffer(struct dri_drawable *drawable,
762                       struct dri_context *ctx,
763                       struct pipe_resource *res)
764{
765   /* no-op */
766}
767
768static __DRIimage *
769dri2_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
783static __DRIimage *
784dri2_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
861static __DRIimage *
862dri2_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
883static __DRIimage *
884dri2_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
947exit:
948   if (error)
949      *error = err;
950
951   return img;
952}
953
954static __DRIimage *
955dri2_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
967static __DRIimage *
968dri2_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
1025static GLboolean
1026dri2_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
1090static __DRIimage *
1091dri2_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
1111static GLboolean
1112dri2_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
1125static __DRIimage *
1126dri2_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
1156static __DRIimage *
1157dri2_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
1176static __DRIimage *
1177dri2_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
1242static __DRIimage *
1243dri2_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
1260static __DRIimage *
1261dri2_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
1291static void
1292dri2_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
1338static void *
1339dri2_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
1368static void
1369dri2_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
1377static void
1378dri2_destroy_image(__DRIimage *img)
1379{
1380   pipe_resource_reference(&img->texture, NULL);
1381   FREE(img);
1382}
1383
1384static int
1385dri2_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 */
1393static __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
1415static bool
1416dri2_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
1424static bool
1425dri2_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
1454struct dri2_fence {
1455   struct dri_screen *driscreen;
1456   struct pipe_fence_handle *pipe_fence;
1457   void *cl_event;
1458};
1459
1460static 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
1472static void *
1473dri2_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
1492static void *
1493dri2_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
1515static int
1516dri2_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
1525static void *
1526dri2_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
1549static void
1550dri2_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
1566static GLboolean
1567dri2_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
1593static void
1594dri2_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
1603static __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
1616static const __DRIrobustnessExtension dri2Robustness = {
1617   .base = { __DRI2_ROBUSTNESS, 1 }
1618};
1619
1620static int
1621dri2_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
1644static int
1645dri2_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, 0)) {
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
1873static 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
1883static 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
1895static 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 */
1913static const __DRIconfig **
1914dri2_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   if (pipe_loader_drm_probe_fd(&screen->dev, fd))
1937      pscreen = pipe_loader_create_screen(screen->dev);
1938
1939   if (!pscreen)
1940       goto release_pipe;
1941
1942   throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE);
1943   dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD);
1944
1945   if (throttle_ret && throttle_ret->val.val_int != -1) {
1946      screen->throttling_enabled = TRUE;
1947      screen->default_throttle_frames = throttle_ret->val.val_int;
1948   }
1949
1950   if (dmabuf_ret && dmabuf_ret->val.val_bool) {
1951      uint64_t cap;
1952
1953      if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1954          (cap & DRM_PRIME_CAP_IMPORT)) {
1955         dri2ImageExtension.createImageFromFds = dri2_from_fds;
1956         dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1957      }
1958   }
1959
1960   if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
1961      sPriv->extensions = dri_robust_screen_extensions;
1962      screen->has_reset_status_query = true;
1963   }
1964   else
1965      sPriv->extensions = dri_screen_extensions;
1966
1967   configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name);
1968   if (!configs)
1969      goto destroy_screen;
1970
1971   screen->can_share_buffer = true;
1972   screen->auto_fake_front = dri_with_format(sPriv);
1973   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1974   screen->lookup_egl_image = dri2_lookup_egl_image;
1975
1976   return configs;
1977
1978destroy_screen:
1979   dri_destroy_screen_helper(screen);
1980
1981release_pipe:
1982   if (screen->dev)
1983      pipe_loader_release(&screen->dev, 1);
1984   else
1985      close(fd);
1986
1987free_screen:
1988   FREE(screen);
1989   return NULL;
1990}
1991
1992/**
1993 * This is the driver specific part of the createNewScreen entry point.
1994 *
1995 * Returns the struct gl_config supported by this driver.
1996 */
1997static const __DRIconfig **
1998dri_kms_init_screen(__DRIscreen * sPriv)
1999{
2000#if defined(GALLIUM_SOFTPIPE)
2001   const __DRIconfig **configs;
2002   struct dri_screen *screen;
2003   struct pipe_screen *pscreen = NULL;
2004   uint64_t cap;
2005   int fd;
2006
2007   screen = CALLOC_STRUCT(dri_screen);
2008   if (!screen)
2009      return NULL;
2010
2011   screen->sPriv = sPriv;
2012   screen->fd = sPriv->fd;
2013
2014   sPriv->driverPrivate = (void *)screen;
2015
2016   if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0)
2017      goto free_screen;
2018
2019   if (pipe_loader_sw_probe_kms(&screen->dev, fd))
2020      pscreen = pipe_loader_create_screen(screen->dev);
2021
2022   if (!pscreen)
2023       goto release_pipe;
2024
2025   if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2026          (cap & DRM_PRIME_CAP_IMPORT)) {
2027      dri2ImageExtension.createImageFromFds = dri2_from_fds;
2028      dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2029   }
2030
2031   sPriv->extensions = dri_screen_extensions;
2032
2033   configs = dri_init_screen_helper(screen, pscreen, "swrast");
2034   if (!configs)
2035      goto destroy_screen;
2036
2037   screen->can_share_buffer = false;
2038   screen->auto_fake_front = dri_with_format(sPriv);
2039   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2040   screen->lookup_egl_image = dri2_lookup_egl_image;
2041
2042   return configs;
2043
2044destroy_screen:
2045   dri_destroy_screen_helper(screen);
2046
2047release_pipe:
2048   if (screen->dev)
2049      pipe_loader_release(&screen->dev, 1);
2050   else
2051      close(fd);
2052
2053free_screen:
2054   FREE(screen);
2055#endif // GALLIUM_SOFTPIPE
2056   return NULL;
2057}
2058
2059static boolean
2060dri2_create_buffer(__DRIscreen * sPriv,
2061                   __DRIdrawable * dPriv,
2062                   const struct gl_config * visual, boolean isPixmap)
2063{
2064   struct dri_drawable *drawable = NULL;
2065
2066   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
2067      return FALSE;
2068
2069   drawable = dPriv->driverPrivate;
2070
2071   drawable->allocate_textures = dri2_allocate_textures;
2072   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2073   drawable->update_tex_buffer = dri2_update_tex_buffer;
2074
2075   return TRUE;
2076}
2077
2078/**
2079 * DRI driver virtual function table.
2080 *
2081 * DRI versions differ in their implementation of init_screen and swap_buffers.
2082 */
2083const struct __DriverAPIRec galliumdrm_driver_api = {
2084   .InitScreen = dri2_init_screen,
2085   .DestroyScreen = dri_destroy_screen,
2086   .CreateContext = dri_create_context,
2087   .DestroyContext = dri_destroy_context,
2088   .CreateBuffer = dri2_create_buffer,
2089   .DestroyBuffer = dri_destroy_buffer,
2090   .MakeCurrent = dri_make_current,
2091   .UnbindContext = dri_unbind_context,
2092
2093   .AllocateBuffer = dri2_allocate_buffer,
2094   .ReleaseBuffer  = dri2_release_buffer,
2095};
2096
2097/**
2098 * DRI driver virtual function table.
2099 *
2100 * KMS/DRM version of the DriverAPI above sporting a different InitScreen
2101 * hook. The latter is used to explicitly initialise the kms_swrast driver
2102 * rather than selecting the approapriate driver as suggested by the loader.
2103 */
2104const struct __DriverAPIRec dri_kms_driver_api = {
2105   .InitScreen = dri_kms_init_screen,
2106   .DestroyScreen = dri_destroy_screen,
2107   .CreateContext = dri_create_context,
2108   .DestroyContext = dri_destroy_context,
2109   .CreateBuffer = dri2_create_buffer,
2110   .DestroyBuffer = dri_destroy_buffer,
2111   .MakeCurrent = dri_make_current,
2112   .UnbindContext = dri_unbind_context,
2113
2114   .AllocateBuffer = dri2_allocate_buffer,
2115   .ReleaseBuffer  = dri2_release_buffer,
2116};
2117
2118/* This is the table of extensions that the loader will dlsym() for. */
2119const __DRIextension *galliumdrm_driver_extensions[] = {
2120    &driCoreExtension.base,
2121    &driImageDriverExtension.base,
2122    &driDRI2Extension.base,
2123    &gallium_config_options.base,
2124    &dri2FenceExtension.base,
2125    NULL
2126};
2127
2128/* vim: set sw=3 ts=8 sts=3 expandtab: */
2129