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