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