1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright 2009, VMware, Inc.
5848b8605Smrg * All Rights Reserved.
6848b8605Smrg * Copyright (C) 2010 LunarG Inc.
7848b8605Smrg *
8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
9848b8605Smrg * copy of this software and associated documentation files (the "Software"),
10848b8605Smrg * to deal in the Software without restriction, including without limitation
11848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
13848b8605Smrg * Software is furnished to do so, subject to the following conditions:
14848b8605Smrg *
15848b8605Smrg * The above copyright notice and this permission notice shall be included
16848b8605Smrg * in all copies or substantial portions of the Software.
17848b8605Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
25848b8605Smrg *
26848b8605Smrg * Authors:
27848b8605Smrg *    Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz
28848b8605Smrg *    <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
29848b8605Smrg */
30848b8605Smrg
31848b8605Smrg#include <xf86drm.h>
32b8e80941Smrg#include "GL/mesa_glinterop.h"
33848b8605Smrg#include "util/u_memory.h"
34848b8605Smrg#include "util/u_inlines.h"
35848b8605Smrg#include "util/u_format.h"
36848b8605Smrg#include "util/u_debug.h"
37848b8605Smrg#include "state_tracker/drm_driver.h"
38b8e80941Smrg#include "state_tracker/st_cb_bufferobjects.h"
39b8e80941Smrg#include "state_tracker/st_cb_fbo.h"
40b8e80941Smrg#include "state_tracker/st_cb_texture.h"
41848b8605Smrg#include "state_tracker/st_texture.h"
42848b8605Smrg#include "state_tracker/st_context.h"
43848b8605Smrg#include "pipe-loader/pipe_loader.h"
44b8e80941Smrg#include "main/bufferobj.h"
45848b8605Smrg#include "main/texobj.h"
46848b8605Smrg
47b8e80941Smrg#include "dri_util.h"
48b8e80941Smrg
49b8e80941Smrg#include "dri_helpers.h"
50848b8605Smrg#include "dri_drawable.h"
51848b8605Smrg#include "dri_query_renderer.h"
52848b8605Smrg
53b8e80941Smrg#include "drm-uapi/drm_fourcc.h"
54b8e80941Smrg
55b8e80941Smrgstruct dri2_buffer
56848b8605Smrg{
57b8e80941Smrg   __DRIbuffer base;
58b8e80941Smrg   struct pipe_resource *resource;
59b8e80941Smrg};
60b8e80941Smrg
61b8e80941Smrgstatic inline struct dri2_buffer *
62b8e80941Smrgdri2_buffer(__DRIbuffer * driBufferPriv)
63b8e80941Smrg{
64b8e80941Smrg   return (struct dri2_buffer *) driBufferPriv;
65b8e80941Smrg}
66b8e80941Smrg
67b8e80941Smrgstruct dri2_format_mapping {
68b8e80941Smrg   int dri_fourcc;
69b8e80941Smrg   int dri_format;
70848b8605Smrg   int dri_components;
71b8e80941Smrg   enum pipe_format pipe_format;
72b8e80941Smrg};
73b8e80941Smrg
74b8e80941Smrgstatic const struct dri2_format_mapping dri2_format_table[] = {
75b8e80941Smrg      { __DRI_IMAGE_FOURCC_ARGB2101010,   __DRI_IMAGE_FORMAT_ARGB2101010,
76b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_B10G10R10A2_UNORM },
77b8e80941Smrg      { __DRI_IMAGE_FOURCC_XRGB2101010,   __DRI_IMAGE_FORMAT_XRGB2101010,
78b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_B10G10R10X2_UNORM },
79b8e80941Smrg      { __DRI_IMAGE_FOURCC_ABGR2101010,   __DRI_IMAGE_FORMAT_ABGR2101010,
80b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_R10G10B10A2_UNORM },
81b8e80941Smrg      { __DRI_IMAGE_FOURCC_XBGR2101010,   __DRI_IMAGE_FORMAT_XBGR2101010,
82b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_R10G10B10X2_UNORM },
83b8e80941Smrg      { __DRI_IMAGE_FOURCC_ARGB8888,      __DRI_IMAGE_FORMAT_ARGB8888,
84b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_BGRA8888_UNORM },
85b8e80941Smrg      { __DRI_IMAGE_FOURCC_ABGR8888,      __DRI_IMAGE_FORMAT_ABGR8888,
86b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_RGBA8888_UNORM },
87b8e80941Smrg      { __DRI_IMAGE_FOURCC_SARGB8888,     __DRI_IMAGE_FORMAT_SARGB8,
88b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_BGRA8888_SRGB },
89b8e80941Smrg      { __DRI_IMAGE_FOURCC_XRGB8888,      __DRI_IMAGE_FORMAT_XRGB8888,
90b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_BGRX8888_UNORM },
91b8e80941Smrg      { __DRI_IMAGE_FOURCC_XBGR8888,      __DRI_IMAGE_FORMAT_XBGR8888,
92b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_RGBX8888_UNORM },
93b8e80941Smrg      { __DRI_IMAGE_FOURCC_ARGB1555,      __DRI_IMAGE_FORMAT_ARGB1555,
94b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGBA,      PIPE_FORMAT_B5G5R5A1_UNORM },
95b8e80941Smrg      { __DRI_IMAGE_FOURCC_RGB565,        __DRI_IMAGE_FORMAT_RGB565,
96b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RGB,       PIPE_FORMAT_B5G6R5_UNORM },
97b8e80941Smrg      { __DRI_IMAGE_FOURCC_R8,            __DRI_IMAGE_FORMAT_R8,
98b8e80941Smrg        __DRI_IMAGE_COMPONENTS_R,         PIPE_FORMAT_R8_UNORM },
99b8e80941Smrg      { __DRI_IMAGE_FOURCC_R16,           __DRI_IMAGE_FORMAT_R16,
100b8e80941Smrg        __DRI_IMAGE_COMPONENTS_R,         PIPE_FORMAT_R16_UNORM },
101b8e80941Smrg      { __DRI_IMAGE_FOURCC_GR88,          __DRI_IMAGE_FORMAT_GR88,
102b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RG,        PIPE_FORMAT_RG88_UNORM },
103b8e80941Smrg      { __DRI_IMAGE_FOURCC_GR1616,        __DRI_IMAGE_FORMAT_GR88,
104b8e80941Smrg        __DRI_IMAGE_COMPONENTS_RG,        PIPE_FORMAT_RG1616_UNORM },
105b8e80941Smrg      { __DRI_IMAGE_FOURCC_YUV420,        __DRI_IMAGE_FORMAT_NONE,
106b8e80941Smrg        __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_IYUV },
107b8e80941Smrg      { __DRI_IMAGE_FOURCC_YVU420,        __DRI_IMAGE_FORMAT_NONE,
108b8e80941Smrg        __DRI_IMAGE_COMPONENTS_Y_U_V,     PIPE_FORMAT_YV12 },
109b8e80941Smrg      { __DRI_IMAGE_FOURCC_NV12,          __DRI_IMAGE_FORMAT_NONE,
110b8e80941Smrg        __DRI_IMAGE_COMPONENTS_Y_UV,      PIPE_FORMAT_NV12 },
111b8e80941Smrg      { __DRI_IMAGE_FOURCC_YUYV,          __DRI_IMAGE_FORMAT_YUYV,
112b8e80941Smrg        __DRI_IMAGE_COMPONENTS_Y_XUXV,    PIPE_FORMAT_YUYV },
113b8e80941Smrg      { __DRI_IMAGE_FOURCC_UYVY,          __DRI_IMAGE_FORMAT_UYVY,
114b8e80941Smrg        __DRI_IMAGE_COMPONENTS_Y_UXVX,    PIPE_FORMAT_UYVY },
115b8e80941Smrg};
116b8e80941Smrg
117b8e80941Smrgstatic const struct dri2_format_mapping *
118b8e80941Smrgdri2_get_mapping_by_fourcc(int fourcc) {
119b8e80941Smrg   for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
120b8e80941Smrg      if (dri2_format_table[i].dri_fourcc == fourcc)
121b8e80941Smrg               return &dri2_format_table[i];
122848b8605Smrg   }
123b8e80941Smrg
124b8e80941Smrg   return NULL;
125b8e80941Smrg}
126b8e80941Smrg
127b8e80941Smrgstatic const struct dri2_format_mapping *
128b8e80941Smrgdri2_get_mapping_by_format(int format) {
129b8e80941Smrg   for (unsigned i = 0; i < ARRAY_SIZE(dri2_format_table); i++) {
130b8e80941Smrg      if (dri2_format_table[i].dri_format == format)
131b8e80941Smrg               return &dri2_format_table[i];
132b8e80941Smrg   }
133b8e80941Smrg
134b8e80941Smrg   return NULL;
135848b8605Smrg}
136848b8605Smrg
137848b8605Smrg/**
138848b8605Smrg * DRI2 flush extension.
139848b8605Smrg */
140848b8605Smrgstatic void
141848b8605Smrgdri2_flush_drawable(__DRIdrawable *dPriv)
142848b8605Smrg{
143848b8605Smrg   dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);
144848b8605Smrg}
145848b8605Smrg
146848b8605Smrgstatic void
147848b8605Smrgdri2_invalidate_drawable(__DRIdrawable *dPriv)
148848b8605Smrg{
149848b8605Smrg   struct dri_drawable *drawable = dri_drawable(dPriv);
150848b8605Smrg
151848b8605Smrg   dri2InvalidateDrawable(dPriv);
152848b8605Smrg   drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;
153b8e80941Smrg   drawable->texture_mask = 0;
154848b8605Smrg
155848b8605Smrg   p_atomic_inc(&drawable->base.stamp);
156848b8605Smrg}
157848b8605Smrg
158848b8605Smrgstatic const __DRI2flushExtension dri2FlushExtension = {
159848b8605Smrg    .base = { __DRI2_FLUSH, 4 },
160848b8605Smrg
161848b8605Smrg    .flush                = dri2_flush_drawable,
162848b8605Smrg    .invalidate           = dri2_invalidate_drawable,
163848b8605Smrg    .flush_with_flags     = dri_flush,
164848b8605Smrg};
165848b8605Smrg
166848b8605Smrg/**
167848b8605Smrg * Retrieve __DRIbuffer from the DRI loader.
168848b8605Smrg */
169848b8605Smrgstatic __DRIbuffer *
170848b8605Smrgdri2_drawable_get_buffers(struct dri_drawable *drawable,
171848b8605Smrg                          const enum st_attachment_type *atts,
172848b8605Smrg                          unsigned *count)
173848b8605Smrg{
174848b8605Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
175848b8605Smrg   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
176848b8605Smrg   boolean with_format;
177848b8605Smrg   __DRIbuffer *buffers;
178848b8605Smrg   int num_buffers;
179848b8605Smrg   unsigned attachments[10];
180848b8605Smrg   unsigned num_attachments, i;
181848b8605Smrg
182848b8605Smrg   assert(loader);
183848b8605Smrg   with_format = dri_with_format(drawable->sPriv);
184848b8605Smrg
185848b8605Smrg   num_attachments = 0;
186848b8605Smrg
187848b8605Smrg   /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */
188848b8605Smrg   if (!with_format)
189848b8605Smrg      attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;
190848b8605Smrg
191848b8605Smrg   for (i = 0; i < *count; i++) {
192848b8605Smrg      enum pipe_format format;
193848b8605Smrg      unsigned bind;
194848b8605Smrg      int att, depth;
195848b8605Smrg
196848b8605Smrg      dri_drawable_get_format(drawable, atts[i], &format, &bind);
197848b8605Smrg      if (format == PIPE_FORMAT_NONE)
198848b8605Smrg         continue;
199848b8605Smrg
200848b8605Smrg      switch (atts[i]) {
201848b8605Smrg      case ST_ATTACHMENT_FRONT_LEFT:
202848b8605Smrg         /* already added */
203848b8605Smrg         if (!with_format)
204848b8605Smrg            continue;
205848b8605Smrg         att = __DRI_BUFFER_FRONT_LEFT;
206848b8605Smrg         break;
207848b8605Smrg      case ST_ATTACHMENT_BACK_LEFT:
208848b8605Smrg         att = __DRI_BUFFER_BACK_LEFT;
209848b8605Smrg         break;
210848b8605Smrg      case ST_ATTACHMENT_FRONT_RIGHT:
211848b8605Smrg         att = __DRI_BUFFER_FRONT_RIGHT;
212848b8605Smrg         break;
213848b8605Smrg      case ST_ATTACHMENT_BACK_RIGHT:
214848b8605Smrg         att = __DRI_BUFFER_BACK_RIGHT;
215848b8605Smrg         break;
216848b8605Smrg      default:
217848b8605Smrg         continue;
218848b8605Smrg      }
219848b8605Smrg
220848b8605Smrg      /*
221848b8605Smrg       * In this switch statement we must support all formats that
222848b8605Smrg       * may occur as the stvis->color_format.
223848b8605Smrg       */
224848b8605Smrg      switch(format) {
225b8e80941Smrg      case PIPE_FORMAT_B10G10R10A2_UNORM:
226b8e80941Smrg      case PIPE_FORMAT_R10G10B10A2_UNORM:
227b8e80941Smrg      case PIPE_FORMAT_BGRA8888_UNORM:
228b8e80941Smrg      case PIPE_FORMAT_RGBA8888_UNORM:
229848b8605Smrg	 depth = 32;
230848b8605Smrg	 break;
231b8e80941Smrg      case PIPE_FORMAT_R10G10B10X2_UNORM:
232b8e80941Smrg      case PIPE_FORMAT_B10G10R10X2_UNORM:
233b8e80941Smrg         depth = 30;
234b8e80941Smrg         break;
235b8e80941Smrg      case PIPE_FORMAT_BGRX8888_UNORM:
236b8e80941Smrg      case PIPE_FORMAT_RGBX8888_UNORM:
237848b8605Smrg	 depth = 24;
238848b8605Smrg	 break;
239848b8605Smrg      case PIPE_FORMAT_B5G6R5_UNORM:
240848b8605Smrg	 depth = 16;
241848b8605Smrg	 break;
242848b8605Smrg      default:
243848b8605Smrg	 depth = util_format_get_blocksizebits(format);
244848b8605Smrg	 assert(!"Unexpected format in dri2_drawable_get_buffers()");
245848b8605Smrg      }
246848b8605Smrg
247848b8605Smrg      attachments[num_attachments++] = att;
248848b8605Smrg      if (with_format) {
249848b8605Smrg         attachments[num_attachments++] = depth;
250848b8605Smrg      }
251848b8605Smrg   }
252848b8605Smrg
253848b8605Smrg   if (with_format) {
254848b8605Smrg      num_attachments /= 2;
255848b8605Smrg      buffers = loader->getBuffersWithFormat(dri_drawable,
256848b8605Smrg            &dri_drawable->w, &dri_drawable->h,
257848b8605Smrg            attachments, num_attachments,
258848b8605Smrg            &num_buffers, dri_drawable->loaderPrivate);
259848b8605Smrg   }
260848b8605Smrg   else {
261848b8605Smrg      buffers = loader->getBuffers(dri_drawable,
262848b8605Smrg            &dri_drawable->w, &dri_drawable->h,
263848b8605Smrg            attachments, num_attachments,
264848b8605Smrg            &num_buffers, dri_drawable->loaderPrivate);
265848b8605Smrg   }
266848b8605Smrg
267848b8605Smrg   if (buffers)
268848b8605Smrg      *count = num_buffers;
269848b8605Smrg
270848b8605Smrg   return buffers;
271848b8605Smrg}
272848b8605Smrg
273848b8605Smrgstatic bool
274848b8605Smrgdri_image_drawable_get_buffers(struct dri_drawable *drawable,
275848b8605Smrg                               struct __DRIimageList *images,
276848b8605Smrg                               const enum st_attachment_type *statts,
277848b8605Smrg                               unsigned statts_count)
278848b8605Smrg{
279848b8605Smrg   __DRIdrawable *dPriv = drawable->dPriv;
280848b8605Smrg   __DRIscreen *sPriv = drawable->sPriv;
281848b8605Smrg   unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;
282848b8605Smrg   enum pipe_format pf;
283848b8605Smrg   uint32_t buffer_mask = 0;
284848b8605Smrg   unsigned i, bind;
285848b8605Smrg
286848b8605Smrg   for (i = 0; i < statts_count; i++) {
287848b8605Smrg      dri_drawable_get_format(drawable, statts[i], &pf, &bind);
288848b8605Smrg      if (pf == PIPE_FORMAT_NONE)
289848b8605Smrg         continue;
290848b8605Smrg
291848b8605Smrg      switch (statts[i]) {
292848b8605Smrg      case ST_ATTACHMENT_FRONT_LEFT:
293848b8605Smrg         buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;
294848b8605Smrg         break;
295848b8605Smrg      case ST_ATTACHMENT_BACK_LEFT:
296848b8605Smrg         buffer_mask |= __DRI_IMAGE_BUFFER_BACK;
297848b8605Smrg         break;
298848b8605Smrg      default:
299848b8605Smrg         continue;
300848b8605Smrg      }
301848b8605Smrg
302848b8605Smrg      switch (pf) {
303b8e80941Smrg      case PIPE_FORMAT_B5G5R5A1_UNORM:
304b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB1555;
305b8e80941Smrg         break;
306848b8605Smrg      case PIPE_FORMAT_B5G6R5_UNORM:
307848b8605Smrg         image_format = __DRI_IMAGE_FORMAT_RGB565;
308848b8605Smrg         break;
309b8e80941Smrg      case PIPE_FORMAT_BGRX8888_UNORM:
310848b8605Smrg         image_format = __DRI_IMAGE_FORMAT_XRGB8888;
311848b8605Smrg         break;
312b8e80941Smrg      case PIPE_FORMAT_BGRA8888_UNORM:
313848b8605Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB8888;
314848b8605Smrg         break;
315b8e80941Smrg      case PIPE_FORMAT_RGBX8888_UNORM:
316b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_XBGR8888;
317b8e80941Smrg         break;
318b8e80941Smrg      case PIPE_FORMAT_RGBA8888_UNORM:
319848b8605Smrg         image_format = __DRI_IMAGE_FORMAT_ABGR8888;
320848b8605Smrg         break;
321b8e80941Smrg      case PIPE_FORMAT_B10G10R10X2_UNORM:
322b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_XRGB2101010;
323b8e80941Smrg         break;
324b8e80941Smrg      case PIPE_FORMAT_B10G10R10A2_UNORM:
325b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_ARGB2101010;
326b8e80941Smrg         break;
327b8e80941Smrg      case PIPE_FORMAT_R10G10B10X2_UNORM:
328b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_XBGR2101010;
329b8e80941Smrg         break;
330b8e80941Smrg      case PIPE_FORMAT_R10G10B10A2_UNORM:
331b8e80941Smrg         image_format = __DRI_IMAGE_FORMAT_ABGR2101010;
332b8e80941Smrg         break;
333848b8605Smrg      default:
334848b8605Smrg         image_format = __DRI_IMAGE_FORMAT_NONE;
335848b8605Smrg         break;
336848b8605Smrg      }
337848b8605Smrg   }
338848b8605Smrg
339848b8605Smrg   return (*sPriv->image.loader->getBuffers) (dPriv, image_format,
340848b8605Smrg                                       (uint32_t *) &drawable->base.stamp,
341848b8605Smrg                                       dPriv->loaderPrivate, buffer_mask,
342848b8605Smrg                                       images);
343848b8605Smrg}
344848b8605Smrg
345848b8605Smrgstatic __DRIbuffer *
346848b8605Smrgdri2_allocate_buffer(__DRIscreen *sPriv,
347848b8605Smrg                     unsigned attachment, unsigned format,
348848b8605Smrg                     int width, int height)
349848b8605Smrg{
350848b8605Smrg   struct dri_screen *screen = dri_screen(sPriv);
351848b8605Smrg   struct dri2_buffer *buffer;
352848b8605Smrg   struct pipe_resource templ;
353848b8605Smrg   enum pipe_format pf;
354848b8605Smrg   unsigned bind = 0;
355848b8605Smrg   struct winsys_handle whandle;
356848b8605Smrg
357848b8605Smrg   switch (attachment) {
358848b8605Smrg      case __DRI_BUFFER_FRONT_LEFT:
359848b8605Smrg      case __DRI_BUFFER_FAKE_FRONT_LEFT:
360848b8605Smrg         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
361848b8605Smrg         break;
362848b8605Smrg      case __DRI_BUFFER_BACK_LEFT:
363848b8605Smrg         bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
364848b8605Smrg         break;
365848b8605Smrg      case __DRI_BUFFER_DEPTH:
366848b8605Smrg      case __DRI_BUFFER_DEPTH_STENCIL:
367848b8605Smrg      case __DRI_BUFFER_STENCIL:
368848b8605Smrg            bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */
369848b8605Smrg         break;
370848b8605Smrg   }
371848b8605Smrg
372848b8605Smrg   /* because we get the handle and stride */
373848b8605Smrg   bind |= PIPE_BIND_SHARED;
374848b8605Smrg
375848b8605Smrg   switch (format) {
376848b8605Smrg      case 32:
377b8e80941Smrg         pf = PIPE_FORMAT_BGRA8888_UNORM;
378b8e80941Smrg         break;
379b8e80941Smrg      case 30:
380b8e80941Smrg         pf = PIPE_FORMAT_B10G10R10X2_UNORM;
381848b8605Smrg         break;
382848b8605Smrg      case 24:
383b8e80941Smrg         pf = PIPE_FORMAT_BGRX8888_UNORM;
384848b8605Smrg         break;
385848b8605Smrg      case 16:
386848b8605Smrg         pf = PIPE_FORMAT_Z16_UNORM;
387848b8605Smrg         break;
388848b8605Smrg      default:
389848b8605Smrg         return NULL;
390848b8605Smrg   }
391848b8605Smrg
392848b8605Smrg   buffer = CALLOC_STRUCT(dri2_buffer);
393848b8605Smrg   if (!buffer)
394848b8605Smrg      return NULL;
395848b8605Smrg
396848b8605Smrg   memset(&templ, 0, sizeof(templ));
397848b8605Smrg   templ.bind = bind;
398848b8605Smrg   templ.format = pf;
399848b8605Smrg   templ.target = PIPE_TEXTURE_2D;
400848b8605Smrg   templ.last_level = 0;
401848b8605Smrg   templ.width0 = width;
402848b8605Smrg   templ.height0 = height;
403848b8605Smrg   templ.depth0 = 1;
404848b8605Smrg   templ.array_size = 1;
405848b8605Smrg
406848b8605Smrg   buffer->resource =
407848b8605Smrg      screen->base.screen->resource_create(screen->base.screen, &templ);
408848b8605Smrg   if (!buffer->resource) {
409848b8605Smrg      FREE(buffer);
410848b8605Smrg      return NULL;
411848b8605Smrg   }
412848b8605Smrg
413848b8605Smrg   memset(&whandle, 0, sizeof(whandle));
414848b8605Smrg   if (screen->can_share_buffer)
415b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
416848b8605Smrg   else
417b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
418848b8605Smrg
419b8e80941Smrg   screen->base.screen->resource_get_handle(screen->base.screen, NULL,
420b8e80941Smrg         buffer->resource, &whandle,
421b8e80941Smrg         PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
422848b8605Smrg
423848b8605Smrg   buffer->base.attachment = attachment;
424848b8605Smrg   buffer->base.name = whandle.handle;
425848b8605Smrg   buffer->base.cpp = util_format_get_blocksize(pf);
426848b8605Smrg   buffer->base.pitch = whandle.stride;
427848b8605Smrg
428848b8605Smrg   return &buffer->base;
429848b8605Smrg}
430848b8605Smrg
431848b8605Smrgstatic void
432848b8605Smrgdri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)
433848b8605Smrg{
434848b8605Smrg   struct dri2_buffer *buffer = dri2_buffer(bPriv);
435848b8605Smrg
436848b8605Smrg   pipe_resource_reference(&buffer->resource, NULL);
437848b8605Smrg   FREE(buffer);
438848b8605Smrg}
439848b8605Smrg
440848b8605Smrg/*
441848b8605Smrg * Backend functions for st_framebuffer interface.
442848b8605Smrg */
443848b8605Smrg
444848b8605Smrgstatic void
445848b8605Smrgdri2_allocate_textures(struct dri_context *ctx,
446848b8605Smrg                       struct dri_drawable *drawable,
447848b8605Smrg                       const enum st_attachment_type *statts,
448848b8605Smrg                       unsigned statts_count)
449848b8605Smrg{
450848b8605Smrg   __DRIscreen *sPriv = drawable->sPriv;
451848b8605Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
452848b8605Smrg   struct dri_screen *screen = dri_screen(sPriv);
453848b8605Smrg   struct pipe_resource templ;
454848b8605Smrg   boolean alloc_depthstencil = FALSE;
455848b8605Smrg   unsigned i, j, bind;
456848b8605Smrg   const __DRIimageLoaderExtension *image = sPriv->image.loader;
457848b8605Smrg   /* Image specific variables */
458848b8605Smrg   struct __DRIimageList images;
459848b8605Smrg   /* Dri2 specific variables */
460b8e80941Smrg   __DRIbuffer *buffers = NULL;
461848b8605Smrg   struct winsys_handle whandle;
462848b8605Smrg   unsigned num_buffers = statts_count;
463848b8605Smrg
464848b8605Smrg   /* First get the buffers from the loader */
465848b8605Smrg   if (image) {
466848b8605Smrg      if (!dri_image_drawable_get_buffers(drawable, &images,
467848b8605Smrg                                          statts, statts_count))
468848b8605Smrg         return;
469848b8605Smrg   }
470848b8605Smrg   else {
471848b8605Smrg      buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);
472848b8605Smrg      if (!buffers || (drawable->old_num == num_buffers &&
473848b8605Smrg                       drawable->old_w == dri_drawable->w &&
474848b8605Smrg                       drawable->old_h == dri_drawable->h &&
475848b8605Smrg                       memcmp(drawable->old, buffers,
476848b8605Smrg                              sizeof(__DRIbuffer) * num_buffers) == 0))
477848b8605Smrg         return;
478848b8605Smrg   }
479848b8605Smrg
480848b8605Smrg   /* Second clean useless resources*/
481848b8605Smrg
482848b8605Smrg   /* See if we need a depth-stencil buffer. */
483848b8605Smrg   for (i = 0; i < statts_count; i++) {
484848b8605Smrg      if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {
485848b8605Smrg         alloc_depthstencil = TRUE;
486848b8605Smrg         break;
487848b8605Smrg      }
488848b8605Smrg   }
489848b8605Smrg
490848b8605Smrg   /* Delete the resources we won't need. */
491848b8605Smrg   for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
492848b8605Smrg      /* Don't delete the depth-stencil buffer, we can reuse it. */
493848b8605Smrg      if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)
494848b8605Smrg         continue;
495848b8605Smrg
496848b8605Smrg      /* Flush the texture before unreferencing, so that other clients can
497848b8605Smrg       * see what the driver has rendered.
498848b8605Smrg       */
499848b8605Smrg      if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {
500848b8605Smrg         struct pipe_context *pipe = ctx->st->pipe;
501848b8605Smrg         pipe->flush_resource(pipe, drawable->textures[i]);
502848b8605Smrg      }
503848b8605Smrg
504848b8605Smrg      pipe_resource_reference(&drawable->textures[i], NULL);
505848b8605Smrg   }
506848b8605Smrg
507848b8605Smrg   if (drawable->stvis.samples > 1) {
508848b8605Smrg      for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {
509848b8605Smrg         boolean del = TRUE;
510848b8605Smrg
511848b8605Smrg         /* Don't delete MSAA resources for the attachments which are enabled,
512848b8605Smrg          * we can reuse them. */
513848b8605Smrg         for (j = 0; j < statts_count; j++) {
514848b8605Smrg            if (i == statts[j]) {
515848b8605Smrg               del = FALSE;
516848b8605Smrg               break;
517848b8605Smrg            }
518848b8605Smrg         }
519848b8605Smrg
520848b8605Smrg         if (del) {
521848b8605Smrg            pipe_resource_reference(&drawable->msaa_textures[i], NULL);
522848b8605Smrg         }
523848b8605Smrg      }
524848b8605Smrg   }
525848b8605Smrg
526848b8605Smrg   /* Third use the buffers retrieved to fill the drawable info */
527848b8605Smrg
528848b8605Smrg   memset(&templ, 0, sizeof(templ));
529848b8605Smrg   templ.target = screen->target;
530848b8605Smrg   templ.last_level = 0;
531848b8605Smrg   templ.depth0 = 1;
532848b8605Smrg   templ.array_size = 1;
533848b8605Smrg
534848b8605Smrg   if (image) {
535848b8605Smrg      if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {
536848b8605Smrg         struct pipe_resource **buf =
537848b8605Smrg            &drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
538848b8605Smrg         struct pipe_resource *texture = images.front->texture;
539848b8605Smrg
540848b8605Smrg         dri_drawable->w = texture->width0;
541848b8605Smrg         dri_drawable->h = texture->height0;
542848b8605Smrg
543848b8605Smrg         pipe_resource_reference(buf, texture);
544848b8605Smrg      }
545848b8605Smrg
546848b8605Smrg      if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {
547848b8605Smrg         struct pipe_resource **buf =
548848b8605Smrg            &drawable->textures[ST_ATTACHMENT_BACK_LEFT];
549848b8605Smrg         struct pipe_resource *texture = images.back->texture;
550848b8605Smrg
551848b8605Smrg         dri_drawable->w = texture->width0;
552848b8605Smrg         dri_drawable->h = texture->height0;
553848b8605Smrg
554848b8605Smrg         pipe_resource_reference(buf, texture);
555848b8605Smrg      }
556848b8605Smrg
557848b8605Smrg      /* Note: if there is both a back and a front buffer,
558848b8605Smrg       * then they have the same size.
559848b8605Smrg       */
560848b8605Smrg      templ.width0 = dri_drawable->w;
561848b8605Smrg      templ.height0 = dri_drawable->h;
562848b8605Smrg   }
563848b8605Smrg   else {
564848b8605Smrg      memset(&whandle, 0, sizeof(whandle));
565848b8605Smrg
566848b8605Smrg      /* Process DRI-provided buffers and get pipe_resources. */
567848b8605Smrg      for (i = 0; i < num_buffers; i++) {
568848b8605Smrg         __DRIbuffer *buf = &buffers[i];
569848b8605Smrg         enum st_attachment_type statt;
570848b8605Smrg         enum pipe_format format;
571848b8605Smrg
572848b8605Smrg         switch (buf->attachment) {
573848b8605Smrg         case __DRI_BUFFER_FRONT_LEFT:
574848b8605Smrg            if (!screen->auto_fake_front) {
575848b8605Smrg               continue; /* invalid attachment */
576848b8605Smrg            }
577848b8605Smrg            /* fallthrough */
578848b8605Smrg         case __DRI_BUFFER_FAKE_FRONT_LEFT:
579848b8605Smrg            statt = ST_ATTACHMENT_FRONT_LEFT;
580848b8605Smrg            break;
581848b8605Smrg         case __DRI_BUFFER_BACK_LEFT:
582848b8605Smrg            statt = ST_ATTACHMENT_BACK_LEFT;
583848b8605Smrg            break;
584848b8605Smrg         default:
585848b8605Smrg            continue; /* invalid attachment */
586848b8605Smrg         }
587848b8605Smrg
588848b8605Smrg         dri_drawable_get_format(drawable, statt, &format, &bind);
589848b8605Smrg         if (format == PIPE_FORMAT_NONE)
590848b8605Smrg            continue;
591848b8605Smrg
592848b8605Smrg         /* dri2_drawable_get_buffers has already filled dri_drawable->w
593848b8605Smrg          * and dri_drawable->h */
594848b8605Smrg         templ.width0 = dri_drawable->w;
595848b8605Smrg         templ.height0 = dri_drawable->h;
596848b8605Smrg         templ.format = format;
597848b8605Smrg         templ.bind = bind;
598848b8605Smrg         whandle.handle = buf->name;
599848b8605Smrg         whandle.stride = buf->pitch;
600b8e80941Smrg         whandle.offset = 0;
601b8e80941Smrg         whandle.modifier = DRM_FORMAT_MOD_INVALID;
602848b8605Smrg         if (screen->can_share_buffer)
603b8e80941Smrg            whandle.type = WINSYS_HANDLE_TYPE_SHARED;
604848b8605Smrg         else
605b8e80941Smrg            whandle.type = WINSYS_HANDLE_TYPE_KMS;
606848b8605Smrg         drawable->textures[statt] =
607848b8605Smrg            screen->base.screen->resource_from_handle(screen->base.screen,
608b8e80941Smrg                  &templ, &whandle,
609b8e80941Smrg                  PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);
610848b8605Smrg         assert(drawable->textures[statt]);
611848b8605Smrg      }
612848b8605Smrg   }
613848b8605Smrg
614848b8605Smrg   /* Allocate private MSAA colorbuffers. */
615848b8605Smrg   if (drawable->stvis.samples > 1) {
616848b8605Smrg      for (i = 0; i < statts_count; i++) {
617848b8605Smrg         enum st_attachment_type statt = statts[i];
618848b8605Smrg
619848b8605Smrg         if (statt == ST_ATTACHMENT_DEPTH_STENCIL)
620848b8605Smrg            continue;
621848b8605Smrg
622848b8605Smrg         if (drawable->textures[statt]) {
623848b8605Smrg            templ.format = drawable->textures[statt]->format;
624b8e80941Smrg            templ.bind = drawable->textures[statt]->bind &
625b8e80941Smrg                         ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
626848b8605Smrg            templ.nr_samples = drawable->stvis.samples;
627b8e80941Smrg            templ.nr_storage_samples = drawable->stvis.samples;
628848b8605Smrg
629848b8605Smrg            /* Try to reuse the resource.
630848b8605Smrg             * (the other resource parameters should be constant)
631848b8605Smrg             */
632848b8605Smrg            if (!drawable->msaa_textures[statt] ||
633848b8605Smrg                drawable->msaa_textures[statt]->width0 != templ.width0 ||
634848b8605Smrg                drawable->msaa_textures[statt]->height0 != templ.height0) {
635848b8605Smrg               /* Allocate a new one. */
636848b8605Smrg               pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
637848b8605Smrg
638848b8605Smrg               drawable->msaa_textures[statt] =
639848b8605Smrg                  screen->base.screen->resource_create(screen->base.screen,
640848b8605Smrg                                                       &templ);
641848b8605Smrg               assert(drawable->msaa_textures[statt]);
642848b8605Smrg
643848b8605Smrg               /* If there are any MSAA resources, we should initialize them
644848b8605Smrg                * such that they contain the same data as the single-sample
645848b8605Smrg                * resources we just got from the X server.
646848b8605Smrg                *
647848b8605Smrg                * The reason for this is that the state tracker (and
648848b8605Smrg                * therefore the app) can access the MSAA resources only.
649848b8605Smrg                * The single-sample resources are not exposed
650848b8605Smrg                * to the state tracker.
651848b8605Smrg                *
652848b8605Smrg                */
653848b8605Smrg               dri_pipe_blit(ctx->st->pipe,
654848b8605Smrg                             drawable->msaa_textures[statt],
655848b8605Smrg                             drawable->textures[statt]);
656848b8605Smrg            }
657848b8605Smrg         }
658848b8605Smrg         else {
659848b8605Smrg            pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
660848b8605Smrg         }
661848b8605Smrg      }
662848b8605Smrg   }
663848b8605Smrg
664848b8605Smrg   /* Allocate a private depth-stencil buffer. */
665848b8605Smrg   if (alloc_depthstencil) {
666848b8605Smrg      enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;
667848b8605Smrg      struct pipe_resource **zsbuf;
668848b8605Smrg      enum pipe_format format;
669848b8605Smrg      unsigned bind;
670848b8605Smrg
671848b8605Smrg      dri_drawable_get_format(drawable, statt, &format, &bind);
672848b8605Smrg
673848b8605Smrg      if (format) {
674848b8605Smrg         templ.format = format;
675b8e80941Smrg         templ.bind = bind & ~PIPE_BIND_SHARED;
676848b8605Smrg
677848b8605Smrg         if (drawable->stvis.samples > 1) {
678848b8605Smrg            templ.nr_samples = drawable->stvis.samples;
679b8e80941Smrg            templ.nr_storage_samples = drawable->stvis.samples;
680848b8605Smrg            zsbuf = &drawable->msaa_textures[statt];
681848b8605Smrg         }
682848b8605Smrg         else {
683848b8605Smrg            templ.nr_samples = 0;
684b8e80941Smrg            templ.nr_storage_samples = 0;
685848b8605Smrg            zsbuf = &drawable->textures[statt];
686848b8605Smrg         }
687848b8605Smrg
688848b8605Smrg         /* Try to reuse the resource.
689848b8605Smrg          * (the other resource parameters should be constant)
690848b8605Smrg          */
691848b8605Smrg         if (!*zsbuf ||
692848b8605Smrg             (*zsbuf)->width0 != templ.width0 ||
693848b8605Smrg             (*zsbuf)->height0 != templ.height0) {
694848b8605Smrg            /* Allocate a new one. */
695848b8605Smrg            pipe_resource_reference(zsbuf, NULL);
696848b8605Smrg            *zsbuf = screen->base.screen->resource_create(screen->base.screen,
697848b8605Smrg                                                          &templ);
698848b8605Smrg            assert(*zsbuf);
699848b8605Smrg         }
700848b8605Smrg      }
701848b8605Smrg      else {
702848b8605Smrg         pipe_resource_reference(&drawable->msaa_textures[statt], NULL);
703848b8605Smrg         pipe_resource_reference(&drawable->textures[statt], NULL);
704848b8605Smrg      }
705848b8605Smrg   }
706848b8605Smrg
707848b8605Smrg   /* For DRI2, we may get the same buffers again from the server.
708848b8605Smrg    * To prevent useless imports of gem names, drawable->old* is used
709848b8605Smrg    * to bypass the import if we get the same buffers. This doesn't apply
710848b8605Smrg    * to DRI3/Wayland, users of image.loader, since the buffer is managed
711848b8605Smrg    * by the client (no import), and the back buffer is going to change
712848b8605Smrg    * at every redraw.
713848b8605Smrg    */
714848b8605Smrg   if (!image) {
715848b8605Smrg      drawable->old_num = num_buffers;
716848b8605Smrg      drawable->old_w = dri_drawable->w;
717848b8605Smrg      drawable->old_h = dri_drawable->h;
718848b8605Smrg      memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);
719848b8605Smrg   }
720848b8605Smrg}
721848b8605Smrg
722848b8605Smrgstatic void
723848b8605Smrgdri2_flush_frontbuffer(struct dri_context *ctx,
724848b8605Smrg                       struct dri_drawable *drawable,
725848b8605Smrg                       enum st_attachment_type statt)
726848b8605Smrg{
727848b8605Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
728848b8605Smrg   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
729848b8605Smrg   const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;
730848b8605Smrg   struct pipe_context *pipe = ctx->st->pipe;
731848b8605Smrg
732848b8605Smrg   if (statt != ST_ATTACHMENT_FRONT_LEFT)
733848b8605Smrg      return;
734848b8605Smrg
735848b8605Smrg   if (drawable->stvis.samples > 1) {
736848b8605Smrg      /* Resolve the front buffer. */
737848b8605Smrg      dri_pipe_blit(ctx->st->pipe,
738848b8605Smrg                    drawable->textures[ST_ATTACHMENT_FRONT_LEFT],
739848b8605Smrg                    drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]);
740848b8605Smrg   }
741848b8605Smrg
742848b8605Smrg   if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) {
743848b8605Smrg      pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]);
744848b8605Smrg   }
745848b8605Smrg
746848b8605Smrg   pipe->flush(pipe, NULL, 0);
747848b8605Smrg
748848b8605Smrg   if (image) {
749848b8605Smrg      image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
750848b8605Smrg   }
751848b8605Smrg   else if (loader->flushFrontBuffer) {
752848b8605Smrg      loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);
753848b8605Smrg   }
754848b8605Smrg}
755848b8605Smrg
756b8e80941Smrg/**
757b8e80941Smrg * The struct dri_drawable flush_swapbuffers callback
758b8e80941Smrg */
759b8e80941Smrgstatic void
760b8e80941Smrgdri2_flush_swapbuffers(struct dri_context *ctx,
761b8e80941Smrg                       struct dri_drawable *drawable)
762b8e80941Smrg{
763b8e80941Smrg   __DRIdrawable *dri_drawable = drawable->dPriv;
764b8e80941Smrg   const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;
765b8e80941Smrg
766b8e80941Smrg   if (image && image->base.version >= 3 && image->flushSwapBuffers) {
767b8e80941Smrg      image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate);
768b8e80941Smrg   }
769b8e80941Smrg}
770b8e80941Smrg
771848b8605Smrgstatic void
772848b8605Smrgdri2_update_tex_buffer(struct dri_drawable *drawable,
773848b8605Smrg                       struct dri_context *ctx,
774848b8605Smrg                       struct pipe_resource *res)
775848b8605Smrg{
776848b8605Smrg   /* no-op */
777848b8605Smrg}
778848b8605Smrg
779848b8605Smrgstatic __DRIimage *
780848b8605Smrgdri2_create_image_from_winsys(__DRIscreen *_screen,
781b8e80941Smrg                              int width, int height, enum pipe_format pf,
782b8e80941Smrg                              int num_handles, struct winsys_handle *whandle,
783848b8605Smrg                              void *loaderPrivate)
784848b8605Smrg{
785848b8605Smrg   struct dri_screen *screen = dri_screen(_screen);
786b8e80941Smrg   struct pipe_screen *pscreen = screen->base.screen;
787848b8605Smrg   __DRIimage *img;
788848b8605Smrg   struct pipe_resource templ;
789b8e80941Smrg   unsigned tex_usage = 0;
790b8e80941Smrg   int i;
791b8e80941Smrg
792b8e80941Smrg   if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0,
793b8e80941Smrg                                    PIPE_BIND_RENDER_TARGET))
794b8e80941Smrg      tex_usage |= PIPE_BIND_RENDER_TARGET;
795b8e80941Smrg   if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0,
796b8e80941Smrg                                    PIPE_BIND_SAMPLER_VIEW))
797b8e80941Smrg      tex_usage |= PIPE_BIND_SAMPLER_VIEW;
798b8e80941Smrg
799b8e80941Smrg   if (!tex_usage && util_format_is_yuv(pf)) {
800b8e80941Smrg      /* YUV format sampling can be emulated by the Mesa state tracker by
801b8e80941Smrg       * using multiple R8/RG88 samplers. So try to rewrite the pipe format.
802b8e80941Smrg       */
803b8e80941Smrg      pf = PIPE_FORMAT_R8_UNORM;
804848b8605Smrg
805b8e80941Smrg      if (pscreen->is_format_supported(pscreen, pf, screen->target, 0, 0,
806b8e80941Smrg                                       PIPE_BIND_SAMPLER_VIEW))
807b8e80941Smrg         tex_usage |= PIPE_BIND_SAMPLER_VIEW;
808848b8605Smrg   }
809b8e80941Smrg
810b8e80941Smrg   if (!tex_usage)
811848b8605Smrg      return NULL;
812848b8605Smrg
813848b8605Smrg   img = CALLOC_STRUCT(__DRIimageRec);
814848b8605Smrg   if (!img)
815848b8605Smrg      return NULL;
816848b8605Smrg
817848b8605Smrg   memset(&templ, 0, sizeof(templ));
818848b8605Smrg   templ.bind = tex_usage;
819848b8605Smrg   templ.target = screen->target;
820848b8605Smrg   templ.last_level = 0;
821848b8605Smrg   templ.depth0 = 1;
822848b8605Smrg   templ.array_size = 1;
823848b8605Smrg
824b8e80941Smrg   for (i = num_handles - 1; i >= 0; i--) {
825b8e80941Smrg      struct pipe_resource *tex;
826848b8605Smrg
827b8e80941Smrg      /* TODO: something a lot less ugly */
828b8e80941Smrg      switch (i) {
829b8e80941Smrg      case 0:
830b8e80941Smrg         templ.width0 = width;
831b8e80941Smrg         templ.height0 = height;
832b8e80941Smrg         templ.format = pf;
833b8e80941Smrg         break;
834b8e80941Smrg      case 1:
835b8e80941Smrg         templ.width0 = width / 2;
836b8e80941Smrg         templ.height0 = height / 2;
837b8e80941Smrg         templ.format = (num_handles == 2) ?
838b8e80941Smrg               PIPE_FORMAT_RG88_UNORM :   /* NV12, etc */
839b8e80941Smrg               PIPE_FORMAT_R8_UNORM;      /* I420, etc */
840b8e80941Smrg         break;
841b8e80941Smrg      case 2:
842b8e80941Smrg         templ.width0 = width / 2;
843b8e80941Smrg         templ.height0 = height / 2;
844b8e80941Smrg         templ.format = PIPE_FORMAT_R8_UNORM;
845b8e80941Smrg         break;
846b8e80941Smrg      default:
847b8e80941Smrg         unreachable("too many planes!");
848b8e80941Smrg      }
849b8e80941Smrg
850b8e80941Smrg      tex = pscreen->resource_from_handle(pscreen,
851b8e80941Smrg            &templ, &whandle[i], PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
852b8e80941Smrg      if (!tex) {
853b8e80941Smrg         pipe_resource_reference(&img->texture, NULL);
854b8e80941Smrg         FREE(img);
855b8e80941Smrg         return NULL;
856b8e80941Smrg      }
857b8e80941Smrg
858b8e80941Smrg      tex->next = img->texture;
859b8e80941Smrg      img->texture = tex;
860848b8605Smrg   }
861848b8605Smrg
862848b8605Smrg   img->level = 0;
863848b8605Smrg   img->layer = 0;
864b8e80941Smrg   img->use = 0;
865848b8605Smrg   img->loader_private = loaderPrivate;
866848b8605Smrg
867848b8605Smrg   return img;
868848b8605Smrg}
869848b8605Smrg
870848b8605Smrgstatic __DRIimage *
871848b8605Smrgdri2_create_image_from_name(__DRIscreen *_screen,
872848b8605Smrg                            int width, int height, int format,
873848b8605Smrg                            int name, int pitch, void *loaderPrivate)
874848b8605Smrg{
875b8e80941Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
876848b8605Smrg   struct winsys_handle whandle;
877b8e80941Smrg   __DRIimage *img;
878b8e80941Smrg
879b8e80941Smrg   if (!map)
880b8e80941Smrg      return NULL;
881848b8605Smrg
882848b8605Smrg   memset(&whandle, 0, sizeof(whandle));
883b8e80941Smrg   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
884848b8605Smrg   whandle.handle = name;
885b8e80941Smrg   whandle.modifier = DRM_FORMAT_MOD_INVALID;
886848b8605Smrg
887b8e80941Smrg   whandle.stride = pitch * util_format_get_blocksize(map->pipe_format);
888848b8605Smrg
889b8e80941Smrg   img = dri2_create_image_from_winsys(_screen, width, height, map->pipe_format,
890b8e80941Smrg                                       1, &whandle, loaderPrivate);
891848b8605Smrg
892b8e80941Smrg   if (!img)
893848b8605Smrg      return NULL;
894848b8605Smrg
895b8e80941Smrg   img->dri_components = map->dri_components;
896b8e80941Smrg   img->dri_fourcc = map->dri_fourcc;
897b8e80941Smrg   img->dri_format = map->dri_format;
898848b8605Smrg
899b8e80941Smrg   return img;
900848b8605Smrg}
901848b8605Smrg
902848b8605Smrgstatic __DRIimage *
903b8e80941Smrgdri2_create_image_from_fd(__DRIscreen *_screen,
904b8e80941Smrg                          int width, int height, int fourcc,
905b8e80941Smrg                          uint64_t modifier, int *fds, int num_fds,
906b8e80941Smrg                          int *strides, int *offsets, unsigned *error,
907b8e80941Smrg                          void *loaderPrivate)
908848b8605Smrg{
909b8e80941Smrg   struct winsys_handle whandles[3];
910b8e80941Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
911b8e80941Smrg   __DRIimage *img = NULL;
912b8e80941Smrg   unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
913b8e80941Smrg   int expected_num_fds, i;
914b8e80941Smrg
915b8e80941Smrg   if (!map) {
916b8e80941Smrg      err = __DRI_IMAGE_ERROR_BAD_MATCH;
917b8e80941Smrg      goto exit;
918b8e80941Smrg   }
919848b8605Smrg
920b8e80941Smrg   switch (fourcc) {
921b8e80941Smrg   case __DRI_IMAGE_FOURCC_YUV420:
922b8e80941Smrg   case __DRI_IMAGE_FOURCC_YVU420:
923b8e80941Smrg      expected_num_fds = 3;
924b8e80941Smrg      break;
925b8e80941Smrg   case __DRI_IMAGE_FOURCC_NV12:
926b8e80941Smrg      expected_num_fds = 2;
927b8e80941Smrg      break;
928b8e80941Smrg   default:
929b8e80941Smrg      expected_num_fds = 1;
930b8e80941Smrg      break;
931b8e80941Smrg   }
932848b8605Smrg
933b8e80941Smrg   if (num_fds != expected_num_fds) {
934b8e80941Smrg      err = __DRI_IMAGE_ERROR_BAD_MATCH;
935b8e80941Smrg      goto exit;
936b8e80941Smrg   }
937b8e80941Smrg
938b8e80941Smrg   memset(whandles, 0, sizeof(whandles));
939b8e80941Smrg
940b8e80941Smrg   for (i = 0; i < num_fds; i++) {
941b8e80941Smrg      if (fds[i] < 0) {
942b8e80941Smrg         err = __DRI_IMAGE_ERROR_BAD_ALLOC;
943b8e80941Smrg         goto exit;
944b8e80941Smrg      }
945b8e80941Smrg
946b8e80941Smrg      whandles[i].type = WINSYS_HANDLE_TYPE_FD;
947b8e80941Smrg      whandles[i].handle = (unsigned)fds[i];
948b8e80941Smrg      whandles[i].stride = (unsigned)strides[i];
949b8e80941Smrg      whandles[i].offset = (unsigned)offsets[i];
950b8e80941Smrg      whandles[i].modifier = modifier;
951b8e80941Smrg   }
952b8e80941Smrg
953b8e80941Smrg   if (fourcc == __DRI_IMAGE_FOURCC_YVU420) {
954b8e80941Smrg      /* convert to YUV420 by swapping 2nd and 3rd planes: */
955b8e80941Smrg      struct winsys_handle tmp = whandles[1];
956b8e80941Smrg      whandles[1] = whandles[2];
957b8e80941Smrg      whandles[2] = tmp;
958b8e80941Smrg      fourcc = __DRI_IMAGE_FOURCC_YUV420;
959b8e80941Smrg      map = dri2_get_mapping_by_fourcc(fourcc);
960b8e80941Smrg   }
961b8e80941Smrg
962b8e80941Smrg   img = dri2_create_image_from_winsys(_screen, width, height, map->pipe_format,
963b8e80941Smrg                                       num_fds, whandles, loaderPrivate);
964b8e80941Smrg   if(img == NULL) {
965b8e80941Smrg      err = __DRI_IMAGE_ERROR_BAD_ALLOC;
966b8e80941Smrg      goto exit;
967b8e80941Smrg   }
968b8e80941Smrg
969b8e80941Smrg   img->dri_components = map->dri_components;
970b8e80941Smrg   img->dri_fourcc = fourcc;
971b8e80941Smrg   img->dri_format = map->dri_format;
972b8e80941Smrg
973b8e80941Smrgexit:
974b8e80941Smrg   if (error)
975b8e80941Smrg      *error = err;
976b8e80941Smrg
977b8e80941Smrg   return img;
978848b8605Smrg}
979848b8605Smrg
980848b8605Smrgstatic __DRIimage *
981b8e80941Smrgdri2_create_image_common(__DRIscreen *_screen,
982b8e80941Smrg                         int width, int height,
983b8e80941Smrg                         int format, unsigned int use,
984b8e80941Smrg                         const uint64_t *modifiers,
985b8e80941Smrg                         const unsigned count,
986b8e80941Smrg                         void *loaderPrivate)
987848b8605Smrg{
988b8e80941Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
989848b8605Smrg   struct dri_screen *screen = dri_screen(_screen);
990848b8605Smrg   __DRIimage *img;
991848b8605Smrg   struct pipe_resource templ;
992848b8605Smrg   unsigned tex_usage;
993b8e80941Smrg
994b8e80941Smrg   if (!map)
995b8e80941Smrg      return NULL;
996848b8605Smrg
997848b8605Smrg   tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
998b8e80941Smrg
999848b8605Smrg   if (use & __DRI_IMAGE_USE_SCANOUT)
1000848b8605Smrg      tex_usage |= PIPE_BIND_SCANOUT;
1001848b8605Smrg   if (use & __DRI_IMAGE_USE_SHARE)
1002848b8605Smrg      tex_usage |= PIPE_BIND_SHARED;
1003848b8605Smrg   if (use & __DRI_IMAGE_USE_LINEAR)
1004848b8605Smrg      tex_usage |= PIPE_BIND_LINEAR;
1005848b8605Smrg   if (use & __DRI_IMAGE_USE_CURSOR) {
1006848b8605Smrg      if (width != 64 || height != 64)
1007848b8605Smrg         return NULL;
1008848b8605Smrg      tex_usage |= PIPE_BIND_CURSOR;
1009848b8605Smrg   }
1010848b8605Smrg
1011848b8605Smrg   img = CALLOC_STRUCT(__DRIimageRec);
1012848b8605Smrg   if (!img)
1013848b8605Smrg      return NULL;
1014848b8605Smrg
1015848b8605Smrg   memset(&templ, 0, sizeof(templ));
1016848b8605Smrg   templ.bind = tex_usage;
1017b8e80941Smrg   templ.format = map->pipe_format;
1018848b8605Smrg   templ.target = PIPE_TEXTURE_2D;
1019848b8605Smrg   templ.last_level = 0;
1020848b8605Smrg   templ.width0 = width;
1021848b8605Smrg   templ.height0 = height;
1022848b8605Smrg   templ.depth0 = 1;
1023848b8605Smrg   templ.array_size = 1;
1024848b8605Smrg
1025b8e80941Smrg   if (modifiers)
1026b8e80941Smrg      img->texture =
1027b8e80941Smrg         screen->base.screen
1028b8e80941Smrg            ->resource_create_with_modifiers(screen->base.screen,
1029b8e80941Smrg                                             &templ,
1030b8e80941Smrg                                             modifiers,
1031b8e80941Smrg                                             count);
1032b8e80941Smrg   else
1033b8e80941Smrg      img->texture =
1034b8e80941Smrg         screen->base.screen->resource_create(screen->base.screen, &templ);
1035848b8605Smrg   if (!img->texture) {
1036848b8605Smrg      FREE(img);
1037848b8605Smrg      return NULL;
1038848b8605Smrg   }
1039848b8605Smrg
1040848b8605Smrg   img->level = 0;
1041848b8605Smrg   img->layer = 0;
1042848b8605Smrg   img->dri_format = format;
1043b8e80941Smrg   img->dri_fourcc = map->dri_fourcc;
1044848b8605Smrg   img->dri_components = 0;
1045b8e80941Smrg   img->use = use;
1046848b8605Smrg
1047848b8605Smrg   img->loader_private = loaderPrivate;
1048848b8605Smrg   return img;
1049848b8605Smrg}
1050848b8605Smrg
1051b8e80941Smrgstatic __DRIimage *
1052b8e80941Smrgdri2_create_image(__DRIscreen *_screen,
1053b8e80941Smrg                   int width, int height, int format,
1054b8e80941Smrg                   unsigned int use, void *loaderPrivate)
1055b8e80941Smrg{
1056b8e80941Smrg   return dri2_create_image_common(_screen, width, height, format, use,
1057b8e80941Smrg                                   NULL /* modifiers */, 0 /* count */,
1058b8e80941Smrg                                   loaderPrivate);
1059b8e80941Smrg}
1060b8e80941Smrg
1061b8e80941Smrgstatic __DRIimage *
1062b8e80941Smrgdri2_create_image_with_modifiers(__DRIscreen *dri_screen,
1063b8e80941Smrg                                 int width, int height, int format,
1064b8e80941Smrg                                 const uint64_t *modifiers,
1065b8e80941Smrg                                 const unsigned count,
1066b8e80941Smrg                                 void *loaderPrivate)
1067b8e80941Smrg{
1068b8e80941Smrg   return dri2_create_image_common(dri_screen, width, height, format,
1069b8e80941Smrg                                   __DRI_IMAGE_USE_SHARE, modifiers, count,
1070b8e80941Smrg                                   loaderPrivate);
1071b8e80941Smrg}
1072b8e80941Smrg
1073848b8605Smrgstatic GLboolean
1074848b8605Smrgdri2_query_image(__DRIimage *image, int attrib, int *value)
1075848b8605Smrg{
1076848b8605Smrg   struct winsys_handle whandle;
1077b8e80941Smrg   unsigned usage;
1078b8e80941Smrg
1079b8e80941Smrg   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
1080b8e80941Smrg      usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
1081b8e80941Smrg   else
1082b8e80941Smrg      usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
1083b8e80941Smrg
1084848b8605Smrg   memset(&whandle, 0, sizeof(whandle));
1085848b8605Smrg
1086848b8605Smrg   switch (attrib) {
1087848b8605Smrg   case __DRI_IMAGE_ATTRIB_STRIDE:
1088b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
1089b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1090b8e80941Smrg            NULL, image->texture, &whandle, usage))
1091b8e80941Smrg         return GL_FALSE;
1092848b8605Smrg      *value = whandle.stride;
1093848b8605Smrg      return GL_TRUE;
1094b8e80941Smrg   case __DRI_IMAGE_ATTRIB_OFFSET:
1095b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
1096b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1097b8e80941Smrg            NULL, image->texture, &whandle, usage))
1098b8e80941Smrg         return GL_FALSE;
1099b8e80941Smrg      *value = whandle.offset;
1100b8e80941Smrg      return GL_TRUE;
1101848b8605Smrg   case __DRI_IMAGE_ATTRIB_HANDLE:
1102b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
1103b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1104b8e80941Smrg         NULL, image->texture, &whandle, usage))
1105b8e80941Smrg         return GL_FALSE;
1106848b8605Smrg      *value = whandle.handle;
1107848b8605Smrg      return GL_TRUE;
1108848b8605Smrg   case __DRI_IMAGE_ATTRIB_NAME:
1109b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1110b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1111b8e80941Smrg         NULL, image->texture, &whandle, usage))
1112b8e80941Smrg         return GL_FALSE;
1113848b8605Smrg      *value = whandle.handle;
1114848b8605Smrg      return GL_TRUE;
1115848b8605Smrg   case __DRI_IMAGE_ATTRIB_FD:
1116b8e80941Smrg      whandle.type= WINSYS_HANDLE_TYPE_FD;
1117b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1118b8e80941Smrg            NULL, image->texture, &whandle, usage))
1119b8e80941Smrg         return GL_FALSE;
1120b8e80941Smrg
1121848b8605Smrg      *value = whandle.handle;
1122848b8605Smrg      return GL_TRUE;
1123848b8605Smrg   case __DRI_IMAGE_ATTRIB_FORMAT:
1124848b8605Smrg      *value = image->dri_format;
1125848b8605Smrg      return GL_TRUE;
1126848b8605Smrg   case __DRI_IMAGE_ATTRIB_WIDTH:
1127848b8605Smrg      *value = image->texture->width0;
1128848b8605Smrg      return GL_TRUE;
1129848b8605Smrg   case __DRI_IMAGE_ATTRIB_HEIGHT:
1130848b8605Smrg      *value = image->texture->height0;
1131848b8605Smrg      return GL_TRUE;
1132848b8605Smrg   case __DRI_IMAGE_ATTRIB_COMPONENTS:
1133848b8605Smrg      if (image->dri_components == 0)
1134848b8605Smrg         return GL_FALSE;
1135848b8605Smrg      *value = image->dri_components;
1136848b8605Smrg      return GL_TRUE;
1137b8e80941Smrg   case __DRI_IMAGE_ATTRIB_FOURCC:
1138b8e80941Smrg      if (image->dri_fourcc) {
1139b8e80941Smrg         *value = image->dri_fourcc;
1140b8e80941Smrg      } else {
1141b8e80941Smrg         const struct dri2_format_mapping *map;
1142b8e80941Smrg
1143b8e80941Smrg         map = dri2_get_mapping_by_format(image->dri_format);
1144b8e80941Smrg         if (!map)
1145b8e80941Smrg            return GL_FALSE;
1146b8e80941Smrg
1147b8e80941Smrg         *value = map->dri_fourcc;
1148b8e80941Smrg      }
1149b8e80941Smrg      return GL_TRUE;
1150b8e80941Smrg   case __DRI_IMAGE_ATTRIB_NUM_PLANES:
1151b8e80941Smrg      *value = 1;
1152b8e80941Smrg      return GL_TRUE;
1153b8e80941Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:
1154b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
1155b8e80941Smrg      whandle.modifier = DRM_FORMAT_MOD_INVALID;
1156b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1157b8e80941Smrg            NULL, image->texture, &whandle, usage))
1158b8e80941Smrg         return GL_FALSE;
1159b8e80941Smrg      if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1160b8e80941Smrg         return GL_FALSE;
1161b8e80941Smrg      *value = (whandle.modifier >> 32) & 0xffffffff;
1162b8e80941Smrg      return GL_TRUE;
1163b8e80941Smrg   case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:
1164b8e80941Smrg      whandle.type = WINSYS_HANDLE_TYPE_KMS;
1165b8e80941Smrg      whandle.modifier = DRM_FORMAT_MOD_INVALID;
1166b8e80941Smrg      if (!image->texture->screen->resource_get_handle(image->texture->screen,
1167b8e80941Smrg            NULL, image->texture, &whandle, usage))
1168b8e80941Smrg         return GL_FALSE;
1169b8e80941Smrg      if (whandle.modifier == DRM_FORMAT_MOD_INVALID)
1170b8e80941Smrg         return GL_FALSE;
1171b8e80941Smrg      *value = whandle.modifier & 0xffffffff;
1172b8e80941Smrg      return GL_TRUE;
1173848b8605Smrg   default:
1174848b8605Smrg      return GL_FALSE;
1175848b8605Smrg   }
1176848b8605Smrg}
1177848b8605Smrg
1178848b8605Smrgstatic __DRIimage *
1179848b8605Smrgdri2_dup_image(__DRIimage *image, void *loaderPrivate)
1180848b8605Smrg{
1181848b8605Smrg   __DRIimage *img;
1182848b8605Smrg
1183848b8605Smrg   img = CALLOC_STRUCT(__DRIimageRec);
1184848b8605Smrg   if (!img)
1185848b8605Smrg      return NULL;
1186848b8605Smrg
1187848b8605Smrg   img->texture = NULL;
1188848b8605Smrg   pipe_resource_reference(&img->texture, image->texture);
1189848b8605Smrg   img->level = image->level;
1190848b8605Smrg   img->layer = image->layer;
1191848b8605Smrg   img->dri_format = image->dri_format;
1192848b8605Smrg   /* This should be 0 for sub images, but dup is also used for base images. */
1193848b8605Smrg   img->dri_components = image->dri_components;
1194848b8605Smrg   img->loader_private = loaderPrivate;
1195848b8605Smrg
1196848b8605Smrg   return img;
1197848b8605Smrg}
1198848b8605Smrg
1199848b8605Smrgstatic GLboolean
1200848b8605Smrgdri2_validate_usage(__DRIimage *image, unsigned int use)
1201848b8605Smrg{
1202b8e80941Smrg   if (!image || !image->texture)
1203b8e80941Smrg      return false;
1204b8e80941Smrg
1205b8e80941Smrg   struct pipe_screen *screen = image->texture->screen;
1206b8e80941Smrg   if (!screen->check_resource_capability)
1207b8e80941Smrg      return true;
1208b8e80941Smrg
1209b8e80941Smrg   /* We don't want to check these:
1210b8e80941Smrg    *   __DRI_IMAGE_USE_SHARE (all images are shareable)
1211b8e80941Smrg    *   __DRI_IMAGE_USE_BACKBUFFER (all images support this)
1212848b8605Smrg    */
1213b8e80941Smrg   unsigned bind = 0;
1214b8e80941Smrg   if (use & __DRI_IMAGE_USE_SCANOUT)
1215b8e80941Smrg      bind |= PIPE_BIND_SCANOUT;
1216b8e80941Smrg   if (use & __DRI_IMAGE_USE_LINEAR)
1217b8e80941Smrg      bind |= PIPE_BIND_LINEAR;
1218b8e80941Smrg   if (use & __DRI_IMAGE_USE_CURSOR)
1219b8e80941Smrg      bind |= PIPE_BIND_CURSOR;
1220b8e80941Smrg
1221b8e80941Smrg   if (!bind)
1222b8e80941Smrg      return true;
1223b8e80941Smrg
1224b8e80941Smrg   return screen->check_resource_capability(screen, image->texture, bind);
1225848b8605Smrg}
1226848b8605Smrg
1227848b8605Smrgstatic __DRIimage *
1228848b8605Smrgdri2_from_names(__DRIscreen *screen, int width, int height, int format,
1229848b8605Smrg                int *names, int num_names, int *strides, int *offsets,
1230848b8605Smrg                void *loaderPrivate)
1231848b8605Smrg{
1232b8e80941Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);
1233848b8605Smrg   __DRIimage *img;
1234b8e80941Smrg   struct winsys_handle whandle;
1235848b8605Smrg
1236b8e80941Smrg   if (!map)
1237848b8605Smrg      return NULL;
1238848b8605Smrg
1239b8e80941Smrg   if (num_names != 1)
1240848b8605Smrg      return NULL;
1241848b8605Smrg
1242b8e80941Smrg   memset(&whandle, 0, sizeof(whandle));
1243b8e80941Smrg   whandle.type = WINSYS_HANDLE_TYPE_SHARED;
1244b8e80941Smrg   whandle.handle = names[0];
1245b8e80941Smrg   whandle.stride = strides[0];
1246b8e80941Smrg   whandle.offset = offsets[0];
1247b8e80941Smrg   whandle.modifier = DRM_FORMAT_MOD_INVALID;
1248b8e80941Smrg
1249b8e80941Smrg   img = dri2_create_image_from_winsys(screen, width, height, map->pipe_format,
1250b8e80941Smrg                                       1, &whandle, loaderPrivate);
1251848b8605Smrg   if (img == NULL)
1252848b8605Smrg      return NULL;
1253848b8605Smrg
1254b8e80941Smrg   img->dri_components = map->dri_components;
1255b8e80941Smrg   img->dri_fourcc = map->dri_fourcc;
1256b8e80941Smrg   img->dri_format = map->pipe_format;
1257b8e80941Smrg
1258848b8605Smrg   return img;
1259848b8605Smrg}
1260848b8605Smrg
1261848b8605Smrgstatic __DRIimage *
1262848b8605Smrgdri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)
1263848b8605Smrg{
1264848b8605Smrg   __DRIimage *img;
1265848b8605Smrg
1266848b8605Smrg   if (plane != 0)
1267848b8605Smrg      return NULL;
1268848b8605Smrg
1269848b8605Smrg   if (image->dri_components == 0)
1270848b8605Smrg      return NULL;
1271848b8605Smrg
1272848b8605Smrg   img = dri2_dup_image(image, loaderPrivate);
1273848b8605Smrg   if (img == NULL)
1274848b8605Smrg      return NULL;
1275848b8605Smrg
1276b8e80941Smrg   if (img->texture->screen->resource_changed)
1277b8e80941Smrg      img->texture->screen->resource_changed(img->texture->screen,
1278b8e80941Smrg                                             img->texture);
1279b8e80941Smrg
1280848b8605Smrg   /* set this to 0 for sub images. */
1281848b8605Smrg   img->dri_components = 0;
1282848b8605Smrg   return img;
1283848b8605Smrg}
1284848b8605Smrg
1285848b8605Smrgstatic __DRIimage *
1286848b8605Smrgdri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,
1287848b8605Smrg              int *fds, int num_fds, int *strides, int *offsets,
1288848b8605Smrg              void *loaderPrivate)
1289848b8605Smrg{
1290b8e80941Smrg   return dri2_create_image_from_fd(screen, width, height, fourcc,
1291b8e80941Smrg                                   DRM_FORMAT_MOD_INVALID, fds, num_fds,
1292b8e80941Smrg                                   strides, offsets, NULL, loaderPrivate);
1293b8e80941Smrg}
1294848b8605Smrg
1295b8e80941Smrgstatic boolean
1296b8e80941Smrgdri2_query_dma_buf_formats(__DRIscreen *_screen, int max, int *formats,
1297b8e80941Smrg                           int *count)
1298b8e80941Smrg{
1299b8e80941Smrg   struct dri_screen *screen = dri_screen(_screen);
1300b8e80941Smrg   struct pipe_screen *pscreen = screen->base.screen;
1301b8e80941Smrg   int i, j;
1302848b8605Smrg
1303b8e80941Smrg   for (i = 0, j = 0; (i < ARRAY_SIZE(dri2_format_table)) &&
1304b8e80941Smrg         (j < max || max == 0); i++) {
1305b8e80941Smrg      const struct dri2_format_mapping *map = &dri2_format_table[i];
1306848b8605Smrg
1307b8e80941Smrg      /* The sRGB format is not a real FourCC as defined by drm_fourcc.h, so we
1308b8e80941Smrg       * must not leak it out to clients.
1309b8e80941Smrg       */
1310b8e80941Smrg      if (dri2_format_table[i].dri_fourcc == __DRI_IMAGE_FOURCC_SARGB8888)
1311b8e80941Smrg         continue;
1312848b8605Smrg
1313b8e80941Smrg      if (pscreen->is_format_supported(pscreen, map->pipe_format,
1314b8e80941Smrg                                       screen->target, 0, 0,
1315b8e80941Smrg                                       PIPE_BIND_RENDER_TARGET) ||
1316b8e80941Smrg          pscreen->is_format_supported(pscreen, map->pipe_format,
1317b8e80941Smrg                                       screen->target, 0, 0,
1318b8e80941Smrg                                       PIPE_BIND_SAMPLER_VIEW)) {
1319b8e80941Smrg         if (j < max)
1320b8e80941Smrg            formats[j] = map->dri_fourcc;
1321b8e80941Smrg         j++;
1322b8e80941Smrg      }
1323b8e80941Smrg   }
1324b8e80941Smrg   *count = j;
1325b8e80941Smrg   return true;
1326b8e80941Smrg}
1327848b8605Smrg
1328b8e80941Smrgstatic boolean
1329b8e80941Smrgdri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,
1330b8e80941Smrg                             uint64_t *modifiers, unsigned int *external_only,
1331b8e80941Smrg                             int *count)
1332b8e80941Smrg{
1333b8e80941Smrg   struct dri_screen *screen = dri_screen(_screen);
1334b8e80941Smrg   struct pipe_screen *pscreen = screen->base.screen;
1335b8e80941Smrg   const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);
1336b8e80941Smrg   enum pipe_format format;
1337b8e80941Smrg
1338b8e80941Smrg   if (!map)
1339b8e80941Smrg      return false;
1340b8e80941Smrg
1341b8e80941Smrg   format = map->pipe_format;
1342b8e80941Smrg
1343b8e80941Smrg   if (pscreen->query_dmabuf_modifiers != NULL &&
1344b8e80941Smrg       (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1345b8e80941Smrg                                     PIPE_BIND_RENDER_TARGET) ||
1346b8e80941Smrg        pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,
1347b8e80941Smrg                                     PIPE_BIND_SAMPLER_VIEW))) {
1348b8e80941Smrg      pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,
1349b8e80941Smrg                                      external_only, count);
1350b8e80941Smrg      return true;
1351b8e80941Smrg   }
1352b8e80941Smrg   return false;
1353848b8605Smrg}
1354848b8605Smrg
1355848b8605Smrgstatic __DRIimage *
1356848b8605Smrgdri2_from_dma_bufs(__DRIscreen *screen,
1357848b8605Smrg                   int width, int height, int fourcc,
1358848b8605Smrg                   int *fds, int num_fds,
1359848b8605Smrg                   int *strides, int *offsets,
1360848b8605Smrg                   enum __DRIYUVColorSpace yuv_color_space,
1361848b8605Smrg                   enum __DRISampleRange sample_range,
1362848b8605Smrg                   enum __DRIChromaSiting horizontal_siting,
1363848b8605Smrg                   enum __DRIChromaSiting vertical_siting,
1364848b8605Smrg                   unsigned *error,
1365848b8605Smrg                   void *loaderPrivate)
1366848b8605Smrg{
1367848b8605Smrg   __DRIimage *img;
1368848b8605Smrg
1369b8e80941Smrg   img = dri2_create_image_from_fd(screen, width, height, fourcc,
1370b8e80941Smrg                                   DRM_FORMAT_MOD_INVALID, fds, num_fds,
1371b8e80941Smrg                                   strides, offsets, error, loaderPrivate);
1372b8e80941Smrg   if (img == NULL)
1373848b8605Smrg      return NULL;
1374848b8605Smrg
1375b8e80941Smrg   img->yuv_color_space = yuv_color_space;
1376b8e80941Smrg   img->sample_range = sample_range;
1377b8e80941Smrg   img->horizontal_siting = horizontal_siting;
1378b8e80941Smrg   img->vertical_siting = vertical_siting;
1379848b8605Smrg
1380b8e80941Smrg   *error = __DRI_IMAGE_ERROR_SUCCESS;
1381b8e80941Smrg   return img;
1382b8e80941Smrg}
1383b8e80941Smrg
1384b8e80941Smrgstatic __DRIimage *
1385b8e80941Smrgdri2_from_dma_bufs2(__DRIscreen *screen,
1386b8e80941Smrg                    int width, int height, int fourcc,
1387b8e80941Smrg                    uint64_t modifier, int *fds, int num_fds,
1388b8e80941Smrg                    int *strides, int *offsets,
1389b8e80941Smrg                    enum __DRIYUVColorSpace yuv_color_space,
1390b8e80941Smrg                    enum __DRISampleRange sample_range,
1391b8e80941Smrg                    enum __DRIChromaSiting horizontal_siting,
1392b8e80941Smrg                    enum __DRIChromaSiting vertical_siting,
1393b8e80941Smrg                    unsigned *error,
1394b8e80941Smrg                    void *loaderPrivate)
1395b8e80941Smrg{
1396b8e80941Smrg   __DRIimage *img;
1397848b8605Smrg
1398b8e80941Smrg   img = dri2_create_image_from_fd(screen, width, height, fourcc,
1399b8e80941Smrg                                   modifier, fds, num_fds, strides, offsets,
1400b8e80941Smrg                                   error, loaderPrivate);
1401b8e80941Smrg   if (img == NULL)
1402848b8605Smrg      return NULL;
1403848b8605Smrg
1404848b8605Smrg   img->yuv_color_space = yuv_color_space;
1405848b8605Smrg   img->sample_range = sample_range;
1406848b8605Smrg   img->horizontal_siting = horizontal_siting;
1407848b8605Smrg   img->vertical_siting = vertical_siting;
1408848b8605Smrg
1409848b8605Smrg   *error = __DRI_IMAGE_ERROR_SUCCESS;
1410848b8605Smrg   return img;
1411848b8605Smrg}
1412848b8605Smrg
1413848b8605Smrgstatic void
1414848b8605Smrgdri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,
1415848b8605Smrg                int dstx0, int dsty0, int dstwidth, int dstheight,
1416848b8605Smrg                int srcx0, int srcy0, int srcwidth, int srcheight,
1417848b8605Smrg                int flush_flag)
1418848b8605Smrg{
1419848b8605Smrg   struct dri_context *ctx = dri_context(context);
1420848b8605Smrg   struct pipe_context *pipe = ctx->st->pipe;
1421848b8605Smrg   struct pipe_screen *screen;
1422848b8605Smrg   struct pipe_fence_handle *fence;
1423848b8605Smrg   struct pipe_blit_info blit;
1424848b8605Smrg
1425848b8605Smrg   if (!dst || !src)
1426848b8605Smrg      return;
1427848b8605Smrg
1428848b8605Smrg   memset(&blit, 0, sizeof(blit));
1429848b8605Smrg   blit.dst.resource = dst->texture;
1430848b8605Smrg   blit.dst.box.x = dstx0;
1431848b8605Smrg   blit.dst.box.y = dsty0;
1432848b8605Smrg   blit.dst.box.width = dstwidth;
1433848b8605Smrg   blit.dst.box.height = dstheight;
1434848b8605Smrg   blit.dst.box.depth = 1;
1435848b8605Smrg   blit.dst.format = dst->texture->format;
1436848b8605Smrg   blit.src.resource = src->texture;
1437848b8605Smrg   blit.src.box.x = srcx0;
1438848b8605Smrg   blit.src.box.y = srcy0;
1439848b8605Smrg   blit.src.box.width = srcwidth;
1440848b8605Smrg   blit.src.box.height = srcheight;
1441848b8605Smrg   blit.src.box.depth = 1;
1442848b8605Smrg   blit.src.format = src->texture->format;
1443848b8605Smrg   blit.mask = PIPE_MASK_RGBA;
1444848b8605Smrg   blit.filter = PIPE_TEX_FILTER_NEAREST;
1445848b8605Smrg
1446848b8605Smrg   pipe->blit(pipe, &blit);
1447848b8605Smrg
1448848b8605Smrg   if (flush_flag == __BLIT_FLAG_FLUSH) {
1449848b8605Smrg      pipe->flush_resource(pipe, dst->texture);
1450848b8605Smrg      ctx->st->flush(ctx->st, 0, NULL);
1451848b8605Smrg   } else if (flush_flag == __BLIT_FLAG_FINISH) {
1452848b8605Smrg      screen = dri_screen(ctx->sPriv)->base.screen;
1453848b8605Smrg      pipe->flush_resource(pipe, dst->texture);
1454848b8605Smrg      ctx->st->flush(ctx->st, 0, &fence);
1455b8e80941Smrg      (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);
1456848b8605Smrg      screen->fence_reference(screen, &fence, NULL);
1457848b8605Smrg   }
1458848b8605Smrg}
1459848b8605Smrg
1460b8e80941Smrgstatic void *
1461b8e80941Smrgdri2_map_image(__DRIcontext *context, __DRIimage *image,
1462b8e80941Smrg                int x0, int y0, int width, int height,
1463b8e80941Smrg                unsigned int flags, int *stride, void **data)
1464b8e80941Smrg{
1465b8e80941Smrg   struct dri_context *ctx = dri_context(context);
1466b8e80941Smrg   struct pipe_context *pipe = ctx->st->pipe;
1467b8e80941Smrg   enum pipe_transfer_usage pipe_access = 0;
1468b8e80941Smrg   struct pipe_transfer *trans;
1469b8e80941Smrg   void *map;
1470b8e80941Smrg
1471b8e80941Smrg   if (!image || !data || *data)
1472b8e80941Smrg      return NULL;
1473b8e80941Smrg
1474b8e80941Smrg   if (flags & __DRI_IMAGE_TRANSFER_READ)
1475b8e80941Smrg         pipe_access |= PIPE_TRANSFER_READ;
1476b8e80941Smrg   if (flags & __DRI_IMAGE_TRANSFER_WRITE)
1477b8e80941Smrg         pipe_access |= PIPE_TRANSFER_WRITE;
1478b8e80941Smrg
1479b8e80941Smrg   map = pipe_transfer_map(pipe, image->texture,
1480b8e80941Smrg                           0, 0, pipe_access, x0, y0, width, height,
1481b8e80941Smrg                           &trans);
1482b8e80941Smrg   if (map) {
1483b8e80941Smrg      *data = trans;
1484b8e80941Smrg      *stride = trans->stride;
1485b8e80941Smrg   }
1486b8e80941Smrg
1487b8e80941Smrg   return map;
1488b8e80941Smrg}
1489b8e80941Smrg
1490848b8605Smrgstatic void
1491b8e80941Smrgdri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)
1492848b8605Smrg{
1493b8e80941Smrg   struct dri_context *ctx = dri_context(context);
1494b8e80941Smrg   struct pipe_context *pipe = ctx->st->pipe;
1495b8e80941Smrg
1496b8e80941Smrg   pipe_transfer_unmap(pipe, (struct pipe_transfer *)data);
1497848b8605Smrg}
1498848b8605Smrg
1499848b8605Smrgstatic int
1500848b8605Smrgdri2_get_capabilities(__DRIscreen *_screen)
1501848b8605Smrg{
1502848b8605Smrg   struct dri_screen *screen = dri_screen(_screen);
1503848b8605Smrg
1504848b8605Smrg   return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);
1505848b8605Smrg}
1506848b8605Smrg
1507848b8605Smrg/* The extension is modified during runtime if DRI_PRIME is detected */
1508848b8605Smrgstatic __DRIimageExtension dri2ImageExtension = {
1509b8e80941Smrg    .base = { __DRI_IMAGE, 17 },
1510848b8605Smrg
1511848b8605Smrg    .createImageFromName          = dri2_create_image_from_name,
1512848b8605Smrg    .createImageFromRenderbuffer  = dri2_create_image_from_renderbuffer,
1513848b8605Smrg    .destroyImage                 = dri2_destroy_image,
1514848b8605Smrg    .createImage                  = dri2_create_image,
1515848b8605Smrg    .queryImage                   = dri2_query_image,
1516848b8605Smrg    .dupImage                     = dri2_dup_image,
1517848b8605Smrg    .validateUsage                = dri2_validate_usage,
1518848b8605Smrg    .createImageFromNames         = dri2_from_names,
1519848b8605Smrg    .fromPlanar                   = dri2_from_planar,
1520848b8605Smrg    .createImageFromTexture       = dri2_create_from_texture,
1521848b8605Smrg    .createImageFromFds           = NULL,
1522848b8605Smrg    .createImageFromDmaBufs       = NULL,
1523848b8605Smrg    .blitImage                    = dri2_blit_image,
1524848b8605Smrg    .getCapabilities              = dri2_get_capabilities,
1525b8e80941Smrg    .mapImage                     = dri2_map_image,
1526b8e80941Smrg    .unmapImage                   = dri2_unmap_image,
1527b8e80941Smrg    .createImageWithModifiers     = NULL,
1528b8e80941Smrg    .createImageFromDmaBufs2      = NULL,
1529b8e80941Smrg    .queryDmaBufFormats           = NULL,
1530b8e80941Smrg    .queryDmaBufModifiers         = NULL,
1531b8e80941Smrg    .queryDmaBufFormatModifierAttribs = NULL,
1532b8e80941Smrg    .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,
1533b8e80941Smrg};
1534b8e80941Smrg
1535b8e80941Smrgstatic const __DRIrobustnessExtension dri2Robustness = {
1536b8e80941Smrg   .base = { __DRI2_ROBUSTNESS, 1 }
1537b8e80941Smrg};
1538b8e80941Smrg
1539b8e80941Smrgstatic int
1540b8e80941Smrgdri2_interop_query_device_info(__DRIcontext *_ctx,
1541b8e80941Smrg                               struct mesa_glinterop_device_info *out)
1542b8e80941Smrg{
1543b8e80941Smrg   struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;
1544b8e80941Smrg
1545b8e80941Smrg   /* There is no version 0, thus we do not support it */
1546b8e80941Smrg   if (out->version == 0)
1547b8e80941Smrg      return MESA_GLINTEROP_INVALID_VERSION;
1548b8e80941Smrg
1549b8e80941Smrg   out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);
1550b8e80941Smrg   out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);
1551b8e80941Smrg   out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);
1552b8e80941Smrg   out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);
1553b8e80941Smrg
1554b8e80941Smrg   out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);
1555b8e80941Smrg   out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);
1556b8e80941Smrg
1557b8e80941Smrg   /* Instruct the caller that we support up-to version one of the interface */
1558b8e80941Smrg   out->version = 1;
1559b8e80941Smrg
1560b8e80941Smrg   return MESA_GLINTEROP_SUCCESS;
1561b8e80941Smrg}
1562b8e80941Smrg
1563b8e80941Smrgstatic int
1564b8e80941Smrgdri2_interop_export_object(__DRIcontext *_ctx,
1565b8e80941Smrg                           struct mesa_glinterop_export_in *in,
1566b8e80941Smrg                           struct mesa_glinterop_export_out *out)
1567b8e80941Smrg{
1568b8e80941Smrg   struct st_context_iface *st = dri_context(_ctx)->st;
1569b8e80941Smrg   struct pipe_screen *screen = st->pipe->screen;
1570b8e80941Smrg   struct gl_context *ctx = ((struct st_context *)st)->ctx;
1571b8e80941Smrg   struct pipe_resource *res = NULL;
1572b8e80941Smrg   struct winsys_handle whandle;
1573b8e80941Smrg   unsigned target, usage;
1574b8e80941Smrg   boolean success;
1575b8e80941Smrg
1576b8e80941Smrg   /* There is no version 0, thus we do not support it */
1577b8e80941Smrg   if (in->version == 0 || out->version == 0)
1578b8e80941Smrg      return MESA_GLINTEROP_INVALID_VERSION;
1579b8e80941Smrg
1580b8e80941Smrg   /* Validate the target. */
1581b8e80941Smrg   switch (in->target) {
1582b8e80941Smrg   case GL_TEXTURE_BUFFER:
1583b8e80941Smrg   case GL_TEXTURE_1D:
1584b8e80941Smrg   case GL_TEXTURE_2D:
1585b8e80941Smrg   case GL_TEXTURE_3D:
1586b8e80941Smrg   case GL_TEXTURE_RECTANGLE:
1587b8e80941Smrg   case GL_TEXTURE_1D_ARRAY:
1588b8e80941Smrg   case GL_TEXTURE_2D_ARRAY:
1589b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
1590b8e80941Smrg   case GL_TEXTURE_CUBE_MAP:
1591b8e80941Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
1592b8e80941Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1593b8e80941Smrg   case GL_TEXTURE_EXTERNAL_OES:
1594b8e80941Smrg   case GL_RENDERBUFFER:
1595b8e80941Smrg   case GL_ARRAY_BUFFER:
1596b8e80941Smrg      target = in->target;
1597b8e80941Smrg      break;
1598b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1599b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1600b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1601b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1602b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1603b8e80941Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1604b8e80941Smrg      target = GL_TEXTURE_CUBE_MAP;
1605b8e80941Smrg      break;
1606b8e80941Smrg   default:
1607b8e80941Smrg      return MESA_GLINTEROP_INVALID_TARGET;
1608b8e80941Smrg   }
1609b8e80941Smrg
1610b8e80941Smrg   /* Validate the simple case of miplevel. */
1611b8e80941Smrg   if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&
1612b8e80941Smrg       in->miplevel != 0)
1613b8e80941Smrg      return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1614b8e80941Smrg
1615b8e80941Smrg   /* Validate the OpenGL object and get pipe_resource. */
1616b8e80941Smrg   simple_mtx_lock(&ctx->Shared->Mutex);
1617b8e80941Smrg
1618b8e80941Smrg   if (target == GL_ARRAY_BUFFER) {
1619b8e80941Smrg      /* Buffer objects.
1620b8e80941Smrg       *
1621b8e80941Smrg       * The error checking is based on the documentation of
1622b8e80941Smrg       * clCreateFromGLBuffer from OpenCL 2.0 SDK.
1623b8e80941Smrg       */
1624b8e80941Smrg      struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);
1625b8e80941Smrg
1626b8e80941Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLBuffer:
1627b8e80941Smrg       *  "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is
1628b8e80941Smrg       *   a GL buffer object but does not have an existing data store or
1629b8e80941Smrg       *   the size of the buffer is 0."
1630b8e80941Smrg       */
1631b8e80941Smrg      if (!buf || buf->Size == 0) {
1632b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1633b8e80941Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
1634b8e80941Smrg      }
1635b8e80941Smrg
1636b8e80941Smrg      res = st_buffer_object(buf)->buffer;
1637b8e80941Smrg      if (!res) {
1638b8e80941Smrg         /* this shouldn't happen */
1639b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1640b8e80941Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
1641b8e80941Smrg      }
1642b8e80941Smrg
1643b8e80941Smrg      out->buf_offset = 0;
1644b8e80941Smrg      out->buf_size = buf->Size;
1645b8e80941Smrg
1646b8e80941Smrg      buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1647b8e80941Smrg   } else if (target == GL_RENDERBUFFER) {
1648b8e80941Smrg      /* Renderbuffers.
1649b8e80941Smrg       *
1650b8e80941Smrg       * The error checking is based on the documentation of
1651b8e80941Smrg       * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.
1652b8e80941Smrg       */
1653b8e80941Smrg      struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);
1654b8e80941Smrg
1655b8e80941Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1656b8e80941Smrg       *   "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer
1657b8e80941Smrg       *    object or if the width or height of renderbuffer is zero."
1658b8e80941Smrg       */
1659b8e80941Smrg      if (!rb || rb->Width == 0 || rb->Height == 0) {
1660b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1661b8e80941Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
1662b8e80941Smrg      }
1663b8e80941Smrg
1664b8e80941Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1665b8e80941Smrg       *   "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL
1666b8e80941Smrg       *    renderbuffer object."
1667b8e80941Smrg       */
1668b8e80941Smrg      if (rb->NumSamples > 1) {
1669b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1670b8e80941Smrg         return MESA_GLINTEROP_INVALID_OPERATION;
1671b8e80941Smrg      }
1672b8e80941Smrg
1673b8e80941Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:
1674b8e80941Smrg       *   "CL_OUT_OF_RESOURCES if there is a failure to allocate resources
1675b8e80941Smrg       *    required by the OpenCL implementation on the device."
1676b8e80941Smrg       */
1677b8e80941Smrg      res = st_renderbuffer(rb)->texture;
1678b8e80941Smrg      if (!res) {
1679b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1680b8e80941Smrg         return MESA_GLINTEROP_OUT_OF_RESOURCES;
1681b8e80941Smrg      }
1682b8e80941Smrg
1683b8e80941Smrg      out->internal_format = rb->InternalFormat;
1684b8e80941Smrg      out->view_minlevel = 0;
1685b8e80941Smrg      out->view_numlevels = 1;
1686b8e80941Smrg      out->view_minlayer = 0;
1687b8e80941Smrg      out->view_numlayers = 1;
1688b8e80941Smrg   } else {
1689b8e80941Smrg      /* Texture objects.
1690b8e80941Smrg       *
1691b8e80941Smrg       * The error checking is based on the documentation of
1692b8e80941Smrg       * clCreateFromGLTexture from OpenCL 2.0 SDK.
1693b8e80941Smrg       */
1694b8e80941Smrg      struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);
1695b8e80941Smrg
1696b8e80941Smrg      if (obj)
1697b8e80941Smrg         _mesa_test_texobj_completeness(ctx, obj);
1698b8e80941Smrg
1699b8e80941Smrg      /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1700b8e80941Smrg       *   "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose
1701b8e80941Smrg       *    type matches texture_target, if the specified miplevel of texture
1702b8e80941Smrg       *    is not defined, or if the width or height of the specified
1703b8e80941Smrg       *    miplevel is zero or if the GL texture object is incomplete."
1704b8e80941Smrg       */
1705b8e80941Smrg      if (!obj ||
1706b8e80941Smrg          obj->Target != target ||
1707b8e80941Smrg          !obj->_BaseComplete ||
1708b8e80941Smrg          (in->miplevel > 0 && !obj->_MipmapComplete)) {
1709b8e80941Smrg         simple_mtx_unlock(&ctx->Shared->Mutex);
1710b8e80941Smrg         return MESA_GLINTEROP_INVALID_OBJECT;
1711b8e80941Smrg      }
1712b8e80941Smrg
1713b8e80941Smrg      if (target == GL_TEXTURE_BUFFER) {
1714b8e80941Smrg         struct st_buffer_object *stBuf =
1715b8e80941Smrg            st_buffer_object(obj->BufferObject);
1716b8e80941Smrg
1717b8e80941Smrg         if (!stBuf || !stBuf->buffer) {
1718b8e80941Smrg            /* this shouldn't happen */
1719b8e80941Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
1720b8e80941Smrg            return MESA_GLINTEROP_INVALID_OBJECT;
1721b8e80941Smrg         }
1722b8e80941Smrg         res = stBuf->buffer;
1723b8e80941Smrg
1724b8e80941Smrg         out->internal_format = obj->BufferObjectFormat;
1725b8e80941Smrg         out->buf_offset = obj->BufferOffset;
1726b8e80941Smrg         out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :
1727b8e80941Smrg                                                 obj->BufferSize;
1728b8e80941Smrg
1729b8e80941Smrg         obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;
1730b8e80941Smrg      } else {
1731b8e80941Smrg         /* From OpenCL 2.0 SDK, clCreateFromGLTexture:
1732b8e80941Smrg          *   "CL_INVALID_MIP_LEVEL if miplevel is less than the value of
1733b8e80941Smrg          *    levelbase (for OpenGL implementations) or zero (for OpenGL ES
1734b8e80941Smrg          *    implementations); or greater than the value of q (for both OpenGL
1735b8e80941Smrg          *    and OpenGL ES). levelbase and q are defined for the texture in
1736b8e80941Smrg          *    section 3.8.10 (Texture Completeness) of the OpenGL 2.1
1737b8e80941Smrg          *    specification and section 3.7.10 of the OpenGL ES 2.0."
1738b8e80941Smrg          */
1739b8e80941Smrg         if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) {
1740b8e80941Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
1741b8e80941Smrg            return MESA_GLINTEROP_INVALID_MIP_LEVEL;
1742b8e80941Smrg         }
1743b8e80941Smrg
1744b8e80941Smrg         if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {
1745b8e80941Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
1746b8e80941Smrg            return MESA_GLINTEROP_OUT_OF_RESOURCES;
1747b8e80941Smrg         }
1748b8e80941Smrg
1749b8e80941Smrg         res = st_get_texobj_resource(obj);
1750b8e80941Smrg         if (!res) {
1751b8e80941Smrg            /* Incomplete texture buffer object? This shouldn't really occur. */
1752b8e80941Smrg            simple_mtx_unlock(&ctx->Shared->Mutex);
1753b8e80941Smrg            return MESA_GLINTEROP_INVALID_OBJECT;
1754b8e80941Smrg         }
1755b8e80941Smrg
1756b8e80941Smrg         out->internal_format = obj->Image[0][0]->InternalFormat;
1757b8e80941Smrg         out->view_minlevel = obj->MinLevel;
1758b8e80941Smrg         out->view_numlevels = obj->NumLevels;
1759b8e80941Smrg         out->view_minlayer = obj->MinLayer;
1760b8e80941Smrg         out->view_numlayers = obj->NumLayers;
1761b8e80941Smrg      }
1762b8e80941Smrg   }
1763b8e80941Smrg
1764b8e80941Smrg   /* Get the handle. */
1765b8e80941Smrg   switch (in->access) {
1766b8e80941Smrg   case MESA_GLINTEROP_ACCESS_READ_ONLY:
1767b8e80941Smrg      usage = 0;
1768b8e80941Smrg      break;
1769b8e80941Smrg   case MESA_GLINTEROP_ACCESS_READ_WRITE:
1770b8e80941Smrg   case MESA_GLINTEROP_ACCESS_WRITE_ONLY:
1771b8e80941Smrg      usage = PIPE_HANDLE_USAGE_SHADER_WRITE;
1772b8e80941Smrg      break;
1773b8e80941Smrg   default:
1774b8e80941Smrg      usage = 0;
1775b8e80941Smrg   }
1776b8e80941Smrg
1777b8e80941Smrg   memset(&whandle, 0, sizeof(whandle));
1778b8e80941Smrg   whandle.type = WINSYS_HANDLE_TYPE_FD;
1779b8e80941Smrg
1780b8e80941Smrg   success = screen->resource_get_handle(screen, st->pipe, res, &whandle,
1781b8e80941Smrg                                         usage);
1782b8e80941Smrg   simple_mtx_unlock(&ctx->Shared->Mutex);
1783b8e80941Smrg
1784b8e80941Smrg   if (!success)
1785b8e80941Smrg      return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;
1786b8e80941Smrg
1787b8e80941Smrg   out->dmabuf_fd = whandle.handle;
1788b8e80941Smrg   out->out_driver_data_written = 0;
1789b8e80941Smrg
1790b8e80941Smrg   if (res->target == PIPE_BUFFER)
1791b8e80941Smrg      out->buf_offset += whandle.offset;
1792b8e80941Smrg
1793b8e80941Smrg   /* Instruct the caller that we support up-to version one of the interface */
1794b8e80941Smrg   in->version = 1;
1795b8e80941Smrg   out->version = 1;
1796b8e80941Smrg
1797b8e80941Smrg   return MESA_GLINTEROP_SUCCESS;
1798b8e80941Smrg}
1799b8e80941Smrg
1800b8e80941Smrgstatic const __DRI2interopExtension dri2InteropExtension = {
1801b8e80941Smrg   .base = { __DRI2_INTEROP, 1 },
1802b8e80941Smrg   .query_device_info = dri2_interop_query_device_info,
1803b8e80941Smrg   .export_object = dri2_interop_export_object
1804b8e80941Smrg};
1805b8e80941Smrg
1806b8e80941Smrg/**
1807b8e80941Smrg * \brief the DRI2ConfigQueryExtension configQueryb method
1808b8e80941Smrg */
1809b8e80941Smrgstatic int
1810b8e80941Smrgdri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,
1811b8e80941Smrg                        unsigned char *val)
1812b8e80941Smrg{
1813b8e80941Smrg   struct dri_screen *screen = dri_screen(sPriv);
1814b8e80941Smrg
1815b8e80941Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))
1816b8e80941Smrg      return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);
1817b8e80941Smrg
1818b8e80941Smrg   *val = driQueryOptionb(&screen->dev->option_cache, var);
1819b8e80941Smrg
1820b8e80941Smrg   return 0;
1821b8e80941Smrg}
1822b8e80941Smrg
1823b8e80941Smrg/**
1824b8e80941Smrg * \brief the DRI2ConfigQueryExtension configQueryi method
1825b8e80941Smrg */
1826b8e80941Smrgstatic int
1827b8e80941Smrgdri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)
1828b8e80941Smrg{
1829b8e80941Smrg   struct dri_screen *screen = dri_screen(sPriv);
1830b8e80941Smrg
1831b8e80941Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&
1832b8e80941Smrg       !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))
1833b8e80941Smrg      return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);
1834b8e80941Smrg
1835b8e80941Smrg    *val = driQueryOptioni(&screen->dev->option_cache, var);
1836b8e80941Smrg
1837b8e80941Smrg    return 0;
1838b8e80941Smrg}
1839b8e80941Smrg
1840b8e80941Smrg/**
1841b8e80941Smrg * \brief the DRI2ConfigQueryExtension configQueryf method
1842b8e80941Smrg */
1843b8e80941Smrgstatic int
1844b8e80941Smrgdri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)
1845b8e80941Smrg{
1846b8e80941Smrg   struct dri_screen *screen = dri_screen(sPriv);
1847b8e80941Smrg
1848b8e80941Smrg   if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))
1849b8e80941Smrg      return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);
1850b8e80941Smrg
1851b8e80941Smrg    *val = driQueryOptionf(&screen->dev->option_cache, var);
1852b8e80941Smrg
1853b8e80941Smrg    return 0;
1854b8e80941Smrg}
1855b8e80941Smrg
1856b8e80941Smrg/**
1857b8e80941Smrg * \brief the DRI2ConfigQueryExtension struct.
1858b8e80941Smrg *
1859b8e80941Smrg * We first query the driver option cache. Then the dri2 option cache.
1860b8e80941Smrg */
1861b8e80941Smrgstatic const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {
1862b8e80941Smrg   .base = { __DRI2_CONFIG_QUERY, 1 },
1863b8e80941Smrg
1864b8e80941Smrg   .configQueryb        = dri2GalliumConfigQueryb,
1865b8e80941Smrg   .configQueryi        = dri2GalliumConfigQueryi,
1866b8e80941Smrg   .configQueryf        = dri2GalliumConfigQueryf,
1867848b8605Smrg};
1868848b8605Smrg
1869848b8605Smrg/*
1870848b8605Smrg * Backend function init_screen.
1871848b8605Smrg */
1872848b8605Smrg
1873848b8605Smrgstatic const __DRIextension *dri_screen_extensions[] = {
1874848b8605Smrg   &driTexBufferExtension.base,
1875848b8605Smrg   &dri2FlushExtension.base,
1876848b8605Smrg   &dri2ImageExtension.base,
1877848b8605Smrg   &dri2RendererQueryExtension.base,
1878b8e80941Smrg   &dri2GalliumConfigQueryExtension.base,
1879848b8605Smrg   &dri2ThrottleExtension.base,
1880b8e80941Smrg   &dri2FenceExtension.base,
1881b8e80941Smrg   &dri2InteropExtension.base,
1882b8e80941Smrg   &dri2NoErrorExtension.base,
1883b8e80941Smrg   NULL
1884b8e80941Smrg};
1885b8e80941Smrg
1886b8e80941Smrgstatic const __DRIextension *dri_robust_screen_extensions[] = {
1887b8e80941Smrg   &driTexBufferExtension.base,
1888b8e80941Smrg   &dri2FlushExtension.base,
1889b8e80941Smrg   &dri2ImageExtension.base,
1890b8e80941Smrg   &dri2RendererQueryExtension.base,
1891b8e80941Smrg   &dri2GalliumConfigQueryExtension.base,
1892b8e80941Smrg   &dri2ThrottleExtension.base,
1893b8e80941Smrg   &dri2FenceExtension.base,
1894b8e80941Smrg   &dri2InteropExtension.base,
1895b8e80941Smrg   &dri2Robustness.base,
1896b8e80941Smrg   &dri2NoErrorExtension.base,
1897848b8605Smrg   NULL
1898848b8605Smrg};
1899848b8605Smrg
1900848b8605Smrg/**
1901848b8605Smrg * This is the driver specific part of the createNewScreen entry point.
1902848b8605Smrg *
1903848b8605Smrg * Returns the struct gl_config supported by this driver.
1904848b8605Smrg */
1905848b8605Smrgstatic const __DRIconfig **
1906848b8605Smrgdri2_init_screen(__DRIscreen * sPriv)
1907848b8605Smrg{
1908848b8605Smrg   const __DRIconfig **configs;
1909848b8605Smrg   struct dri_screen *screen;
1910848b8605Smrg   struct pipe_screen *pscreen = NULL;
1911848b8605Smrg
1912848b8605Smrg   screen = CALLOC_STRUCT(dri_screen);
1913848b8605Smrg   if (!screen)
1914848b8605Smrg      return NULL;
1915848b8605Smrg
1916848b8605Smrg   screen->sPriv = sPriv;
1917848b8605Smrg   screen->fd = sPriv->fd;
1918b8e80941Smrg   (void) mtx_init(&screen->opencl_func_mutex, mtx_plain);
1919848b8605Smrg
1920848b8605Smrg   sPriv->driverPrivate = (void *)screen;
1921848b8605Smrg
1922b8e80941Smrg   if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) {
1923b8e80941Smrg      dri_init_options(screen);
1924848b8605Smrg
1925b8e80941Smrg      pscreen = pipe_loader_create_screen(screen->dev);
1926848b8605Smrg   }
1927848b8605Smrg
1928b8e80941Smrg   if (!pscreen)
1929b8e80941Smrg       goto release_pipe;
1930b8e80941Smrg
1931b8e80941Smrg   screen->default_throttle_frames =
1932b8e80941Smrg      pscreen->get_param(pscreen, PIPE_CAP_MAX_FRAMES_IN_FLIGHT);
1933848b8605Smrg
1934b8e80941Smrg   if (pscreen->resource_create_with_modifiers)
1935b8e80941Smrg      dri2ImageExtension.createImageWithModifiers =
1936b8e80941Smrg         dri2_create_image_with_modifiers;
1937b8e80941Smrg
1938b8e80941Smrg   if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) {
1939848b8605Smrg      uint64_t cap;
1940848b8605Smrg
1941848b8605Smrg      if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
1942848b8605Smrg          (cap & DRM_PRIME_CAP_IMPORT)) {
1943848b8605Smrg         dri2ImageExtension.createImageFromFds = dri2_from_fds;
1944848b8605Smrg         dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
1945b8e80941Smrg         dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
1946b8e80941Smrg         if (pscreen->query_dmabuf_modifiers) {
1947b8e80941Smrg            dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
1948b8e80941Smrg            dri2ImageExtension.queryDmaBufModifiers =
1949b8e80941Smrg                                       dri2_query_dma_buf_modifiers;
1950b8e80941Smrg         }
1951848b8605Smrg      }
1952848b8605Smrg   }
1953848b8605Smrg
1954b8e80941Smrg   if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {
1955b8e80941Smrg      sPriv->extensions = dri_robust_screen_extensions;
1956b8e80941Smrg      screen->has_reset_status_query = true;
1957b8e80941Smrg   }
1958b8e80941Smrg   else
1959b8e80941Smrg      sPriv->extensions = dri_screen_extensions;
1960848b8605Smrg
1961b8e80941Smrg   configs = dri_init_screen_helper(screen, pscreen);
1962848b8605Smrg   if (!configs)
1963b8e80941Smrg      goto destroy_screen;
1964848b8605Smrg
1965848b8605Smrg   screen->can_share_buffer = true;
1966848b8605Smrg   screen->auto_fake_front = dri_with_format(sPriv);
1967848b8605Smrg   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
1968848b8605Smrg   screen->lookup_egl_image = dri2_lookup_egl_image;
1969848b8605Smrg
1970848b8605Smrg   return configs;
1971b8e80941Smrg
1972b8e80941Smrgdestroy_screen:
1973848b8605Smrg   dri_destroy_screen_helper(screen);
1974b8e80941Smrg
1975b8e80941Smrgrelease_pipe:
1976848b8605Smrg   if (screen->dev)
1977848b8605Smrg      pipe_loader_release(&screen->dev, 1);
1978b8e80941Smrg
1979848b8605Smrg   FREE(screen);
1980848b8605Smrg   return NULL;
1981848b8605Smrg}
1982848b8605Smrg
1983848b8605Smrg/**
1984848b8605Smrg * This is the driver specific part of the createNewScreen entry point.
1985848b8605Smrg *
1986848b8605Smrg * Returns the struct gl_config supported by this driver.
1987848b8605Smrg */
1988848b8605Smrgstatic const __DRIconfig **
1989848b8605Smrgdri_kms_init_screen(__DRIscreen * sPriv)
1990848b8605Smrg{
1991848b8605Smrg#if defined(GALLIUM_SOFTPIPE)
1992848b8605Smrg   const __DRIconfig **configs;
1993848b8605Smrg   struct dri_screen *screen;
1994848b8605Smrg   struct pipe_screen *pscreen = NULL;
1995848b8605Smrg   uint64_t cap;
1996848b8605Smrg
1997848b8605Smrg   screen = CALLOC_STRUCT(dri_screen);
1998848b8605Smrg   if (!screen)
1999848b8605Smrg      return NULL;
2000848b8605Smrg
2001848b8605Smrg   screen->sPriv = sPriv;
2002848b8605Smrg   screen->fd = sPriv->fd;
2003848b8605Smrg
2004848b8605Smrg   sPriv->driverPrivate = (void *)screen;
2005848b8605Smrg
2006b8e80941Smrg   if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) {
2007b8e80941Smrg      dri_init_options(screen);
2008b8e80941Smrg      pscreen = pipe_loader_create_screen(screen->dev);
2009b8e80941Smrg   }
2010b8e80941Smrg
2011b8e80941Smrg   if (!pscreen)
2012b8e80941Smrg       goto release_pipe;
2013b8e80941Smrg
2014b8e80941Smrg   if (pscreen->resource_create_with_modifiers)
2015b8e80941Smrg      dri2ImageExtension.createImageWithModifiers =
2016b8e80941Smrg         dri2_create_image_with_modifiers;
2017848b8605Smrg
2018848b8605Smrg   if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
2019848b8605Smrg          (cap & DRM_PRIME_CAP_IMPORT)) {
2020848b8605Smrg      dri2ImageExtension.createImageFromFds = dri2_from_fds;
2021848b8605Smrg      dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
2022b8e80941Smrg      dri2ImageExtension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;
2023b8e80941Smrg      if (pscreen->query_dmabuf_modifiers) {
2024b8e80941Smrg         dri2ImageExtension.queryDmaBufFormats = dri2_query_dma_buf_formats;
2025b8e80941Smrg         dri2ImageExtension.queryDmaBufModifiers = dri2_query_dma_buf_modifiers;
2026b8e80941Smrg      }
2027848b8605Smrg   }
2028848b8605Smrg
2029848b8605Smrg   sPriv->extensions = dri_screen_extensions;
2030848b8605Smrg
2031b8e80941Smrg   configs = dri_init_screen_helper(screen, pscreen);
2032848b8605Smrg   if (!configs)
2033b8e80941Smrg      goto destroy_screen;
2034848b8605Smrg
2035848b8605Smrg   screen->can_share_buffer = false;
2036848b8605Smrg   screen->auto_fake_front = dri_with_format(sPriv);
2037848b8605Smrg   screen->broken_invalidate = !sPriv->dri2.useInvalidate;
2038848b8605Smrg   screen->lookup_egl_image = dri2_lookup_egl_image;
2039848b8605Smrg
2040848b8605Smrg   return configs;
2041b8e80941Smrg
2042b8e80941Smrgdestroy_screen:
2043848b8605Smrg   dri_destroy_screen_helper(screen);
2044b8e80941Smrg
2045b8e80941Smrgrelease_pipe:
2046b8e80941Smrg   if (screen->dev)
2047b8e80941Smrg      pipe_loader_release(&screen->dev, 1);
2048b8e80941Smrg
2049848b8605Smrg   FREE(screen);
2050848b8605Smrg#endif // GALLIUM_SOFTPIPE
2051848b8605Smrg   return NULL;
2052848b8605Smrg}
2053848b8605Smrg
2054848b8605Smrgstatic boolean
2055848b8605Smrgdri2_create_buffer(__DRIscreen * sPriv,
2056848b8605Smrg                   __DRIdrawable * dPriv,
2057848b8605Smrg                   const struct gl_config * visual, boolean isPixmap)
2058848b8605Smrg{
2059848b8605Smrg   struct dri_drawable *drawable = NULL;
2060848b8605Smrg
2061848b8605Smrg   if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))
2062848b8605Smrg      return FALSE;
2063848b8605Smrg
2064848b8605Smrg   drawable = dPriv->driverPrivate;
2065848b8605Smrg
2066848b8605Smrg   drawable->allocate_textures = dri2_allocate_textures;
2067848b8605Smrg   drawable->flush_frontbuffer = dri2_flush_frontbuffer;
2068848b8605Smrg   drawable->update_tex_buffer = dri2_update_tex_buffer;
2069b8e80941Smrg   drawable->flush_swapbuffers = dri2_flush_swapbuffers;
2070848b8605Smrg
2071848b8605Smrg   return TRUE;
2072848b8605Smrg}
2073848b8605Smrg
2074848b8605Smrg/**
2075848b8605Smrg * DRI driver virtual function table.
2076848b8605Smrg *
2077848b8605Smrg * DRI versions differ in their implementation of init_screen and swap_buffers.
2078848b8605Smrg */
2079848b8605Smrgconst struct __DriverAPIRec galliumdrm_driver_api = {
2080848b8605Smrg   .InitScreen = dri2_init_screen,
2081848b8605Smrg   .DestroyScreen = dri_destroy_screen,
2082848b8605Smrg   .CreateContext = dri_create_context,
2083848b8605Smrg   .DestroyContext = dri_destroy_context,
2084848b8605Smrg   .CreateBuffer = dri2_create_buffer,
2085848b8605Smrg   .DestroyBuffer = dri_destroy_buffer,
2086848b8605Smrg   .MakeCurrent = dri_make_current,
2087848b8605Smrg   .UnbindContext = dri_unbind_context,
2088848b8605Smrg
2089848b8605Smrg   .AllocateBuffer = dri2_allocate_buffer,
2090848b8605Smrg   .ReleaseBuffer  = dri2_release_buffer,
2091848b8605Smrg};
2092848b8605Smrg
2093848b8605Smrg/**
2094848b8605Smrg * DRI driver virtual function table.
2095848b8605Smrg *
2096848b8605Smrg * KMS/DRM version of the DriverAPI above sporting a different InitScreen
2097848b8605Smrg * hook. The latter is used to explicitly initialise the kms_swrast driver
2098848b8605Smrg * rather than selecting the approapriate driver as suggested by the loader.
2099848b8605Smrg */
2100848b8605Smrgconst struct __DriverAPIRec dri_kms_driver_api = {
2101848b8605Smrg   .InitScreen = dri_kms_init_screen,
2102848b8605Smrg   .DestroyScreen = dri_destroy_screen,
2103848b8605Smrg   .CreateContext = dri_create_context,
2104848b8605Smrg   .DestroyContext = dri_destroy_context,
2105848b8605Smrg   .CreateBuffer = dri2_create_buffer,
2106848b8605Smrg   .DestroyBuffer = dri_destroy_buffer,
2107848b8605Smrg   .MakeCurrent = dri_make_current,
2108848b8605Smrg   .UnbindContext = dri_unbind_context,
2109848b8605Smrg
2110848b8605Smrg   .AllocateBuffer = dri2_allocate_buffer,
2111848b8605Smrg   .ReleaseBuffer  = dri2_release_buffer,
2112848b8605Smrg};
2113848b8605Smrg
2114848b8605Smrg/* This is the table of extensions that the loader will dlsym() for. */
2115848b8605Smrgconst __DRIextension *galliumdrm_driver_extensions[] = {
2116848b8605Smrg    &driCoreExtension.base,
2117848b8605Smrg    &driImageDriverExtension.base,
2118848b8605Smrg    &driDRI2Extension.base,
2119848b8605Smrg    &gallium_config_options.base,
2120848b8605Smrg    NULL
2121848b8605Smrg};
2122848b8605Smrg
2123848b8605Smrg/* vim: set sw=3 ts=8 sts=3 expandtab: */
2124