1848b8605Smrg/**************************************************************************
2b8e80941Smrg *
3848b8605Smrg * Copyright 2007 VMware, Inc.
4848b8605Smrg * All Rights Reserved.
5b8e80941Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the
8848b8605Smrg * "Software"), to deal in the Software without restriction, including
9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
12848b8605Smrg * the following conditions:
13b8e80941Smrg *
14848b8605Smrg * The above copyright notice and this permission notice (including the
15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
16848b8605Smrg * of the Software.
17b8e80941Smrg *
18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25b8e80941Smrg *
26848b8605Smrg **************************************************************************/
27848b8605Smrg
28848b8605Smrg#include <stdio.h>
29848b8605Smrg
30848b8605Smrg#include "st_context.h"
31848b8605Smrg#include "st_format.h"
32848b8605Smrg#include "st_texture.h"
33848b8605Smrg#include "st_cb_fbo.h"
34848b8605Smrg#include "main/enums.h"
35848b8605Smrg
36848b8605Smrg#include "pipe/p_state.h"
37848b8605Smrg#include "pipe/p_context.h"
38848b8605Smrg#include "pipe/p_defines.h"
39848b8605Smrg#include "util/u_inlines.h"
40848b8605Smrg#include "util/u_format.h"
41848b8605Smrg#include "util/u_rect.h"
42848b8605Smrg#include "util/u_math.h"
43848b8605Smrg#include "util/u_memory.h"
44b8e80941Smrg#include "tgsi/tgsi_from_mesa.h"
45848b8605Smrg
46848b8605Smrg
47848b8605Smrg#define DBG if(0) printf
48848b8605Smrg
49848b8605Smrg
50848b8605Smrg/**
51848b8605Smrg * Allocate a new pipe_resource object
52848b8605Smrg * width0, height0, depth0 are the dimensions of the level 0 image
53848b8605Smrg * (the highest resolution).  last_level indicates how many mipmap levels
54848b8605Smrg * to allocate storage for.  For non-mipmapped textures, this will be zero.
55848b8605Smrg */
56848b8605Smrgstruct pipe_resource *
57848b8605Smrgst_texture_create(struct st_context *st,
58848b8605Smrg                  enum pipe_texture_target target,
59b8e80941Smrg                  enum pipe_format format,
60b8e80941Smrg                  GLuint last_level,
61b8e80941Smrg                  GLuint width0,
62b8e80941Smrg                  GLuint height0,
63b8e80941Smrg                  GLuint depth0,
64848b8605Smrg                  GLuint layers,
65848b8605Smrg                  GLuint nr_samples,
66b8e80941Smrg                  GLuint bind)
67848b8605Smrg{
68848b8605Smrg   struct pipe_resource pt, *newtex;
69848b8605Smrg   struct pipe_screen *screen = st->pipe->screen;
70848b8605Smrg
71848b8605Smrg   assert(target < PIPE_MAX_TEXTURE_TYPES);
72848b8605Smrg   assert(width0 > 0);
73848b8605Smrg   assert(height0 > 0);
74848b8605Smrg   assert(depth0 > 0);
75848b8605Smrg   if (target == PIPE_TEXTURE_CUBE)
76848b8605Smrg      assert(layers == 6);
77848b8605Smrg
78b8e80941Smrg   DBG("%s target %d format %s last_level %d\n", __func__,
79848b8605Smrg       (int) target, util_format_name(format), last_level);
80848b8605Smrg
81848b8605Smrg   assert(format);
82b8e80941Smrg   assert(screen->is_format_supported(screen, format, target, 0, 0,
83848b8605Smrg                                      PIPE_BIND_SAMPLER_VIEW));
84848b8605Smrg
85848b8605Smrg   memset(&pt, 0, sizeof(pt));
86848b8605Smrg   pt.target = target;
87848b8605Smrg   pt.format = format;
88848b8605Smrg   pt.last_level = last_level;
89848b8605Smrg   pt.width0 = width0;
90848b8605Smrg   pt.height0 = height0;
91848b8605Smrg   pt.depth0 = depth0;
92b8e80941Smrg   pt.array_size = layers;
93848b8605Smrg   pt.usage = PIPE_USAGE_DEFAULT;
94848b8605Smrg   pt.bind = bind;
95b8e80941Smrg   /* only set this for OpenGL textures, not renderbuffers */
96b8e80941Smrg   pt.flags = PIPE_RESOURCE_FLAG_TEXTURING_MORE_LIKELY;
97848b8605Smrg   pt.nr_samples = nr_samples;
98b8e80941Smrg   pt.nr_storage_samples = nr_samples;
99848b8605Smrg
100848b8605Smrg   newtex = screen->resource_create(screen, &pt);
101848b8605Smrg
102848b8605Smrg   assert(!newtex || pipe_is_referenced(&newtex->reference));
103848b8605Smrg
104848b8605Smrg   return newtex;
105848b8605Smrg}
106848b8605Smrg
107848b8605Smrg
108848b8605Smrg/**
109848b8605Smrg * In OpenGL the number of 1D array texture layers is the "height" and
110848b8605Smrg * the number of 2D array texture layers is the "depth".  In Gallium the
111848b8605Smrg * number of layers in an array texture is a separate 'array_size' field.
112848b8605Smrg * This function converts dimensions from the former to the later.
113848b8605Smrg */
114848b8605Smrgvoid
115848b8605Smrgst_gl_texture_dims_to_pipe_dims(GLenum texture,
116b8e80941Smrg                                unsigned widthIn,
117b8e80941Smrg                                uint16_t heightIn,
118b8e80941Smrg                                uint16_t depthIn,
119b8e80941Smrg                                unsigned *widthOut,
120b8e80941Smrg                                uint16_t *heightOut,
121b8e80941Smrg                                uint16_t *depthOut,
122b8e80941Smrg                                uint16_t *layersOut)
123848b8605Smrg{
124848b8605Smrg   switch (texture) {
125848b8605Smrg   case GL_TEXTURE_1D:
126848b8605Smrg   case GL_PROXY_TEXTURE_1D:
127848b8605Smrg      assert(heightIn == 1);
128848b8605Smrg      assert(depthIn == 1);
129848b8605Smrg      *widthOut = widthIn;
130848b8605Smrg      *heightOut = 1;
131848b8605Smrg      *depthOut = 1;
132848b8605Smrg      *layersOut = 1;
133848b8605Smrg      break;
134848b8605Smrg   case GL_TEXTURE_1D_ARRAY:
135848b8605Smrg   case GL_PROXY_TEXTURE_1D_ARRAY:
136848b8605Smrg      assert(depthIn == 1);
137848b8605Smrg      *widthOut = widthIn;
138848b8605Smrg      *heightOut = 1;
139848b8605Smrg      *depthOut = 1;
140848b8605Smrg      *layersOut = heightIn;
141848b8605Smrg      break;
142848b8605Smrg   case GL_TEXTURE_2D:
143848b8605Smrg   case GL_PROXY_TEXTURE_2D:
144848b8605Smrg   case GL_TEXTURE_RECTANGLE:
145848b8605Smrg   case GL_PROXY_TEXTURE_RECTANGLE:
146848b8605Smrg   case GL_TEXTURE_EXTERNAL_OES:
147848b8605Smrg   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
148848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE:
149848b8605Smrg      assert(depthIn == 1);
150848b8605Smrg      *widthOut = widthIn;
151848b8605Smrg      *heightOut = heightIn;
152848b8605Smrg      *depthOut = 1;
153848b8605Smrg      *layersOut = 1;
154848b8605Smrg      break;
155848b8605Smrg   case GL_TEXTURE_CUBE_MAP:
156848b8605Smrg   case GL_PROXY_TEXTURE_CUBE_MAP:
157848b8605Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
158848b8605Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
159848b8605Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
160848b8605Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
161848b8605Smrg   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
162848b8605Smrg   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
163848b8605Smrg      assert(depthIn == 1);
164848b8605Smrg      *widthOut = widthIn;
165848b8605Smrg      *heightOut = heightIn;
166848b8605Smrg      *depthOut = 1;
167848b8605Smrg      *layersOut = 6;
168848b8605Smrg      break;
169848b8605Smrg   case GL_TEXTURE_2D_ARRAY:
170848b8605Smrg   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
171848b8605Smrg   case GL_PROXY_TEXTURE_2D_ARRAY:
172848b8605Smrg   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
173848b8605Smrg      *widthOut = widthIn;
174848b8605Smrg      *heightOut = heightIn;
175848b8605Smrg      *depthOut = 1;
176848b8605Smrg      *layersOut = depthIn;
177848b8605Smrg      break;
178848b8605Smrg   case GL_TEXTURE_CUBE_MAP_ARRAY:
179848b8605Smrg   case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
180848b8605Smrg      *widthOut = widthIn;
181848b8605Smrg      *heightOut = heightIn;
182848b8605Smrg      *depthOut = 1;
183b8e80941Smrg      *layersOut = util_align_npot(depthIn, 6);
184848b8605Smrg      break;
185848b8605Smrg   default:
186848b8605Smrg      assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
187848b8605Smrg      /* fall-through */
188848b8605Smrg   case GL_TEXTURE_3D:
189848b8605Smrg   case GL_PROXY_TEXTURE_3D:
190848b8605Smrg      *widthOut = widthIn;
191848b8605Smrg      *heightOut = heightIn;
192848b8605Smrg      *depthOut = depthIn;
193848b8605Smrg      *layersOut = 1;
194848b8605Smrg      break;
195848b8605Smrg   }
196848b8605Smrg}
197848b8605Smrg
198848b8605Smrg
199848b8605Smrg/**
200848b8605Smrg * Check if a texture image can be pulled into a unified mipmap texture.
201848b8605Smrg */
202848b8605SmrgGLboolean
203848b8605Smrgst_texture_match_image(struct st_context *st,
204848b8605Smrg                       const struct pipe_resource *pt,
205848b8605Smrg                       const struct gl_texture_image *image)
206848b8605Smrg{
207b8e80941Smrg   unsigned ptWidth;
208b8e80941Smrg   uint16_t ptHeight, ptDepth, ptLayers;
209848b8605Smrg
210b8e80941Smrg   /* Images with borders are never pulled into mipmap textures.
211848b8605Smrg    */
212b8e80941Smrg   if (image->Border)
213848b8605Smrg      return GL_FALSE;
214848b8605Smrg
215848b8605Smrg   /* Check if this image's format matches the established texture's format.
216848b8605Smrg    */
217848b8605Smrg   if (st_mesa_format_to_pipe_format(st, image->TexFormat) != pt->format)
218848b8605Smrg      return GL_FALSE;
219848b8605Smrg
220848b8605Smrg   st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
221848b8605Smrg                                   image->Width, image->Height, image->Depth,
222848b8605Smrg                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);
223848b8605Smrg
224848b8605Smrg   /* Test if this image's size matches what's expected in the
225848b8605Smrg    * established texture.
226848b8605Smrg    */
227848b8605Smrg   if (ptWidth != u_minify(pt->width0, image->Level) ||
228848b8605Smrg       ptHeight != u_minify(pt->height0, image->Level) ||
229848b8605Smrg       ptDepth != u_minify(pt->depth0, image->Level) ||
230848b8605Smrg       ptLayers != pt->array_size)
231848b8605Smrg      return GL_FALSE;
232848b8605Smrg
233b8e80941Smrg   if (image->Level > pt->last_level)
234b8e80941Smrg      return GL_FALSE;
235b8e80941Smrg
236848b8605Smrg   return GL_TRUE;
237848b8605Smrg}
238848b8605Smrg
239848b8605Smrg
240848b8605Smrg/**
241848b8605Smrg * Map a texture image and return the address for a particular 2D face/slice/
242848b8605Smrg * layer.  The stImage indicates the cube face and mipmap level.  The slice
243848b8605Smrg * of the 3D texture is passed in 'zoffset'.
244848b8605Smrg * \param usage  one of the PIPE_TRANSFER_x values
245848b8605Smrg * \param x, y, w, h  the region of interest of the 2D image.
246848b8605Smrg * \return address of mapping or NULL if any error
247848b8605Smrg */
248848b8605SmrgGLubyte *
249848b8605Smrgst_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
250848b8605Smrg                     enum pipe_transfer_usage usage,
251848b8605Smrg                     GLuint x, GLuint y, GLuint z,
252848b8605Smrg                     GLuint w, GLuint h, GLuint d,
253848b8605Smrg                     struct pipe_transfer **transfer)
254848b8605Smrg{
255848b8605Smrg   struct st_texture_object *stObj =
256848b8605Smrg      st_texture_object(stImage->base.TexObject);
257848b8605Smrg   GLuint level;
258848b8605Smrg   void *map;
259848b8605Smrg
260b8e80941Smrg   DBG("%s \n", __func__);
261848b8605Smrg
262848b8605Smrg   if (!stImage->pt)
263848b8605Smrg      return NULL;
264848b8605Smrg
265848b8605Smrg   if (stObj->pt != stImage->pt)
266848b8605Smrg      level = 0;
267848b8605Smrg   else
268848b8605Smrg      level = stImage->base.Level;
269848b8605Smrg
270b8e80941Smrg   if (stObj->base.Immutable) {
271b8e80941Smrg      level += stObj->base.MinLevel;
272b8e80941Smrg      z += stObj->base.MinLayer;
273b8e80941Smrg      if (stObj->pt->array_size > 1)
274b8e80941Smrg         d = MIN2(d, stObj->base.NumLayers);
275b8e80941Smrg   }
276b8e80941Smrg
277848b8605Smrg   z += stImage->base.Face;
278848b8605Smrg
279848b8605Smrg   map = pipe_transfer_map_3d(st->pipe, stImage->pt, level, usage,
280848b8605Smrg                              x, y, z, w, h, d, transfer);
281848b8605Smrg   if (map) {
282848b8605Smrg      /* Enlarge the transfer array if it's not large enough. */
283848b8605Smrg      if (z >= stImage->num_transfers) {
284848b8605Smrg         unsigned new_size = z + 1;
285848b8605Smrg
286848b8605Smrg         stImage->transfer = realloc(stImage->transfer,
287848b8605Smrg                     new_size * sizeof(struct st_texture_image_transfer));
288848b8605Smrg         memset(&stImage->transfer[stImage->num_transfers], 0,
289848b8605Smrg                (new_size - stImage->num_transfers) *
290848b8605Smrg                sizeof(struct st_texture_image_transfer));
291848b8605Smrg         stImage->num_transfers = new_size;
292848b8605Smrg      }
293848b8605Smrg
294848b8605Smrg      assert(!stImage->transfer[z].transfer);
295848b8605Smrg      stImage->transfer[z].transfer = *transfer;
296848b8605Smrg   }
297848b8605Smrg   return map;
298848b8605Smrg}
299848b8605Smrg
300848b8605Smrg
301848b8605Smrgvoid
302848b8605Smrgst_texture_image_unmap(struct st_context *st,
303848b8605Smrg                       struct st_texture_image *stImage, unsigned slice)
304848b8605Smrg{
305848b8605Smrg   struct pipe_context *pipe = st->pipe;
306b8e80941Smrg   struct st_texture_object *stObj =
307b8e80941Smrg      st_texture_object(stImage->base.TexObject);
308b8e80941Smrg   struct pipe_transfer **transfer;
309848b8605Smrg
310b8e80941Smrg   if (stObj->base.Immutable)
311b8e80941Smrg      slice += stObj->base.MinLayer;
312b8e80941Smrg   transfer = &stImage->transfer[slice + stImage->base.Face].transfer;
313b8e80941Smrg
314b8e80941Smrg   DBG("%s\n", __func__);
315848b8605Smrg
316848b8605Smrg   pipe_transfer_unmap(pipe, *transfer);
317848b8605Smrg   *transfer = NULL;
318848b8605Smrg}
319848b8605Smrg
320848b8605Smrg
321848b8605Smrg/**
322848b8605Smrg * For debug only: get/print center pixel in the src resource.
323848b8605Smrg */
324848b8605Smrgstatic void
325848b8605Smrgprint_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
326848b8605Smrg{
327848b8605Smrg   struct pipe_transfer *xfer;
328848b8605Smrg   struct pipe_box region;
329848b8605Smrg   ubyte *map;
330848b8605Smrg
331848b8605Smrg   region.x = src->width0 / 2;
332848b8605Smrg   region.y = src->height0 / 2;
333848b8605Smrg   region.z = 0;
334848b8605Smrg   region.width = 1;
335848b8605Smrg   region.height = 1;
336848b8605Smrg   region.depth = 1;
337848b8605Smrg
338848b8605Smrg   map = pipe->transfer_map(pipe, src, 0, PIPE_TRANSFER_READ, &region, &xfer);
339848b8605Smrg
340848b8605Smrg   printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
341848b8605Smrg
342848b8605Smrg   pipe->transfer_unmap(pipe, xfer);
343848b8605Smrg}
344848b8605Smrg
345848b8605Smrg
346848b8605Smrg/**
347848b8605Smrg * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
348848b8605Smrg * This is used to copy mipmap images from one texture buffer to another.
349848b8605Smrg * This typically happens when our initial guess at the total texture size
350848b8605Smrg * is incorrect (see the guess_and_alloc_texture() function).
351848b8605Smrg */
352848b8605Smrgvoid
353848b8605Smrgst_texture_image_copy(struct pipe_context *pipe,
354848b8605Smrg                      struct pipe_resource *dst, GLuint dstLevel,
355848b8605Smrg                      struct pipe_resource *src, GLuint srcLevel,
356848b8605Smrg                      GLuint face)
357848b8605Smrg{
358848b8605Smrg   GLuint width = u_minify(dst->width0, dstLevel);
359848b8605Smrg   GLuint height = u_minify(dst->height0, dstLevel);
360848b8605Smrg   GLuint depth = u_minify(dst->depth0, dstLevel);
361848b8605Smrg   struct pipe_box src_box;
362848b8605Smrg   GLuint i;
363848b8605Smrg
364848b8605Smrg   if (u_minify(src->width0, srcLevel) != width ||
365848b8605Smrg       u_minify(src->height0, srcLevel) != height ||
366848b8605Smrg       u_minify(src->depth0, srcLevel) != depth) {
367848b8605Smrg      /* The source image size doesn't match the destination image size.
368848b8605Smrg       * This can happen in some degenerate situations such as rendering to a
369848b8605Smrg       * cube map face which was set up with mismatched texture sizes.
370848b8605Smrg       */
371848b8605Smrg      return;
372848b8605Smrg   }
373848b8605Smrg
374848b8605Smrg   src_box.x = 0;
375848b8605Smrg   src_box.y = 0;
376848b8605Smrg   src_box.width = width;
377848b8605Smrg   src_box.height = height;
378848b8605Smrg   src_box.depth = 1;
379848b8605Smrg
380848b8605Smrg   if (src->target == PIPE_TEXTURE_1D_ARRAY ||
381848b8605Smrg       src->target == PIPE_TEXTURE_2D_ARRAY ||
382848b8605Smrg       src->target == PIPE_TEXTURE_CUBE_ARRAY) {
383848b8605Smrg      face = 0;
384848b8605Smrg      depth = src->array_size;
385848b8605Smrg   }
386848b8605Smrg
387848b8605Smrg   /* Loop over 3D image slices */
388848b8605Smrg   /* could (and probably should) use "true" 3d box here -
389848b8605Smrg      but drivers can't quite handle it yet */
390848b8605Smrg   for (i = face; i < face + depth; i++) {
391848b8605Smrg      src_box.z = i;
392848b8605Smrg
393848b8605Smrg      if (0)  {
394848b8605Smrg         print_center_pixel(pipe, src);
395848b8605Smrg      }
396848b8605Smrg
397848b8605Smrg      pipe->resource_copy_region(pipe,
398848b8605Smrg                                 dst,
399848b8605Smrg                                 dstLevel,
400848b8605Smrg                                 0, 0, i,/* destX, Y, Z */
401848b8605Smrg                                 src,
402848b8605Smrg                                 srcLevel,
403848b8605Smrg                                 &src_box);
404848b8605Smrg   }
405848b8605Smrg}
406848b8605Smrg
407848b8605Smrg
408848b8605Smrgstruct pipe_resource *
409848b8605Smrgst_create_color_map_texture(struct gl_context *ctx)
410848b8605Smrg{
411848b8605Smrg   struct st_context *st = st_context(ctx);
412848b8605Smrg   struct pipe_resource *pt;
413848b8605Smrg   enum pipe_format format;
414848b8605Smrg   const uint texSize = 256; /* simple, and usually perfect */
415848b8605Smrg
416848b8605Smrg   /* find an RGBA texture format */
417848b8605Smrg   format = st_choose_format(st, GL_RGBA, GL_NONE, GL_NONE,
418b8e80941Smrg                             PIPE_TEXTURE_2D, 0, 0, PIPE_BIND_SAMPLER_VIEW,
419848b8605Smrg                             FALSE);
420848b8605Smrg
421848b8605Smrg   /* create texture for color map/table */
422848b8605Smrg   pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
423848b8605Smrg                          texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
424848b8605Smrg   return pt;
425848b8605Smrg}
426848b8605Smrg
427b8e80941Smrg
428848b8605Smrg/**
429b8e80941Smrg * Destroy bound texture handles for the given stage.
430848b8605Smrg */
431b8e80941Smrgstatic void
432b8e80941Smrgst_destroy_bound_texture_handles_per_stage(struct st_context *st,
433b8e80941Smrg                                           enum pipe_shader_type shader)
434848b8605Smrg{
435b8e80941Smrg   struct st_bound_handles *bound_handles = &st->bound_texture_handles[shader];
436b8e80941Smrg   struct pipe_context *pipe = st->pipe;
437b8e80941Smrg   unsigned i;
438848b8605Smrg
439b8e80941Smrg   if (likely(!bound_handles->num_handles))
440b8e80941Smrg      return;
441b8e80941Smrg
442b8e80941Smrg   for (i = 0; i < bound_handles->num_handles; i++) {
443b8e80941Smrg      uint64_t handle = bound_handles->handles[i];
444b8e80941Smrg
445b8e80941Smrg      pipe->make_texture_handle_resident(pipe, handle, false);
446b8e80941Smrg      pipe->delete_texture_handle(pipe, handle);
447848b8605Smrg   }
448b8e80941Smrg   free(bound_handles->handles);
449b8e80941Smrg   bound_handles->handles = NULL;
450b8e80941Smrg   bound_handles->num_handles = 0;
451b8e80941Smrg}
452848b8605Smrg
453848b8605Smrg
454b8e80941Smrg/**
455b8e80941Smrg * Destroy all bound texture handles in the context.
456b8e80941Smrg */
457b8e80941Smrgvoid
458b8e80941Smrgst_destroy_bound_texture_handles(struct st_context *st)
459b8e80941Smrg{
460b8e80941Smrg   unsigned i;
461b8e80941Smrg
462b8e80941Smrg   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
463b8e80941Smrg      st_destroy_bound_texture_handles_per_stage(st, i);
464848b8605Smrg   }
465b8e80941Smrg}
466848b8605Smrg
467848b8605Smrg
468b8e80941Smrg/**
469b8e80941Smrg * Destroy bound image handles for the given stage.
470b8e80941Smrg */
471b8e80941Smrgstatic void
472b8e80941Smrgst_destroy_bound_image_handles_per_stage(struct st_context *st,
473b8e80941Smrg                                         enum pipe_shader_type shader)
474b8e80941Smrg{
475b8e80941Smrg   struct st_bound_handles *bound_handles = &st->bound_image_handles[shader];
476b8e80941Smrg   struct pipe_context *pipe = st->pipe;
477b8e80941Smrg   unsigned i;
478b8e80941Smrg
479b8e80941Smrg   if (likely(!bound_handles->num_handles))
480b8e80941Smrg      return;
481b8e80941Smrg
482b8e80941Smrg   for (i = 0; i < bound_handles->num_handles; i++) {
483b8e80941Smrg      uint64_t handle = bound_handles->handles[i];
484b8e80941Smrg
485b8e80941Smrg      pipe->make_image_handle_resident(pipe, handle, GL_READ_WRITE, false);
486b8e80941Smrg      pipe->delete_image_handle(pipe, handle);
487b8e80941Smrg   }
488b8e80941Smrg   free(bound_handles->handles);
489b8e80941Smrg   bound_handles->handles = NULL;
490b8e80941Smrg   bound_handles->num_handles = 0;
491848b8605Smrg}
492848b8605Smrg
493b8e80941Smrg
494b8e80941Smrg/**
495b8e80941Smrg * Destroy all bound image handles in the context.
496b8e80941Smrg */
497848b8605Smrgvoid
498b8e80941Smrgst_destroy_bound_image_handles(struct st_context *st)
499848b8605Smrg{
500b8e80941Smrg   unsigned i;
501848b8605Smrg
502b8e80941Smrg   for (i = 0; i < PIPE_SHADER_TYPES; i++) {
503b8e80941Smrg      st_destroy_bound_image_handles_per_stage(st, i);
504848b8605Smrg   }
505848b8605Smrg}
506848b8605Smrg
507b8e80941Smrg
508b8e80941Smrg/**
509b8e80941Smrg * Create a texture handle from a texture unit.
510b8e80941Smrg */
511b8e80941Smrgstatic GLuint64
512b8e80941Smrgst_create_texture_handle_from_unit(struct st_context *st,
513b8e80941Smrg                                   struct gl_program *prog, GLuint texUnit)
514b8e80941Smrg{
515b8e80941Smrg   struct pipe_context *pipe = st->pipe;
516b8e80941Smrg   struct pipe_sampler_view *view;
517b8e80941Smrg   struct pipe_sampler_state sampler = {0};
518b8e80941Smrg
519b8e80941Smrg   /* TODO: Clarify the interaction of ARB_bindless_texture and EXT_texture_sRGB_decode */
520b8e80941Smrg   st_update_single_texture(st, &view, texUnit, prog->sh.data->Version >= 130, true);
521b8e80941Smrg   if (!view)
522b8e80941Smrg      return 0;
523b8e80941Smrg
524b8e80941Smrg   if (view->target != PIPE_BUFFER)
525b8e80941Smrg      st_convert_sampler_from_unit(st, &sampler, texUnit);
526b8e80941Smrg
527b8e80941Smrg   assert(st->ctx->Texture.Unit[texUnit]._Current);
528b8e80941Smrg
529b8e80941Smrg   return pipe->create_texture_handle(pipe, view, &sampler);
530b8e80941Smrg}
531b8e80941Smrg
532b8e80941Smrg
533b8e80941Smrg/**
534b8e80941Smrg * Create an image handle from an image unit.
535b8e80941Smrg */
536b8e80941Smrgstatic GLuint64
537b8e80941Smrgst_create_image_handle_from_unit(struct st_context *st,
538b8e80941Smrg                                 struct gl_program *prog, GLuint imgUnit)
539b8e80941Smrg{
540b8e80941Smrg   struct pipe_context *pipe = st->pipe;
541b8e80941Smrg   struct pipe_image_view img;
542b8e80941Smrg
543b8e80941Smrg   st_convert_image_from_unit(st, &img, imgUnit, GL_READ_WRITE);
544b8e80941Smrg
545b8e80941Smrg   return pipe->create_image_handle(pipe, &img);
546b8e80941Smrg}
547b8e80941Smrg
548b8e80941Smrg
549b8e80941Smrg/**
550b8e80941Smrg * Make all bindless samplers bound to texture units resident in the context.
551b8e80941Smrg */
552848b8605Smrgvoid
553b8e80941Smrgst_make_bound_samplers_resident(struct st_context *st,
554b8e80941Smrg                                struct gl_program *prog)
555848b8605Smrg{
556b8e80941Smrg   enum pipe_shader_type shader = pipe_shader_type_from_mesa(prog->info.stage);
557b8e80941Smrg   struct st_bound_handles *bound_handles = &st->bound_texture_handles[shader];
558b8e80941Smrg   struct pipe_context *pipe = st->pipe;
559b8e80941Smrg   GLuint64 handle;
560b8e80941Smrg   int i;
561b8e80941Smrg
562b8e80941Smrg   /* Remove previous bound texture handles for this stage. */
563b8e80941Smrg   st_destroy_bound_texture_handles_per_stage(st, shader);
564b8e80941Smrg
565b8e80941Smrg   if (likely(!prog->sh.HasBoundBindlessSampler))
566b8e80941Smrg      return;
567b8e80941Smrg
568b8e80941Smrg   for (i = 0; i < prog->sh.NumBindlessSamplers; i++) {
569b8e80941Smrg      struct gl_bindless_sampler *sampler = &prog->sh.BindlessSamplers[i];
570b8e80941Smrg
571b8e80941Smrg      if (!sampler->bound)
572b8e80941Smrg         continue;
573848b8605Smrg
574b8e80941Smrg      /* Request a new texture handle from the driver and make it resident. */
575b8e80941Smrg      handle = st_create_texture_handle_from_unit(st, prog, sampler->unit);
576b8e80941Smrg      if (!handle)
577b8e80941Smrg         continue;
578b8e80941Smrg
579b8e80941Smrg      pipe->make_texture_handle_resident(st->pipe, handle, true);
580b8e80941Smrg
581b8e80941Smrg      /* Overwrite the texture unit value by the resident handle before
582b8e80941Smrg       * uploading the constant buffer.
583b8e80941Smrg       */
584b8e80941Smrg      *(uint64_t *)sampler->data = handle;
585b8e80941Smrg
586b8e80941Smrg      /* Store the handle in the context. */
587b8e80941Smrg      bound_handles->handles = (uint64_t *)
588b8e80941Smrg         realloc(bound_handles->handles,
589b8e80941Smrg                 (bound_handles->num_handles + 1) * sizeof(uint64_t));
590b8e80941Smrg      bound_handles->handles[bound_handles->num_handles] = handle;
591b8e80941Smrg      bound_handles->num_handles++;
592b8e80941Smrg   }
593848b8605Smrg}
594848b8605Smrg
595848b8605Smrg
596b8e80941Smrg/**
597b8e80941Smrg * Make all bindless images bound to image units resident in the context.
598b8e80941Smrg */
599848b8605Smrgvoid
600b8e80941Smrgst_make_bound_images_resident(struct st_context *st,
601b8e80941Smrg                              struct gl_program *prog)
602848b8605Smrg{
603b8e80941Smrg   enum pipe_shader_type shader = pipe_shader_type_from_mesa(prog->info.stage);
604b8e80941Smrg   struct st_bound_handles *bound_handles = &st->bound_image_handles[shader];
605b8e80941Smrg   struct pipe_context *pipe = st->pipe;
606b8e80941Smrg   GLuint64 handle;
607b8e80941Smrg   int i;
608b8e80941Smrg
609b8e80941Smrg   /* Remove previous bound image handles for this stage. */
610b8e80941Smrg   st_destroy_bound_image_handles_per_stage(st, shader);
611b8e80941Smrg
612b8e80941Smrg   if (likely(!prog->sh.HasBoundBindlessImage))
613b8e80941Smrg      return;
614b8e80941Smrg
615b8e80941Smrg   for (i = 0; i < prog->sh.NumBindlessImages; i++) {
616b8e80941Smrg      struct gl_bindless_image *image = &prog->sh.BindlessImages[i];
617b8e80941Smrg
618b8e80941Smrg      if (!image->bound)
619b8e80941Smrg         continue;
620b8e80941Smrg
621b8e80941Smrg      /* Request a new image handle from the driver and make it resident. */
622b8e80941Smrg      handle = st_create_image_handle_from_unit(st, prog, image->unit);
623b8e80941Smrg      if (!handle)
624b8e80941Smrg         continue;
625b8e80941Smrg
626b8e80941Smrg      pipe->make_image_handle_resident(st->pipe, handle, GL_READ_WRITE, true);
627b8e80941Smrg
628b8e80941Smrg      /* Overwrite the image unit value by the resident handle before uploading
629b8e80941Smrg       * the constant buffer.
630b8e80941Smrg       */
631b8e80941Smrg      *(uint64_t *)image->data = handle;
632b8e80941Smrg
633b8e80941Smrg      /* Store the handle in the context. */
634b8e80941Smrg      bound_handles->handles = (uint64_t *)
635b8e80941Smrg         realloc(bound_handles->handles,
636b8e80941Smrg                 (bound_handles->num_handles + 1) * sizeof(uint64_t));
637b8e80941Smrg      bound_handles->handles[bound_handles->num_handles] = handle;
638b8e80941Smrg      bound_handles->num_handles++;
639b8e80941Smrg   }
640848b8605Smrg}
641