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, ®ion, &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