17ec681f3Smrg/*
27ec681f3Smrg * Mesa 3-D graphics library
37ec681f3Smrg *
47ec681f3Smrg * Copyright 2009, VMware, Inc.
57ec681f3Smrg * All Rights Reserved.
67ec681f3Smrg * Copyright (C) 2010 LunarG Inc.
77ec681f3Smrg *
87ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
107ec681f3Smrg * to deal in the Software without restriction, including without limitation
117ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
137ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
147ec681f3Smrg *
157ec681f3Smrg * The above copyright notice and this permission notice shall be included
167ec681f3Smrg * in all copies or substantial portions of the Software.
177ec681f3Smrg *
187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
227ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
237ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
247ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE.
257ec681f3Smrg *
267ec681f3Smrg * Authors:
277ec681f3Smrg *    Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz
287ec681f3Smrg *    <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
297ec681f3Smrg */
307ec681f3Smrg
317ec681f3Smrg#include <xf86drm.h>
327ec681f3Smrg#include "GL/mesa_glinterop.h"
337ec681f3Smrg#include "util/disk_cache.h"
347ec681f3Smrg#include "util/u_memory.h"
357ec681f3Smrg#include "util/u_inlines.h"
367ec681f3Smrg#include "util/format/u_format.h"
377ec681f3Smrg#include "util/u_debug.h"
387ec681f3Smrg#include "frontend/drm_driver.h"
397ec681f3Smrg#include "state_tracker/st_cb_bufferobjects.h"
407ec681f3Smrg#include "state_tracker/st_cb_fbo.h"
417ec681f3Smrg#include "state_tracker/st_cb_texture.h"
427ec681f3Smrg#include "state_tracker/st_texture.h"
437ec681f3Smrg#include "state_tracker/st_context.h"
447ec681f3Smrg#include "pipe-loader/pipe_loader.h"
457ec681f3Smrg#include "main/bufferobj.h"
467ec681f3Smrg#include "main/texobj.h"
477ec681f3Smrg
487ec681f3Smrg#include "dri_util.h"
497ec681f3Smrg
507ec681f3Smrg#include "dri_helpers.h"
517ec681f3Smrg#include "dri_drawable.h"
527ec681f3Smrg#include "dri_query_renderer.h"
537ec681f3Smrg
547ec681f3Smrg#include "drm-uapi/drm_fourcc.h"
557ec681f3Smrg
567ec681f3Smrgstruct dri2_buffer
577ec681f3Smrg{
587ec681f3Smrg   __DRIbuffer base;
597ec681f3Smrg   struct pipe_resource *resource;
607ec681f3Smrg};
617ec681f3Smrg
627ec681f3Smrgstatic inline struct dri2_buffer *
637ec681f3Smrgdri2_buffer(__DRIbuffer * driBufferPriv)
647ec681f3Smrg{
657ec681f3Smrg   return (struct dri2_buffer *) driBufferPriv;
667ec681f3Smrg}
677ec681f3Smrg
687ec681f3Smrg/**
697ec681f3Smrg * DRI2 flush extension.
707ec681f3Smrg */
717ec681f3Smrgstatic void
727ec681f3Smrgdri2_flush_drawable(__DRIdrawable *dPriv)
737ec681f3Smrg{
747ec681f3Smrg   dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
757ec681f3Smrg}
767ec681f3Smrg
777ec681f3Smrgstatic void
787ec681f3Smrgdri2_invalidate_drawable(__DRIdrawable *dPriv)
797ec681f3Smrg{
807ec681f3Smrg   struct dri_drawable *drawable = dri_drawable(dPriv);
817ec681f3Smrg
827ec681f3Smrg   dri2InvalidateDrawable(dPriv);
837ec681f3Smrg   drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
847ec681f3Smrg   drawable->texture_mask = 0;
857ec681f3Smrg
867ec681f3Smrg   p_atomic_inc(&drawable->base.stamp);
877ec681f3Smrg}
887ec681f3Smrg
897ec681f3Smrgstatic const __DRI2flushExtension dri2FlushExtension = {
907ec681f3Smrg    .base = { __DRI2_FLUSH, 4 },
917ec681f3Smrg
927ec681f3Smrg    .flush                = dri2_flush_drawable,
937ec681f3Smrg    .invalidate           = dri2_invalidate_drawable,
947ec681f3Smrg    .flush_with_flags     = dri_flush,
957ec681f3Smrg};
967ec681f3Smrg
977ec681f3Smrg/**
987ec681f3Smrg * Retrieve __DRIbuffer from the DRI loader.
997ec681f3Smrg */
1007ec681f3Smrgstatic __DRIbuffer *
1017ec681f3Smrgdri2_drawable_get_buffers(struct dri_drawable *drawable,
1027ec681f3Smrg                          const enum st_attachment_type *atts,
1037ec681f3Smrg                          unsigned *count)
1047ec681f3Smrg{
1057ec681f3Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
1067ec681f3Smrg   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
1077ec681f3Smrg   boolean with_format;
1087ec681f3Smrg   __DRIbuffer *buffers;
1097ec681f3Smrg   int num_buffers;
1107ec681f3Smrg   unsigned attachments[__DRI_BUFFER_COUNT];
1117ec681f3Smrg   unsigned num_attachments, i;
1127ec681f3Smrg
1137ec681f3Smrg   assert(loader);
1147ec681f3Smrg   assert(*count <= __DRI_BUFFER_COUNT);
1157ec681f3Smrg   with_format = dri_with_format(drawable->sPriv);
1167ec681f3Smrg
1177ec681f3Smrg   num_attachments = 0;
1187ec681f3Smrg
1197ec681f3Smrg   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
1207ec681f3Smrg   if (!with_format)
1217ec681f3Smrg      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
1227ec681f3Smrg
1237ec681f3Smrg   for (i = 0; i < *count; i++) {
1247ec681f3Smrg      enum pipe_format format;
1257ec681f3Smrg      unsigned bind;
1267ec681f3Smrg      int att, depth;
1277ec681f3Smrg
1287ec681f3Smrg      dri_drawable_get_format(drawable, atts[i], &format, &bind);
1297ec681f3Smrg      if (format == PIPE_FORMAT_NONE)
1307ec681f3Smrg         continue;
1317ec681f3Smrg
1327ec681f3Smrg      switch (atts[i]) {
1337ec681f3Smrg      case ST_ATTACHMENT_FRONT_LEFT:
1347ec681f3Smrg         /* already added */
1357ec681f3Smrg         if (!with_format)
1367ec681f3Smrg            continue;
1377ec681f3Smrg         att = __DRI_BUFFER_FRONT_LEFT;
1387ec681f3Smrg         break;
1397ec681f3Smrg      case ST_ATTACHMENT_BACK_LEFT:
1407ec681f3Smrg         att = __DRI_BUFFER_BACK_LEFT;
1417ec681f3Smrg         break;
1427ec681f3Smrg      case ST_ATTACHMENT_FRONT_RIGHT:
1437ec681f3Smrg         att = __DRI_BUFFER_FRONT_RIGHT;
1447ec681f3Smrg         break;
1457ec681f3Smrg      case ST_ATTACHMENT_BACK_RIGHT:
1467ec681f3Smrg         att = __DRI_BUFFER_BACK_RIGHT;
1477ec681f3Smrg         break;
1487ec681f3Smrg      default:
1497ec681f3Smrg         continue;
1507ec681f3Smrg      }
1517ec681f3Smrg
1527ec681f3Smrg      /*
1537ec681f3Smrg       * In this switch statement we must support all formats that
1547ec681f3Smrg       * may occur as the stvis->color_format.
1557ec681f3Smrg       */
1567ec681f3Smrg      switch(format) {
1577ec681f3Smrg      case PIPE_FORMAT_R16G16B16A16_FLOAT:
1587ec681f3Smrg         depth = 64;
1597ec681f3Smrg         break;
1607ec681f3Smrg      case PIPE_FORMAT_R16G16B16X16_FLOAT:
1617ec681f3Smrg         depth = 48;
1627ec681f3Smrg         break;
1637ec681f3Smrg      case PIPE_FORMAT_B10G10R10A2_UNORM:
1647ec681f3Smrg      case PIPE_FORMAT_R10G10B10A2_UNORM:
1657ec681f3Smrg      case PIPE_FORMAT_BGRA8888_UNORM:
1667ec681f3Smrg      case PIPE_FORMAT_RGBA8888_UNORM:
1677ec681f3Smrg	 depth = 32;
1687ec681f3Smrg	 break;
1697ec681f3Smrg      case PIPE_FORMAT_R10G10B10X2_UNORM:
1707ec681f3Smrg      case PIPE_FORMAT_B10G10R10X2_UNORM:
1717ec681f3Smrg         depth = 30;
1727ec681f3Smrg         break;
1737ec681f3Smrg      case PIPE_FORMAT_BGRX8888_UNORM:
1747ec681f3Smrg      case PIPE_FORMAT_RGBX8888_UNORM:
1757ec681f3Smrg	 depth = 24;
1767ec681f3Smrg	 break;
1777ec681f3Smrg      case PIPE_FORMAT_B5G6R5_UNORM:
1787ec681f3Smrg	 depth = 16;
1797ec681f3Smrg	 break;
1807ec681f3Smrg      default:
1817ec681f3Smrg	 depth = util_format_get_blocksizebits(format);
1827ec681f3Smrg	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
1837ec681f3Smrg      }
1847ec681f3Smrg
1857ec681f3Smrg      attachments[num_attachments++] = att;
1867ec681f3Smrg      if (with_format) {
1877ec681f3Smrg         attachments[num_attachments++] = depth;
1887ec681f3Smrg      }
1897ec681f3Smrg   }
1907ec681f3Smrg
1917ec681f3Smrg   if (with_format) {
1927ec681f3Smrg      num_attachments /= 2;
1937ec681f3Smrg      buffers = loader->getBuffersWithFormat(dri_drawable,
1947ec681f3Smrg            &dri_drawable->w, &dri_drawable->h,
1957ec681f3Smrg            attachments, num_attachments,
1967ec681f3Smrg            &num_buffers, dri_drawable->loaderPrivate);
1977ec681f3Smrg   }
1987ec681f3Smrg   else {
1997ec681f3Smrg      buffers = loader->getBuffers(dri_drawable,
2007ec681f3Smrg            &dri_drawable->w, &dri_drawable->h,
2017ec681f3Smrg            attachments, num_attachments,
2027ec681f3Smrg            &num_buffers, dri_drawable->loaderPrivate);
2037ec681f3Smrg   }
2047ec681f3Smrg
2057ec681f3Smrg   if (buffers)
2067ec681f3Smrg      *count = num_buffers;
2077ec681f3Smrg
2087ec681f3Smrg   return buffers;
2097ec681f3Smrg}
2107ec681f3Smrg
2117ec681f3Smrgstatic bool
2127ec681f3Smrgdri_image_drawable_get_buffers(struct dri_drawable *drawable,
2137ec681f3Smrg                               struct __DRIimageList *images,
2147ec681f3Smrg                               const enum st_attachment_type *statts,
2157ec681f3Smrg                               unsigned statts_count)
2167ec681f3Smrg{
2177ec681f3Smrg   __DRIdrawable *dPriv = drawable->dPriv;
2187ec681f3Smrg   __DRIscreen *sPriv = drawable->sPriv;
2197ec681f3Smrg   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
2207ec681f3Smrg   enum pipe_format pf;
2217ec681f3Smrg   uint32_t buffer_mask = 0;
2227ec681f3Smrg   unsigned i, bind;
2237ec681f3Smrg
2247ec681f3Smrg   for (i = 0; i < statts_count; i++) {
2257ec681f3Smrg      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
2267ec681f3Smrg      if (pf == PIPE_FORMAT_NONE)
2277ec681f3Smrg         continue;
2287ec681f3Smrg
2297ec681f3Smrg      switch (statts[i]) {
2307ec681f3Smrg      case ST_ATTACHMENT_FRONT_LEFT:
2317ec681f3Smrg         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
2327ec681f3Smrg         break;
2337ec681f3Smrg      case ST_ATTACHMENT_BACK_LEFT:
2347ec681f3Smrg         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
2357ec681f3Smrg         break;
2367ec681f3Smrg      default:
2377ec681f3Smrg         continue;
2387ec681f3Smrg      }
2397ec681f3Smrg
2407ec681f3Smrg      switch (pf) {
2417ec681f3Smrg      case PIPE_FORMAT_R16G16B16A16_FLOAT:
2427ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ABGR16161616F;
2437ec681f3Smrg         break;
2447ec681f3Smrg      case PIPE_FORMAT_R16G16B16X16_FLOAT:
2457ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_XBGR16161616F;
2467ec681f3Smrg         break;
2477ec681f3Smrg      case PIPE_FORMAT_B5G5R5A1_UNORM:
2487ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB1555;
2497ec681f3Smrg         break;
2507ec681f3Smrg      case PIPE_FORMAT_B5G6R5_UNORM:
2517ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_RGB565;
2527ec681f3Smrg         break;
2537ec681f3Smrg      case PIPE_FORMAT_BGRX8888_UNORM:
2547ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
2557ec681f3Smrg         break;
2567ec681f3Smrg      case PIPE_FORMAT_BGRA8888_UNORM:
2577ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
2587ec681f3Smrg         break;
2597ec681f3Smrg      case PIPE_FORMAT_RGBX8888_UNORM:
2607ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_XBGR8888;
2617ec681f3Smrg         break;
2627ec681f3Smrg      case PIPE_FORMAT_RGBA8888_UNORM:
2637ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
2647ec681f3Smrg         break;
2657ec681f3Smrg      case PIPE_FORMAT_B10G10R10X2_UNORM:
2667ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
2677ec681f3Smrg         break;
2687ec681f3Smrg      case PIPE_FORMAT_B10G10R10A2_UNORM:
2697ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
2707ec681f3Smrg         break;
2717ec681f3Smrg      case PIPE_FORMAT_R10G10B10X2_UNORM:
2727ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_XBGR2101010;
2737ec681f3Smrg         break;
2747ec681f3Smrg      case PIPE_FORMAT_R10G10B10A2_UNORM:
2757ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_ABGR2101010;
2767ec681f3Smrg         break;
2777ec681f3Smrg      default:
2787ec681f3Smrg         image_format = __DRI_IMAGE_FORMAT_NONE;
2797ec681f3Smrg         break;
2807ec681f3Smrg      }
2817ec681f3Smrg   }
2827ec681f3Smrg
2837ec681f3Smrg   return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
2847ec681f3Smrg                                       (uint32_t *) &drawable->base.stamp,
2857ec681f3Smrg                                       dPriv->loaderPrivate, buffer_mask,
2867ec681f3Smrg                                       images);
2877ec681f3Smrg}
2887ec681f3Smrg
2897ec681f3Smrgstatic __DRIbuffer *
2907ec681f3Smrgdri2_allocate_buffer(__DRIscreen *sPriv,
2917ec681f3Smrg                     unsigned attachment, unsigned format,
2927ec681f3Smrg                     int width, int height)
2937ec681f3Smrg{
2947ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
2957ec681f3Smrg   struct dri2_buffer *buffer;
2967ec681f3Smrg   struct pipe_resource templ;
2977ec681f3Smrg   enum pipe_format pf;
2987ec681f3Smrg   unsigned bind = 0;
2997ec681f3Smrg   struct winsys_handle whandle;
3007ec681f3Smrg
3017ec681f3Smrg   switch (attachment) {
3027ec681f3Smrg      case __DRI_BUFFER_FRONT_LEFT:
3037ec681f3Smrg      case __DRI_BUFFER_FAKE_FRONT_LEFT:
3047ec681f3Smrg         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
3057ec681f3Smrg         break;
3067ec681f3Smrg      case __DRI_BUFFER_BACK_LEFT:
3077ec681f3Smrg         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
3087ec681f3Smrg         break;
3097ec681f3Smrg      case __DRI_BUFFER_DEPTH:
3107ec681f3Smrg      case __DRI_BUFFER_DEPTH_STENCIL:
3117ec681f3Smrg      case __DRI_BUFFER_STENCIL:
3127ec681f3Smrg            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
3137ec681f3Smrg         break;
3147ec681f3Smrg   }
3157ec681f3Smrg
3167ec681f3Smrg   /* because we get the handle and stride */
3177ec681f3Smrg   bind |= PIPE_BIND_SHARED;
3187ec681f3Smrg
3197ec681f3Smrg   switch (format) {
3207ec681f3Smrg      case 64:
3217ec681f3Smrg         pf = PIPE_FORMAT_R16G16B16A16_FLOAT;
3227ec681f3Smrg         break;
3237ec681f3Smrg      case 48:
3247ec681f3Smrg         pf = PIPE_FORMAT_R16G16B16X16_FLOAT;
3257ec681f3Smrg         break;
3267ec681f3Smrg      case 32:
3277ec681f3Smrg         pf = PIPE_FORMAT_BGRA8888_UNORM;
3287ec681f3Smrg         break;
3297ec681f3Smrg      case 30:
3307ec681f3Smrg         pf = PIPE_FORMAT_B10G10R10X2_UNORM;
3317ec681f3Smrg         break;
3327ec681f3Smrg      case 24:
3337ec681f3Smrg         pf = PIPE_FORMAT_BGRX8888_UNORM;
3347ec681f3Smrg         break;
3357ec681f3Smrg      case 16:
3367ec681f3Smrg         pf = PIPE_FORMAT_Z16_UNORM;
3377ec681f3Smrg         break;
3387ec681f3Smrg      default:
3397ec681f3Smrg         return NULL;
3407ec681f3Smrg   }
3417ec681f3Smrg
3427ec681f3Smrg   buffer = CALLOC_STRUCT(dri2_buffer);
3437ec681f3Smrg   if (!buffer)
3447ec681f3Smrg      return NULL;
3457ec681f3Smrg
3467ec681f3Smrg   memset(&templ, 0, sizeof(templ));
3477ec681f3Smrg   templ.bind = bind;
3487ec681f3Smrg   templ.format = pf;
3497ec681f3Smrg   templ.target = PIPE_TEXTURE_2D;
3507ec681f3Smrg   templ.last_level = 0;
3517ec681f3Smrg   templ.width0 = width;
3527ec681f3Smrg   templ.height0 = height;
3537ec681f3Smrg   templ.depth0 = 1;
3547ec681f3Smrg   templ.array_size = 1;
3557ec681f3Smrg
3567ec681f3Smrg   buffer->resource =
3577ec681f3Smrg      screen->base.screen->resource_create(screen->base.screen, &templ);
3587ec681f3Smrg   if (!buffer->resource) {
3597ec681f3Smrg      FREE(buffer);
3607ec681f3Smrg      return NULL;
3617ec681f3Smrg   }
3627ec681f3Smrg
3637ec681f3Smrg   memset(&whandle, 0, sizeof(whandle));
3647ec681f3Smrg   if (screen->can_share_buffer)
3657ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
3667ec681f3Smrg   else
3677ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
3687ec681f3Smrg
3697ec681f3Smrg   screen->base.screen->resource_get_handle(screen->base.screen, NULL,
3707ec681f3Smrg         buffer->resource, &whandle,
3717ec681f3Smrg         PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
3727ec681f3Smrg
3737ec681f3Smrg   buffer->base.attachment = attachment;
3747ec681f3Smrg   buffer->base.name = whandle.handle;
3757ec681f3Smrg   buffer->base.cpp = util_format_get_blocksize(pf);
3767ec681f3Smrg   buffer->base.pitch = whandle.stride;
3777ec681f3Smrg
3787ec681f3Smrg   return &buffer->base;
3797ec681f3Smrg}
3807ec681f3Smrg
3817ec681f3Smrgstatic void
3827ec681f3Smrgdri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
3837ec681f3Smrg{
3847ec681f3Smrg   struct dri2_buffer *buffer = dri2_buffer(bPriv);
3857ec681f3Smrg
3867ec681f3Smrg   pipe_resource_reference(&buffer->resource, NULL);
3877ec681f3Smrg   FREE(buffer);
3887ec681f3Smrg}
3897ec681f3Smrg
3907ec681f3Smrg/*
3917ec681f3Smrg * Backend functions for st_framebuffer interface.
3927ec681f3Smrg */
3937ec681f3Smrg
3947ec681f3Smrgstatic void
3957ec681f3Smrgdri2_allocate_textures(struct dri_context *ctx,
3967ec681f3Smrg                       struct dri_drawable *drawable,
3977ec681f3Smrg                       const enum st_attachment_type *statts,
3987ec681f3Smrg                       unsigned statts_count)
3997ec681f3Smrg{
4007ec681f3Smrg   __DRIscreen *sPriv = drawable->sPriv;
4017ec681f3Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
4027ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
4037ec681f3Smrg   struct pipe_resource templ;
4047ec681f3Smrg   boolean alloc_depthstencil = FALSE;
4057ec681f3Smrg   unsigned i, j, bind;
4067ec681f3Smrg   const __DRIimageLoaderExtension *image = sPriv->image.loader;
4077ec681f3Smrg   /* Image specific variables */
4087ec681f3Smrg   struct __DRIimageList images;
4097ec681f3Smrg   /* Dri2 specific variables */
4107ec681f3Smrg   __DRIbuffer *buffers = NULL;
4117ec681f3Smrg   struct winsys_handle whandle;
4127ec681f3Smrg   unsigned num_buffers = statts_count;
4137ec681f3Smrg
4147ec681f3Smrg   assert(num_buffers <= __DRI_BUFFER_COUNT);
4157ec681f3Smrg
4167ec681f3Smrg   /* First get the buffers from the loader */
4177ec681f3Smrg   if (image) {
4187ec681f3Smrg      if (!dri_image_drawable_get_buffers(drawable, &images,
4197ec681f3Smrg                                          statts, statts_count))
4207ec681f3Smrg         return;
4217ec681f3Smrg   }
4227ec681f3Smrg   else {
4237ec681f3Smrg      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
4247ec681f3Smrg      if (!buffers || (drawable->old_num == num_buffers &&
4257ec681f3Smrg                       drawable->old_w == dri_drawable->w &&
4267ec681f3Smrg                       drawable->old_h == dri_drawable->h &&
4277ec681f3Smrg                       memcmp(drawable->old, buffers,
4287ec681f3Smrg                              sizeof(__DRIbuffer) * num_buffers) == 0))
4297ec681f3Smrg         return;
4307ec681f3Smrg   }
4317ec681f3Smrg
4327ec681f3Smrg   /* Second clean useless resources*/
4337ec681f3Smrg
4347ec681f3Smrg   /* See if we need a depth-stencil buffer. */
4357ec681f3Smrg   for (i = 0; i < statts_count; i++) {
4367ec681f3Smrg      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
4377ec681f3Smrg         alloc_depthstencil = TRUE;
4387ec681f3Smrg         break;
4397ec681f3Smrg      }
4407ec681f3Smrg   }
4417ec681f3Smrg
4427ec681f3Smrg   /* Delete the resources we won't need. */
4437ec681f3Smrg   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
4447ec681f3Smrg      /* Don't delete the depth-stencil buffer, we can reuse it. */
4457ec681f3Smrg      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
4467ec681f3Smrg         continue;
4477ec681f3Smrg
4487ec681f3Smrg      /* Flush the texture before unreferencing, so that other clients can
4497ec681f3Smrg       * see what the driver has rendered.
4507ec681f3Smrg       */
4517ec681f3Smrg      if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
4527ec681f3Smrg         struct pipe_context *pipe = ctx->st->pipe;
4537ec681f3Smrg         pipe->flush_resource(pipe, drawable->textures[i]);
4547ec681f3Smrg      }
4557ec681f3Smrg
4567ec681f3Smrg      pipe_resource_reference(&drawable->textures[i], NULL);
4577ec681f3Smrg   }
4587ec681f3Smrg
4597ec681f3Smrg   if (drawable->stvis.samples > 1) {
4607ec681f3Smrg      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
4617ec681f3Smrg         boolean del = TRUE;
4627ec681f3Smrg
4637ec681f3Smrg         /* Don't delete MSAA resources for the attachments which are enabled,
4647ec681f3Smrg          * we can reuse them. */
4657ec681f3Smrg         for (j = 0; j < statts_count; j++) {
4667ec681f3Smrg            if (i == statts[j]) {
4677ec681f3Smrg               del = FALSE;
4687ec681f3Smrg               break;
4697ec681f3Smrg            }
4707ec681f3Smrg         }
4717ec681f3Smrg
4727ec681f3Smrg         if (del) {
4737ec681f3Smrg            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
4747ec681f3Smrg         }
4757ec681f3Smrg      }
4767ec681f3Smrg   }
4777ec681f3Smrg
4787ec681f3Smrg   /* Third use the buffers retrieved to fill the drawable info */
4797ec681f3Smrg
4807ec681f3Smrg   memset(&templ, 0, sizeof(templ));
4817ec681f3Smrg   templ.target = screen->target;
4827ec681f3Smrg   templ.last_level = 0;
4837ec681f3Smrg   templ.depth0 = 1;
4847ec681f3Smrg   templ.array_size = 1;
4857ec681f3Smrg
4867ec681f3Smrg   if (image) {
4877ec681f3Smrg      if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
4887ec681f3Smrg         struct pipe_resource **buf =
4897ec681f3Smrg            &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
4907ec681f3Smrg         struct pipe_resource *texture = images.front->texture;
4917ec681f3Smrg
4927ec681f3Smrg         dri_drawable->w = texture->width0;
4937ec681f3Smrg         dri_drawable->h = texture->height0;
4947ec681f3Smrg
4957ec681f3Smrg         pipe_resource_reference(buf, texture);
4967ec681f3Smrg      }
4977ec681f3Smrg
4987ec681f3Smrg      if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
4997ec681f3Smrg         struct pipe_resource **buf =
5007ec681f3Smrg            &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
5017ec681f3Smrg         struct pipe_resource *texture = images.back->texture;
5027ec681f3Smrg
5037ec681f3Smrg         dri_drawable->w = texture->width0;
5047ec681f3Smrg         dri_drawable->h = texture->height0;
5057ec681f3Smrg
5067ec681f3Smrg         pipe_resource_reference(buf, texture);
5077ec681f3Smrg      }
5087ec681f3Smrg
5097ec681f3Smrg      if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {
5107ec681f3Smrg         struct pipe_resource **buf =
5117ec681f3Smrg            &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
5127ec681f3Smrg         struct pipe_resource *texture = images.back->texture;
5137ec681f3Smrg
5147ec681f3Smrg         dri_drawable->w = texture->width0;
5157ec681f3Smrg         dri_drawable->h = texture->height0;
5167ec681f3Smrg
5177ec681f3Smrg         pipe_resource_reference(buf, texture);
5187ec681f3Smrg
5197ec681f3Smrg         ctx->is_shared_buffer_bound = true;
5207ec681f3Smrg      } else {
5217ec681f3Smrg         ctx->is_shared_buffer_bound = false;
5227ec681f3Smrg      }
5237ec681f3Smrg
5247ec681f3Smrg      /* Note: if there is both a back and a front buffer,
5257ec681f3Smrg       * then they have the same size.
5267ec681f3Smrg       */
5277ec681f3Smrg      templ.width0 = dri_drawable->w;
5287ec681f3Smrg      templ.height0 = dri_drawable->h;
5297ec681f3Smrg   }
5307ec681f3Smrg   else {
5317ec681f3Smrg      memset(&whandle, 0, sizeof(whandle));
5327ec681f3Smrg
5337ec681f3Smrg      /* Process DRI-provided buffers and get pipe_resources. */
5347ec681f3Smrg      for (i = 0; i < num_buffers; i++) {
5357ec681f3Smrg         __DRIbuffer *buf = &buffers[i];
5367ec681f3Smrg         enum st_attachment_type statt;
5377ec681f3Smrg         enum pipe_format format;
5387ec681f3Smrg
5397ec681f3Smrg         switch (buf->attachment) {
5407ec681f3Smrg         case __DRI_BUFFER_FRONT_LEFT:
5417ec681f3Smrg            if (!screen->auto_fake_front) {
5427ec681f3Smrg               continue; /* invalid attachment */
5437ec681f3Smrg            }
5447ec681f3Smrg            FALLTHROUGH;
5457ec681f3Smrg         case __DRI_BUFFER_FAKE_FRONT_LEFT:
5467ec681f3Smrg            statt = ST_ATTACHMENT_FRONT_LEFT;
5477ec681f3Smrg            break;
5487ec681f3Smrg         case __DRI_BUFFER_BACK_LEFT:
5497ec681f3Smrg            statt = ST_ATTACHMENT_BACK_LEFT;
5507ec681f3Smrg            break;
5517ec681f3Smrg         default:
5527ec681f3Smrg            continue; /* invalid attachment */
5537ec681f3Smrg         }
5547ec681f3Smrg
5557ec681f3Smrg         dri_drawable_get_format(drawable, statt, &format, &bind);
5567ec681f3Smrg         if (format == PIPE_FORMAT_NONE)
5577ec681f3Smrg            continue;
5587ec681f3Smrg
5597ec681f3Smrg         /* dri2_drawable_get_buffers has already filled dri_drawable->w
5607ec681f3Smrg          * and dri_drawable->h */
5617ec681f3Smrg         templ.width0 = dri_drawable->w;
5627ec681f3Smrg         templ.height0 = dri_drawable->h;
5637ec681f3Smrg         templ.format = format;
5647ec681f3Smrg         templ.bind = bind;
5657ec681f3Smrg         whandle.handle = buf->name;
5667ec681f3Smrg         whandle.stride = buf->pitch;
5677ec681f3Smrg         whandle.offset = 0;
5687ec681f3Smrg         whandle.format = format;
5697ec681f3Smrg         whandle.modifier = DRM_FORMAT_MOD_INVALID;
5707ec681f3Smrg         if (screen->can_share_buffer)
5717ec681f3Smrg            whandle.type = WINSYS_HANDLE_TYPE_SHARED;
5727ec681f3Smrg         else
5737ec681f3Smrg            whandle.type = WINSYS_HANDLE_TYPE_KMS;
5747ec681f3Smrg         drawable->textures[statt] =
5757ec681f3Smrg            screen->base.screen->resource_from_handle(screen->base.screen,
5767ec681f3Smrg                  &templ, &whandle,
5777ec681f3Smrg                  PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
5787ec681f3Smrg         assert(drawable->textures[statt]);
5797ec681f3Smrg      }
5807ec681f3Smrg   }
5817ec681f3Smrg
5827ec681f3Smrg   /* Allocate private MSAA colorbuffers. */
5837ec681f3Smrg   if (drawable->stvis.samples > 1) {
5847ec681f3Smrg      for (i = 0; i < statts_count; i++) {
5857ec681f3Smrg         enum st_attachment_type statt = statts[i];
5867ec681f3Smrg
5877ec681f3Smrg         if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
5887ec681f3Smrg            continue;
5897ec681f3Smrg
5907ec681f3Smrg         if (drawable->textures[statt]) {
5917ec681f3Smrg            templ.format = drawable->textures[statt]->format;
5927ec681f3Smrg            templ.bind = drawable->textures[statt]->bind &
5937ec681f3Smrg                         ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
5947ec681f3Smrg            templ.nr_samples = drawable->stvis.samples;
5957ec681f3Smrg            templ.nr_storage_samples = drawable->stvis.samples;
5967ec681f3Smrg
5977ec681f3Smrg            /* Try to reuse the resource.
5987ec681f3Smrg             * (the other resource parameters should be constant)
5997ec681f3Smrg             */
6007ec681f3Smrg            if (!drawable->msaa_textures[statt] ||
6017ec681f3Smrg                drawable->msaa_textures[statt]->width0 != templ.width0 ||
6027ec681f3Smrg                drawable->msaa_textures[statt]->height0 != templ.height0) {
6037ec681f3Smrg               /* Allocate a new one. */
6047ec681f3Smrg               pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
6057ec681f3Smrg
6067ec681f3Smrg               drawable->msaa_textures[statt] =
6077ec681f3Smrg                  screen->base.screen->resource_create(screen->base.screen,
6087ec681f3Smrg                                                       &templ);
6097ec681f3Smrg               assert(drawable->msaa_textures[statt]);
6107ec681f3Smrg
6117ec681f3Smrg               /* If there are any MSAA resources, we should initialize them
6127ec681f3Smrg                * such that they contain the same data as the single-sample
6137ec681f3Smrg                * resources we just got from the X server.
6147ec681f3Smrg                *
6157ec681f3Smrg                * The reason for this is that the gallium frontend (and
6167ec681f3Smrg                * therefore the app) can access the MSAA resources only.
6177ec681f3Smrg                * The single-sample resources are not exposed
6187ec681f3Smrg                * to the gallium frontend.
6197ec681f3Smrg                *
6207ec681f3Smrg                */
6217ec681f3Smrg               dri_pipe_blit(ctx->st->pipe,
6227ec681f3Smrg                             drawable->msaa_textures[statt],
6237ec681f3Smrg                             drawable->textures[statt]);
6247ec681f3Smrg            }
6257ec681f3Smrg         }
6267ec681f3Smrg         else {
6277ec681f3Smrg            pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
6287ec681f3Smrg         }
6297ec681f3Smrg      }
6307ec681f3Smrg   }
6317ec681f3Smrg
6327ec681f3Smrg   /* Allocate a private depth-stencil buffer. */
6337ec681f3Smrg   if (alloc_depthstencil) {
6347ec681f3Smrg      enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
6357ec681f3Smrg      struct pipe_resource **zsbuf;
6367ec681f3Smrg      enum pipe_format format;
6377ec681f3Smrg      unsigned bind;
6387ec681f3Smrg
6397ec681f3Smrg      dri_drawable_get_format(drawable, statt, &format, &bind);
6407ec681f3Smrg
6417ec681f3Smrg      if (format) {
6427ec681f3Smrg         templ.format = format;
6437ec681f3Smrg         templ.bind = bind & ~PIPE_BIND_SHARED;
6447ec681f3Smrg
6457ec681f3Smrg         if (drawable->stvis.samples > 1) {
6467ec681f3Smrg            templ.nr_samples = drawable->stvis.samples;
6477ec681f3Smrg            templ.nr_storage_samples = drawable->stvis.samples;
6487ec681f3Smrg            zsbuf = &drawable->msaa_textures[statt];
6497ec681f3Smrg         }
6507ec681f3Smrg         else {
6517ec681f3Smrg            templ.nr_samples = 0;
6527ec681f3Smrg            templ.nr_storage_samples = 0;
6537ec681f3Smrg            zsbuf = &drawable->textures[statt];
6547ec681f3Smrg         }
6557ec681f3Smrg
6567ec681f3Smrg         /* Try to reuse the resource.
6577ec681f3Smrg          * (the other resource parameters should be constant)
6587ec681f3Smrg          */
6597ec681f3Smrg         if (!*zsbuf ||
6607ec681f3Smrg             (*zsbuf)->width0 != templ.width0 ||
6617ec681f3Smrg             (*zsbuf)->height0 != templ.height0) {
6627ec681f3Smrg            /* Allocate a new one. */
6637ec681f3Smrg            pipe_resource_reference(zsbuf, NULL);
6647ec681f3Smrg            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
6657ec681f3Smrg                                                          &templ);
6667ec681f3Smrg            assert(*zsbuf);
6677ec681f3Smrg         }
6687ec681f3Smrg      }
6697ec681f3Smrg      else {
6707ec681f3Smrg         pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
6717ec681f3Smrg         pipe_resource_reference(&drawable->textures[statt], NULL);
6727ec681f3Smrg      }
6737ec681f3Smrg   }
6747ec681f3Smrg
6757ec681f3Smrg   /* For DRI2, we may get the same buffers again from the server.
6767ec681f3Smrg    * To prevent useless imports of gem names, drawable->old* is used
6777ec681f3Smrg    * to bypass the import if we get the same buffers. This doesn't apply
6787ec681f3Smrg    * to DRI3/Wayland, users of image.loader, since the buffer is managed
6797ec681f3Smrg    * by the client (no import), and the back buffer is going to change
6807ec681f3Smrg    * at every redraw.
6817ec681f3Smrg    */
6827ec681f3Smrg   if (!image) {
6837ec681f3Smrg      drawable->old_num = num_buffers;
6847ec681f3Smrg      drawable->old_w = dri_drawable->w;
6857ec681f3Smrg      drawable->old_h = dri_drawable->h;
6867ec681f3Smrg      memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
6877ec681f3Smrg   }
6887ec681f3Smrg}
6897ec681f3Smrg
6907ec681f3Smrgstatic bool
6917ec681f3Smrgdri2_flush_frontbuffer(struct dri_context *ctx,
6927ec681f3Smrg                       struct dri_drawable *drawable,
6937ec681f3Smrg                       enum st_attachment_type statt)
6947ec681f3Smrg{
6957ec681f3Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
6967ec681f3Smrg   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
6977ec681f3Smrg   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
6987ec681f3Smrg   const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader =
6997ec681f3Smrg      drawable->sPriv->mutableRenderBuffer.loader;
7007ec681f3Smrg   struct pipe_context *pipe = ctx->st->pipe;
7017ec681f3Smrg   struct pipe_fence_handle *fence = NULL;
7027ec681f3Smrg   int fence_fd = -1;
7037ec681f3Smrg
7047ec681f3Smrg   /* We need to flush for front buffer rendering when either we're using the
7057ec681f3Smrg    * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer
7067ec681f3Smrg    * has redirected GL_BACK to the front buffer.
7077ec681f3Smrg    */
7087ec681f3Smrg   if (statt != ST_ATTACHMENT_FRONT_LEFT &&
7097ec681f3Smrg       (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT))
7107ec681f3Smrg         return false;
7117ec681f3Smrg
7127ec681f3Smrg   if (drawable->stvis.samples > 1) {
7137ec681f3Smrg      /* Resolve the buffer used for front rendering. */
7147ec681f3Smrg      dri_pipe_blit(ctx->st->pipe, drawable->textures[statt],
7157ec681f3Smrg                    drawable->msaa_textures[statt]);
7167ec681f3Smrg   }
7177ec681f3Smrg
7187ec681f3Smrg   if (drawable->textures[statt]) {
7197ec681f3Smrg      pipe->flush_resource(pipe, drawable->textures[statt]);
7207ec681f3Smrg   }
7217ec681f3Smrg
7227ec681f3Smrg   if (ctx->is_shared_buffer_bound) {
7237ec681f3Smrg      /* is_shared_buffer_bound should only be true with image extension: */
7247ec681f3Smrg      assert(image);
7257ec681f3Smrg      pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD);
7267ec681f3Smrg   } else {
7277ec681f3Smrg      pipe->flush(pipe, NULL, 0);
7287ec681f3Smrg   }
7297ec681f3Smrg
7307ec681f3Smrg   if (image) {
7317ec681f3Smrg      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
7327ec681f3Smrg      if (ctx->is_shared_buffer_bound) {
7337ec681f3Smrg         if (fence)
7347ec681f3Smrg            fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence);
7357ec681f3Smrg
7367ec681f3Smrg         shared_buffer_loader->displaySharedBuffer(dri_drawable, fence_fd,
7377ec681f3Smrg                                                   dri_drawable->loaderPrivate);
7387ec681f3Smrg
7397ec681f3Smrg         pipe->screen->fence_reference(pipe->screen, &fence, NULL);
7407ec681f3Smrg      }
7417ec681f3Smrg   }
7427ec681f3Smrg   else if (loader->flushFrontBuffer) {
7437ec681f3Smrg      loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
7447ec681f3Smrg   }
7457ec681f3Smrg
7467ec681f3Smrg   return true;
7477ec681f3Smrg}
7487ec681f3Smrg
7497ec681f3Smrg/**
7507ec681f3Smrg * The struct dri_drawable flush_swapbuffers callback
7517ec681f3Smrg */
7527ec681f3Smrgstatic void
7537ec681f3Smrgdri2_flush_swapbuffers(struct dri_context *ctx,
7547ec681f3Smrg                       struct dri_drawable *drawable)
7557ec681f3Smrg{
7567ec681f3Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
7577ec681f3Smrg   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
7587ec681f3Smrg
7597ec681f3Smrg   if (image && image->base.version >= 3 && image->flushSwapBuffers) {
7607ec681f3Smrg      image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate);
7617ec681f3Smrg   }
7627ec681f3Smrg}
7637ec681f3Smrg
7647ec681f3Smrgstatic void
7657ec681f3Smrgdri2_update_tex_buffer(struct dri_drawable *drawable,
7667ec681f3Smrg                       struct dri_context *ctx,
7677ec681f3Smrg                       struct pipe_resource *res)
7687ec681f3Smrg{
7697ec681f3Smrg   /* no-op */
7707ec681f3Smrg}
7717ec681f3Smrg
7727ec681f3Smrgstatic const struct dri2_format_mapping r8_g8b8_mapping = {
7737ec681f3Smrg   DRM_FORMAT_NV12,
7747ec681f3Smrg   __DRI_IMAGE_FORMAT_NONE,
7757ec681f3Smrg   __DRI_IMAGE_COMPONENTS_Y_UV,
7767ec681f3Smrg   PIPE_FORMAT_R8_G8B8_420_UNORM,
7777ec681f3Smrg   2,
7787ec681f3Smrg   { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },
7797ec681f3Smrg     { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }
7807ec681f3Smrg};
7817ec681f3Smrg
7827ec681f3Smrgstatic const struct dri2_format_mapping r8g8_r8b8_mapping = {
7837ec681f3Smrg   DRM_FORMAT_YUYV,
7847ec681f3Smrg   __DRI_IMAGE_FORMAT_NONE,
7857ec681f3Smrg   __DRI_IMAGE_COMPONENTS_Y_XUXV,
7867ec681f3Smrg   PIPE_FORMAT_R8G8_R8B8_UNORM, 2,
7877ec681f3Smrg   { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
7887ec681f3Smrg     { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }
7897ec681f3Smrg};
7907ec681f3Smrg
7917ec681f3Smrgstatic const struct dri2_format_mapping g8r8_b8r8_mapping = {
7927ec681f3Smrg   DRM_FORMAT_UYVY,
7937ec681f3Smrg   __DRI_IMAGE_FORMAT_NONE,
7947ec681f3Smrg   __DRI_IMAGE_COMPONENTS_Y_XUXV,
7957ec681f3Smrg   PIPE_FORMAT_G8R8_B8R8_UNORM, 2,
7967ec681f3Smrg   { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },
7977ec681f3Smrg     { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }
7987ec681f3Smrg};
7997ec681f3Smrg
8007ec681f3Smrgstatic __DRIimage *
8017ec681f3Smrgdri2_create_image_from_winsys(__DRIscreen *_screen,
8027ec681f3Smrg                              int width, int height, const struct dri2_format_mapping *map,
8037ec681f3Smrg                              int num_handles, struct winsys_handle *whandle,
8047ec681f3Smrg                              bool is_protected_content,
8057ec681f3Smrg                              void *loaderPrivate)
8067ec681f3Smrg{
8077ec681f3Smrg   struct dri_screen *screen = dri_screen(_screen);
8087ec681f3Smrg   struct pipe_screen *pscreen = screen->base.screen;
8097ec681f3Smrg   __DRIimage *img;
8107ec681f3Smrg   struct pipe_resource templ;
8117ec681f3Smrg   unsigned tex_usage = 0;
8127ec681f3Smrg   int i;
8137ec681f3Smrg   bool use_lowered = false;
8147ec681f3Smrg   const unsigned format_planes = util_format_get_num_planes(map->pipe_format);
8157ec681f3Smrg
8167ec681f3Smrg   if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
8177ec681f3Smrg                                    PIPE_BIND_RENDER_TARGET))
8187ec681f3Smrg      tex_usage |= PIPE_BIND_RENDER_TARGET;
8197ec681f3Smrg   if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,
8207ec681f3Smrg                                    PIPE_BIND_SAMPLER_VIEW))
8217ec681f3Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
8227ec681f3Smrg
8237ec681f3Smrg   /* For NV12, see if we have support for sampling r8_b8g8 */
8247ec681f3Smrg   if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 &&
8257ec681f3Smrg       pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM,
8267ec681f3Smrg                                    screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
8277ec681f3Smrg      map = &r8_g8b8_mapping;
8287ec681f3Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
8297ec681f3Smrg   }
8307ec681f3Smrg
8317ec681f3Smrg   /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these
8327ec681f3Smrg    * can be used for YUYV and UYVY formats.
8337ec681f3Smrg    */
8347ec681f3Smrg   if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV &&
8357ec681f3Smrg       pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM,
8367ec681f3Smrg                                    screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
8377ec681f3Smrg      map = &r8g8_r8b8_mapping;
8387ec681f3Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
8397ec681f3Smrg   }
8407ec681f3Smrg
8417ec681f3Smrg   if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY &&
8427ec681f3Smrg       pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM,
8437ec681f3Smrg                                    screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
8447ec681f3Smrg      map = &g8r8_b8r8_mapping;
8457ec681f3Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
8467ec681f3Smrg   }
8477ec681f3Smrg
8487ec681f3Smrg   if (!tex_usage && util_format_is_yuv(map->pipe_format)) {
8497ec681f3Smrg      /* YUV format sampling can be emulated by the GL gallium frontend by
8507ec681f3Smrg       * using multiple samplers of varying formats.
8517ec681f3Smrg       * If no tex_usage is set and we detect a YUV format,
8527ec681f3Smrg       * test for support of all planes' sampler formats and
8537ec681f3Smrg       * add sampler view usage.
8547ec681f3Smrg       */
8557ec681f3Smrg      use_lowered = true;
8567ec681f3Smrg      if (dri2_yuv_dma_buf_supported(screen, map))
8577ec681f3Smrg         tex_usage |= PIPE_BIND_SAMPLER_VIEW;
8587ec681f3Smrg   }
8597ec681f3Smrg
8607ec681f3Smrg   if (!tex_usage)
8617ec681f3Smrg      return NULL;
8627ec681f3Smrg
8637ec681f3Smrg   if (is_protected_content)
8647ec681f3Smrg      tex_usage |= PIPE_BIND_PROTECTED;
8657ec681f3Smrg
8667ec681f3Smrg   img = CALLOC_STRUCT(__DRIimageRec);
8677ec681f3Smrg   if (!img)
8687ec681f3Smrg      return NULL;
8697ec681f3Smrg
8707ec681f3Smrg   memset(&templ, 0, sizeof(templ));
8717ec681f3Smrg   templ.bind = tex_usage;
8727ec681f3Smrg   templ.target = screen->target;
8737ec681f3Smrg   templ.last_level = 0;
8747ec681f3Smrg   templ.depth0 = 1;
8757ec681f3Smrg   templ.array_size = 1;
8767ec681f3Smrg
8777ec681f3Smrg   for (i = num_handles - 1; i >= format_planes; i--) {
8787ec681f3Smrg      struct pipe_resource *tex;
8797ec681f3Smrg
8807ec681f3Smrg      templ.next = img->texture;
8817ec681f3Smrg
8827ec681f3Smrg      tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i],
8837ec681f3Smrg                                          PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
8847ec681f3Smrg      if (!tex) {
8857ec681f3Smrg         pipe_resource_reference(&img->texture, NULL);
8867ec681f3Smrg         FREE(img);
8877ec681f3Smrg         return NULL;
8887ec681f3Smrg      }
8897ec681f3Smrg
8907ec681f3Smrg      img->texture = tex;
8917ec681f3Smrg   }
8927ec681f3Smrg
8937ec681f3Smrg   for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) {
8947ec681f3Smrg      struct pipe_resource *tex;
8957ec681f3Smrg
8967ec681f3Smrg      templ.next = img->texture;
8977ec681f3Smrg      templ.width0 = width >> map->planes[i].width_shift;
8987ec681f3Smrg      templ.height0 = height >> map->planes[i].height_shift;
8997ec681f3Smrg      if (use_lowered)
9007ec681f3Smrg         templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);
9017ec681f3Smrg      else
9027ec681f3Smrg         templ.format = map->pipe_format;
9037ec681f3Smrg      assert(templ.format != PIPE_FORMAT_NONE);
9047ec681f3Smrg
9057ec681f3Smrg      tex = pscreen->resource_from_handle(pscreen,
9067ec681f3Smrg               &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i],
9077ec681f3Smrg               PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
9087ec681f3Smrg      if (!tex) {
9097ec681f3Smrg         pipe_resource_reference(&img->texture, NULL);
9107ec681f3Smrg         FREE(img);
9117ec681f3Smrg         return NULL;
9127ec681f3Smrg      }
9137ec681f3Smrg
9147ec681f3Smrg      /* Reject image creation if there's an inconsistency between
9157ec681f3Smrg       * content protection status of tex and img.
9167ec681f3Smrg       */
9177ec681f3Smrg      const struct driOptionCache *optionCache = &screen->dev->option_cache;
9187ec681f3Smrg      if (!driQueryOptionb(optionCache, "disable_protected_content_check") &&
9197ec681f3Smrg          (bool)(tex->bind & PIPE_BIND_PROTECTED) != is_protected_content) {
9207ec681f3Smrg         pipe_resource_reference(&img->texture, NULL);
9217ec681f3Smrg         pipe_resource_reference(&tex, NULL);
9227ec681f3Smrg         FREE(img);
9237ec681f3Smrg         return NULL;
9247ec681f3Smrg      }
9257ec681f3Smrg
9267ec681f3Smrg      img->texture = tex;
9277ec681f3Smrg   }
9287ec681f3Smrg
9297ec681f3Smrg   img->level = 0;
9307ec681f3Smrg   img->layer = 0;
9317ec681f3Smrg   img->use = 0;
9327ec681f3Smrg   img->loader_private = loaderPrivate;
9337ec681f3Smrg   img->sPriv = _screen;
9347ec681f3Smrg
9357ec681f3Smrg   return img;
9367ec681f3Smrg}
9377ec681f3Smrg
9387ec681f3Smrgstatic __DRIimage *
9397ec681f3Smrgdri2_create_image_from_name(__DRIscreen *_screen,
9407ec681f3Smrg                            int width, int height, int format,
9417ec681f3Smrg                            int name, int pitch, void *loaderPrivate)
9427ec681f3Smrg{
9437ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
9447ec681f3Smrg   struct winsys_handle whandle;
9457ec681f3Smrg   __DRIimage *img;
9467ec681f3Smrg
9477ec681f3Smrg   if (!map)
9487ec681f3Smrg      return NULL;
9497ec681f3Smrg
9507ec681f3Smrg   memset(&whandle, 0, sizeof(whandle));
9517ec681f3Smrg   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
9527ec681f3Smrg   whandle.handle = name;
9537ec681f3Smrg   whandle.format = map->pipe_format;
9547ec681f3Smrg   whandle.modifier = DRM_FORMAT_MOD_INVALID;
9557ec681f3Smrg
9567ec681f3Smrg   whandle.stride = pitch * util_format_get_blocksize(map->pipe_format);
9577ec681f3Smrg
9587ec681f3Smrg   img = dri2_create_image_from_winsys(_screen, width, height, map,
9597ec681f3Smrg                                       1, &whandle, false, loaderPrivate);
9607ec681f3Smrg
9617ec681f3Smrg   if (!img)
9627ec681f3Smrg      return NULL;
9637ec681f3Smrg
9647ec681f3Smrg   img->dri_components = map->dri_components;
9657ec681f3Smrg   img->dri_fourcc = map->dri_fourcc;
9667ec681f3Smrg   img->dri_format = map->dri_format;
9677ec681f3Smrg
9687ec681f3Smrg   return img;
9697ec681f3Smrg}
9707ec681f3Smrg
9717ec681f3Smrgstatic unsigned
9727ec681f3Smrgdri2_get_modifier_num_planes(__DRIscreen *_screen,
9737ec681f3Smrg                             uint64_t modifier, int fourcc)
9747ec681f3Smrg{
9757ec681f3Smrg   struct pipe_screen *pscreen = dri_screen(_screen)->base.screen;
9767ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
9777ec681f3Smrg
9787ec681f3Smrg   if (!map)
9797ec681f3Smrg      return 0;
9807ec681f3Smrg
9817ec681f3Smrg   switch (modifier) {
9827ec681f3Smrg   case DRM_FORMAT_MOD_LINEAR:
9837ec681f3Smrg   /* DRM_FORMAT_MOD_NONE is the same as LINEAR */
9847ec681f3Smrg   case DRM_FORMAT_MOD_INVALID:
9857ec681f3Smrg      return util_format_get_num_planes(map->pipe_format);
9867ec681f3Smrg   default:
9877ec681f3Smrg      if (!pscreen->is_dmabuf_modifier_supported ||
9887ec681f3Smrg          !pscreen->is_dmabuf_modifier_supported(pscreen, modifier,
9897ec681f3Smrg                                                 map->pipe_format, NULL)) {
9907ec681f3Smrg         return 0;
9917ec681f3Smrg      }
9927ec681f3Smrg
9937ec681f3Smrg      if (pscreen->get_dmabuf_modifier_planes) {
9947ec681f3Smrg         return pscreen->get_dmabuf_modifier_planes(pscreen, modifier,
9957ec681f3Smrg                                                    map->pipe_format);
9967ec681f3Smrg      }
9977ec681f3Smrg
9987ec681f3Smrg      return map->nplanes;
9997ec681f3Smrg   }
10007ec681f3Smrg}
10017ec681f3Smrg
10027ec681f3Smrgstatic __DRIimage *
10037ec681f3Smrgdri2_create_image_from_fd(__DRIscreen *_screen,
10047ec681f3Smrg                          int width, int height, int fourcc,
10057ec681f3Smrg                          uint64_t modifier, int *fds, int num_fds,
10067ec681f3Smrg                          int *strides, int *offsets, bool protected_content,
10077ec681f3Smrg                          unsigned *error, void *loaderPrivate)
10087ec681f3Smrg{
10097ec681f3Smrg   struct winsys_handle whandles[4];
10107ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
10117ec681f3Smrg   __DRIimage *img = NULL;
10127ec681f3Smrg   unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
10137ec681f3Smrg   int i;
10147ec681f3Smrg   const int expected_num_fds = dri2_get_modifier_num_planes(_screen, modifier, fourcc);
10157ec681f3Smrg
10167ec681f3Smrg   if (!map || expected_num_fds == 0) {
10177ec681f3Smrg      err = __DRI_IMAGE_ERROR_BAD_MATCH;
10187ec681f3Smrg      goto exit;
10197ec681f3Smrg   }
10207ec681f3Smrg
10217ec681f3Smrg   if (num_fds != expected_num_fds) {
10227ec681f3Smrg      err = __DRI_IMAGE_ERROR_BAD_MATCH;
10237ec681f3Smrg      goto exit;
10247ec681f3Smrg   }
10257ec681f3Smrg
10267ec681f3Smrg   memset(whandles, 0, sizeof(whandles));
10277ec681f3Smrg
10287ec681f3Smrg   for (i = 0; i < num_fds; i++) {
10297ec681f3Smrg      if (fds[i] < 0) {
10307ec681f3Smrg         err = __DRI_IMAGE_ERROR_BAD_ALLOC;
10317ec681f3Smrg         goto exit;
10327ec681f3Smrg      }
10337ec681f3Smrg
10347ec681f3Smrg      whandles[i].type = WINSYS_HANDLE_TYPE_FD;
10357ec681f3Smrg      whandles[i].handle = (unsigned)fds[i];
10367ec681f3Smrg      whandles[i].stride = (unsigned)strides[i];
10377ec681f3Smrg      whandles[i].offset = (unsigned)offsets[i];
10387ec681f3Smrg      whandles[i].format = map->pipe_format;
10397ec681f3Smrg      whandles[i].modifier = modifier;
10407ec681f3Smrg      whandles[i].plane = i;
10417ec681f3Smrg   }
10427ec681f3Smrg
10437ec681f3Smrg   img = dri2_create_image_from_winsys(_screen, width, height, map,
10447ec681f3Smrg                                       num_fds, whandles, protected_content,
10457ec681f3Smrg                                       loaderPrivate);
10467ec681f3Smrg   if(img == NULL) {
10477ec681f3Smrg      err = __DRI_IMAGE_ERROR_BAD_ALLOC;
10487ec681f3Smrg      goto exit;
10497ec681f3Smrg   }
10507ec681f3Smrg
10517ec681f3Smrg   img->dri_components = map->dri_components;
10527ec681f3Smrg   img->dri_fourcc = fourcc;
10537ec681f3Smrg   img->dri_format = map->dri_format;
10547ec681f3Smrg   img->imported_dmabuf = TRUE;
10557ec681f3Smrg
10567ec681f3Smrgexit:
10577ec681f3Smrg   if (error)
10587ec681f3Smrg      *error = err;
10597ec681f3Smrg
10607ec681f3Smrg   return img;
10617ec681f3Smrg}
10627ec681f3Smrg
10637ec681f3Smrgstatic __DRIimage *
10647ec681f3Smrgdri2_create_image_common(__DRIscreen *_screen,
10657ec681f3Smrg                         int width, int height,
10667ec681f3Smrg                         int format, unsigned int use,
10677ec681f3Smrg                         const uint64_t *modifiers,
10687ec681f3Smrg                         const unsigned count,
10697ec681f3Smrg                         void *loaderPrivate)
10707ec681f3Smrg{
10717ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
10727ec681f3Smrg   struct dri_screen *screen = dri_screen(_screen);
10737ec681f3Smrg   struct pipe_screen *pscreen = screen->base.screen;
10747ec681f3Smrg   __DRIimage *img;
10757ec681f3Smrg   struct pipe_resource templ;
10767ec681f3Smrg   unsigned tex_usage = 0;
10777ec681f3Smrg
10787ec681f3Smrg   if (!map)
10797ec681f3Smrg      return NULL;
10807ec681f3Smrg
10817ec681f3Smrg   if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
10827ec681f3Smrg                                    0, 0, PIPE_BIND_RENDER_TARGET))
10837ec681f3Smrg      tex_usage |= PIPE_BIND_RENDER_TARGET;
10847ec681f3Smrg   if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,
10857ec681f3Smrg                                    0, 0, PIPE_BIND_SAMPLER_VIEW))
10867ec681f3Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
10877ec681f3Smrg
10887ec681f3Smrg   if (!tex_usage)
10897ec681f3Smrg      return NULL;
10907ec681f3Smrg
10917ec681f3Smrg   if (use & __DRI_IMAGE_USE_SCANOUT)
10927ec681f3Smrg      tex_usage |= PIPE_BIND_SCANOUT;
10937ec681f3Smrg   if (use & __DRI_IMAGE_USE_SHARE)
10947ec681f3Smrg      tex_usage |= PIPE_BIND_SHARED;
10957ec681f3Smrg   if (use & __DRI_IMAGE_USE_LINEAR)
10967ec681f3Smrg      tex_usage |= PIPE_BIND_LINEAR;
10977ec681f3Smrg   if (use & __DRI_IMAGE_USE_CURSOR) {
10987ec681f3Smrg      if (width != 64 || height != 64)
10997ec681f3Smrg         return NULL;
11007ec681f3Smrg      tex_usage |= PIPE_BIND_CURSOR;
11017ec681f3Smrg   }
11027ec681f3Smrg   if (use & __DRI_IMAGE_USE_PROTECTED)
11037ec681f3Smrg      tex_usage |= PIPE_BIND_PROTECTED;
11047ec681f3Smrg
11057ec681f3Smrg   img = CALLOC_STRUCT(__DRIimageRec);
11067ec681f3Smrg   if (!img)
11077ec681f3Smrg      return NULL;
11087ec681f3Smrg
11097ec681f3Smrg   memset(&templ, 0, sizeof(templ));
11107ec681f3Smrg   templ.bind = tex_usage;
11117ec681f3Smrg   templ.format = map->pipe_format;
11127ec681f3Smrg   templ.target = PIPE_TEXTURE_2D;
11137ec681f3Smrg   templ.last_level = 0;
11147ec681f3Smrg   templ.width0 = width;
11157ec681f3Smrg   templ.height0 = height;
11167ec681f3Smrg   templ.depth0 = 1;
11177ec681f3Smrg   templ.array_size = 1;
11187ec681f3Smrg
11197ec681f3Smrg   if (modifiers)
11207ec681f3Smrg      img->texture =
11217ec681f3Smrg         screen->base.screen
11227ec681f3Smrg            ->resource_create_with_modifiers(screen->base.screen,
11237ec681f3Smrg                                             &templ,
11247ec681f3Smrg                                             modifiers,
11257ec681f3Smrg                                             count);
11267ec681f3Smrg   else
11277ec681f3Smrg      img->texture =
11287ec681f3Smrg         screen->base.screen->resource_create(screen->base.screen, &templ);
11297ec681f3Smrg   if (!img->texture) {
11307ec681f3Smrg      FREE(img);
11317ec681f3Smrg      return NULL;
11327ec681f3Smrg   }
11337ec681f3Smrg
11347ec681f3Smrg   img->level = 0;
11357ec681f3Smrg   img->layer = 0;
11367ec681f3Smrg   img->dri_format = format;
11377ec681f3Smrg   img->dri_fourcc = map->dri_fourcc;
11387ec681f3Smrg   img->dri_components = 0;
11397ec681f3Smrg   img->use = use;
11407ec681f3Smrg
11417ec681f3Smrg   img->loader_private = loaderPrivate;
11427ec681f3Smrg   img->sPriv = _screen;
11437ec681f3Smrg   return img;
11447ec681f3Smrg}
11457ec681f3Smrg
11467ec681f3Smrgstatic __DRIimage *
11477ec681f3Smrgdri2_create_image(__DRIscreen *_screen,
11487ec681f3Smrg                   int width, int height, int format,
11497ec681f3Smrg                   unsigned int use, void *loaderPrivate)
11507ec681f3Smrg{
11517ec681f3Smrg   return dri2_create_image_common(_screen, width, height, format, use,
11527ec681f3Smrg                                   NULL /* modifiers */, 0 /* count */,
11537ec681f3Smrg                                   loaderPrivate);
11547ec681f3Smrg}
11557ec681f3Smrg
11567ec681f3Smrgstatic __DRIimage *
11577ec681f3Smrgdri2_create_image_with_modifiers(__DRIscreen *dri_screen,
11587ec681f3Smrg                                 int width, int height, int format,
11597ec681f3Smrg                                 const uint64_t *modifiers,
11607ec681f3Smrg                                 const unsigned count,
11617ec681f3Smrg                                 void *loaderPrivate)
11627ec681f3Smrg{
11637ec681f3Smrg   return dri2_create_image_common(dri_screen, width, height, format,
11647ec681f3Smrg                                   __DRI_IMAGE_USE_SHARE, modifiers, count,
11657ec681f3Smrg                                   loaderPrivate);
11667ec681f3Smrg}
11677ec681f3Smrg
11687ec681f3Smrgstatic __DRIimage *
11697ec681f3Smrgdri2_create_image_with_modifiers2(__DRIscreen *dri_screen,
11707ec681f3Smrg                                 int width, int height, int format,
11717ec681f3Smrg                                 const uint64_t *modifiers,
11727ec681f3Smrg                                 const unsigned count, unsigned int use,
11737ec681f3Smrg                                 void *loaderPrivate)
11747ec681f3Smrg{
11757ec681f3Smrg   return dri2_create_image_common(dri_screen, width, height, format, use,
11767ec681f3Smrg                                   modifiers, count, loaderPrivate);
11777ec681f3Smrg}
11787ec681f3Smrg
11797ec681f3Smrgstatic bool
11807ec681f3Smrgdri2_query_image_common(__DRIimage *image, int attrib, int *value)
11817ec681f3Smrg{
11827ec681f3Smrg   switch (attrib) {
11837ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FORMAT:
11847ec681f3Smrg      *value = image->dri_format;
11857ec681f3Smrg      return true;
11867ec681f3Smrg   case __DRI_IMAGE_ATTRIB_WIDTH:
11877ec681f3Smrg      *value = image->texture->width0;
11887ec681f3Smrg      return true;
11897ec681f3Smrg   case __DRI_IMAGE_ATTRIB_HEIGHT:
11907ec681f3Smrg      *value = image->texture->height0;
11917ec681f3Smrg      return true;
11927ec681f3Smrg   case __DRI_IMAGE_ATTRIB_COMPONENTS:
11937ec681f3Smrg      if (image->dri_components == 0)
11947ec681f3Smrg         return false;
11957ec681f3Smrg      *value = image->dri_components;
11967ec681f3Smrg      return true;
11977ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FOURCC:
11987ec681f3Smrg      if (image->dri_fourcc) {
11997ec681f3Smrg         *value = image->dri_fourcc;
12007ec681f3Smrg      } else {
12017ec681f3Smrg         const struct dri2_format_mapping *map;
12027ec681f3Smrg
12037ec681f3Smrg         map = dri2_get_mapping_by_format(image->dri_format);
12047ec681f3Smrg         if (!map)
12057ec681f3Smrg            return false;
12067ec681f3Smrg
12077ec681f3Smrg         *value = map->dri_fourcc;
12087ec681f3Smrg      }
12097ec681f3Smrg      return true;
12107ec681f3Smrg   default:
12117ec681f3Smrg      return false;
12127ec681f3Smrg   }
12137ec681f3Smrg}
12147ec681f3Smrg
12157ec681f3Smrgstatic bool
12167ec681f3Smrgdri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value)
12177ec681f3Smrg{
12187ec681f3Smrg   struct pipe_screen *pscreen = image->texture->screen;
12197ec681f3Smrg   struct winsys_handle whandle;
12207ec681f3Smrg   struct pipe_resource *tex;
12217ec681f3Smrg   unsigned usage;
12227ec681f3Smrg   memset(&whandle, 0, sizeof(whandle));
12237ec681f3Smrg   whandle.plane = image->plane;
12247ec681f3Smrg   int i;
12257ec681f3Smrg
12267ec681f3Smrg   switch (attrib) {
12277ec681f3Smrg   case __DRI_IMAGE_ATTRIB_STRIDE:
12287ec681f3Smrg   case __DRI_IMAGE_ATTRIB_OFFSET:
12297ec681f3Smrg   case __DRI_IMAGE_ATTRIB_HANDLE:
12307ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
12317ec681f3Smrg      break;
12327ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NAME:
12337ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
12347ec681f3Smrg      break;
12357ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FD:
12367ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_FD;
12377ec681f3Smrg      break;
12387ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
12397ec681f3Smrg      for (i = 0, tex = image->texture; tex; tex = tex->next)
12407ec681f3Smrg         i++;
12417ec681f3Smrg      *value = i;
12427ec681f3Smrg      return true;
12437ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
12447ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
12457ec681f3Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
12467ec681f3Smrg      whandle.modifier = DRM_FORMAT_MOD_INVALID;
12477ec681f3Smrg      break;
12487ec681f3Smrg   default:
12497ec681f3Smrg      return false;
12507ec681f3Smrg   }
12517ec681f3Smrg
12527ec681f3Smrg   usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
12537ec681f3Smrg
12547ec681f3Smrg   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
12557ec681f3Smrg      usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
12567ec681f3Smrg
12577ec681f3Smrg   if (!pscreen->resource_get_handle(pscreen, NULL, image->texture,
12587ec681f3Smrg                                     &whandle, usage))
12597ec681f3Smrg      return false;
12607ec681f3Smrg
12617ec681f3Smrg   switch (attrib) {
12627ec681f3Smrg   case __DRI_IMAGE_ATTRIB_STRIDE:
12637ec681f3Smrg      *value = whandle.stride;
12647ec681f3Smrg      return true;
12657ec681f3Smrg   case __DRI_IMAGE_ATTRIB_OFFSET:
12667ec681f3Smrg      *value = whandle.offset;
12677ec681f3Smrg      return true;
12687ec681f3Smrg   case __DRI_IMAGE_ATTRIB_HANDLE:
12697ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NAME:
12707ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FD:
12717ec681f3Smrg      *value = whandle.handle;
12727ec681f3Smrg      return true;
12737ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
12747ec681f3Smrg      if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
12757ec681f3Smrg         return false;
12767ec681f3Smrg      *value = (whandle.modifier >> 32) & 0xffffffff;
12777ec681f3Smrg      return true;
12787ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
12797ec681f3Smrg      if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
12807ec681f3Smrg         return false;
12817ec681f3Smrg      *value = whandle.modifier & 0xffffffff;
12827ec681f3Smrg      return true;
12837ec681f3Smrg   default:
12847ec681f3Smrg      return false;
12857ec681f3Smrg   }
12867ec681f3Smrg}
12877ec681f3Smrg
12887ec681f3Smrgstatic bool
12897ec681f3Smrgdri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param,
12907ec681f3Smrg                        unsigned handle_usage, uint64_t *value)
12917ec681f3Smrg{
12927ec681f3Smrg   struct pipe_screen *pscreen = image->texture->screen;
12937ec681f3Smrg   if (!pscreen->resource_get_param)
12947ec681f3Smrg      return false;
12957ec681f3Smrg
12967ec681f3Smrg   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
12977ec681f3Smrg      handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
12987ec681f3Smrg
12997ec681f3Smrg   return pscreen->resource_get_param(pscreen, NULL, image->texture,
13007ec681f3Smrg                                      image->plane, 0, 0, param, handle_usage,
13017ec681f3Smrg                                      value);
13027ec681f3Smrg}
13037ec681f3Smrg
13047ec681f3Smrgstatic bool
13057ec681f3Smrgdri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value)
13067ec681f3Smrg{
13077ec681f3Smrg   enum pipe_resource_param param;
13087ec681f3Smrg   uint64_t res_param;
13097ec681f3Smrg   unsigned handle_usage;
13107ec681f3Smrg
13117ec681f3Smrg   if (!image->texture->screen->resource_get_param)
13127ec681f3Smrg      return false;
13137ec681f3Smrg
13147ec681f3Smrg   switch (attrib) {
13157ec681f3Smrg   case __DRI_IMAGE_ATTRIB_STRIDE:
13167ec681f3Smrg      param = PIPE_RESOURCE_PARAM_STRIDE;
13177ec681f3Smrg      break;
13187ec681f3Smrg   case __DRI_IMAGE_ATTRIB_OFFSET:
13197ec681f3Smrg      param = PIPE_RESOURCE_PARAM_OFFSET;
13207ec681f3Smrg      break;
13217ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
13227ec681f3Smrg      param = PIPE_RESOURCE_PARAM_NPLANES;
13237ec681f3Smrg      break;
13247ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
13257ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
13267ec681f3Smrg      param = PIPE_RESOURCE_PARAM_MODIFIER;
13277ec681f3Smrg      break;
13287ec681f3Smrg   case __DRI_IMAGE_ATTRIB_HANDLE:
13297ec681f3Smrg      param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS;
13307ec681f3Smrg      break;
13317ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NAME:
13327ec681f3Smrg      param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED;
13337ec681f3Smrg      break;
13347ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FD:
13357ec681f3Smrg      param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD;
13367ec681f3Smrg      break;
13377ec681f3Smrg   default:
13387ec681f3Smrg      return false;
13397ec681f3Smrg   }
13407ec681f3Smrg
13417ec681f3Smrg   handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
13427ec681f3Smrg
13437ec681f3Smrg   if (!dri2_resource_get_param(image, param, handle_usage, &res_param))
13447ec681f3Smrg      return false;
13457ec681f3Smrg
13467ec681f3Smrg   switch (attrib) {
13477ec681f3Smrg   case __DRI_IMAGE_ATTRIB_STRIDE:
13487ec681f3Smrg   case __DRI_IMAGE_ATTRIB_OFFSET:
13497ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
13507ec681f3Smrg      if (res_param > INT_MAX)
13517ec681f3Smrg         return false;
13527ec681f3Smrg      *value = (int)res_param;
13537ec681f3Smrg      return true;
13547ec681f3Smrg   case __DRI_IMAGE_ATTRIB_HANDLE:
13557ec681f3Smrg   case __DRI_IMAGE_ATTRIB_NAME:
13567ec681f3Smrg   case __DRI_IMAGE_ATTRIB_FD:
13577ec681f3Smrg      if (res_param > UINT_MAX)
13587ec681f3Smrg         return false;
13597ec681f3Smrg      *value = (int)res_param;
13607ec681f3Smrg      return true;
13617ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
13627ec681f3Smrg      if (res_param == DRM_FORMAT_MOD_INVALID)
13637ec681f3Smrg         return false;
13647ec681f3Smrg      *value = (res_param >> 32) & 0xffffffff;
13657ec681f3Smrg      return true;
13667ec681f3Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
13677ec681f3Smrg      if (res_param == DRM_FORMAT_MOD_INVALID)
13687ec681f3Smrg         return false;
13697ec681f3Smrg      *value = res_param & 0xffffffff;
13707ec681f3Smrg      return true;
13717ec681f3Smrg   default:
13727ec681f3Smrg      return false;
13737ec681f3Smrg   }
13747ec681f3Smrg}
13757ec681f3Smrg
13767ec681f3Smrgstatic GLboolean
13777ec681f3Smrgdri2_query_image(__DRIimage *image, int attrib, int *value)
13787ec681f3Smrg{
13797ec681f3Smrg   if (dri2_query_image_common(image, attrib, value))
13807ec681f3Smrg      return GL_TRUE;
13817ec681f3Smrg   else if (dri2_query_image_by_resource_param(image, attrib, value))
13827ec681f3Smrg      return GL_TRUE;
13837ec681f3Smrg   else if (dri2_query_image_by_resource_handle(image, attrib, value))
13847ec681f3Smrg      return GL_TRUE;
13857ec681f3Smrg   else
13867ec681f3Smrg      return GL_FALSE;
13877ec681f3Smrg}
13887ec681f3Smrg
13897ec681f3Smrgstatic __DRIimage *
13907ec681f3Smrgdri2_dup_image(__DRIimage *image, void *loaderPrivate)
13917ec681f3Smrg{
13927ec681f3Smrg   __DRIimage *img;
13937ec681f3Smrg
13947ec681f3Smrg   img = CALLOC_STRUCT(__DRIimageRec);
13957ec681f3Smrg   if (!img)
13967ec681f3Smrg      return NULL;
13977ec681f3Smrg
13987ec681f3Smrg   img->texture = NULL;
13997ec681f3Smrg   pipe_resource_reference(&img->texture, image->texture);
14007ec681f3Smrg   img->level = image->level;
14017ec681f3Smrg   img->layer = image->layer;
14027ec681f3Smrg   img->dri_format = image->dri_format;
14037ec681f3Smrg   /* This should be 0 for sub images, but dup is also used for base images. */
14047ec681f3Smrg   img->dri_components = image->dri_components;
14057ec681f3Smrg   img->use = image->use;
14067ec681f3Smrg   img->loader_private = loaderPrivate;
14077ec681f3Smrg   img->sPriv = image->sPriv;
14087ec681f3Smrg
14097ec681f3Smrg   return img;
14107ec681f3Smrg}
14117ec681f3Smrg
14127ec681f3Smrgstatic GLboolean
14137ec681f3Smrgdri2_validate_usage(__DRIimage *image, unsigned int use)
14147ec681f3Smrg{
14157ec681f3Smrg   if (!image || !image->texture)
14167ec681f3Smrg      return false;
14177ec681f3Smrg
14187ec681f3Smrg   struct pipe_screen *screen = image->texture->screen;
14197ec681f3Smrg   if (!screen->check_resource_capability)
14207ec681f3Smrg      return true;
14217ec681f3Smrg
14227ec681f3Smrg   /* We don't want to check these:
14237ec681f3Smrg    *   __DRI_IMAGE_USE_SHARE (all images are shareable)
14247ec681f3Smrg    *   __DRI_IMAGE_USE_BACKBUFFER (all images support this)
14257ec681f3Smrg    */
14267ec681f3Smrg   unsigned bind = 0;
14277ec681f3Smrg   if (use & __DRI_IMAGE_USE_SCANOUT)
14287ec681f3Smrg      bind |= PIPE_BIND_SCANOUT;
14297ec681f3Smrg   if (use & __DRI_IMAGE_USE_LINEAR)
14307ec681f3Smrg      bind |= PIPE_BIND_LINEAR;
14317ec681f3Smrg   if (use & __DRI_IMAGE_USE_CURSOR)
14327ec681f3Smrg      bind |= PIPE_BIND_CURSOR;
14337ec681f3Smrg
14347ec681f3Smrg   if (!bind)
14357ec681f3Smrg      return true;
14367ec681f3Smrg
14377ec681f3Smrg   return screen->check_resource_capability(screen, image->texture, bind);
14387ec681f3Smrg}
14397ec681f3Smrg
14407ec681f3Smrgstatic __DRIimage *
14417ec681f3Smrgdri2_from_names(__DRIscreen *screen, int width, int height, int format,
14427ec681f3Smrg                int *names, int num_names, int *strides, int *offsets,
14437ec681f3Smrg                void *loaderPrivate)
14447ec681f3Smrg{
14457ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
14467ec681f3Smrg   __DRIimage *img;
14477ec681f3Smrg   struct winsys_handle whandle;
14487ec681f3Smrg
14497ec681f3Smrg   if (!map)
14507ec681f3Smrg      return NULL;
14517ec681f3Smrg
14527ec681f3Smrg   if (num_names != 1)
14537ec681f3Smrg      return NULL;
14547ec681f3Smrg
14557ec681f3Smrg   memset(&whandle, 0, sizeof(whandle));
14567ec681f3Smrg   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
14577ec681f3Smrg   whandle.handle = names[0];
14587ec681f3Smrg   whandle.stride = strides[0];
14597ec681f3Smrg   whandle.offset = offsets[0];
14607ec681f3Smrg   whandle.format = map->pipe_format;
14617ec681f3Smrg   whandle.modifier = DRM_FORMAT_MOD_INVALID;
14627ec681f3Smrg
14637ec681f3Smrg   img = dri2_create_image_from_winsys(screen, width, height, map,
14647ec681f3Smrg                                       1, &whandle, false, loaderPrivate);
14657ec681f3Smrg   if (img == NULL)
14667ec681f3Smrg      return NULL;
14677ec681f3Smrg
14687ec681f3Smrg   img->dri_components = map->dri_components;
14697ec681f3Smrg   img->dri_fourcc = map->dri_fourcc;
14707ec681f3Smrg   img->dri_format = map->pipe_format;
14717ec681f3Smrg
14727ec681f3Smrg   return img;
14737ec681f3Smrg}
14747ec681f3Smrg
14757ec681f3Smrgstatic __DRIimage *
14767ec681f3Smrgdri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
14777ec681f3Smrg{
14787ec681f3Smrg   __DRIimage *img;
14797ec681f3Smrg
14807ec681f3Smrg   if (plane < 0) {
14817ec681f3Smrg      return NULL;
14827ec681f3Smrg   } else if (plane > 0) {
14837ec681f3Smrg      uint64_t planes;
14847ec681f3Smrg      if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0,
14857ec681f3Smrg                                   &planes) ||
14867ec681f3Smrg          plane >= planes) {
14877ec681f3Smrg         return NULL;
14887ec681f3Smrg      }
14897ec681f3Smrg   }
14907ec681f3Smrg
14917ec681f3Smrg   if (image->dri_components == 0) {
14927ec681f3Smrg      uint64_t modifier;
14937ec681f3Smrg      if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0,
14947ec681f3Smrg                                   &modifier) ||
14957ec681f3Smrg          modifier == DRM_FORMAT_MOD_INVALID) {
14967ec681f3Smrg         return NULL;
14977ec681f3Smrg      }
14987ec681f3Smrg   }
14997ec681f3Smrg
15007ec681f3Smrg   img = dri2_dup_image(image, loaderPrivate);
15017ec681f3Smrg   if (img == NULL)
15027ec681f3Smrg      return NULL;
15037ec681f3Smrg
15047ec681f3Smrg   if (img->texture->screen->resource_changed)
15057ec681f3Smrg      img->texture->screen->resource_changed(img->texture->screen,
15067ec681f3Smrg                                             img->texture);
15077ec681f3Smrg
15087ec681f3Smrg   /* set this to 0 for sub images. */
15097ec681f3Smrg   img->dri_components = 0;
15107ec681f3Smrg   img->plane = plane;
15117ec681f3Smrg   return img;
15127ec681f3Smrg}
15137ec681f3Smrg
15147ec681f3Smrgstatic __DRIimage *
15157ec681f3Smrgdri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
15167ec681f3Smrg              int *fds, int num_fds, int *strides, int *offsets,
15177ec681f3Smrg              void *loaderPrivate)
15187ec681f3Smrg{
15197ec681f3Smrg   return dri2_create_image_from_fd(screen, width, height, fourcc,
15207ec681f3Smrg                                   DRM_FORMAT_MOD_INVALID, fds, num_fds,
15217ec681f3Smrg                                   strides, offsets, false, NULL, loaderPrivate);
15227ec681f3Smrg}
15237ec681f3Smrg
15247ec681f3Smrgstatic boolean
15257ec681f3Smrgdri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
15267ec681f3Smrg                             uint64_t *modifiers, unsigned int *external_only,
15277ec681f3Smrg                             int *count)
15287ec681f3Smrg{
15297ec681f3Smrg   struct dri_screen *screen = dri_screen(_screen);
15307ec681f3Smrg   struct pipe_screen *pscreen = screen->base.screen;
15317ec681f3Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
15327ec681f3Smrg   enum pipe_format format;
15337ec681f3Smrg
15347ec681f3Smrg   if (!map)
15357ec681f3Smrg      return false;
15367ec681f3Smrg
15377ec681f3Smrg   format = map->pipe_format;
15387ec681f3Smrg
15397ec681f3Smrg   bool native_sampling = pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
15407ec681f3Smrg                                                       PIPE_BIND_SAMPLER_VIEW);
15417ec681f3Smrg   if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
15427ec681f3Smrg                                    PIPE_BIND_RENDER_TARGET) ||
15437ec681f3Smrg       native_sampling ||
15447ec681f3Smrg       dri2_yuv_dma_buf_supported(screen, map))  {
15457ec681f3Smrg      if (pscreen->query_dmabuf_modifiers != NULL) {
15467ec681f3Smrg         pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
15477ec681f3Smrg                                         external_only, count);
15487ec681f3Smrg         if (!native_sampling && external_only) {
15497ec681f3Smrg            /* To support it using YUV lowering, we need it to be samplerExternalOES.
15507ec681f3Smrg             */
15517ec681f3Smrg            for (int i = 0; i < *count; i++)
15527ec681f3Smrg               external_only[i] = true;
15537ec681f3Smrg         }
15547ec681f3Smrg      } else {
15557ec681f3Smrg         *count = 0;
15567ec681f3Smrg      }
15577ec681f3Smrg      return true;
15587ec681f3Smrg   }
15597ec681f3Smrg   return false;
15607ec681f3Smrg}
15617ec681f3Smrg
15627ec681f3Smrgstatic boolean
15637ec681f3Smrgdri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen,
15647ec681f3Smrg                                           uint32_t fourcc, uint64_t modifier,
15657ec681f3Smrg                                           int attrib, uint64_t *value)
15667ec681f3Smrg{
15677ec681f3Smrg   struct dri_screen *screen = dri_screen(_screen);
15687ec681f3Smrg   struct pipe_screen *pscreen = screen->base.screen;
15697ec681f3Smrg
15707ec681f3Smrg   if (!pscreen->query_dmabuf_modifiers)
15717ec681f3Smrg      return false;
15727ec681f3Smrg
15737ec681f3Smrg   switch (attrib) {
15747ec681f3Smrg   case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: {
15757ec681f3Smrg      uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier,
15767ec681f3Smrg                                                         fourcc);
15777ec681f3Smrg      if (mod_planes > 0)
15787ec681f3Smrg         *value = mod_planes;
15797ec681f3Smrg      return mod_planes > 0;
15807ec681f3Smrg   }
15817ec681f3Smrg   default:
15827ec681f3Smrg      return false;
15837ec681f3Smrg   }
15847ec681f3Smrg}
15857ec681f3Smrg
15867ec681f3Smrgstatic __DRIimage *
15877ec681f3Smrgdri2_from_dma_bufs(__DRIscreen *screen,
15887ec681f3Smrg                   int width, int height, int fourcc,
15897ec681f3Smrg                   int *fds, int num_fds,
15907ec681f3Smrg                   int *strides, int *offsets,
15917ec681f3Smrg                   enum __DRIYUVColorSpace yuv_color_space,
15927ec681f3Smrg                   enum __DRISampleRange sample_range,
15937ec681f3Smrg                   enum __DRIChromaSiting horizontal_siting,
15947ec681f3Smrg                   enum __DRIChromaSiting vertical_siting,
15957ec681f3Smrg                   unsigned *error,
15967ec681f3Smrg                   void *loaderPrivate)
15977ec681f3Smrg{
15987ec681f3Smrg   __DRIimage *img;
15997ec681f3Smrg
16007ec681f3Smrg   img = dri2_create_image_from_fd(screen, width, height, fourcc,
16017ec681f3Smrg                                   DRM_FORMAT_MOD_INVALID, fds, num_fds,
16027ec681f3Smrg                                   strides, offsets, false, error, loaderPrivate);
16037ec681f3Smrg   if (img == NULL)
16047ec681f3Smrg      return NULL;
16057ec681f3Smrg
16067ec681f3Smrg   img->yuv_color_space = yuv_color_space;
16077ec681f3Smrg   img->sample_range = sample_range;
16087ec681f3Smrg   img->horizontal_siting = horizontal_siting;
16097ec681f3Smrg   img->vertical_siting = vertical_siting;
16107ec681f3Smrg
16117ec681f3Smrg   *error = __DRI_IMAGE_ERROR_SUCCESS;
16127ec681f3Smrg   return img;
16137ec681f3Smrg}
16147ec681f3Smrg
16157ec681f3Smrgstatic __DRIimage *
16167ec681f3Smrgdri2_from_dma_bufs2(__DRIscreen *screen,
16177ec681f3Smrg                    int width, int height, int fourcc,
16187ec681f3Smrg                    uint64_t modifier, int *fds, int num_fds,
16197ec681f3Smrg                    int *strides, int *offsets,
16207ec681f3Smrg                    enum __DRIYUVColorSpace yuv_color_space,
16217ec681f3Smrg                    enum __DRISampleRange sample_range,
16227ec681f3Smrg                    enum __DRIChromaSiting horizontal_siting,
16237ec681f3Smrg                    enum __DRIChromaSiting vertical_siting,
16247ec681f3Smrg                    unsigned *error,
16257ec681f3Smrg                    void *loaderPrivate)
16267ec681f3Smrg{
16277ec681f3Smrg   __DRIimage *img;
16287ec681f3Smrg
16297ec681f3Smrg   img = dri2_create_image_from_fd(screen, width, height, fourcc,
16307ec681f3Smrg                                   modifier, fds, num_fds, strides, offsets,
16317ec681f3Smrg                                   false, error, loaderPrivate);
16327ec681f3Smrg   if (img == NULL)
16337ec681f3Smrg      return NULL;
16347ec681f3Smrg
16357ec681f3Smrg   img->yuv_color_space = yuv_color_space;
16367ec681f3Smrg   img->sample_range = sample_range;
16377ec681f3Smrg   img->horizontal_siting = horizontal_siting;
16387ec681f3Smrg   img->vertical_siting = vertical_siting;
16397ec681f3Smrg
16407ec681f3Smrg   *error = __DRI_IMAGE_ERROR_SUCCESS;
16417ec681f3Smrg   return img;
16427ec681f3Smrg}
16437ec681f3Smrg
16447ec681f3Smrgstatic __DRIimage *
16457ec681f3Smrgdri2_from_dma_bufs3(__DRIscreen *screen,
16467ec681f3Smrg                    int width, int height, int fourcc,
16477ec681f3Smrg                    uint64_t modifier, int *fds, int num_fds,
16487ec681f3Smrg                    int *strides, int *offsets,
16497ec681f3Smrg                    enum __DRIYUVColorSpace yuv_color_space,
16507ec681f3Smrg                    enum __DRISampleRange sample_range,
16517ec681f3Smrg                    enum __DRIChromaSiting horizontal_siting,
16527ec681f3Smrg                    enum __DRIChromaSiting vertical_siting,
16537ec681f3Smrg                    uint32_t flags,
16547ec681f3Smrg                    unsigned *error,
16557ec681f3Smrg                    void *loaderPrivate)
16567ec681f3Smrg{
16577ec681f3Smrg   __DRIimage *img;
16587ec681f3Smrg
16597ec681f3Smrg   img = dri2_create_image_from_fd(screen, width, height, fourcc,
16607ec681f3Smrg                                   modifier, fds, num_fds, strides, offsets,
16617ec681f3Smrg                                   flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG,
16627ec681f3Smrg                                   error, loaderPrivate);
16637ec681f3Smrg   if (img == NULL)
16647ec681f3Smrg      return NULL;
16657ec681f3Smrg
16667ec681f3Smrg   img->yuv_color_space = yuv_color_space;
16677ec681f3Smrg   img->sample_range = sample_range;
16687ec681f3Smrg   img->horizontal_siting = horizontal_siting;
16697ec681f3Smrg   img->vertical_siting = vertical_siting;
16707ec681f3Smrg
16717ec681f3Smrg   *error = __DRI_IMAGE_ERROR_SUCCESS;
16727ec681f3Smrg   return img;
16737ec681f3Smrg}
16747ec681f3Smrg
16757ec681f3Smrgstatic void
16767ec681f3Smrgdri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
16777ec681f3Smrg                int dstx0, int dsty0, int dstwidth, int dstheight,
16787ec681f3Smrg                int srcx0, int srcy0, int srcwidth, int srcheight,
16797ec681f3Smrg                int flush_flag)
16807ec681f3Smrg{
16817ec681f3Smrg   struct dri_context *ctx = dri_context(context);
16827ec681f3Smrg   struct pipe_context *pipe = ctx->st->pipe;
16837ec681f3Smrg   struct pipe_screen *screen;
16847ec681f3Smrg   struct pipe_fence_handle *fence;
16857ec681f3Smrg   struct pipe_blit_info blit;
16867ec681f3Smrg
16877ec681f3Smrg   if (!dst || !src)
16887ec681f3Smrg      return;
16897ec681f3Smrg
16907ec681f3Smrg   memset(&blit, 0, sizeof(blit));
16917ec681f3Smrg   blit.dst.resource = dst->texture;
16927ec681f3Smrg   blit.dst.box.x = dstx0;
16937ec681f3Smrg   blit.dst.box.y = dsty0;
16947ec681f3Smrg   blit.dst.box.width = dstwidth;
16957ec681f3Smrg   blit.dst.box.height = dstheight;
16967ec681f3Smrg   blit.dst.box.depth = 1;
16977ec681f3Smrg   blit.dst.format = dst->texture->format;
16987ec681f3Smrg   blit.src.resource = src->texture;
16997ec681f3Smrg   blit.src.box.x = srcx0;
17007ec681f3Smrg   blit.src.box.y = srcy0;
17017ec681f3Smrg   blit.src.box.width = srcwidth;
17027ec681f3Smrg   blit.src.box.height = srcheight;
17037ec681f3Smrg   blit.src.box.depth = 1;
17047ec681f3Smrg   blit.src.format = src->texture->format;
17057ec681f3Smrg   blit.mask = PIPE_MASK_RGBA;
17067ec681f3Smrg   blit.filter = PIPE_TEX_FILTER_NEAREST;
17077ec681f3Smrg   blit.is_dri_blit_image = true;
17087ec681f3Smrg
17097ec681f3Smrg   pipe->blit(pipe, &blit);
17107ec681f3Smrg
17117ec681f3Smrg   if (flush_flag == __BLIT_FLAG_FLUSH) {
17127ec681f3Smrg      pipe->flush_resource(pipe, dst->texture);
17137ec681f3Smrg      ctx->st->flush(ctx->st, 0, NULL, NULL, NULL);
17147ec681f3Smrg   } else if (flush_flag == __BLIT_FLAG_FINISH) {
17157ec681f3Smrg      screen = dri_screen(ctx->sPriv)->base.screen;
17167ec681f3Smrg      pipe->flush_resource(pipe, dst->texture);
17177ec681f3Smrg      ctx->st->flush(ctx->st, 0, &fence, NULL, NULL);
17187ec681f3Smrg      (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
17197ec681f3Smrg      screen->fence_reference(screen, &fence, NULL);
17207ec681f3Smrg   }
17217ec681f3Smrg}
17227ec681f3Smrg
17237ec681f3Smrgstatic void *
17247ec681f3Smrgdri2_map_image(__DRIcontext *context, __DRIimage *image,
17257ec681f3Smrg                int x0, int y0, int width, int height,
17267ec681f3Smrg                unsigned int flags, int *stride, void **data)
17277ec681f3Smrg{
17287ec681f3Smrg   struct dri_context *ctx = dri_context(context);
17297ec681f3Smrg   struct pipe_context *pipe = ctx->st->pipe;
17307ec681f3Smrg   enum pipe_map_flags pipe_access = 0;
17317ec681f3Smrg   struct pipe_transfer *trans;
17327ec681f3Smrg   void *map;
17337ec681f3Smrg
17347ec681f3Smrg   if (!image || !data || *data)
17357ec681f3Smrg      return NULL;
17367ec681f3Smrg
17377ec681f3Smrg   unsigned plane = image->plane;
17387ec681f3Smrg   if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes)
17397ec681f3Smrg      return NULL;
17407ec681f3Smrg
17417ec681f3Smrg   struct pipe_resource *resource = image->texture;
17427ec681f3Smrg   while (plane--)
17437ec681f3Smrg      resource = resource->next;
17447ec681f3Smrg
17457ec681f3Smrg   if (flags & __DRI_IMAGE_TRANSFER_READ)
17467ec681f3Smrg         pipe_access |= PIPE_MAP_READ;
17477ec681f3Smrg   if (flags & __DRI_IMAGE_TRANSFER_WRITE)
17487ec681f3Smrg         pipe_access |= PIPE_MAP_WRITE;
17497ec681f3Smrg
17507ec681f3Smrg   map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0,
17517ec681f3Smrg                           width, height, &trans);
17527ec681f3Smrg   if (map) {
17537ec681f3Smrg      *data = trans;
17547ec681f3Smrg      *stride = trans->stride;
17557ec681f3Smrg   }
17567ec681f3Smrg
17577ec681f3Smrg   return map;
17587ec681f3Smrg}
17597ec681f3Smrg
17607ec681f3Smrgstatic void
17617ec681f3Smrgdri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
17627ec681f3Smrg{
17637ec681f3Smrg   struct dri_context *ctx = dri_context(context);
17647ec681f3Smrg   struct pipe_context *pipe = ctx->st->pipe;
17657ec681f3Smrg
17667ec681f3Smrg   pipe_texture_unmap(pipe, (struct pipe_transfer *)data);
17677ec681f3Smrg}
17687ec681f3Smrg
17697ec681f3Smrgstatic int
17707ec681f3Smrgdri2_get_capabilities(__DRIscreen *_screen)
17717ec681f3Smrg{
17727ec681f3Smrg   struct dri_screen *screen = dri_screen(_screen);
17737ec681f3Smrg
17747ec681f3Smrg   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
17757ec681f3Smrg}
17767ec681f3Smrg
17777ec681f3Smrg/* The extension is modified during runtime if DRI_PRIME is detected */
17787ec681f3Smrgstatic const __DRIimageExtension dri2ImageExtensionTempl = {
17797ec681f3Smrg    .base = { __DRI_IMAGE, 19 },
17807ec681f3Smrg
17817ec681f3Smrg    .createImageFromName          = dri2_create_image_from_name,
17827ec681f3Smrg    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
17837ec681f3Smrg    .destroyImage                 = dri2_destroy_image,
17847ec681f3Smrg    .createImage                  = dri2_create_image,
17857ec681f3Smrg    .queryImage                   = dri2_query_image,
17867ec681f3Smrg    .dupImage                     = dri2_dup_image,
17877ec681f3Smrg    .validateUsage                = dri2_validate_usage,
17887ec681f3Smrg    .createImageFromNames         = dri2_from_names,
17897ec681f3Smrg    .fromPlanar                   = dri2_from_planar,
17907ec681f3Smrg    .createImageFromTexture       = dri2_create_from_texture,
17917ec681f3Smrg    .createImageFromFds           = NULL,
17927ec681f3Smrg    .createImageFromDmaBufs       = NULL,
17937ec681f3Smrg    .blitImage                    = dri2_blit_image,
17947ec681f3Smrg    .getCapabilities              = dri2_get_capabilities,
17957ec681f3Smrg    .mapImage                     = dri2_map_image,
17967ec681f3Smrg    .unmapImage                   = dri2_unmap_image,
17977ec681f3Smrg    .createImageWithModifiers     = NULL,
17987ec681f3Smrg    .createImageFromDmaBufs2      = NULL,
17997ec681f3Smrg    .createImageFromDmaBufs3      = NULL,
18007ec681f3Smrg    .queryDmaBufFormats           = NULL,
18017ec681f3Smrg    .queryDmaBufModifiers         = NULL,
18027ec681f3Smrg    .queryDmaBufFormatModifierAttribs = NULL,
18037ec681f3Smrg    .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
18047ec681f3Smrg    .createImageWithModifiers2    = NULL,
18057ec681f3Smrg};
18067ec681f3Smrg
18077ec681f3Smrgstatic const __DRIrobustnessExtension dri2Robustness = {
18087ec681f3Smrg   .base = { __DRI2_ROBUSTNESS, 1 }
18097ec681f3Smrg};
18107ec681f3Smrg
18117ec681f3Smrgstatic int
18127ec681f3Smrgdri2_interop_query_device_info(__DRIcontext *_ctx,
18137ec681f3Smrg                               struct mesa_glinterop_device_info *out)
18147ec681f3Smrg{
18157ec681f3Smrg   struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
18167ec681f3Smrg
18177ec681f3Smrg   /* There is no version 0, thus we do not support it */
18187ec681f3Smrg   if (out->version == 0)
18197ec681f3Smrg      return MESA_GLINTEROP_INVALID_VERSION;
18207ec681f3Smrg
18217ec681f3Smrg   out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
18227ec681f3Smrg   out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
18237ec681f3Smrg   out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
18247ec681f3Smrg   out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
18257ec681f3Smrg
18267ec681f3Smrg   out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
18277ec681f3Smrg   out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
18287ec681f3Smrg
18297ec681f3Smrg   /* Instruct the caller that we support up-to version one of the interface */
18307ec681f3Smrg   out->version = 1;
18317ec681f3Smrg
18327ec681f3Smrg   return MESA_GLINTEROP_SUCCESS;
18337ec681f3Smrg}
18347ec681f3Smrg
18357ec681f3Smrgstatic int
18367ec681f3Smrgdri2_interop_export_object(__DRIcontext *_ctx,
18377ec681f3Smrg                           struct mesa_glinterop_export_in *in,
18387ec681f3Smrg                           struct mesa_glinterop_export_out *out)
18397ec681f3Smrg{
18407ec681f3Smrg   struct st_context_iface *st = dri_context(_ctx)->st;
18417ec681f3Smrg   struct pipe_screen *screen = st->pipe->screen;
18427ec681f3Smrg   struct gl_context *ctx = ((struct st_context *)st)->ctx;
18437ec681f3Smrg   struct pipe_resource *res = NULL;
18447ec681f3Smrg   struct winsys_handle whandle;
18457ec681f3Smrg   unsigned target, usage;
18467ec681f3Smrg   boolean success;
18477ec681f3Smrg
18487ec681f3Smrg   /* There is no version 0, thus we do not support it */
18497ec681f3Smrg   if (in->version == 0 || out->version == 0)
18507ec681f3Smrg      return MESA_GLINTEROP_INVALID_VERSION;
18517ec681f3Smrg
18527ec681f3Smrg   /* Validate the target. */
18537ec681f3Smrg   switch (in->target) {
18547ec681f3Smrg   case GL_TEXTURE_BUFFER:
18557ec681f3Smrg   case GL_TEXTURE_1D:
18567ec681f3Smrg   case GL_TEXTURE_2D:
18577ec681f3Smrg   case GL_TEXTURE_3D:
18587ec681f3Smrg   case GL_TEXTURE_RECTANGLE:
18597ec681f3Smrg   case GL_TEXTURE_1D_ARRAY:
18607ec681f3Smrg   case GL_TEXTURE_2D_ARRAY:
18617ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
18627ec681f3Smrg   case GL_TEXTURE_CUBE_MAP:
18637ec681f3Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
18647ec681f3Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
18657ec681f3Smrg   case GL_TEXTURE_EXTERNAL_OES:
18667ec681f3Smrg   case GL_RENDERBUFFER:
18677ec681f3Smrg   case GL_ARRAY_BUFFER:
18687ec681f3Smrg      target = in->target;
18697ec681f3Smrg      break;
18707ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
18717ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
18727ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
18737ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
18747ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
18757ec681f3Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
18767ec681f3Smrg      target = GL_TEXTURE_CUBE_MAP;
18777ec681f3Smrg      break;
18787ec681f3Smrg   default:
18797ec681f3Smrg      return MESA_GLINTEROP_INVALID_TARGET;
18807ec681f3Smrg   }
18817ec681f3Smrg
18827ec681f3Smrg   /* Validate the simple case of miplevel. */
18837ec681f3Smrg   if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
18847ec681f3Smrg       in->miplevel != 0)
18857ec681f3Smrg      return MESA_GLINTEROP_INVALID_MIP_LEVEL;
18867ec681f3Smrg
18877ec681f3Smrg   /* Validate the OpenGL object and get pipe_resource. */
18887ec681f3Smrg   simple_mtx_lock(&ctx->Shared->Mutex);
18897ec681f3Smrg
18907ec681f3Smrg   if (target == GL_ARRAY_BUFFER) {
18917ec681f3Smrg      /* Buffer objects.
18927ec681f3Smrg       *
18937ec681f3Smrg       * The error checking is based on the documentation of
18947ec681f3Smrg       * clCreateFromGLBuffer from OpenCL 2.0 SDK.
18957ec681f3Smrg       */
18967ec681f3Smrg      struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
18977ec681f3Smrg
18987ec681f3Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
18997ec681f3Smrg       *  "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
19007ec681f3Smrg       *   a GL buffer object but does not have an existing data store or
19017ec681f3Smrg       *   the size of the buffer is 0."
19027ec681f3Smrg       */
19037ec681f3Smrg      if (!buf || buf->Size == 0) {
19047ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19057ec681f3Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
19067ec681f3Smrg      }
19077ec681f3Smrg
19087ec681f3Smrg      res = st_buffer_object(buf)->buffer;
19097ec681f3Smrg      if (!res) {
19107ec681f3Smrg         /* this shouldn't happen */
19117ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19127ec681f3Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
19137ec681f3Smrg      }
19147ec681f3Smrg
19157ec681f3Smrg      out->buf_offset = 0;
19167ec681f3Smrg      out->buf_size = buf->Size;
19177ec681f3Smrg
19187ec681f3Smrg      buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
19197ec681f3Smrg   } else if (target == GL_RENDERBUFFER) {
19207ec681f3Smrg      /* Renderbuffers.
19217ec681f3Smrg       *
19227ec681f3Smrg       * The error checking is based on the documentation of
19237ec681f3Smrg       * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
19247ec681f3Smrg       */
19257ec681f3Smrg      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
19267ec681f3Smrg
19277ec681f3Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
19287ec681f3Smrg       *   "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
19297ec681f3Smrg       *    object or if the width or height of renderbuffer is zero."
19307ec681f3Smrg       */
19317ec681f3Smrg      if (!rb || rb->Width == 0 || rb->Height == 0) {
19327ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19337ec681f3Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
19347ec681f3Smrg      }
19357ec681f3Smrg
19367ec681f3Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
19377ec681f3Smrg       *   "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
19387ec681f3Smrg       *    renderbuffer object."
19397ec681f3Smrg       */
19407ec681f3Smrg      if (rb->NumSamples > 1) {
19417ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19427ec681f3Smrg         return MESA_GLINTEROP_INVALID_OPERATION;
19437ec681f3Smrg      }
19447ec681f3Smrg
19457ec681f3Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
19467ec681f3Smrg       *   "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
19477ec681f3Smrg       *    required by the OpenCL implementation on the device."
19487ec681f3Smrg       */
19497ec681f3Smrg      res = st_renderbuffer(rb)->texture;
19507ec681f3Smrg      if (!res) {
19517ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19527ec681f3Smrg         return MESA_GLINTEROP_OUT_OF_RESOURCES;
19537ec681f3Smrg      }
19547ec681f3Smrg
19557ec681f3Smrg      out->internal_format = rb->InternalFormat;
19567ec681f3Smrg      out->view_minlevel = 0;
19577ec681f3Smrg      out->view_numlevels = 1;
19587ec681f3Smrg      out->view_minlayer = 0;
19597ec681f3Smrg      out->view_numlayers = 1;
19607ec681f3Smrg   } else {
19617ec681f3Smrg      /* Texture objects.
19627ec681f3Smrg       *
19637ec681f3Smrg       * The error checking is based on the documentation of
19647ec681f3Smrg       * clCreateFromGLTexture from OpenCL 2.0 SDK.
19657ec681f3Smrg       */
19667ec681f3Smrg      struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
19677ec681f3Smrg
19687ec681f3Smrg      if (obj)
19697ec681f3Smrg         _mesa_test_texobj_completeness(ctx, obj);
19707ec681f3Smrg
19717ec681f3Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
19727ec681f3Smrg       *   "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
19737ec681f3Smrg       *    type matches texture_target, if the specified miplevel of texture
19747ec681f3Smrg       *    is not defined, or if the width or height of the specified
19757ec681f3Smrg       *    miplevel is zero or if the GL texture object is incomplete."
19767ec681f3Smrg       */
19777ec681f3Smrg      if (!obj ||
19787ec681f3Smrg          obj->Target != target ||
19797ec681f3Smrg          !obj->_BaseComplete ||
19807ec681f3Smrg          (in->miplevel > 0 && !obj->_MipmapComplete)) {
19817ec681f3Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
19827ec681f3Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
19837ec681f3Smrg      }
19847ec681f3Smrg
19857ec681f3Smrg      if (target == GL_TEXTURE_BUFFER) {
19867ec681f3Smrg         struct st_buffer_object *stBuf =
19877ec681f3Smrg            st_buffer_object(obj->BufferObject);
19887ec681f3Smrg
19897ec681f3Smrg         if (!stBuf || !stBuf->buffer) {
19907ec681f3Smrg            /* this shouldn't happen */
19917ec681f3Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
19927ec681f3Smrg            return MESA_GLINTEROP_INVALID_OBJECT;
19937ec681f3Smrg         }
19947ec681f3Smrg         res = stBuf->buffer;
19957ec681f3Smrg
19967ec681f3Smrg         out->internal_format = obj->BufferObjectFormat;
19977ec681f3Smrg         out->buf_offset = obj->BufferOffset;
19987ec681f3Smrg         out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
19997ec681f3Smrg                                                 obj->BufferSize;
20007ec681f3Smrg
20017ec681f3Smrg         obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
20027ec681f3Smrg      } else {
20037ec681f3Smrg         /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
20047ec681f3Smrg          *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
20057ec681f3Smrg          *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
20067ec681f3Smrg          *    implementations); or greater than the value of q (for both OpenGL
20077ec681f3Smrg          *    and OpenGL ES). levelbase and q are defined for the texture in
20087ec681f3Smrg          *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
20097ec681f3Smrg          *    specification and section 3.7.10 of the OpenGL ES 2.0."
20107ec681f3Smrg          */
20117ec681f3Smrg         if (in->miplevel < obj->Attrib.BaseLevel || in->miplevel > obj->_MaxLevel) {
20127ec681f3Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
20137ec681f3Smrg            return MESA_GLINTEROP_INVALID_MIP_LEVEL;
20147ec681f3Smrg         }
20157ec681f3Smrg
20167ec681f3Smrg         if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
20177ec681f3Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
20187ec681f3Smrg            return MESA_GLINTEROP_OUT_OF_RESOURCES;
20197ec681f3Smrg         }
20207ec681f3Smrg
20217ec681f3Smrg         res = st_get_texobj_resource(obj);
20227ec681f3Smrg         if (!res) {
20237ec681f3Smrg            /* Incomplete texture buffer object? This shouldn't really occur. */
20247ec681f3Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
20257ec681f3Smrg            return MESA_GLINTEROP_INVALID_OBJECT;
20267ec681f3Smrg         }
20277ec681f3Smrg
20287ec681f3Smrg         out->internal_format = obj->Image[0][0]->InternalFormat;
20297ec681f3Smrg         out->view_minlevel = obj->Attrib.MinLevel;
20307ec681f3Smrg         out->view_numlevels = obj->Attrib.NumLevels;
20317ec681f3Smrg         out->view_minlayer = obj->Attrib.MinLayer;
20327ec681f3Smrg         out->view_numlayers = obj->Attrib.NumLayers;
20337ec681f3Smrg      }
20347ec681f3Smrg   }
20357ec681f3Smrg
20367ec681f3Smrg   /* Get the handle. */
20377ec681f3Smrg   switch (in->access) {
20387ec681f3Smrg   case MESA_GLINTEROP_ACCESS_READ_ONLY:
20397ec681f3Smrg      usage = 0;
20407ec681f3Smrg      break;
20417ec681f3Smrg   case MESA_GLINTEROP_ACCESS_READ_WRITE:
20427ec681f3Smrg   case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
20437ec681f3Smrg      usage = PIPE_HANDLE_USAGE_SHADER_WRITE;
20447ec681f3Smrg      break;
20457ec681f3Smrg   default:
20467ec681f3Smrg      usage = 0;
20477ec681f3Smrg   }
20487ec681f3Smrg
20497ec681f3Smrg   memset(&whandle, 0, sizeof(whandle));
20507ec681f3Smrg   whandle.type = WINSYS_HANDLE_TYPE_FD;
20517ec681f3Smrg
20527ec681f3Smrg   success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
20537ec681f3Smrg                                         usage);
20547ec681f3Smrg   simple_mtx_unlock(&ctx->Shared->Mutex);
20557ec681f3Smrg
20567ec681f3Smrg   if (!success)
20577ec681f3Smrg      return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
20587ec681f3Smrg
20597ec681f3Smrg   out->dmabuf_fd = whandle.handle;
20607ec681f3Smrg   out->out_driver_data_written = 0;
20617ec681f3Smrg
20627ec681f3Smrg   if (res->target == PIPE_BUFFER)
20637ec681f3Smrg      out->buf_offset += whandle.offset;
20647ec681f3Smrg
20657ec681f3Smrg   /* Instruct the caller that we support up-to version one of the interface */
20667ec681f3Smrg   in->version = 1;
20677ec681f3Smrg   out->version = 1;
20687ec681f3Smrg
20697ec681f3Smrg   return MESA_GLINTEROP_SUCCESS;
20707ec681f3Smrg}
20717ec681f3Smrg
20727ec681f3Smrgstatic const __DRI2interopExtension dri2InteropExtension = {
20737ec681f3Smrg   .base = { __DRI2_INTEROP, 1 },
20747ec681f3Smrg   .query_device_info = dri2_interop_query_device_info,
20757ec681f3Smrg   .export_object = dri2_interop_export_object
20767ec681f3Smrg};
20777ec681f3Smrg
20787ec681f3Smrg/**
20797ec681f3Smrg * \brief the DRI2bufferDamageExtension set_damage_region method
20807ec681f3Smrg */
20817ec681f3Smrgstatic void
20827ec681f3Smrgdri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects)
20837ec681f3Smrg{
20847ec681f3Smrg   struct dri_drawable *drawable = dri_drawable(dPriv);
20857ec681f3Smrg   struct pipe_box *boxes = NULL;
20867ec681f3Smrg
20877ec681f3Smrg   if (nrects) {
20887ec681f3Smrg      boxes = CALLOC(nrects, sizeof(*boxes));
20897ec681f3Smrg      assert(boxes);
20907ec681f3Smrg
20917ec681f3Smrg      for (unsigned int i = 0; i < nrects; i++) {
20927ec681f3Smrg         int *rect = &rects[i * 4];
20937ec681f3Smrg
20947ec681f3Smrg         u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]);
20957ec681f3Smrg      }
20967ec681f3Smrg   }
20977ec681f3Smrg
20987ec681f3Smrg   FREE(drawable->damage_rects);
20997ec681f3Smrg   drawable->damage_rects = boxes;
21007ec681f3Smrg   drawable->num_damage_rects = nrects;
21017ec681f3Smrg
21027ec681f3Smrg   /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */
21037ec681f3Smrg   if (drawable->texture_stamp == drawable->dPriv->lastStamp &&
21047ec681f3Smrg       (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) {
21057ec681f3Smrg      struct pipe_screen *screen = drawable->screen->base.screen;
21067ec681f3Smrg      struct pipe_resource *resource;
21077ec681f3Smrg
21087ec681f3Smrg      if (drawable->stvis.samples > 1)
21097ec681f3Smrg         resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT];
21107ec681f3Smrg      else
21117ec681f3Smrg         resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT];
21127ec681f3Smrg
21137ec681f3Smrg      screen->set_damage_region(screen, resource,
21147ec681f3Smrg                                drawable->num_damage_rects,
21157ec681f3Smrg                                drawable->damage_rects);
21167ec681f3Smrg   }
21177ec681f3Smrg}
21187ec681f3Smrg
21197ec681f3Smrgstatic const __DRI2bufferDamageExtension dri2BufferDamageExtensionTempl = {
21207ec681f3Smrg   .base = { __DRI2_BUFFER_DAMAGE, 1 },
21217ec681f3Smrg};
21227ec681f3Smrg
21237ec681f3Smrg/**
21247ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryb method
21257ec681f3Smrg */
21267ec681f3Smrgstatic int
21277ec681f3Smrgdri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
21287ec681f3Smrg                        unsigned char *val)
21297ec681f3Smrg{
21307ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
21317ec681f3Smrg
21327ec681f3Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))
21337ec681f3Smrg      return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
21347ec681f3Smrg
21357ec681f3Smrg   *val = driQueryOptionb(&screen->dev->option_cache, var);
21367ec681f3Smrg
21377ec681f3Smrg   return 0;
21387ec681f3Smrg}
21397ec681f3Smrg
21407ec681f3Smrg/**
21417ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryi method
21427ec681f3Smrg */
21437ec681f3Smrgstatic int
21447ec681f3Smrgdri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
21457ec681f3Smrg{
21467ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
21477ec681f3Smrg
21487ec681f3Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&
21497ec681f3Smrg       !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))
21507ec681f3Smrg      return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
21517ec681f3Smrg
21527ec681f3Smrg    *val = driQueryOptioni(&screen->dev->option_cache, var);
21537ec681f3Smrg
21547ec681f3Smrg    return 0;
21557ec681f3Smrg}
21567ec681f3Smrg
21577ec681f3Smrg/**
21587ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryf method
21597ec681f3Smrg */
21607ec681f3Smrgstatic int
21617ec681f3Smrgdri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
21627ec681f3Smrg{
21637ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
21647ec681f3Smrg
21657ec681f3Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))
21667ec681f3Smrg      return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
21677ec681f3Smrg
21687ec681f3Smrg    *val = driQueryOptionf(&screen->dev->option_cache, var);
21697ec681f3Smrg
21707ec681f3Smrg    return 0;
21717ec681f3Smrg}
21727ec681f3Smrg
21737ec681f3Smrg/**
21747ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQuerys method
21757ec681f3Smrg */
21767ec681f3Smrgstatic int
21777ec681f3Smrgdri2GalliumConfigQuerys(__DRIscreen *sPriv, const char *var, char **val)
21787ec681f3Smrg{
21797ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
21807ec681f3Smrg
21817ec681f3Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_STRING))
21827ec681f3Smrg      return dri2ConfigQueryExtension.configQuerys(sPriv, var, val);
21837ec681f3Smrg
21847ec681f3Smrg    *val = driQueryOptionstr(&screen->dev->option_cache, var);
21857ec681f3Smrg
21867ec681f3Smrg    return 0;
21877ec681f3Smrg}
21887ec681f3Smrg
21897ec681f3Smrg/**
21907ec681f3Smrg * \brief the DRI2ConfigQueryExtension struct.
21917ec681f3Smrg *
21927ec681f3Smrg * We first query the driver option cache. Then the dri2 option cache.
21937ec681f3Smrg */
21947ec681f3Smrgstatic const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
21957ec681f3Smrg   .base = { __DRI2_CONFIG_QUERY, 2 },
21967ec681f3Smrg
21977ec681f3Smrg   .configQueryb        = dri2GalliumConfigQueryb,
21987ec681f3Smrg   .configQueryi        = dri2GalliumConfigQueryi,
21997ec681f3Smrg   .configQueryf        = dri2GalliumConfigQueryf,
22007ec681f3Smrg   .configQuerys        = dri2GalliumConfigQuerys,
22017ec681f3Smrg};
22027ec681f3Smrg
22037ec681f3Smrg/**
22047ec681f3Smrg * \brief the DRI2blobExtension set_cache_funcs method
22057ec681f3Smrg */
22067ec681f3Smrgstatic void
22077ec681f3Smrgset_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set,
22087ec681f3Smrg                     __DRIblobCacheGet get)
22097ec681f3Smrg{
22107ec681f3Smrg   struct dri_screen *screen = dri_screen(sPriv);
22117ec681f3Smrg   struct pipe_screen *pscreen = screen->base.screen;
22127ec681f3Smrg
22137ec681f3Smrg   if (!pscreen->get_disk_shader_cache)
22147ec681f3Smrg      return;
22157ec681f3Smrg
22167ec681f3Smrg   struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen);
22177ec681f3Smrg
22187ec681f3Smrg   if (!cache)
22197ec681f3Smrg      return;
22207ec681f3Smrg
22217ec681f3Smrg   disk_cache_set_callbacks(cache, set, get);
22227ec681f3Smrg}
22237ec681f3Smrg
22247ec681f3Smrgstatic const __DRI2blobExtension driBlobExtension = {
22257ec681f3Smrg   .base = { __DRI2_BLOB, 1 },
22267ec681f3Smrg   .set_cache_funcs = set_blob_cache_funcs
22277ec681f3Smrg};
22287ec681f3Smrg
22297ec681f3Smrgstatic const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = {
22307ec681f3Smrg   .base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 },
22317ec681f3Smrg};
22327ec681f3Smrg
22337ec681f3Smrg/*
22347ec681f3Smrg * Backend function init_screen.
22357ec681f3Smrg */
22367ec681f3Smrg
22377ec681f3Smrgstatic const __DRIextension *dri_screen_extensions_base[] = {
22387ec681f3Smrg   &driTexBufferExtension.base,
22397ec681f3Smrg   &dri2FlushExtension.base,
22407ec681f3Smrg   &dri2RendererQueryExtension.base,
22417ec681f3Smrg   &dri2GalliumConfigQueryExtension.base,
22427ec681f3Smrg   &dri2ThrottleExtension.base,
22437ec681f3Smrg   &dri2FenceExtension.base,
22447ec681f3Smrg   &dri2InteropExtension.base,
22457ec681f3Smrg   &dri2NoErrorExtension.base,
22467ec681f3Smrg   &driBlobExtension.base,
22477ec681f3Smrg   &driMutableRenderBufferExtension.base,
22487ec681f3Smrg};
22497ec681f3Smrg
22507ec681f3Smrg/**
22517ec681f3Smrg * Set up the DRI extension list for this screen based on its underlying
22527ec681f3Smrg * gallium screen's capabilities.
22537ec681f3Smrg */
22547ec681f3Smrgstatic void
22557ec681f3Smrgdri2_init_screen_extensions(struct dri_screen *screen,
22567ec681f3Smrg                            struct pipe_screen *pscreen,
22577ec681f3Smrg                            bool is_kms_screen)
22587ec681f3Smrg{
22597ec681f3Smrg   const __DRIextension **nExt;
22607ec681f3Smrg
22617ec681f3Smrg   STATIC_ASSERT(sizeof(screen->screen_extensions) >=
22627ec681f3Smrg                 sizeof(dri_screen_extensions_base));
22637ec681f3Smrg   memcpy(&screen->screen_extensions, dri_screen_extensions_base,
22647ec681f3Smrg          sizeof(dri_screen_extensions_base));
22657ec681f3Smrg   screen->sPriv->extensions = screen->screen_extensions;
22667ec681f3Smrg
22677ec681f3Smrg   /* Point nExt at the end of the extension list */
22687ec681f3Smrg   nExt = &screen->screen_extensions[ARRAY_SIZE(dri_screen_extensions_base)];
22697ec681f3Smrg
22707ec681f3Smrg   screen->image_extension = dri2ImageExtensionTempl;
22717ec681f3Smrg   if (pscreen->resource_create_with_modifiers) {
22727ec681f3Smrg      screen->image_extension.createImageWithModifiers =
22737ec681f3Smrg         dri2_create_image_with_modifiers;
22747ec681f3Smrg      screen->image_extension.createImageWithModifiers2 =
22757ec681f3Smrg         dri2_create_image_with_modifiers2;
22767ec681f3Smrg   }
22777ec681f3Smrg
22787ec681f3Smrg   if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) {
22797ec681f3Smrg      uint64_t cap;
22807ec681f3Smrg
22817ec681f3Smrg      if (drmGetCap(screen->sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
22827ec681f3Smrg          (cap & DRM_PRIME_CAP_IMPORT)) {
22837ec681f3Smrg         screen->image_extension.createImageFromFds = dri2_from_fds;
22847ec681f3Smrg         screen->image_extension.createImageFromDmaBufs = dri2_from_dma_bufs;
22857ec681f3Smrg         screen->image_extension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
22867ec681f3Smrg         screen->image_extension.createImageFromDmaBufs3 = dri2_from_dma_bufs3;
22877ec681f3Smrg         screen->image_extension.queryDmaBufFormats =
22887ec681f3Smrg            dri2_query_dma_buf_formats;
22897ec681f3Smrg         screen->image_extension.queryDmaBufModifiers =
22907ec681f3Smrg            dri2_query_dma_buf_modifiers;
22917ec681f3Smrg         if (!is_kms_screen) {
22927ec681f3Smrg            screen->image_extension.queryDmaBufFormatModifierAttribs =
22937ec681f3Smrg               dri2_query_dma_buf_format_modifier_attribs;
22947ec681f3Smrg         }
22957ec681f3Smrg      }
22967ec681f3Smrg   }
22977ec681f3Smrg   *nExt++ = &screen->image_extension.base;
22987ec681f3Smrg
22997ec681f3Smrg   if (!is_kms_screen) {
23007ec681f3Smrg      screen->buffer_damage_extension = dri2BufferDamageExtensionTempl;
23017ec681f3Smrg      if (pscreen->set_damage_region)
23027ec681f3Smrg         screen->buffer_damage_extension.set_damage_region =
23037ec681f3Smrg            dri2_set_damage_region;
23047ec681f3Smrg      *nExt++ = &screen->buffer_damage_extension.base;
23057ec681f3Smrg
23067ec681f3Smrg      if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
23077ec681f3Smrg         *nExt++ = &dri2Robustness.base;
23087ec681f3Smrg         screen->has_reset_status_query = true;
23097ec681f3Smrg      }
23107ec681f3Smrg   }
23117ec681f3Smrg
23127ec681f3Smrg   /* Ensure the extension list didn't overrun its buffer and is still
23137ec681f3Smrg    * NULL-terminated */
23147ec681f3Smrg   assert(nExt - screen->screen_extensions <=
23157ec681f3Smrg          ARRAY_SIZE(screen->screen_extensions) - 1);
23167ec681f3Smrg   assert(!*nExt);
23177ec681f3Smrg}
23187ec681f3Smrg
23197ec681f3Smrg/**
23207ec681f3Smrg * This is the driver specific part of the createNewScreen entry point.
23217ec681f3Smrg *
23227ec681f3Smrg * Returns the struct gl_config supported by this driver.
23237ec681f3Smrg */
23247ec681f3Smrgstatic const __DRIconfig **
23257ec681f3Smrgdri2_init_screen(__DRIscreen * sPriv)
23267ec681f3Smrg{
23277ec681f3Smrg   const __DRIconfig **configs;
23287ec681f3Smrg   struct dri_screen *screen;
23297ec681f3Smrg   struct pipe_screen *pscreen = NULL;
23307ec681f3Smrg
23317ec681f3Smrg   screen = CALLOC_STRUCT(dri_screen);
23327ec681f3Smrg   if (!screen)
23337ec681f3Smrg      return NULL;
23347ec681f3Smrg
23357ec681f3Smrg   screen->sPriv = sPriv;
23367ec681f3Smrg   screen->fd = sPriv->fd;
23377ec681f3Smrg   (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
23387ec681f3Smrg
23397ec681f3Smrg   sPriv->driverPrivate = (void *)screen;
23407ec681f3Smrg
23417ec681f3Smrg   if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) {
23427ec681f3Smrg      pscreen = pipe_loader_create_screen(screen->dev);
23437ec681f3Smrg      dri_init_options(screen);
23447ec681f3Smrg   }
23457ec681f3Smrg
23467ec681f3Smrg   if (!pscreen)
23477ec681f3Smrg       goto release_pipe;
23487ec681f3Smrg
23497ec681f3Smrg   screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE);
23507ec681f3Smrg
23517ec681f3Smrg   dri2_init_screen_extensions(screen, pscreen, false);
23527ec681f3Smrg
23537ec681f3Smrg   configs = dri_init_screen_helper(screen, pscreen);
23547ec681f3Smrg   if (!configs)
23557ec681f3Smrg      goto destroy_screen;
23567ec681f3Smrg
23577ec681f3Smrg   screen->can_share_buffer = true;
23587ec681f3Smrg   screen->auto_fake_front = dri_with_format(sPriv);
23597ec681f3Smrg   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
23607ec681f3Smrg   screen->lookup_egl_image = dri2_lookup_egl_image;
23617ec681f3Smrg
23627ec681f3Smrg   const __DRIimageLookupExtension *loader = sPriv->dri2.image;
23637ec681f3Smrg   if (loader &&
23647ec681f3Smrg       loader->base.version >= 2 &&
23657ec681f3Smrg       loader->validateEGLImage &&
23667ec681f3Smrg       loader->lookupEGLImageValidated) {
23677ec681f3Smrg      screen->validate_egl_image = dri2_validate_egl_image;
23687ec681f3Smrg      screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated;
23697ec681f3Smrg   }
23707ec681f3Smrg
23717ec681f3Smrg   return configs;
23727ec681f3Smrg
23737ec681f3Smrgdestroy_screen:
23747ec681f3Smrg   dri_destroy_screen_helper(screen);
23757ec681f3Smrg
23767ec681f3Smrgrelease_pipe:
23777ec681f3Smrg   if (screen->dev)
23787ec681f3Smrg      pipe_loader_release(&screen->dev, 1);
23797ec681f3Smrg
23807ec681f3Smrg   FREE(screen);
23817ec681f3Smrg   return NULL;
23827ec681f3Smrg}
23837ec681f3Smrg
23847ec681f3Smrg/**
23857ec681f3Smrg * This is the driver specific part of the createNewScreen entry point.
23867ec681f3Smrg *
23877ec681f3Smrg * Returns the struct gl_config supported by this driver.
23887ec681f3Smrg */
23897ec681f3Smrgstatic const __DRIconfig **
23907ec681f3Smrgdri_kms_init_screen(__DRIscreen * sPriv)
23917ec681f3Smrg{
23927ec681f3Smrg#if defined(GALLIUM_SOFTPIPE)
23937ec681f3Smrg   const __DRIconfig **configs;
23947ec681f3Smrg   struct dri_screen *screen;
23957ec681f3Smrg   struct pipe_screen *pscreen = NULL;
23967ec681f3Smrg
23977ec681f3Smrg   screen = CALLOC_STRUCT(dri_screen);
23987ec681f3Smrg   if (!screen)
23997ec681f3Smrg      return NULL;
24007ec681f3Smrg
24017ec681f3Smrg   screen->sPriv = sPriv;
24027ec681f3Smrg   screen->fd = sPriv->fd;
24037ec681f3Smrg
24047ec681f3Smrg   sPriv->driverPrivate = (void *)screen;
24057ec681f3Smrg
24067ec681f3Smrg   if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) {
24077ec681f3Smrg      pscreen = pipe_loader_create_screen(screen->dev);
24087ec681f3Smrg      dri_init_options(screen);
24097ec681f3Smrg   }
24107ec681f3Smrg
24117ec681f3Smrg   if (!pscreen)
24127ec681f3Smrg       goto release_pipe;
24137ec681f3Smrg
24147ec681f3Smrg   dri2_init_screen_extensions(screen, pscreen, true);
24157ec681f3Smrg
24167ec681f3Smrg   configs = dri_init_screen_helper(screen, pscreen);
24177ec681f3Smrg   if (!configs)
24187ec681f3Smrg      goto destroy_screen;
24197ec681f3Smrg
24207ec681f3Smrg   screen->can_share_buffer = false;
24217ec681f3Smrg   screen->auto_fake_front = dri_with_format(sPriv);
24227ec681f3Smrg   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
24237ec681f3Smrg   screen->lookup_egl_image = dri2_lookup_egl_image;
24247ec681f3Smrg
24257ec681f3Smrg   const __DRIimageLookupExtension *loader = sPriv->dri2.image;
24267ec681f3Smrg   if (loader &&
24277ec681f3Smrg       loader->base.version >= 2 &&
24287ec681f3Smrg       loader->validateEGLImage &&
24297ec681f3Smrg       loader->lookupEGLImageValidated) {
24307ec681f3Smrg      screen->validate_egl_image = dri2_validate_egl_image;
24317ec681f3Smrg      screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated;
24327ec681f3Smrg   }
24337ec681f3Smrg
24347ec681f3Smrg   return configs;
24357ec681f3Smrg
24367ec681f3Smrgdestroy_screen:
24377ec681f3Smrg   dri_destroy_screen_helper(screen);
24387ec681f3Smrg
24397ec681f3Smrgrelease_pipe:
24407ec681f3Smrg   if (screen->dev)
24417ec681f3Smrg      pipe_loader_release(&screen->dev, 1);
24427ec681f3Smrg
24437ec681f3Smrg   FREE(screen);
24447ec681f3Smrg#endif // GALLIUM_SOFTPIPE
24457ec681f3Smrg   return NULL;
24467ec681f3Smrg}
24477ec681f3Smrg
24487ec681f3Smrgstatic boolean
24497ec681f3Smrgdri2_create_buffer(__DRIscreen * sPriv,
24507ec681f3Smrg                   __DRIdrawable * dPriv,
24517ec681f3Smrg                   const struct gl_config * visual, boolean isPixmap)
24527ec681f3Smrg{
24537ec681f3Smrg   struct dri_drawable *drawable = NULL;
24547ec681f3Smrg
24557ec681f3Smrg   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
24567ec681f3Smrg      return FALSE;
24577ec681f3Smrg
24587ec681f3Smrg   drawable = dPriv->driverPrivate;
24597ec681f3Smrg
24607ec681f3Smrg   drawable->allocate_textures = dri2_allocate_textures;
24617ec681f3Smrg   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
24627ec681f3Smrg   drawable->update_tex_buffer = dri2_update_tex_buffer;
24637ec681f3Smrg   drawable->flush_swapbuffers = dri2_flush_swapbuffers;
24647ec681f3Smrg
24657ec681f3Smrg   return TRUE;
24667ec681f3Smrg}
24677ec681f3Smrg
24687ec681f3Smrg/**
24697ec681f3Smrg * DRI driver virtual function table.
24707ec681f3Smrg *
24717ec681f3Smrg * DRI versions differ in their implementation of init_screen and swap_buffers.
24727ec681f3Smrg */
24737ec681f3Smrgconst struct __DriverAPIRec galliumdrm_driver_api = {
24747ec681f3Smrg   .InitScreen = dri2_init_screen,
24757ec681f3Smrg   .DestroyScreen = dri_destroy_screen,
24767ec681f3Smrg   .CreateContext = dri_create_context,
24777ec681f3Smrg   .DestroyContext = dri_destroy_context,
24787ec681f3Smrg   .CreateBuffer = dri2_create_buffer,
24797ec681f3Smrg   .DestroyBuffer = dri_destroy_buffer,
24807ec681f3Smrg   .MakeCurrent = dri_make_current,
24817ec681f3Smrg   .UnbindContext = dri_unbind_context,
24827ec681f3Smrg
24837ec681f3Smrg   .AllocateBuffer = dri2_allocate_buffer,
24847ec681f3Smrg   .ReleaseBuffer  = dri2_release_buffer,
24857ec681f3Smrg};
24867ec681f3Smrg
24877ec681f3Smrg/**
24887ec681f3Smrg * DRI driver virtual function table.
24897ec681f3Smrg *
24907ec681f3Smrg * KMS/DRM version of the DriverAPI above sporting a different InitScreen
24917ec681f3Smrg * hook. The latter is used to explicitly initialise the kms_swrast driver
24927ec681f3Smrg * rather than selecting the approapriate driver as suggested by the loader.
24937ec681f3Smrg */
24947ec681f3Smrgconst struct __DriverAPIRec dri_kms_driver_api = {
24957ec681f3Smrg   .InitScreen = dri_kms_init_screen,
24967ec681f3Smrg   .DestroyScreen = dri_destroy_screen,
24977ec681f3Smrg   .CreateContext = dri_create_context,
24987ec681f3Smrg   .DestroyContext = dri_destroy_context,
24997ec681f3Smrg   .CreateBuffer = dri2_create_buffer,
25007ec681f3Smrg   .DestroyBuffer = dri_destroy_buffer,
25017ec681f3Smrg   .MakeCurrent = dri_make_current,
25027ec681f3Smrg   .UnbindContext = dri_unbind_context,
25037ec681f3Smrg
25047ec681f3Smrg   .AllocateBuffer = dri2_allocate_buffer,
25057ec681f3Smrg   .ReleaseBuffer  = dri2_release_buffer,
25067ec681f3Smrg};
25077ec681f3Smrg
25087ec681f3Smrg/* This is the table of extensions that the loader will dlsym() for. */
25097ec681f3Smrgconst __DRIextension *galliumdrm_driver_extensions[] = {
25107ec681f3Smrg    &driCoreExtension.base,
25117ec681f3Smrg    &driImageDriverExtension.base,
25127ec681f3Smrg    &driDRI2Extension.base,
25137ec681f3Smrg    &gallium_config_options.base,
25147ec681f3Smrg    NULL
25157ec681f3Smrg};
25167ec681f3Smrg
25177ec681f3Smrg/* vim: set sw=3 ts=8 sts=3 expandtab: */
2518