1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include <stdio.h> 29bf215546Sopenharmony_ci#include "main/bufferobj.h" 30bf215546Sopenharmony_ci#include "main/enums.h" 31bf215546Sopenharmony_ci#include "main/errors.h" 32bf215546Sopenharmony_ci#include "main/fbobject.h" 33bf215546Sopenharmony_ci#include "main/formats.h" 34bf215546Sopenharmony_ci#include "main/format_utils.h" 35bf215546Sopenharmony_ci#include "main/framebuffer.h" 36bf215546Sopenharmony_ci#include "main/glformats.h" 37bf215546Sopenharmony_ci#include "main/image.h" 38bf215546Sopenharmony_ci#include "main/formatquery.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#include "main/macros.h" 41bf215546Sopenharmony_ci#include "main/mipmap.h" 42bf215546Sopenharmony_ci#include "main/pack.h" 43bf215546Sopenharmony_ci#include "main/pbo.h" 44bf215546Sopenharmony_ci#include "main/pixeltransfer.h" 45bf215546Sopenharmony_ci#include "main/texcompress.h" 46bf215546Sopenharmony_ci#include "main/texcompress_astc.h" 47bf215546Sopenharmony_ci#include "main/texcompress_etc.h" 48bf215546Sopenharmony_ci#include "main/texgetimage.h" 49bf215546Sopenharmony_ci#include "main/teximage.h" 50bf215546Sopenharmony_ci#include "main/texobj.h" 51bf215546Sopenharmony_ci#include "main/texstore.h" 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci#include "state_tracker/st_debug.h" 54bf215546Sopenharmony_ci#include "state_tracker/st_context.h" 55bf215546Sopenharmony_ci#include "state_tracker/st_cb_bitmap.h" 56bf215546Sopenharmony_ci#include "state_tracker/st_cb_drawpixels.h" 57bf215546Sopenharmony_ci#include "state_tracker/st_cb_flush.h" 58bf215546Sopenharmony_ci#include "state_tracker/st_cb_texture.h" 59bf215546Sopenharmony_ci#include "state_tracker/st_format.h" 60bf215546Sopenharmony_ci#include "state_tracker/st_pbo.h" 61bf215546Sopenharmony_ci#include "state_tracker/st_texture.h" 62bf215546Sopenharmony_ci#include "state_tracker/st_gen_mipmap.h" 63bf215546Sopenharmony_ci#include "state_tracker/st_atom.h" 64bf215546Sopenharmony_ci#include "state_tracker/st_sampler_view.h" 65bf215546Sopenharmony_ci#include "state_tracker/st_util.h" 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci#include "pipe/p_context.h" 68bf215546Sopenharmony_ci#include "pipe/p_defines.h" 69bf215546Sopenharmony_ci#include "util/u_inlines.h" 70bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 71bf215546Sopenharmony_ci#include "pipe/p_shader_tokens.h" 72bf215546Sopenharmony_ci#include "util/u_tile.h" 73bf215546Sopenharmony_ci#include "util/format/u_format.h" 74bf215546Sopenharmony_ci#include "util/u_surface.h" 75bf215546Sopenharmony_ci#include "util/u_sampler.h" 76bf215546Sopenharmony_ci#include "util/u_math.h" 77bf215546Sopenharmony_ci#include "util/u_box.h" 78bf215546Sopenharmony_ci#include "util/u_memory.h" 79bf215546Sopenharmony_ci#include "util/u_simple_shaders.h" 80bf215546Sopenharmony_ci#include "cso_cache/cso_context.h" 81bf215546Sopenharmony_ci#include "tgsi/tgsi_ureg.h" 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci#define DBG if (0) printf 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cienum pipe_texture_target 87bf215546Sopenharmony_cigl_target_to_pipe(GLenum target) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci switch (target) { 90bf215546Sopenharmony_ci case GL_TEXTURE_1D: 91bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_1D: 92bf215546Sopenharmony_ci return PIPE_TEXTURE_1D; 93bf215546Sopenharmony_ci case GL_TEXTURE_2D: 94bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_2D: 95bf215546Sopenharmony_ci case GL_TEXTURE_EXTERNAL_OES: 96bf215546Sopenharmony_ci case GL_TEXTURE_2D_MULTISAMPLE: 97bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 98bf215546Sopenharmony_ci return PIPE_TEXTURE_2D; 99bf215546Sopenharmony_ci case GL_TEXTURE_RECTANGLE_NV: 100bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_RECTANGLE_NV: 101bf215546Sopenharmony_ci return PIPE_TEXTURE_RECT; 102bf215546Sopenharmony_ci case GL_TEXTURE_3D: 103bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_3D: 104bf215546Sopenharmony_ci return PIPE_TEXTURE_3D; 105bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_ARB: 106bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 107bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 108bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 109bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 110bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 111bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 112bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 113bf215546Sopenharmony_ci return PIPE_TEXTURE_CUBE; 114bf215546Sopenharmony_ci case GL_TEXTURE_1D_ARRAY_EXT: 115bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 116bf215546Sopenharmony_ci return PIPE_TEXTURE_1D_ARRAY; 117bf215546Sopenharmony_ci case GL_TEXTURE_2D_ARRAY_EXT: 118bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 119bf215546Sopenharmony_ci case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 120bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 121bf215546Sopenharmony_ci return PIPE_TEXTURE_2D_ARRAY; 122bf215546Sopenharmony_ci case GL_TEXTURE_BUFFER: 123bf215546Sopenharmony_ci return PIPE_BUFFER; 124bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_ARRAY: 125bf215546Sopenharmony_ci case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 126bf215546Sopenharmony_ci return PIPE_TEXTURE_CUBE_ARRAY; 127bf215546Sopenharmony_ci default: 128bf215546Sopenharmony_ci assert(0); 129bf215546Sopenharmony_ci return 0; 130bf215546Sopenharmony_ci } 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_cienum pipe_format 134bf215546Sopenharmony_cist_pbo_get_src_format(struct pipe_screen *screen, enum pipe_format src_format, struct pipe_resource *src) 135bf215546Sopenharmony_ci{ 136bf215546Sopenharmony_ci /* Convert the source format to what is expected by GetTexImage 137bf215546Sopenharmony_ci * and see if it's supported. 138bf215546Sopenharmony_ci * 139bf215546Sopenharmony_ci * This only applies to glGetTexImage: 140bf215546Sopenharmony_ci * - Luminance must be returned as (L,0,0,1). 141bf215546Sopenharmony_ci * - Luminance alpha must be returned as (L,0,0,A). 142bf215546Sopenharmony_ci * - Intensity must be returned as (I,0,0,1) 143bf215546Sopenharmony_ci */ 144bf215546Sopenharmony_ci src_format = util_format_linear(src_format); 145bf215546Sopenharmony_ci src_format = util_format_luminance_to_red(src_format); 146bf215546Sopenharmony_ci src_format = util_format_intensity_to_red(src_format); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if (!src_format || 149bf215546Sopenharmony_ci !screen->is_format_supported(screen, src_format, src->target, 150bf215546Sopenharmony_ci src->nr_samples, src->nr_storage_samples, 151bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)) { 152bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci return src_format; 155bf215546Sopenharmony_ci} 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_cistatic struct pipe_resource * 158bf215546Sopenharmony_cicreate_dst_texture(struct gl_context *ctx, 159bf215546Sopenharmony_ci enum pipe_format dst_format, enum pipe_texture_target pipe_target, 160bf215546Sopenharmony_ci GLsizei width, GLsizei height, GLint depth, 161bf215546Sopenharmony_ci GLenum gl_target, unsigned bind) 162bf215546Sopenharmony_ci{ 163bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 164bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 165bf215546Sopenharmony_ci struct pipe_resource dst_templ; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci /* create the destination texture of size (width X height X depth) */ 168bf215546Sopenharmony_ci memset(&dst_templ, 0, sizeof(dst_templ)); 169bf215546Sopenharmony_ci dst_templ.target = pipe_target; 170bf215546Sopenharmony_ci dst_templ.format = dst_format; 171bf215546Sopenharmony_ci dst_templ.bind = bind; 172bf215546Sopenharmony_ci dst_templ.usage = PIPE_USAGE_STAGING; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(gl_target, width, height, depth, 175bf215546Sopenharmony_ci &dst_templ.width0, &dst_templ.height0, 176bf215546Sopenharmony_ci &dst_templ.depth0, &dst_templ.array_size); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci return screen->resource_create(screen, &dst_templ); 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cistatic boolean 182bf215546Sopenharmony_cicopy_to_staging_dest(struct gl_context * ctx, struct pipe_resource *dst, 183bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 184bf215546Sopenharmony_ci GLsizei width, GLsizei height, GLint depth, 185bf215546Sopenharmony_ci GLenum format, GLenum type, void * pixels, 186bf215546Sopenharmony_ci struct gl_texture_image *texImage) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 189bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 190bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 191bf215546Sopenharmony_ci struct pipe_resource *src = stObj->pt; 192bf215546Sopenharmony_ci enum pipe_format dst_format = dst->format; 193bf215546Sopenharmony_ci mesa_format mesa_format; 194bf215546Sopenharmony_ci GLenum gl_target = texImage->TexObject->Target; 195bf215546Sopenharmony_ci unsigned dims; 196bf215546Sopenharmony_ci struct pipe_transfer *tex_xfer; 197bf215546Sopenharmony_ci ubyte *map = NULL; 198bf215546Sopenharmony_ci boolean done = FALSE; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci map = pipe_texture_map_3d(pipe, dst, 0, PIPE_MAP_READ, 203bf215546Sopenharmony_ci 0, 0, 0, width, height, depth, &tex_xfer); 204bf215546Sopenharmony_ci if (!map) { 205bf215546Sopenharmony_ci goto end; 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci mesa_format = st_pipe_format_to_mesa_format(dst_format); 209bf215546Sopenharmony_ci dims = _mesa_get_texture_dimensions(gl_target); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci /* copy/pack data into user buffer */ 212bf215546Sopenharmony_ci if (_mesa_format_matches_format_and_type(mesa_format, format, type, 213bf215546Sopenharmony_ci ctx->Pack.SwapBytes, NULL)) { 214bf215546Sopenharmony_ci /* memcpy */ 215bf215546Sopenharmony_ci const uint bytesPerRow = width * util_format_get_blocksize(dst_format); 216bf215546Sopenharmony_ci GLuint row, slice; 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci for (slice = 0; slice < depth; slice++) { 219bf215546Sopenharmony_ci ubyte *slice_map = map; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci for (row = 0; row < height; row++) { 222bf215546Sopenharmony_ci void *dest = _mesa_image_address(dims, &ctx->Pack, pixels, 223bf215546Sopenharmony_ci width, height, format, type, 224bf215546Sopenharmony_ci slice, row, 0); 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci memcpy(dest, slice_map, bytesPerRow); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci slice_map += tex_xfer->stride; 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci map += tex_xfer->layer_stride; 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci } 234bf215546Sopenharmony_ci else { 235bf215546Sopenharmony_ci /* format translation via floats */ 236bf215546Sopenharmony_ci GLuint slice; 237bf215546Sopenharmony_ci GLfloat *rgba; 238bf215546Sopenharmony_ci uint32_t dstMesaFormat; 239bf215546Sopenharmony_ci int dstStride, srcStride; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci assert(util_format_is_compressed(src->format)); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci rgba = malloc(width * height * 4 * sizeof(GLfloat)); 244bf215546Sopenharmony_ci if (!rgba) { 245bf215546Sopenharmony_ci goto end; 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci if (ST_DEBUG & DEBUG_FALLBACK) 249bf215546Sopenharmony_ci debug_printf("%s: fallback format translation\n", __func__); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci dstMesaFormat = _mesa_format_from_format_and_type(format, type); 252bf215546Sopenharmony_ci dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type); 253bf215546Sopenharmony_ci srcStride = 4 * width * sizeof(GLfloat); 254bf215546Sopenharmony_ci for (slice = 0; slice < depth; slice++) { 255bf215546Sopenharmony_ci void *dest = _mesa_image_address(dims, &ctx->Pack, pixels, 256bf215546Sopenharmony_ci width, height, format, type, 257bf215546Sopenharmony_ci slice, 0, 0); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci /* get float[4] rgba row from surface */ 260bf215546Sopenharmony_ci pipe_get_tile_rgba(tex_xfer, map, 0, 0, width, height, dst_format, 261bf215546Sopenharmony_ci rgba); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci _mesa_format_convert(dest, dstMesaFormat, dstStride, 264bf215546Sopenharmony_ci rgba, RGBA32_FLOAT, srcStride, 265bf215546Sopenharmony_ci width, height, NULL); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci /* Handle byte swapping if required */ 268bf215546Sopenharmony_ci if (ctx->Pack.SwapBytes) { 269bf215546Sopenharmony_ci _mesa_swap_bytes_2d_image(format, type, &ctx->Pack, 270bf215546Sopenharmony_ci width, height, dest, dest); 271bf215546Sopenharmony_ci } 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci map += tex_xfer->layer_stride; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci free(rgba); 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci done = TRUE; 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ciend: 281bf215546Sopenharmony_ci if (map) 282bf215546Sopenharmony_ci pipe_texture_unmap(pipe, tex_xfer); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci _mesa_unmap_pbo_dest(ctx, &ctx->Pack); 285bf215546Sopenharmony_ci return done; 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cienum pipe_format 289bf215546Sopenharmony_cist_pbo_get_dst_format(struct gl_context *ctx, enum pipe_texture_target target, 290bf215546Sopenharmony_ci enum pipe_format src_format, bool is_compressed, 291bf215546Sopenharmony_ci GLenum format, GLenum type, unsigned bind) 292bf215546Sopenharmony_ci{ 293bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 294bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 295bf215546Sopenharmony_ci /* Choose the destination format by finding the best match 296bf215546Sopenharmony_ci * for the format+type combo. */ 297bf215546Sopenharmony_ci enum pipe_format dst_format = st_choose_matching_format(st, bind, format, type, 298bf215546Sopenharmony_ci ctx->Pack.SwapBytes); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci if (dst_format == PIPE_FORMAT_NONE) { 301bf215546Sopenharmony_ci GLenum dst_glformat; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci /* Fall back to _mesa_GetTexImage_sw except for compressed formats, 304bf215546Sopenharmony_ci * where decompression with a blit is always preferred. */ 305bf215546Sopenharmony_ci if (!is_compressed) { 306bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci /* Set the appropriate format for the decompressed texture. 310bf215546Sopenharmony_ci * Luminance and sRGB formats shouldn't appear here.*/ 311bf215546Sopenharmony_ci switch (src_format) { 312bf215546Sopenharmony_ci case PIPE_FORMAT_DXT1_RGB: 313bf215546Sopenharmony_ci case PIPE_FORMAT_DXT1_RGBA: 314bf215546Sopenharmony_ci case PIPE_FORMAT_DXT3_RGBA: 315bf215546Sopenharmony_ci case PIPE_FORMAT_DXT5_RGBA: 316bf215546Sopenharmony_ci case PIPE_FORMAT_RGTC1_UNORM: 317bf215546Sopenharmony_ci case PIPE_FORMAT_RGTC2_UNORM: 318bf215546Sopenharmony_ci case PIPE_FORMAT_ETC1_RGB8: 319bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_RGB8: 320bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_RGB8A1: 321bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_RGBA8: 322bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_4x4: 323bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_5x4: 324bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_5x5: 325bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_6x5: 326bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_6x6: 327bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_8x5: 328bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_8x6: 329bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_8x8: 330bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_10x5: 331bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_10x6: 332bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_10x8: 333bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_10x10: 334bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_12x10: 335bf215546Sopenharmony_ci case PIPE_FORMAT_ASTC_12x12: 336bf215546Sopenharmony_ci case PIPE_FORMAT_BPTC_RGBA_UNORM: 337bf215546Sopenharmony_ci case PIPE_FORMAT_FXT1_RGB: 338bf215546Sopenharmony_ci case PIPE_FORMAT_FXT1_RGBA: 339bf215546Sopenharmony_ci dst_glformat = GL_RGBA8; 340bf215546Sopenharmony_ci break; 341bf215546Sopenharmony_ci case PIPE_FORMAT_RGTC1_SNORM: 342bf215546Sopenharmony_ci case PIPE_FORMAT_RGTC2_SNORM: 343bf215546Sopenharmony_ci if (!ctx->Extensions.EXT_texture_snorm) 344bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 345bf215546Sopenharmony_ci dst_glformat = GL_RGBA8_SNORM; 346bf215546Sopenharmony_ci break; 347bf215546Sopenharmony_ci case PIPE_FORMAT_BPTC_RGB_FLOAT: 348bf215546Sopenharmony_ci case PIPE_FORMAT_BPTC_RGB_UFLOAT: 349bf215546Sopenharmony_ci if (!ctx->Extensions.ARB_texture_float) 350bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 351bf215546Sopenharmony_ci dst_glformat = GL_RGBA32F; 352bf215546Sopenharmony_ci break; 353bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_R11_UNORM: 354bf215546Sopenharmony_ci if (bind && !screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM, 355bf215546Sopenharmony_ci target, 0, 0, bind)) 356bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 357bf215546Sopenharmony_ci dst_glformat = GL_R16; 358bf215546Sopenharmony_ci break; 359bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_R11_SNORM: 360bf215546Sopenharmony_ci if (bind && !screen->is_format_supported(screen, PIPE_FORMAT_R16_SNORM, 361bf215546Sopenharmony_ci target, 0, 0, bind)) 362bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 363bf215546Sopenharmony_ci dst_glformat = GL_R16_SNORM; 364bf215546Sopenharmony_ci break; 365bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_RG11_UNORM: 366bf215546Sopenharmony_ci if (bind && !screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, 367bf215546Sopenharmony_ci target, 0, 0, bind)) 368bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 369bf215546Sopenharmony_ci dst_glformat = GL_RG16; 370bf215546Sopenharmony_ci break; 371bf215546Sopenharmony_ci case PIPE_FORMAT_ETC2_RG11_SNORM: 372bf215546Sopenharmony_ci if (bind && !screen->is_format_supported(screen, PIPE_FORMAT_R16G16_SNORM, 373bf215546Sopenharmony_ci target, 0, 0, bind)) 374bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 375bf215546Sopenharmony_ci dst_glformat = GL_RG16_SNORM; 376bf215546Sopenharmony_ci break; 377bf215546Sopenharmony_ci default: 378bf215546Sopenharmony_ci assert(0); 379bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci dst_format = st_choose_format(st, dst_glformat, format, type, 383bf215546Sopenharmony_ci target, 0, 0, bind, 384bf215546Sopenharmony_ci false, false); 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci return dst_format; 387bf215546Sopenharmony_ci} 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_civoid 390bf215546Sopenharmony_cist_FreeTextureImageBuffer(struct gl_context *ctx, 391bf215546Sopenharmony_ci struct gl_texture_image *texImage) 392bf215546Sopenharmony_ci{ 393bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 394bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 395bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci DBG("%s\n", __func__); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci if (stImage->pt) { 400bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, NULL); 401bf215546Sopenharmony_ci } 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci free(stImage->transfer); 404bf215546Sopenharmony_ci stImage->transfer = NULL; 405bf215546Sopenharmony_ci stImage->num_transfers = 0; 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci if (stImage->compressed_data && 408bf215546Sopenharmony_ci pipe_reference(&stImage->compressed_data->reference, NULL)) { 409bf215546Sopenharmony_ci free(stImage->compressed_data->ptr); 410bf215546Sopenharmony_ci FREE(stImage->compressed_data); 411bf215546Sopenharmony_ci stImage->compressed_data = NULL; 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci /* if the texture image is being deallocated, the structure of the 415bf215546Sopenharmony_ci * texture is changing so we'll likely need a new sampler view. 416bf215546Sopenharmony_ci */ 417bf215546Sopenharmony_ci st_texture_release_all_sampler_views(st, stObj); 418bf215546Sopenharmony_ci} 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_cibool 421bf215546Sopenharmony_cist_astc_format_fallback(const struct st_context *st, mesa_format format) 422bf215546Sopenharmony_ci{ 423bf215546Sopenharmony_ci if (!_mesa_is_format_astc_2d(format)) 424bf215546Sopenharmony_ci return false; 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci if (format == MESA_FORMAT_RGBA_ASTC_5x5 || 427bf215546Sopenharmony_ci format == MESA_FORMAT_SRGB8_ALPHA8_ASTC_5x5) 428bf215546Sopenharmony_ci return !st->has_astc_5x5_ldr; 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci return !st->has_astc_2d_ldr; 431bf215546Sopenharmony_ci} 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_cibool 434bf215546Sopenharmony_cist_compressed_format_fallback(struct st_context *st, mesa_format format) 435bf215546Sopenharmony_ci{ 436bf215546Sopenharmony_ci if (format == MESA_FORMAT_ETC1_RGB8) 437bf215546Sopenharmony_ci return !st->has_etc1; 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci if (_mesa_is_format_etc2(format)) 440bf215546Sopenharmony_ci return !st->has_etc2; 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci if (st_astc_format_fallback(st, format)) 443bf215546Sopenharmony_ci return true; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci return false; 446bf215546Sopenharmony_ci} 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_cistatic void 450bf215546Sopenharmony_cicompressed_tex_fallback_allocate(struct st_context *st, 451bf215546Sopenharmony_ci struct gl_texture_image *texImage) 452bf215546Sopenharmony_ci{ 453bf215546Sopenharmony_ci if (!st_compressed_format_fallback(st, texImage->TexFormat)) 454bf215546Sopenharmony_ci return; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci if (texImage->compressed_data && 457bf215546Sopenharmony_ci pipe_reference(&texImage->compressed_data->reference, NULL)) { 458bf215546Sopenharmony_ci free(texImage->compressed_data->ptr); 459bf215546Sopenharmony_ci FREE(texImage->compressed_data); 460bf215546Sopenharmony_ci } 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci unsigned data_size = _mesa_format_image_size(texImage->TexFormat, 463bf215546Sopenharmony_ci texImage->Width2, 464bf215546Sopenharmony_ci texImage->Height2, 465bf215546Sopenharmony_ci texImage->Depth2); 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci texImage->compressed_data = CALLOC_STRUCT(st_compressed_data); 468bf215546Sopenharmony_ci texImage->compressed_data->ptr = 469bf215546Sopenharmony_ci malloc(data_size * _mesa_num_tex_faces(texImage->TexObject->Target)); 470bf215546Sopenharmony_ci pipe_reference_init(&texImage->compressed_data->reference, 1); 471bf215546Sopenharmony_ci} 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_civoid 475bf215546Sopenharmony_cist_MapTextureImage(struct gl_context *ctx, 476bf215546Sopenharmony_ci struct gl_texture_image *texImage, 477bf215546Sopenharmony_ci GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h, 478bf215546Sopenharmony_ci GLbitfield mode, 479bf215546Sopenharmony_ci GLubyte **mapOut, GLint *rowStrideOut) 480bf215546Sopenharmony_ci{ 481bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 482bf215546Sopenharmony_ci GLubyte *map; 483bf215546Sopenharmony_ci struct pipe_transfer *transfer; 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci /* Check for unexpected flags */ 486bf215546Sopenharmony_ci assert((mode & ~(GL_MAP_READ_BIT | 487bf215546Sopenharmony_ci GL_MAP_WRITE_BIT | 488bf215546Sopenharmony_ci GL_MAP_INVALIDATE_RANGE_BIT)) == 0); 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci const enum pipe_map_flags transfer_flags = 491bf215546Sopenharmony_ci _mesa_access_flags_to_transfer_flags(mode, false); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci map = st_texture_image_map(st, texImage, transfer_flags, x, y, slice, w, h, 1, 494bf215546Sopenharmony_ci &transfer); 495bf215546Sopenharmony_ci if (map) { 496bf215546Sopenharmony_ci if (st_compressed_format_fallback(st, texImage->TexFormat)) { 497bf215546Sopenharmony_ci /* Some compressed formats don't have to be supported by drivers, 498bf215546Sopenharmony_ci * and st/mesa transparently handles decompression on upload (Unmap), 499bf215546Sopenharmony_ci * so that drivers don't see the compressed formats. 500bf215546Sopenharmony_ci * 501bf215546Sopenharmony_ci * We store the compressed data (it's needed for glGetCompressedTex- 502bf215546Sopenharmony_ci * Image and image copies in OES_copy_image). 503bf215546Sopenharmony_ci */ 504bf215546Sopenharmony_ci unsigned z = transfer->box.z; 505bf215546Sopenharmony_ci struct st_texture_image_transfer *itransfer = &texImage->transfer[z]; 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci unsigned blk_w, blk_h; 508bf215546Sopenharmony_ci _mesa_get_format_block_size(texImage->TexFormat, &blk_w, &blk_h); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci unsigned y_blocks = DIV_ROUND_UP(texImage->Height2, blk_h); 511bf215546Sopenharmony_ci unsigned stride = *rowStrideOut = itransfer->temp_stride = 512bf215546Sopenharmony_ci _mesa_format_row_stride(texImage->TexFormat, texImage->Width2); 513bf215546Sopenharmony_ci unsigned block_size = _mesa_get_format_bytes(texImage->TexFormat); 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci assert(texImage->compressed_data); 516bf215546Sopenharmony_ci *mapOut = itransfer->temp_data = 517bf215546Sopenharmony_ci texImage->compressed_data->ptr + 518bf215546Sopenharmony_ci (z * y_blocks + (y / blk_h)) * stride + 519bf215546Sopenharmony_ci (x / blk_w) * block_size; 520bf215546Sopenharmony_ci itransfer->map = map; 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci else { 523bf215546Sopenharmony_ci /* supported mapping */ 524bf215546Sopenharmony_ci *mapOut = map; 525bf215546Sopenharmony_ci *rowStrideOut = transfer->stride; 526bf215546Sopenharmony_ci } 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci else { 529bf215546Sopenharmony_ci *mapOut = NULL; 530bf215546Sopenharmony_ci *rowStrideOut = 0; 531bf215546Sopenharmony_ci } 532bf215546Sopenharmony_ci} 533bf215546Sopenharmony_ci 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_civoid 536bf215546Sopenharmony_cist_UnmapTextureImage(struct gl_context *ctx, 537bf215546Sopenharmony_ci struct gl_texture_image *texImage, 538bf215546Sopenharmony_ci GLuint slice) 539bf215546Sopenharmony_ci{ 540bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 541bf215546Sopenharmony_ci 542bf215546Sopenharmony_ci if (st_compressed_format_fallback(st, texImage->TexFormat)) { 543bf215546Sopenharmony_ci /* Decompress the compressed image on upload if the driver doesn't 544bf215546Sopenharmony_ci * support the compressed format. */ 545bf215546Sopenharmony_ci unsigned z = slice + texImage->Face; 546bf215546Sopenharmony_ci struct st_texture_image_transfer *itransfer = &texImage->transfer[z]; 547bf215546Sopenharmony_ci struct pipe_transfer *transfer = itransfer->transfer; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci assert(z == transfer->box.z); 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci if (transfer->usage & PIPE_MAP_WRITE) { 552bf215546Sopenharmony_ci if (util_format_is_compressed(texImage->pt->format)) { 553bf215546Sopenharmony_ci /* Transcode into a different compressed format. */ 554bf215546Sopenharmony_ci unsigned size = 555bf215546Sopenharmony_ci _mesa_format_image_size(PIPE_FORMAT_R8G8B8A8_UNORM, 556bf215546Sopenharmony_ci transfer->box.width, 557bf215546Sopenharmony_ci transfer->box.height, 1); 558bf215546Sopenharmony_ci void *tmp = malloc(size); 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci /* Decompress to tmp. */ 561bf215546Sopenharmony_ci if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) { 562bf215546Sopenharmony_ci _mesa_etc1_unpack_rgba8888(tmp, transfer->box.width * 4, 563bf215546Sopenharmony_ci itransfer->temp_data, 564bf215546Sopenharmony_ci itransfer->temp_stride, 565bf215546Sopenharmony_ci transfer->box.width, 566bf215546Sopenharmony_ci transfer->box.height); 567bf215546Sopenharmony_ci } else if (_mesa_is_format_etc2(texImage->TexFormat)) { 568bf215546Sopenharmony_ci bool bgra = texImage->pt->format == PIPE_FORMAT_B8G8R8A8_SRGB; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci _mesa_unpack_etc2_format(tmp, transfer->box.width * 4, 571bf215546Sopenharmony_ci itransfer->temp_data, 572bf215546Sopenharmony_ci itransfer->temp_stride, 573bf215546Sopenharmony_ci transfer->box.width, 574bf215546Sopenharmony_ci transfer->box.height, 575bf215546Sopenharmony_ci texImage->TexFormat, 576bf215546Sopenharmony_ci bgra); 577bf215546Sopenharmony_ci } else if (_mesa_is_format_astc_2d(texImage->TexFormat)) { 578bf215546Sopenharmony_ci _mesa_unpack_astc_2d_ldr(tmp, transfer->box.width * 4, 579bf215546Sopenharmony_ci itransfer->temp_data, 580bf215546Sopenharmony_ci itransfer->temp_stride, 581bf215546Sopenharmony_ci transfer->box.width, 582bf215546Sopenharmony_ci transfer->box.height, 583bf215546Sopenharmony_ci texImage->TexFormat); 584bf215546Sopenharmony_ci } else { 585bf215546Sopenharmony_ci unreachable("unexpected format for a compressed format fallback"); 586bf215546Sopenharmony_ci } 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci /* Compress it to the target format. */ 589bf215546Sopenharmony_ci struct gl_pixelstore_attrib pack = {0}; 590bf215546Sopenharmony_ci pack.Alignment = 4; 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci _mesa_texstore(ctx, 2, GL_RGBA, texImage->pt->format, 593bf215546Sopenharmony_ci transfer->stride, &itransfer->map, 594bf215546Sopenharmony_ci transfer->box.width, 595bf215546Sopenharmony_ci transfer->box.height, 1, GL_RGBA, 596bf215546Sopenharmony_ci GL_UNSIGNED_BYTE, tmp, &pack); 597bf215546Sopenharmony_ci free(tmp); 598bf215546Sopenharmony_ci } else { 599bf215546Sopenharmony_ci /* Decompress into an uncompressed format. */ 600bf215546Sopenharmony_ci if (texImage->TexFormat == MESA_FORMAT_ETC1_RGB8) { 601bf215546Sopenharmony_ci _mesa_etc1_unpack_rgba8888(itransfer->map, transfer->stride, 602bf215546Sopenharmony_ci itransfer->temp_data, 603bf215546Sopenharmony_ci itransfer->temp_stride, 604bf215546Sopenharmony_ci transfer->box.width, 605bf215546Sopenharmony_ci transfer->box.height); 606bf215546Sopenharmony_ci } else if (_mesa_is_format_etc2(texImage->TexFormat)) { 607bf215546Sopenharmony_ci bool bgra = texImage->pt->format == PIPE_FORMAT_B8G8R8A8_SRGB; 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci _mesa_unpack_etc2_format(itransfer->map, transfer->stride, 610bf215546Sopenharmony_ci itransfer->temp_data, 611bf215546Sopenharmony_ci itransfer->temp_stride, 612bf215546Sopenharmony_ci transfer->box.width, transfer->box.height, 613bf215546Sopenharmony_ci texImage->TexFormat, 614bf215546Sopenharmony_ci bgra); 615bf215546Sopenharmony_ci } else if (_mesa_is_format_astc_2d(texImage->TexFormat)) { 616bf215546Sopenharmony_ci _mesa_unpack_astc_2d_ldr(itransfer->map, transfer->stride, 617bf215546Sopenharmony_ci itransfer->temp_data, 618bf215546Sopenharmony_ci itransfer->temp_stride, 619bf215546Sopenharmony_ci transfer->box.width, transfer->box.height, 620bf215546Sopenharmony_ci texImage->TexFormat); 621bf215546Sopenharmony_ci } else { 622bf215546Sopenharmony_ci unreachable("unexpected format for a compressed format fallback"); 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci } 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci itransfer->temp_data = NULL; 628bf215546Sopenharmony_ci itransfer->temp_stride = 0; 629bf215546Sopenharmony_ci itransfer->map = NULL; 630bf215546Sopenharmony_ci } 631bf215546Sopenharmony_ci 632bf215546Sopenharmony_ci st_texture_image_unmap(st, texImage, slice); 633bf215546Sopenharmony_ci} 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci/** 637bf215546Sopenharmony_ci * Return default texture resource binding bitmask for the given format. 638bf215546Sopenharmony_ci */ 639bf215546Sopenharmony_cistatic GLuint 640bf215546Sopenharmony_cidefault_bindings(struct st_context *st, enum pipe_format format) 641bf215546Sopenharmony_ci{ 642bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 643bf215546Sopenharmony_ci const unsigned target = PIPE_TEXTURE_2D; 644bf215546Sopenharmony_ci unsigned bindings; 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(format)) 647bf215546Sopenharmony_ci bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL; 648bf215546Sopenharmony_ci else 649bf215546Sopenharmony_ci bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci if (screen->is_format_supported(screen, format, target, 0, 0, bindings)) 652bf215546Sopenharmony_ci return bindings; 653bf215546Sopenharmony_ci else { 654bf215546Sopenharmony_ci /* Try non-sRGB. */ 655bf215546Sopenharmony_ci format = util_format_linear(format); 656bf215546Sopenharmony_ci 657bf215546Sopenharmony_ci if (screen->is_format_supported(screen, format, target, 0, 0, bindings)) 658bf215546Sopenharmony_ci return bindings; 659bf215546Sopenharmony_ci else 660bf215546Sopenharmony_ci return PIPE_BIND_SAMPLER_VIEW; 661bf215546Sopenharmony_ci } 662bf215546Sopenharmony_ci} 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci/** 666bf215546Sopenharmony_ci * Given the size of a mipmap image, try to compute the size of the level=0 667bf215546Sopenharmony_ci * mipmap image. 668bf215546Sopenharmony_ci * 669bf215546Sopenharmony_ci * Note that this isn't always accurate for odd-sized, non-POW textures. 670bf215546Sopenharmony_ci * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. 671bf215546Sopenharmony_ci * 672bf215546Sopenharmony_ci * \return GL_TRUE for success, GL_FALSE for failure 673bf215546Sopenharmony_ci */ 674bf215546Sopenharmony_cistatic GLboolean 675bf215546Sopenharmony_ciguess_base_level_size(GLenum target, 676bf215546Sopenharmony_ci GLuint width, GLuint height, GLuint depth, GLuint level, 677bf215546Sopenharmony_ci GLuint *width0, GLuint *height0, GLuint *depth0) 678bf215546Sopenharmony_ci{ 679bf215546Sopenharmony_ci assert(width >= 1); 680bf215546Sopenharmony_ci assert(height >= 1); 681bf215546Sopenharmony_ci assert(depth >= 1); 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci if (level > 0) { 684bf215546Sopenharmony_ci /* Guess the size of the base level. 685bf215546Sopenharmony_ci * Depending on the image's size, we can't always make a guess here. 686bf215546Sopenharmony_ci */ 687bf215546Sopenharmony_ci switch (target) { 688bf215546Sopenharmony_ci case GL_TEXTURE_1D: 689bf215546Sopenharmony_ci case GL_TEXTURE_1D_ARRAY: 690bf215546Sopenharmony_ci width <<= level; 691bf215546Sopenharmony_ci break; 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci case GL_TEXTURE_2D: 694bf215546Sopenharmony_ci case GL_TEXTURE_2D_ARRAY: 695bf215546Sopenharmony_ci /* We can't make a good guess here, because the base level dimensions 696bf215546Sopenharmony_ci * can be non-square. 697bf215546Sopenharmony_ci */ 698bf215546Sopenharmony_ci if (width == 1 || height == 1) { 699bf215546Sopenharmony_ci return GL_FALSE; 700bf215546Sopenharmony_ci } 701bf215546Sopenharmony_ci width <<= level; 702bf215546Sopenharmony_ci height <<= level; 703bf215546Sopenharmony_ci break; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP: 706bf215546Sopenharmony_ci case GL_TEXTURE_CUBE_MAP_ARRAY: 707bf215546Sopenharmony_ci width <<= level; 708bf215546Sopenharmony_ci height <<= level; 709bf215546Sopenharmony_ci break; 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci case GL_TEXTURE_3D: 712bf215546Sopenharmony_ci /* We can't make a good guess here, because the base level dimensions 713bf215546Sopenharmony_ci * can be non-cube. 714bf215546Sopenharmony_ci */ 715bf215546Sopenharmony_ci if (width == 1 || height == 1 || depth == 1) { 716bf215546Sopenharmony_ci return GL_FALSE; 717bf215546Sopenharmony_ci } 718bf215546Sopenharmony_ci width <<= level; 719bf215546Sopenharmony_ci height <<= level; 720bf215546Sopenharmony_ci depth <<= level; 721bf215546Sopenharmony_ci break; 722bf215546Sopenharmony_ci 723bf215546Sopenharmony_ci case GL_TEXTURE_RECTANGLE: 724bf215546Sopenharmony_ci break; 725bf215546Sopenharmony_ci 726bf215546Sopenharmony_ci default: 727bf215546Sopenharmony_ci assert(0); 728bf215546Sopenharmony_ci } 729bf215546Sopenharmony_ci } 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci *width0 = width; 732bf215546Sopenharmony_ci *height0 = height; 733bf215546Sopenharmony_ci *depth0 = depth; 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci return GL_TRUE; 736bf215546Sopenharmony_ci} 737bf215546Sopenharmony_ci 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci/** 740bf215546Sopenharmony_ci * Try to determine whether we should allocate memory for a full texture 741bf215546Sopenharmony_ci * mipmap. The problem is when we get a glTexImage(level=0) call, we 742bf215546Sopenharmony_ci * can't immediately know if other mipmap levels are coming next. Here 743bf215546Sopenharmony_ci * we try to guess whether to allocate memory for a mipmap or just the 744bf215546Sopenharmony_ci * 0th level. 745bf215546Sopenharmony_ci * 746bf215546Sopenharmony_ci * If we guess incorrectly here we'll later reallocate the right amount of 747bf215546Sopenharmony_ci * memory either in st_AllocTextureImageBuffer() or st_finalize_texture(). 748bf215546Sopenharmony_ci * 749bf215546Sopenharmony_ci * \param stObj the texture object we're going to allocate memory for. 750bf215546Sopenharmony_ci * \param stImage describes the incoming image which we need to store. 751bf215546Sopenharmony_ci */ 752bf215546Sopenharmony_cistatic boolean 753bf215546Sopenharmony_ciallocate_full_mipmap(const struct gl_texture_object *stObj, 754bf215546Sopenharmony_ci const struct gl_texture_image *stImage) 755bf215546Sopenharmony_ci{ 756bf215546Sopenharmony_ci switch (stObj->Target) { 757bf215546Sopenharmony_ci case GL_TEXTURE_RECTANGLE_NV: 758bf215546Sopenharmony_ci case GL_TEXTURE_BUFFER: 759bf215546Sopenharmony_ci case GL_TEXTURE_EXTERNAL_OES: 760bf215546Sopenharmony_ci case GL_TEXTURE_2D_MULTISAMPLE: 761bf215546Sopenharmony_ci case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 762bf215546Sopenharmony_ci /* these texture types cannot be mipmapped */ 763bf215546Sopenharmony_ci return FALSE; 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci if (stImage->Level > 0 || stObj->Attrib.GenerateMipmap) 767bf215546Sopenharmony_ci return TRUE; 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci /* If the application has explicitly called glTextureParameter to set 770bf215546Sopenharmony_ci * GL_TEXTURE_MAX_LEVEL, such that (max - base) > 0, then they're trying 771bf215546Sopenharmony_ci * to communicate that they will have multiple miplevels. 772bf215546Sopenharmony_ci * 773bf215546Sopenharmony_ci * Core Mesa will initialize MaxLevel to value much larger than 774bf215546Sopenharmony_ci * MAX_TEXTURE_LEVELS, so we check that to see if it's been set at all. 775bf215546Sopenharmony_ci */ 776bf215546Sopenharmony_ci if (stObj->Attrib.MaxLevel < MAX_TEXTURE_LEVELS && 777bf215546Sopenharmony_ci stObj->Attrib.MaxLevel - stObj->Attrib.BaseLevel > 0) 778bf215546Sopenharmony_ci return TRUE; 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci if (stImage->_BaseFormat == GL_DEPTH_COMPONENT || 781bf215546Sopenharmony_ci stImage->_BaseFormat == GL_DEPTH_STENCIL_EXT) 782bf215546Sopenharmony_ci /* depth/stencil textures are seldom mipmapped */ 783bf215546Sopenharmony_ci return FALSE; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci if (stObj->Attrib.BaseLevel == 0 && stObj->Attrib.MaxLevel == 0) 786bf215546Sopenharmony_ci return FALSE; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci if (stObj->Sampler.Attrib.MinFilter == GL_NEAREST || 789bf215546Sopenharmony_ci stObj->Sampler.Attrib.MinFilter == GL_LINEAR) 790bf215546Sopenharmony_ci /* not a mipmap minification filter */ 791bf215546Sopenharmony_ci return FALSE; 792bf215546Sopenharmony_ci 793bf215546Sopenharmony_ci /* If the following sequence of GL calls is used: 794bf215546Sopenharmony_ci * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, ... 795bf215546Sopenharmony_ci * glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 796bf215546Sopenharmony_ci * 797bf215546Sopenharmony_ci * we would needlessly allocate a mipmapped texture, because the initial 798bf215546Sopenharmony_ci * MinFilter is GL_NEAREST_MIPMAP_LINEAR. Catch this case and don't 799bf215546Sopenharmony_ci * allocate a mipmapped texture by default. This may cause texture 800bf215546Sopenharmony_ci * reallocation later, but GL_NEAREST_MIPMAP_LINEAR is pretty rare. 801bf215546Sopenharmony_ci */ 802bf215546Sopenharmony_ci if (stObj->Sampler.Attrib.MinFilter == GL_NEAREST_MIPMAP_LINEAR) 803bf215546Sopenharmony_ci return FALSE; 804bf215546Sopenharmony_ci 805bf215546Sopenharmony_ci if (stObj->Target == GL_TEXTURE_3D) 806bf215546Sopenharmony_ci /* 3D textures are seldom mipmapped */ 807bf215546Sopenharmony_ci return FALSE; 808bf215546Sopenharmony_ci 809bf215546Sopenharmony_ci return TRUE; 810bf215546Sopenharmony_ci} 811bf215546Sopenharmony_ci 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci/** 814bf215546Sopenharmony_ci * Try to allocate a pipe_resource object for the given gl_texture_object. 815bf215546Sopenharmony_ci * 816bf215546Sopenharmony_ci * We use the given st_texture_image as a clue to determine the size of the 817bf215546Sopenharmony_ci * mipmap image at level=0. 818bf215546Sopenharmony_ci * 819bf215546Sopenharmony_ci * \return GL_TRUE for success, GL_FALSE if out of memory. 820bf215546Sopenharmony_ci */ 821bf215546Sopenharmony_cistatic GLboolean 822bf215546Sopenharmony_ciguess_and_alloc_texture(struct st_context *st, 823bf215546Sopenharmony_ci struct gl_texture_object *stObj, 824bf215546Sopenharmony_ci const struct gl_texture_image *stImage) 825bf215546Sopenharmony_ci{ 826bf215546Sopenharmony_ci const struct gl_texture_image *firstImage; 827bf215546Sopenharmony_ci GLuint lastLevel, width, height, depth; 828bf215546Sopenharmony_ci GLuint bindings; 829bf215546Sopenharmony_ci unsigned ptWidth; 830bf215546Sopenharmony_ci uint16_t ptHeight, ptDepth, ptLayers; 831bf215546Sopenharmony_ci enum pipe_format fmt; 832bf215546Sopenharmony_ci bool guessed_box = false; 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci DBG("%s\n", __func__); 835bf215546Sopenharmony_ci 836bf215546Sopenharmony_ci assert(!stObj->pt); 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci /* If a base level image with compatible size exists, use that as our guess. 839bf215546Sopenharmony_ci */ 840bf215546Sopenharmony_ci firstImage = _mesa_base_tex_image(stObj); 841bf215546Sopenharmony_ci if (firstImage && 842bf215546Sopenharmony_ci firstImage->Width2 > 0 && 843bf215546Sopenharmony_ci firstImage->Height2 > 0 && 844bf215546Sopenharmony_ci firstImage->Depth2 > 0 && 845bf215546Sopenharmony_ci guess_base_level_size(stObj->Target, 846bf215546Sopenharmony_ci firstImage->Width2, 847bf215546Sopenharmony_ci firstImage->Height2, 848bf215546Sopenharmony_ci firstImage->Depth2, 849bf215546Sopenharmony_ci firstImage->Level, 850bf215546Sopenharmony_ci &width, &height, &depth)) { 851bf215546Sopenharmony_ci if (stImage->Width2 == u_minify(width, stImage->Level) && 852bf215546Sopenharmony_ci stImage->Height2 == u_minify(height, stImage->Level) && 853bf215546Sopenharmony_ci stImage->Depth2 == u_minify(depth, stImage->Level)) 854bf215546Sopenharmony_ci guessed_box = true; 855bf215546Sopenharmony_ci } 856bf215546Sopenharmony_ci 857bf215546Sopenharmony_ci if (!guessed_box) 858bf215546Sopenharmony_ci guessed_box = guess_base_level_size(stObj->Target, 859bf215546Sopenharmony_ci stImage->Width2, 860bf215546Sopenharmony_ci stImage->Height2, 861bf215546Sopenharmony_ci stImage->Depth2, 862bf215546Sopenharmony_ci stImage->Level, 863bf215546Sopenharmony_ci &width, &height, &depth); 864bf215546Sopenharmony_ci 865bf215546Sopenharmony_ci if (!guessed_box) { 866bf215546Sopenharmony_ci /* we can't determine the image size at level=0 */ 867bf215546Sopenharmony_ci /* this is not an out of memory error */ 868bf215546Sopenharmony_ci return GL_TRUE; 869bf215546Sopenharmony_ci } 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci /* At this point, (width x height x depth) is the expected size of 872bf215546Sopenharmony_ci * the level=0 mipmap image. 873bf215546Sopenharmony_ci */ 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci /* Guess a reasonable value for lastLevel. With OpenGL we have no 876bf215546Sopenharmony_ci * idea how many mipmap levels will be in a texture until we start 877bf215546Sopenharmony_ci * to render with it. Make an educated guess here but be prepared 878bf215546Sopenharmony_ci * to re-allocating a texture buffer with space for more (or fewer) 879bf215546Sopenharmony_ci * mipmap levels later. 880bf215546Sopenharmony_ci */ 881bf215546Sopenharmony_ci if (allocate_full_mipmap(stObj, stImage)) { 882bf215546Sopenharmony_ci /* alloc space for a full mipmap */ 883bf215546Sopenharmony_ci lastLevel = _mesa_get_tex_max_num_levels(stObj->Target, 884bf215546Sopenharmony_ci width, height, depth) - 1; 885bf215546Sopenharmony_ci } 886bf215546Sopenharmony_ci else { 887bf215546Sopenharmony_ci /* only alloc space for a single mipmap level */ 888bf215546Sopenharmony_ci lastLevel = 0; 889bf215546Sopenharmony_ci } 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_ci fmt = st_mesa_format_to_pipe_format(st, stImage->TexFormat); 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci bindings = default_bindings(st, fmt); 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(stObj->Target, 896bf215546Sopenharmony_ci width, height, depth, 897bf215546Sopenharmony_ci &ptWidth, &ptHeight, &ptDepth, &ptLayers); 898bf215546Sopenharmony_ci 899bf215546Sopenharmony_ci stObj->pt = st_texture_create(st, 900bf215546Sopenharmony_ci gl_target_to_pipe(stObj->Target), 901bf215546Sopenharmony_ci fmt, 902bf215546Sopenharmony_ci lastLevel, 903bf215546Sopenharmony_ci ptWidth, 904bf215546Sopenharmony_ci ptHeight, 905bf215546Sopenharmony_ci ptDepth, 906bf215546Sopenharmony_ci ptLayers, 0, 907bf215546Sopenharmony_ci bindings, 908bf215546Sopenharmony_ci false); 909bf215546Sopenharmony_ci 910bf215546Sopenharmony_ci stObj->lastLevel = lastLevel; 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci DBG("%s returning %d\n", __func__, (stObj->pt != NULL)); 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci return stObj->pt != NULL; 915bf215546Sopenharmony_ci} 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci/** 919bf215546Sopenharmony_ci * If the texture object/buffer already has space for the indicated image, 920bf215546Sopenharmony_ci * we're done. Otherwise, allocate memory for the new texture image. 921bf215546Sopenharmony_ci */ 922bf215546Sopenharmony_ciGLboolean 923bf215546Sopenharmony_cist_AllocTextureImageBuffer(struct gl_context *ctx, 924bf215546Sopenharmony_ci struct gl_texture_image *texImage) 925bf215546Sopenharmony_ci{ 926bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 927bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 928bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 929bf215546Sopenharmony_ci GLuint width = texImage->Width; 930bf215546Sopenharmony_ci GLuint height = texImage->Height; 931bf215546Sopenharmony_ci GLuint depth = texImage->Depth; 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci DBG("%s\n", __func__); 934bf215546Sopenharmony_ci 935bf215546Sopenharmony_ci assert(!stImage->pt); /* xxx this might be wrong */ 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci stObj->needs_validation = true; 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci compressed_tex_fallback_allocate(st, stImage); 940bf215546Sopenharmony_ci const bool allowAllocateToStObj = !stObj->pt || 941bf215546Sopenharmony_ci stObj->pt->last_level == 0 || 942bf215546Sopenharmony_ci texImage->Level == 0; 943bf215546Sopenharmony_ci 944bf215546Sopenharmony_ci if (allowAllocateToStObj) { 945bf215546Sopenharmony_ci /* Look if the parent texture object has space for this image */ 946bf215546Sopenharmony_ci if (stObj->pt && 947bf215546Sopenharmony_ci st_texture_match_image(st, stObj->pt, texImage)) { 948bf215546Sopenharmony_ci /* this image will fit in the existing texture object's memory */ 949bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, stObj->pt); 950bf215546Sopenharmony_ci assert(stImage->pt); 951bf215546Sopenharmony_ci return GL_TRUE; 952bf215546Sopenharmony_ci } 953bf215546Sopenharmony_ci 954bf215546Sopenharmony_ci /* The parent texture object does not have space for this image */ 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci pipe_resource_reference(&stObj->pt, NULL); 957bf215546Sopenharmony_ci st_texture_release_all_sampler_views(st, stObj); 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci if (!guess_and_alloc_texture(st, stObj, stImage)) { 960bf215546Sopenharmony_ci /* Probably out of memory. 961bf215546Sopenharmony_ci * Try flushing any pending rendering, then retry. 962bf215546Sopenharmony_ci */ 963bf215546Sopenharmony_ci st_finish(st); 964bf215546Sopenharmony_ci if (!guess_and_alloc_texture(st, stObj, stImage)) { 965bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage(internalformat=%s)", 966bf215546Sopenharmony_ci _mesa_enum_to_string(stImage->InternalFormat)); 967bf215546Sopenharmony_ci return GL_FALSE; 968bf215546Sopenharmony_ci } 969bf215546Sopenharmony_ci } 970bf215546Sopenharmony_ci } 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci if (stObj->pt && 973bf215546Sopenharmony_ci st_texture_match_image(st, stObj->pt, texImage)) { 974bf215546Sopenharmony_ci /* The image will live in the object's mipmap memory */ 975bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, stObj->pt); 976bf215546Sopenharmony_ci assert(stImage->pt); 977bf215546Sopenharmony_ci return GL_TRUE; 978bf215546Sopenharmony_ci } 979bf215546Sopenharmony_ci else { 980bf215546Sopenharmony_ci /* Create a new, temporary texture/resource/buffer to hold this 981bf215546Sopenharmony_ci * one texture image. Note that when we later access this image 982bf215546Sopenharmony_ci * (either for mapping or copying) we'll want to always specify 983bf215546Sopenharmony_ci * mipmap level=0, even if the image represents some other mipmap 984bf215546Sopenharmony_ci * level. 985bf215546Sopenharmony_ci */ 986bf215546Sopenharmony_ci enum pipe_format format = 987bf215546Sopenharmony_ci st_mesa_format_to_pipe_format(st, texImage->TexFormat); 988bf215546Sopenharmony_ci GLuint bindings = default_bindings(st, format); 989bf215546Sopenharmony_ci unsigned ptWidth; 990bf215546Sopenharmony_ci uint16_t ptHeight, ptDepth, ptLayers; 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(stObj->Target, 993bf215546Sopenharmony_ci width, height, depth, 994bf215546Sopenharmony_ci &ptWidth, &ptHeight, &ptDepth, &ptLayers); 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_ci stImage->pt = st_texture_create(st, 997bf215546Sopenharmony_ci gl_target_to_pipe(stObj->Target), 998bf215546Sopenharmony_ci format, 999bf215546Sopenharmony_ci 0, /* lastLevel */ 1000bf215546Sopenharmony_ci ptWidth, 1001bf215546Sopenharmony_ci ptHeight, 1002bf215546Sopenharmony_ci ptDepth, 1003bf215546Sopenharmony_ci ptLayers, 0, 1004bf215546Sopenharmony_ci bindings, 1005bf215546Sopenharmony_ci false); 1006bf215546Sopenharmony_ci return stImage->pt != NULL; 1007bf215546Sopenharmony_ci } 1008bf215546Sopenharmony_ci} 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci/** 1012bf215546Sopenharmony_ci * Preparation prior to glTexImage. Basically check the 'surface_based' 1013bf215546Sopenharmony_ci * field and switch to a "normal" tex image if necessary. 1014bf215546Sopenharmony_ci */ 1015bf215546Sopenharmony_cistatic void 1016bf215546Sopenharmony_ciprep_teximage(struct gl_context *ctx, struct gl_texture_image *texImage, 1017bf215546Sopenharmony_ci GLenum format, GLenum type) 1018bf215546Sopenharmony_ci{ 1019bf215546Sopenharmony_ci struct gl_texture_object *texObj = texImage->TexObject; 1020bf215546Sopenharmony_ci 1021bf215546Sopenharmony_ci /* switch to "normal" */ 1022bf215546Sopenharmony_ci if (texObj->surface_based) { 1023bf215546Sopenharmony_ci const GLenum target = texObj->Target; 1024bf215546Sopenharmony_ci const GLuint level = texImage->Level; 1025bf215546Sopenharmony_ci mesa_format texFormat; 1026bf215546Sopenharmony_ci 1027bf215546Sopenharmony_ci assert(!texImage->pt); 1028bf215546Sopenharmony_ci _mesa_clear_texture_object(ctx, texObj, texImage); 1029bf215546Sopenharmony_ci texObj->layer_override = -1; 1030bf215546Sopenharmony_ci texObj->level_override = -1; 1031bf215546Sopenharmony_ci pipe_resource_reference(&texObj->pt, NULL); 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci /* oops, need to init this image again */ 1034bf215546Sopenharmony_ci texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 1035bf215546Sopenharmony_ci texImage->InternalFormat, format, 1036bf215546Sopenharmony_ci type); 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci _mesa_init_teximage_fields(ctx, texImage, 1039bf215546Sopenharmony_ci texImage->Width, texImage->Height, 1040bf215546Sopenharmony_ci texImage->Depth, texImage->Border, 1041bf215546Sopenharmony_ci texImage->InternalFormat, texFormat); 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci texObj->surface_based = GL_FALSE; 1044bf215546Sopenharmony_ci } 1045bf215546Sopenharmony_ci} 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci 1048bf215546Sopenharmony_ci/** 1049bf215546Sopenharmony_ci * Return a writemask for the gallium blit. The parameters can be base 1050bf215546Sopenharmony_ci * formats or "format" from glDrawPixels/glTexImage/glGetTexImage. 1051bf215546Sopenharmony_ci */ 1052bf215546Sopenharmony_ciunsigned 1053bf215546Sopenharmony_cist_get_blit_mask(GLenum srcFormat, GLenum dstFormat) 1054bf215546Sopenharmony_ci{ 1055bf215546Sopenharmony_ci switch (dstFormat) { 1056bf215546Sopenharmony_ci case GL_DEPTH_STENCIL: 1057bf215546Sopenharmony_ci switch (srcFormat) { 1058bf215546Sopenharmony_ci case GL_DEPTH_STENCIL: 1059bf215546Sopenharmony_ci return PIPE_MASK_ZS; 1060bf215546Sopenharmony_ci case GL_DEPTH_COMPONENT: 1061bf215546Sopenharmony_ci return PIPE_MASK_Z; 1062bf215546Sopenharmony_ci case GL_STENCIL_INDEX: 1063bf215546Sopenharmony_ci return PIPE_MASK_S; 1064bf215546Sopenharmony_ci default: 1065bf215546Sopenharmony_ci assert(0); 1066bf215546Sopenharmony_ci return 0; 1067bf215546Sopenharmony_ci } 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci case GL_DEPTH_COMPONENT: 1070bf215546Sopenharmony_ci switch (srcFormat) { 1071bf215546Sopenharmony_ci case GL_DEPTH_STENCIL: 1072bf215546Sopenharmony_ci case GL_DEPTH_COMPONENT: 1073bf215546Sopenharmony_ci return PIPE_MASK_Z; 1074bf215546Sopenharmony_ci default: 1075bf215546Sopenharmony_ci assert(0); 1076bf215546Sopenharmony_ci return 0; 1077bf215546Sopenharmony_ci } 1078bf215546Sopenharmony_ci 1079bf215546Sopenharmony_ci case GL_STENCIL_INDEX: 1080bf215546Sopenharmony_ci switch (srcFormat) { 1081bf215546Sopenharmony_ci case GL_DEPTH_STENCIL: 1082bf215546Sopenharmony_ci case GL_STENCIL_INDEX: 1083bf215546Sopenharmony_ci return PIPE_MASK_S; 1084bf215546Sopenharmony_ci default: 1085bf215546Sopenharmony_ci assert(0); 1086bf215546Sopenharmony_ci return 0; 1087bf215546Sopenharmony_ci } 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci default: 1090bf215546Sopenharmony_ci return PIPE_MASK_RGBA; 1091bf215546Sopenharmony_ci } 1092bf215546Sopenharmony_ci} 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ci/** 1095bf215546Sopenharmony_ci * Converts format to a format with the same components, types 1096bf215546Sopenharmony_ci * and sizes, but with the components in RGBA order. 1097bf215546Sopenharmony_ci */ 1098bf215546Sopenharmony_cistatic enum pipe_format 1099bf215546Sopenharmony_ciunswizzle_format(enum pipe_format format) 1100bf215546Sopenharmony_ci{ 1101bf215546Sopenharmony_ci switch (format) 1102bf215546Sopenharmony_ci { 1103bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8A8_UNORM: 1104bf215546Sopenharmony_ci case PIPE_FORMAT_A8R8G8B8_UNORM: 1105bf215546Sopenharmony_ci case PIPE_FORMAT_A8B8G8R8_UNORM: 1106bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8B8A8_UNORM; 1107bf215546Sopenharmony_ci 1108bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UNORM: 1109bf215546Sopenharmony_ci return PIPE_FORMAT_R10G10B10A2_UNORM; 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_SNORM: 1112bf215546Sopenharmony_ci return PIPE_FORMAT_R10G10B10A2_SNORM; 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UINT: 1115bf215546Sopenharmony_ci return PIPE_FORMAT_R10G10B10A2_UINT; 1116bf215546Sopenharmony_ci 1117bf215546Sopenharmony_ci default: 1118bf215546Sopenharmony_ci return format; 1119bf215546Sopenharmony_ci } 1120bf215546Sopenharmony_ci} 1121bf215546Sopenharmony_ci 1122bf215546Sopenharmony_ci 1123bf215546Sopenharmony_ci/** 1124bf215546Sopenharmony_ci * Converts PIPE_FORMAT_A* to PIPE_FORMAT_R*. 1125bf215546Sopenharmony_ci */ 1126bf215546Sopenharmony_cistatic enum pipe_format 1127bf215546Sopenharmony_cialpha_to_red(enum pipe_format format) 1128bf215546Sopenharmony_ci{ 1129bf215546Sopenharmony_ci switch (format) 1130bf215546Sopenharmony_ci { 1131bf215546Sopenharmony_ci case PIPE_FORMAT_A8_UNORM: 1132bf215546Sopenharmony_ci return PIPE_FORMAT_R8_UNORM; 1133bf215546Sopenharmony_ci case PIPE_FORMAT_A8_SNORM: 1134bf215546Sopenharmony_ci return PIPE_FORMAT_R8_SNORM; 1135bf215546Sopenharmony_ci case PIPE_FORMAT_A8_UINT: 1136bf215546Sopenharmony_ci return PIPE_FORMAT_R8_UINT; 1137bf215546Sopenharmony_ci case PIPE_FORMAT_A8_SINT: 1138bf215546Sopenharmony_ci return PIPE_FORMAT_R8_SINT; 1139bf215546Sopenharmony_ci 1140bf215546Sopenharmony_ci case PIPE_FORMAT_A16_UNORM: 1141bf215546Sopenharmony_ci return PIPE_FORMAT_R16_UNORM; 1142bf215546Sopenharmony_ci case PIPE_FORMAT_A16_SNORM: 1143bf215546Sopenharmony_ci return PIPE_FORMAT_R16_SNORM; 1144bf215546Sopenharmony_ci case PIPE_FORMAT_A16_UINT: 1145bf215546Sopenharmony_ci return PIPE_FORMAT_R16_UINT; 1146bf215546Sopenharmony_ci case PIPE_FORMAT_A16_SINT: 1147bf215546Sopenharmony_ci return PIPE_FORMAT_R16_SINT; 1148bf215546Sopenharmony_ci case PIPE_FORMAT_A16_FLOAT: 1149bf215546Sopenharmony_ci return PIPE_FORMAT_R16_FLOAT; 1150bf215546Sopenharmony_ci 1151bf215546Sopenharmony_ci case PIPE_FORMAT_A32_UINT: 1152bf215546Sopenharmony_ci return PIPE_FORMAT_R32_UINT; 1153bf215546Sopenharmony_ci case PIPE_FORMAT_A32_SINT: 1154bf215546Sopenharmony_ci return PIPE_FORMAT_R32_SINT; 1155bf215546Sopenharmony_ci case PIPE_FORMAT_A32_FLOAT: 1156bf215546Sopenharmony_ci return PIPE_FORMAT_R32_FLOAT; 1157bf215546Sopenharmony_ci 1158bf215546Sopenharmony_ci default: 1159bf215546Sopenharmony_ci return format; 1160bf215546Sopenharmony_ci } 1161bf215546Sopenharmony_ci} 1162bf215546Sopenharmony_ci 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_ci/** 1165bf215546Sopenharmony_ci * Converts PIPE_FORMAT_R*A* to PIPE_FORMAT_R*G*. 1166bf215546Sopenharmony_ci */ 1167bf215546Sopenharmony_cistatic enum pipe_format 1168bf215546Sopenharmony_cired_alpha_to_red_green(enum pipe_format format) 1169bf215546Sopenharmony_ci{ 1170bf215546Sopenharmony_ci switch (format) 1171bf215546Sopenharmony_ci { 1172bf215546Sopenharmony_ci case PIPE_FORMAT_R8A8_UNORM: 1173bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_UNORM; 1174bf215546Sopenharmony_ci case PIPE_FORMAT_R8A8_SNORM: 1175bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_SNORM; 1176bf215546Sopenharmony_ci case PIPE_FORMAT_R8A8_UINT: 1177bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_UINT; 1178bf215546Sopenharmony_ci case PIPE_FORMAT_R8A8_SINT: 1179bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_SINT; 1180bf215546Sopenharmony_ci 1181bf215546Sopenharmony_ci case PIPE_FORMAT_R16A16_UNORM: 1182bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_UNORM; 1183bf215546Sopenharmony_ci case PIPE_FORMAT_R16A16_SNORM: 1184bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_SNORM; 1185bf215546Sopenharmony_ci case PIPE_FORMAT_R16A16_UINT: 1186bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_UINT; 1187bf215546Sopenharmony_ci case PIPE_FORMAT_R16A16_SINT: 1188bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_SINT; 1189bf215546Sopenharmony_ci case PIPE_FORMAT_R16A16_FLOAT: 1190bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_FLOAT; 1191bf215546Sopenharmony_ci 1192bf215546Sopenharmony_ci case PIPE_FORMAT_R32A32_UINT: 1193bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_UINT; 1194bf215546Sopenharmony_ci case PIPE_FORMAT_R32A32_SINT: 1195bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_SINT; 1196bf215546Sopenharmony_ci case PIPE_FORMAT_R32A32_FLOAT: 1197bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_FLOAT; 1198bf215546Sopenharmony_ci 1199bf215546Sopenharmony_ci default: 1200bf215546Sopenharmony_ci return format; 1201bf215546Sopenharmony_ci } 1202bf215546Sopenharmony_ci} 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci 1205bf215546Sopenharmony_ci/** 1206bf215546Sopenharmony_ci * Converts PIPE_FORMAT_L*A* to PIPE_FORMAT_R*G*. 1207bf215546Sopenharmony_ci */ 1208bf215546Sopenharmony_cistatic enum pipe_format 1209bf215546Sopenharmony_ciluminance_alpha_to_red_green(enum pipe_format format) 1210bf215546Sopenharmony_ci{ 1211bf215546Sopenharmony_ci switch (format) 1212bf215546Sopenharmony_ci { 1213bf215546Sopenharmony_ci case PIPE_FORMAT_L8A8_UNORM: 1214bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_UNORM; 1215bf215546Sopenharmony_ci case PIPE_FORMAT_L8A8_SNORM: 1216bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_SNORM; 1217bf215546Sopenharmony_ci case PIPE_FORMAT_L8A8_UINT: 1218bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_UINT; 1219bf215546Sopenharmony_ci case PIPE_FORMAT_L8A8_SINT: 1220bf215546Sopenharmony_ci return PIPE_FORMAT_R8G8_SINT; 1221bf215546Sopenharmony_ci 1222bf215546Sopenharmony_ci case PIPE_FORMAT_L16A16_UNORM: 1223bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_UNORM; 1224bf215546Sopenharmony_ci case PIPE_FORMAT_L16A16_SNORM: 1225bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_SNORM; 1226bf215546Sopenharmony_ci case PIPE_FORMAT_L16A16_UINT: 1227bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_UINT; 1228bf215546Sopenharmony_ci case PIPE_FORMAT_L16A16_SINT: 1229bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_SINT; 1230bf215546Sopenharmony_ci case PIPE_FORMAT_L16A16_FLOAT: 1231bf215546Sopenharmony_ci return PIPE_FORMAT_R16G16_FLOAT; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci case PIPE_FORMAT_L32A32_UINT: 1234bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_UINT; 1235bf215546Sopenharmony_ci case PIPE_FORMAT_L32A32_SINT: 1236bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_SINT; 1237bf215546Sopenharmony_ci case PIPE_FORMAT_L32A32_FLOAT: 1238bf215546Sopenharmony_ci return PIPE_FORMAT_R32G32_FLOAT; 1239bf215546Sopenharmony_ci 1240bf215546Sopenharmony_ci default: 1241bf215546Sopenharmony_ci return format; 1242bf215546Sopenharmony_ci } 1243bf215546Sopenharmony_ci} 1244bf215546Sopenharmony_ci 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci/** 1247bf215546Sopenharmony_ci * Returns true if format is a PIPE_FORMAT_A* format, and false otherwise. 1248bf215546Sopenharmony_ci */ 1249bf215546Sopenharmony_cistatic bool 1250bf215546Sopenharmony_ciformat_is_alpha(enum pipe_format format) 1251bf215546Sopenharmony_ci{ 1252bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 1253bf215546Sopenharmony_ci 1254bf215546Sopenharmony_ci if (desc->nr_channels == 1 && 1255bf215546Sopenharmony_ci desc->swizzle[0] == PIPE_SWIZZLE_0 && 1256bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_0 && 1257bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_0 && 1258bf215546Sopenharmony_ci desc->swizzle[3] == PIPE_SWIZZLE_X) 1259bf215546Sopenharmony_ci return true; 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_ci return false; 1262bf215546Sopenharmony_ci} 1263bf215546Sopenharmony_ci 1264bf215546Sopenharmony_ci 1265bf215546Sopenharmony_ci/** 1266bf215546Sopenharmony_ci * Returns true if format is a PIPE_FORMAT_R* format, and false otherwise. 1267bf215546Sopenharmony_ci */ 1268bf215546Sopenharmony_cistatic bool 1269bf215546Sopenharmony_ciformat_is_red(enum pipe_format format) 1270bf215546Sopenharmony_ci{ 1271bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 1272bf215546Sopenharmony_ci 1273bf215546Sopenharmony_ci if (desc->nr_channels == 1 && 1274bf215546Sopenharmony_ci desc->swizzle[0] == PIPE_SWIZZLE_X && 1275bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_0 && 1276bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_0 && 1277bf215546Sopenharmony_ci desc->swizzle[3] == PIPE_SWIZZLE_1) 1278bf215546Sopenharmony_ci return true; 1279bf215546Sopenharmony_ci 1280bf215546Sopenharmony_ci return false; 1281bf215546Sopenharmony_ci} 1282bf215546Sopenharmony_ci 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_ci/** 1285bf215546Sopenharmony_ci * Returns true if format is a PIPE_FORMAT_L* format, and false otherwise. 1286bf215546Sopenharmony_ci */ 1287bf215546Sopenharmony_cistatic bool 1288bf215546Sopenharmony_ciformat_is_luminance(enum pipe_format format) 1289bf215546Sopenharmony_ci{ 1290bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci if (desc->nr_channels == 1 && 1293bf215546Sopenharmony_ci desc->swizzle[0] == PIPE_SWIZZLE_X && 1294bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_X && 1295bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_X && 1296bf215546Sopenharmony_ci desc->swizzle[3] == PIPE_SWIZZLE_1) 1297bf215546Sopenharmony_ci return true; 1298bf215546Sopenharmony_ci 1299bf215546Sopenharmony_ci return false; 1300bf215546Sopenharmony_ci} 1301bf215546Sopenharmony_ci 1302bf215546Sopenharmony_ci/** 1303bf215546Sopenharmony_ci * Returns true if format is a PIPE_FORMAT_R*A* format, and false otherwise. 1304bf215546Sopenharmony_ci */ 1305bf215546Sopenharmony_cistatic bool 1306bf215546Sopenharmony_ciformat_is_red_alpha(enum pipe_format format) 1307bf215546Sopenharmony_ci{ 1308bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 1309bf215546Sopenharmony_ci 1310bf215546Sopenharmony_ci if (desc->nr_channels == 2 && 1311bf215546Sopenharmony_ci desc->swizzle[0] == PIPE_SWIZZLE_X && 1312bf215546Sopenharmony_ci desc->swizzle[1] == PIPE_SWIZZLE_0 && 1313bf215546Sopenharmony_ci desc->swizzle[2] == PIPE_SWIZZLE_0 && 1314bf215546Sopenharmony_ci desc->swizzle[3] == PIPE_SWIZZLE_Y) 1315bf215546Sopenharmony_ci return true; 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci return false; 1318bf215546Sopenharmony_ci} 1319bf215546Sopenharmony_ci 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_cistatic bool 1322bf215546Sopenharmony_ciformat_is_swizzled_rgba(enum pipe_format format) 1323bf215546Sopenharmony_ci{ 1324bf215546Sopenharmony_ci const struct util_format_description *desc = util_format_description(format); 1325bf215546Sopenharmony_ci 1326bf215546Sopenharmony_ci if ((desc->swizzle[0] == TGSI_SWIZZLE_X || desc->swizzle[0] == PIPE_SWIZZLE_0) && 1327bf215546Sopenharmony_ci (desc->swizzle[1] == TGSI_SWIZZLE_Y || desc->swizzle[1] == PIPE_SWIZZLE_0) && 1328bf215546Sopenharmony_ci (desc->swizzle[2] == TGSI_SWIZZLE_Z || desc->swizzle[2] == PIPE_SWIZZLE_0) && 1329bf215546Sopenharmony_ci (desc->swizzle[3] == TGSI_SWIZZLE_W || desc->swizzle[3] == PIPE_SWIZZLE_1)) 1330bf215546Sopenharmony_ci return false; 1331bf215546Sopenharmony_ci 1332bf215546Sopenharmony_ci return true; 1333bf215546Sopenharmony_ci} 1334bf215546Sopenharmony_ci 1335bf215546Sopenharmony_ci 1336bf215546Sopenharmony_cistruct format_table 1337bf215546Sopenharmony_ci{ 1338bf215546Sopenharmony_ci unsigned char swizzle[4]; 1339bf215546Sopenharmony_ci enum pipe_format format; 1340bf215546Sopenharmony_ci}; 1341bf215546Sopenharmony_ci 1342bf215546Sopenharmony_cistatic const struct format_table table_8888_unorm[] = { 1343bf215546Sopenharmony_ci { { 0, 1, 2, 3 }, PIPE_FORMAT_R8G8B8A8_UNORM }, 1344bf215546Sopenharmony_ci { { 2, 1, 0, 3 }, PIPE_FORMAT_B8G8R8A8_UNORM }, 1345bf215546Sopenharmony_ci { { 3, 0, 1, 2 }, PIPE_FORMAT_A8R8G8B8_UNORM }, 1346bf215546Sopenharmony_ci { { 3, 2, 1, 0 }, PIPE_FORMAT_A8B8G8R8_UNORM } 1347bf215546Sopenharmony_ci}; 1348bf215546Sopenharmony_ci 1349bf215546Sopenharmony_cistatic const struct format_table table_1010102_unorm[] = { 1350bf215546Sopenharmony_ci { { 0, 1, 2, 3 }, PIPE_FORMAT_R10G10B10A2_UNORM }, 1351bf215546Sopenharmony_ci { { 2, 1, 0, 3 }, PIPE_FORMAT_B10G10R10A2_UNORM } 1352bf215546Sopenharmony_ci}; 1353bf215546Sopenharmony_ci 1354bf215546Sopenharmony_cistatic const struct format_table table_1010102_snorm[] = { 1355bf215546Sopenharmony_ci { { 0, 1, 2, 3 }, PIPE_FORMAT_R10G10B10A2_SNORM }, 1356bf215546Sopenharmony_ci { { 2, 1, 0, 3 }, PIPE_FORMAT_B10G10R10A2_SNORM } 1357bf215546Sopenharmony_ci}; 1358bf215546Sopenharmony_ci 1359bf215546Sopenharmony_cistatic const struct format_table table_1010102_uint[] = { 1360bf215546Sopenharmony_ci { { 0, 1, 2, 3 }, PIPE_FORMAT_R10G10B10A2_UINT }, 1361bf215546Sopenharmony_ci { { 2, 1, 0, 3 }, PIPE_FORMAT_B10G10R10A2_UINT } 1362bf215546Sopenharmony_ci}; 1363bf215546Sopenharmony_ci 1364bf215546Sopenharmony_cistatic enum pipe_format 1365bf215546Sopenharmony_ciswizzle_format(enum pipe_format format, const int * const swizzle) 1366bf215546Sopenharmony_ci{ 1367bf215546Sopenharmony_ci unsigned i; 1368bf215546Sopenharmony_ci 1369bf215546Sopenharmony_ci switch (format) { 1370bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8A8_UNORM: 1371bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8A8_UNORM: 1372bf215546Sopenharmony_ci case PIPE_FORMAT_A8R8G8B8_UNORM: 1373bf215546Sopenharmony_ci case PIPE_FORMAT_A8B8G8R8_UNORM: 1374bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(table_8888_unorm); i++) { 1375bf215546Sopenharmony_ci if (swizzle[0] == table_8888_unorm[i].swizzle[0] && 1376bf215546Sopenharmony_ci swizzle[1] == table_8888_unorm[i].swizzle[1] && 1377bf215546Sopenharmony_ci swizzle[2] == table_8888_unorm[i].swizzle[2] && 1378bf215546Sopenharmony_ci swizzle[3] == table_8888_unorm[i].swizzle[3]) 1379bf215546Sopenharmony_ci return table_8888_unorm[i].format; 1380bf215546Sopenharmony_ci } 1381bf215546Sopenharmony_ci break; 1382bf215546Sopenharmony_ci 1383bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UNORM: 1384bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UNORM: 1385bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(table_1010102_unorm); i++) { 1386bf215546Sopenharmony_ci if (swizzle[0] == table_1010102_unorm[i].swizzle[0] && 1387bf215546Sopenharmony_ci swizzle[1] == table_1010102_unorm[i].swizzle[1] && 1388bf215546Sopenharmony_ci swizzle[2] == table_1010102_unorm[i].swizzle[2] && 1389bf215546Sopenharmony_ci swizzle[3] == table_1010102_unorm[i].swizzle[3]) 1390bf215546Sopenharmony_ci return table_1010102_unorm[i].format; 1391bf215546Sopenharmony_ci } 1392bf215546Sopenharmony_ci break; 1393bf215546Sopenharmony_ci 1394bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_SNORM: 1395bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_SNORM: 1396bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(table_1010102_snorm); i++) { 1397bf215546Sopenharmony_ci if (swizzle[0] == table_1010102_snorm[i].swizzle[0] && 1398bf215546Sopenharmony_ci swizzle[1] == table_1010102_snorm[i].swizzle[1] && 1399bf215546Sopenharmony_ci swizzle[2] == table_1010102_snorm[i].swizzle[2] && 1400bf215546Sopenharmony_ci swizzle[3] == table_1010102_snorm[i].swizzle[3]) 1401bf215546Sopenharmony_ci return table_1010102_snorm[i].format; 1402bf215546Sopenharmony_ci } 1403bf215546Sopenharmony_ci break; 1404bf215546Sopenharmony_ci 1405bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UINT: 1406bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UINT: 1407bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(table_1010102_uint); i++) { 1408bf215546Sopenharmony_ci if (swizzle[0] == table_1010102_uint[i].swizzle[0] && 1409bf215546Sopenharmony_ci swizzle[1] == table_1010102_uint[i].swizzle[1] && 1410bf215546Sopenharmony_ci swizzle[2] == table_1010102_uint[i].swizzle[2] && 1411bf215546Sopenharmony_ci swizzle[3] == table_1010102_uint[i].swizzle[3]) 1412bf215546Sopenharmony_ci return table_1010102_uint[i].format; 1413bf215546Sopenharmony_ci } 1414bf215546Sopenharmony_ci break; 1415bf215546Sopenharmony_ci 1416bf215546Sopenharmony_ci default: 1417bf215546Sopenharmony_ci break; 1418bf215546Sopenharmony_ci } 1419bf215546Sopenharmony_ci 1420bf215546Sopenharmony_ci return PIPE_FORMAT_NONE; 1421bf215546Sopenharmony_ci} 1422bf215546Sopenharmony_ci 1423bf215546Sopenharmony_cistatic bool 1424bf215546Sopenharmony_cireinterpret_formats(enum pipe_format *src_format, enum pipe_format *dst_format) 1425bf215546Sopenharmony_ci{ 1426bf215546Sopenharmony_ci enum pipe_format src = *src_format; 1427bf215546Sopenharmony_ci enum pipe_format dst = *dst_format; 1428bf215546Sopenharmony_ci 1429bf215546Sopenharmony_ci /* Note: dst_format has already been transformed from luminance/intensity 1430bf215546Sopenharmony_ci * to red when this function is called. The source format will never 1431bf215546Sopenharmony_ci * be an intensity format, because GL_INTENSITY is not a legal value 1432bf215546Sopenharmony_ci * for the format parameter in glTex(Sub)Image(). */ 1433bf215546Sopenharmony_ci 1434bf215546Sopenharmony_ci if (format_is_alpha(src)) { 1435bf215546Sopenharmony_ci if (!format_is_alpha(dst)) 1436bf215546Sopenharmony_ci return false; 1437bf215546Sopenharmony_ci 1438bf215546Sopenharmony_ci src = alpha_to_red(src); 1439bf215546Sopenharmony_ci dst = alpha_to_red(dst); 1440bf215546Sopenharmony_ci } else if (format_is_luminance(src)) { 1441bf215546Sopenharmony_ci if (!format_is_red(dst) && !format_is_red_alpha(dst)) 1442bf215546Sopenharmony_ci return false; 1443bf215546Sopenharmony_ci 1444bf215546Sopenharmony_ci src = util_format_luminance_to_red(src); 1445bf215546Sopenharmony_ci } else if (util_format_is_luminance_alpha(src)) { 1446bf215546Sopenharmony_ci src = luminance_alpha_to_red_green(src); 1447bf215546Sopenharmony_ci 1448bf215546Sopenharmony_ci if (format_is_red_alpha(dst)) { 1449bf215546Sopenharmony_ci dst = red_alpha_to_red_green(dst); 1450bf215546Sopenharmony_ci } else if (!format_is_red(dst)) 1451bf215546Sopenharmony_ci return false; 1452bf215546Sopenharmony_ci } else if (format_is_swizzled_rgba(src)) { 1453bf215546Sopenharmony_ci const struct util_format_description *src_desc = util_format_description(src); 1454bf215546Sopenharmony_ci const struct util_format_description *dst_desc = util_format_description(dst); 1455bf215546Sopenharmony_ci int swizzle[4]; 1456bf215546Sopenharmony_ci unsigned i; 1457bf215546Sopenharmony_ci 1458bf215546Sopenharmony_ci /* Make sure the format is an RGBA and not an RGBX format */ 1459bf215546Sopenharmony_ci if (src_desc->nr_channels != 4 || src_desc->swizzle[3] == PIPE_SWIZZLE_1) 1460bf215546Sopenharmony_ci return false; 1461bf215546Sopenharmony_ci 1462bf215546Sopenharmony_ci if (dst_desc->nr_channels != 4 || dst_desc->swizzle[3] == PIPE_SWIZZLE_1) 1463bf215546Sopenharmony_ci return false; 1464bf215546Sopenharmony_ci 1465bf215546Sopenharmony_ci for (i = 0; i < 4; i++) 1466bf215546Sopenharmony_ci swizzle[i] = dst_desc->swizzle[src_desc->swizzle[i]]; 1467bf215546Sopenharmony_ci 1468bf215546Sopenharmony_ci dst = swizzle_format(dst, swizzle); 1469bf215546Sopenharmony_ci if (dst == PIPE_FORMAT_NONE) 1470bf215546Sopenharmony_ci return false; 1471bf215546Sopenharmony_ci 1472bf215546Sopenharmony_ci src = unswizzle_format(src); 1473bf215546Sopenharmony_ci } 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci *src_format = src; 1476bf215546Sopenharmony_ci *dst_format = dst; 1477bf215546Sopenharmony_ci return true; 1478bf215546Sopenharmony_ci} 1479bf215546Sopenharmony_ci 1480bf215546Sopenharmony_cistatic bool 1481bf215546Sopenharmony_citry_pbo_upload_common(struct gl_context *ctx, 1482bf215546Sopenharmony_ci struct pipe_surface *surface, 1483bf215546Sopenharmony_ci const struct st_pbo_addresses *addr, 1484bf215546Sopenharmony_ci enum pipe_format src_format) 1485bf215546Sopenharmony_ci{ 1486bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 1487bf215546Sopenharmony_ci struct cso_context *cso = st->cso_context; 1488bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 1489bf215546Sopenharmony_ci bool success = false; 1490bf215546Sopenharmony_ci void *fs; 1491bf215546Sopenharmony_ci 1492bf215546Sopenharmony_ci fs = st_pbo_get_upload_fs(st, src_format, surface->format, addr->depth != 1); 1493bf215546Sopenharmony_ci if (!fs) 1494bf215546Sopenharmony_ci return false; 1495bf215546Sopenharmony_ci 1496bf215546Sopenharmony_ci cso_save_state(cso, (CSO_BIT_VERTEX_ELEMENTS | 1497bf215546Sopenharmony_ci CSO_BIT_FRAMEBUFFER | 1498bf215546Sopenharmony_ci CSO_BIT_VIEWPORT | 1499bf215546Sopenharmony_ci CSO_BIT_BLEND | 1500bf215546Sopenharmony_ci CSO_BIT_DEPTH_STENCIL_ALPHA | 1501bf215546Sopenharmony_ci CSO_BIT_RASTERIZER | 1502bf215546Sopenharmony_ci CSO_BIT_STREAM_OUTPUTS | 1503bf215546Sopenharmony_ci (st->active_queries ? CSO_BIT_PAUSE_QUERIES : 0) | 1504bf215546Sopenharmony_ci CSO_BIT_SAMPLE_MASK | 1505bf215546Sopenharmony_ci CSO_BIT_MIN_SAMPLES | 1506bf215546Sopenharmony_ci CSO_BIT_RENDER_CONDITION | 1507bf215546Sopenharmony_ci CSO_BITS_ALL_SHADERS)); 1508bf215546Sopenharmony_ci 1509bf215546Sopenharmony_ci cso_set_sample_mask(cso, ~0); 1510bf215546Sopenharmony_ci cso_set_min_samples(cso, 1); 1511bf215546Sopenharmony_ci cso_set_render_condition(cso, NULL, FALSE, 0); 1512bf215546Sopenharmony_ci 1513bf215546Sopenharmony_ci /* Set up the sampler_view */ 1514bf215546Sopenharmony_ci { 1515bf215546Sopenharmony_ci struct pipe_sampler_view templ; 1516bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_view; 1517bf215546Sopenharmony_ci 1518bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 1519bf215546Sopenharmony_ci templ.target = PIPE_BUFFER; 1520bf215546Sopenharmony_ci templ.format = src_format; 1521bf215546Sopenharmony_ci templ.u.buf.offset = addr->first_element * addr->bytes_per_pixel; 1522bf215546Sopenharmony_ci templ.u.buf.size = (addr->last_element - addr->first_element + 1) * 1523bf215546Sopenharmony_ci addr->bytes_per_pixel; 1524bf215546Sopenharmony_ci templ.swizzle_r = PIPE_SWIZZLE_X; 1525bf215546Sopenharmony_ci templ.swizzle_g = PIPE_SWIZZLE_Y; 1526bf215546Sopenharmony_ci templ.swizzle_b = PIPE_SWIZZLE_Z; 1527bf215546Sopenharmony_ci templ.swizzle_a = PIPE_SWIZZLE_W; 1528bf215546Sopenharmony_ci 1529bf215546Sopenharmony_ci sampler_view = pipe->create_sampler_view(pipe, addr->buffer, &templ); 1530bf215546Sopenharmony_ci if (sampler_view == NULL) 1531bf215546Sopenharmony_ci goto fail; 1532bf215546Sopenharmony_ci 1533bf215546Sopenharmony_ci pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, 1534bf215546Sopenharmony_ci false, &sampler_view); 1535bf215546Sopenharmony_ci st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 1536bf215546Sopenharmony_ci MAX2(st->state.num_sampler_views[PIPE_SHADER_FRAGMENT], 1); 1537bf215546Sopenharmony_ci 1538bf215546Sopenharmony_ci pipe_sampler_view_reference(&sampler_view, NULL); 1539bf215546Sopenharmony_ci } 1540bf215546Sopenharmony_ci 1541bf215546Sopenharmony_ci /* Framebuffer_state */ 1542bf215546Sopenharmony_ci { 1543bf215546Sopenharmony_ci struct pipe_framebuffer_state fb; 1544bf215546Sopenharmony_ci memset(&fb, 0, sizeof(fb)); 1545bf215546Sopenharmony_ci fb.width = surface->width; 1546bf215546Sopenharmony_ci fb.height = surface->height; 1547bf215546Sopenharmony_ci fb.nr_cbufs = 1; 1548bf215546Sopenharmony_ci fb.cbufs[0] = surface; 1549bf215546Sopenharmony_ci 1550bf215546Sopenharmony_ci cso_set_framebuffer(cso, &fb); 1551bf215546Sopenharmony_ci } 1552bf215546Sopenharmony_ci 1553bf215546Sopenharmony_ci cso_set_viewport_dims(cso, surface->width, surface->height, FALSE); 1554bf215546Sopenharmony_ci 1555bf215546Sopenharmony_ci /* Blend state */ 1556bf215546Sopenharmony_ci cso_set_blend(cso, &st->pbo.upload_blend); 1557bf215546Sopenharmony_ci 1558bf215546Sopenharmony_ci /* Depth/stencil/alpha state */ 1559bf215546Sopenharmony_ci { 1560bf215546Sopenharmony_ci struct pipe_depth_stencil_alpha_state dsa; 1561bf215546Sopenharmony_ci memset(&dsa, 0, sizeof(dsa)); 1562bf215546Sopenharmony_ci cso_set_depth_stencil_alpha(cso, &dsa); 1563bf215546Sopenharmony_ci } 1564bf215546Sopenharmony_ci 1565bf215546Sopenharmony_ci /* Set up the fragment shader */ 1566bf215546Sopenharmony_ci cso_set_fragment_shader_handle(cso, fs); 1567bf215546Sopenharmony_ci 1568bf215546Sopenharmony_ci success = st_pbo_draw(st, addr, surface->width, surface->height); 1569bf215546Sopenharmony_ci 1570bf215546Sopenharmony_cifail: 1571bf215546Sopenharmony_ci /* Unbind all because st/mesa won't do it if the current shader doesn't 1572bf215546Sopenharmony_ci * use them. 1573bf215546Sopenharmony_ci */ 1574bf215546Sopenharmony_ci cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEWS); 1575bf215546Sopenharmony_ci st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0; 1576bf215546Sopenharmony_ci 1577bf215546Sopenharmony_ci ctx->Array.NewVertexElements = true; 1578bf215546Sopenharmony_ci st->dirty |= ST_NEW_VERTEX_ARRAYS | 1579bf215546Sopenharmony_ci ST_NEW_FS_CONSTANTS | 1580bf215546Sopenharmony_ci ST_NEW_FS_SAMPLER_VIEWS; 1581bf215546Sopenharmony_ci 1582bf215546Sopenharmony_ci return success; 1583bf215546Sopenharmony_ci} 1584bf215546Sopenharmony_ci 1585bf215546Sopenharmony_ci 1586bf215546Sopenharmony_cistatic bool 1587bf215546Sopenharmony_citry_pbo_upload(struct gl_context *ctx, GLuint dims, 1588bf215546Sopenharmony_ci struct gl_texture_image *texImage, 1589bf215546Sopenharmony_ci GLenum format, GLenum type, 1590bf215546Sopenharmony_ci enum pipe_format dst_format, 1591bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 1592bf215546Sopenharmony_ci GLint width, GLint height, GLint depth, 1593bf215546Sopenharmony_ci const void *pixels, 1594bf215546Sopenharmony_ci const struct gl_pixelstore_attrib *unpack) 1595bf215546Sopenharmony_ci{ 1596bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 1597bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 1598bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 1599bf215546Sopenharmony_ci struct pipe_resource *texture = stImage->pt; 1600bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 1601bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 1602bf215546Sopenharmony_ci struct pipe_surface *surface = NULL; 1603bf215546Sopenharmony_ci struct st_pbo_addresses addr; 1604bf215546Sopenharmony_ci enum pipe_format src_format; 1605bf215546Sopenharmony_ci const struct util_format_description *desc; 1606bf215546Sopenharmony_ci GLenum gl_target = texImage->TexObject->Target; 1607bf215546Sopenharmony_ci bool success; 1608bf215546Sopenharmony_ci 1609bf215546Sopenharmony_ci if (!st->pbo.upload_enabled) 1610bf215546Sopenharmony_ci return false; 1611bf215546Sopenharmony_ci 1612bf215546Sopenharmony_ci /* From now on, we need the gallium representation of dimensions. */ 1613bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 1614bf215546Sopenharmony_ci depth = height; 1615bf215546Sopenharmony_ci height = 1; 1616bf215546Sopenharmony_ci zoffset = yoffset; 1617bf215546Sopenharmony_ci yoffset = 0; 1618bf215546Sopenharmony_ci } 1619bf215546Sopenharmony_ci 1620bf215546Sopenharmony_ci if (depth != 1 && !st->pbo.layers) 1621bf215546Sopenharmony_ci return false; 1622bf215546Sopenharmony_ci 1623bf215546Sopenharmony_ci /* Choose the source format. Initially, we do so without checking driver 1624bf215546Sopenharmony_ci * support at all because of the remapping we later perform and because 1625bf215546Sopenharmony_ci * at least the Radeon driver actually supports some formats for texture 1626bf215546Sopenharmony_ci * buffers which it doesn't support for regular textures. */ 1627bf215546Sopenharmony_ci src_format = st_choose_matching_format(st, 0, format, type, 1628bf215546Sopenharmony_ci unpack->SwapBytes); 1629bf215546Sopenharmony_ci if (!src_format) { 1630bf215546Sopenharmony_ci return false; 1631bf215546Sopenharmony_ci } 1632bf215546Sopenharmony_ci 1633bf215546Sopenharmony_ci src_format = util_format_linear(src_format); 1634bf215546Sopenharmony_ci desc = util_format_description(src_format); 1635bf215546Sopenharmony_ci 1636bf215546Sopenharmony_ci if (desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) 1637bf215546Sopenharmony_ci return false; 1638bf215546Sopenharmony_ci 1639bf215546Sopenharmony_ci if (desc->colorspace != UTIL_FORMAT_COLORSPACE_RGB) 1640bf215546Sopenharmony_ci return false; 1641bf215546Sopenharmony_ci 1642bf215546Sopenharmony_ci if (st->pbo.rgba_only) { 1643bf215546Sopenharmony_ci enum pipe_format orig_dst_format = dst_format; 1644bf215546Sopenharmony_ci 1645bf215546Sopenharmony_ci if (!reinterpret_formats(&src_format, &dst_format)) { 1646bf215546Sopenharmony_ci return false; 1647bf215546Sopenharmony_ci } 1648bf215546Sopenharmony_ci 1649bf215546Sopenharmony_ci if (dst_format != orig_dst_format && 1650bf215546Sopenharmony_ci !screen->is_format_supported(screen, dst_format, PIPE_TEXTURE_2D, 0, 1651bf215546Sopenharmony_ci 0, PIPE_BIND_RENDER_TARGET)) { 1652bf215546Sopenharmony_ci return false; 1653bf215546Sopenharmony_ci } 1654bf215546Sopenharmony_ci } 1655bf215546Sopenharmony_ci 1656bf215546Sopenharmony_ci if (!src_format || 1657bf215546Sopenharmony_ci !screen->is_format_supported(screen, src_format, PIPE_BUFFER, 0, 0, 1658bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)) { 1659bf215546Sopenharmony_ci return false; 1660bf215546Sopenharmony_ci } 1661bf215546Sopenharmony_ci 1662bf215546Sopenharmony_ci /* Compute buffer addresses */ 1663bf215546Sopenharmony_ci addr.xoffset = xoffset; 1664bf215546Sopenharmony_ci addr.yoffset = yoffset; 1665bf215546Sopenharmony_ci addr.width = width; 1666bf215546Sopenharmony_ci addr.height = height; 1667bf215546Sopenharmony_ci addr.depth = depth; 1668bf215546Sopenharmony_ci addr.bytes_per_pixel = desc->block.bits / 8; 1669bf215546Sopenharmony_ci 1670bf215546Sopenharmony_ci if (!st_pbo_addresses_pixelstore(st, gl_target, dims == 3, unpack, pixels, 1671bf215546Sopenharmony_ci &addr)) 1672bf215546Sopenharmony_ci return false; 1673bf215546Sopenharmony_ci 1674bf215546Sopenharmony_ci /* Set up the surface */ 1675bf215546Sopenharmony_ci { 1676bf215546Sopenharmony_ci unsigned level = stObj->pt != stImage->pt 1677bf215546Sopenharmony_ci ? 0 : texImage->TexObject->Attrib.MinLevel + texImage->Level; 1678bf215546Sopenharmony_ci unsigned max_layer = util_max_layer(texture, level); 1679bf215546Sopenharmony_ci 1680bf215546Sopenharmony_ci zoffset += texImage->Face + texImage->TexObject->Attrib.MinLayer; 1681bf215546Sopenharmony_ci 1682bf215546Sopenharmony_ci struct pipe_surface templ; 1683bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 1684bf215546Sopenharmony_ci templ.format = dst_format; 1685bf215546Sopenharmony_ci templ.u.tex.level = level; 1686bf215546Sopenharmony_ci templ.u.tex.first_layer = MIN2(zoffset, max_layer); 1687bf215546Sopenharmony_ci templ.u.tex.last_layer = MIN2(zoffset + depth - 1, max_layer); 1688bf215546Sopenharmony_ci 1689bf215546Sopenharmony_ci surface = pipe->create_surface(pipe, texture, &templ); 1690bf215546Sopenharmony_ci if (!surface) 1691bf215546Sopenharmony_ci return false; 1692bf215546Sopenharmony_ci } 1693bf215546Sopenharmony_ci 1694bf215546Sopenharmony_ci success = try_pbo_upload_common(ctx, surface, &addr, src_format); 1695bf215546Sopenharmony_ci 1696bf215546Sopenharmony_ci pipe_surface_reference(&surface, NULL); 1697bf215546Sopenharmony_ci 1698bf215546Sopenharmony_ci return success; 1699bf215546Sopenharmony_ci} 1700bf215546Sopenharmony_ci 1701bf215546Sopenharmony_cistatic bool 1702bf215546Sopenharmony_citry_pbo_download(struct st_context *st, 1703bf215546Sopenharmony_ci struct gl_texture_image *texImage, 1704bf215546Sopenharmony_ci enum pipe_format src_format, enum pipe_format dst_format, 1705bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 1706bf215546Sopenharmony_ci GLint width, GLint height, GLint depth, 1707bf215546Sopenharmony_ci const struct gl_pixelstore_attrib *pack, void *pixels) 1708bf215546Sopenharmony_ci{ 1709bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 1710bf215546Sopenharmony_ci struct pipe_screen *screen = pipe->screen; 1711bf215546Sopenharmony_ci struct pipe_resource *texture = texImage->pt; 1712bf215546Sopenharmony_ci struct cso_context *cso = st->cso_context; 1713bf215546Sopenharmony_ci const struct util_format_description *desc; 1714bf215546Sopenharmony_ci struct st_pbo_addresses addr; 1715bf215546Sopenharmony_ci struct pipe_framebuffer_state fb; 1716bf215546Sopenharmony_ci enum pipe_texture_target pipe_target; 1717bf215546Sopenharmony_ci GLenum gl_target = texImage->TexObject->Target; 1718bf215546Sopenharmony_ci GLuint dims; 1719bf215546Sopenharmony_ci bool success = false; 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci if (texture->nr_samples > 1) 1722bf215546Sopenharmony_ci return false; 1723bf215546Sopenharmony_ci 1724bf215546Sopenharmony_ci /* GetTexImage only returns a single face for cubemaps. */ 1725bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_CUBE_MAP) { 1726bf215546Sopenharmony_ci gl_target = GL_TEXTURE_2D; 1727bf215546Sopenharmony_ci } 1728bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_CUBE_MAP_ARRAY) { 1729bf215546Sopenharmony_ci gl_target = GL_TEXTURE_2D_ARRAY; 1730bf215546Sopenharmony_ci } 1731bf215546Sopenharmony_ci pipe_target = gl_target_to_pipe(gl_target); 1732bf215546Sopenharmony_ci dims = _mesa_get_texture_dimensions(gl_target); 1733bf215546Sopenharmony_ci 1734bf215546Sopenharmony_ci /* From now on, we need the gallium representation of dimensions. */ 1735bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 1736bf215546Sopenharmony_ci depth = height; 1737bf215546Sopenharmony_ci height = 1; 1738bf215546Sopenharmony_ci zoffset = yoffset; 1739bf215546Sopenharmony_ci yoffset = 0; 1740bf215546Sopenharmony_ci } 1741bf215546Sopenharmony_ci 1742bf215546Sopenharmony_ci if (depth != 1 && !st->pbo.layers) 1743bf215546Sopenharmony_ci return false; 1744bf215546Sopenharmony_ci 1745bf215546Sopenharmony_ci if (!screen->is_format_supported(screen, dst_format, PIPE_BUFFER, 0, 0, 1746bf215546Sopenharmony_ci PIPE_BIND_SHADER_IMAGE) || 1747bf215546Sopenharmony_ci util_format_is_compressed(src_format) || 1748bf215546Sopenharmony_ci util_format_is_compressed(dst_format)) 1749bf215546Sopenharmony_ci return false; 1750bf215546Sopenharmony_ci 1751bf215546Sopenharmony_ci desc = util_format_description(dst_format); 1752bf215546Sopenharmony_ci 1753bf215546Sopenharmony_ci /* Compute PBO addresses */ 1754bf215546Sopenharmony_ci addr.bytes_per_pixel = desc->block.bits / 8; 1755bf215546Sopenharmony_ci addr.xoffset = xoffset; 1756bf215546Sopenharmony_ci addr.yoffset = yoffset; 1757bf215546Sopenharmony_ci addr.width = width; 1758bf215546Sopenharmony_ci addr.height = height; 1759bf215546Sopenharmony_ci addr.depth = depth; 1760bf215546Sopenharmony_ci if (!st_pbo_addresses_pixelstore(st, gl_target, dims == 3, pack, pixels, &addr)) 1761bf215546Sopenharmony_ci return false; 1762bf215546Sopenharmony_ci 1763bf215546Sopenharmony_ci cso_save_state(cso, (CSO_BIT_VERTEX_ELEMENTS | 1764bf215546Sopenharmony_ci CSO_BIT_FRAMEBUFFER | 1765bf215546Sopenharmony_ci CSO_BIT_VIEWPORT | 1766bf215546Sopenharmony_ci CSO_BIT_BLEND | 1767bf215546Sopenharmony_ci CSO_BIT_DEPTH_STENCIL_ALPHA | 1768bf215546Sopenharmony_ci CSO_BIT_RASTERIZER | 1769bf215546Sopenharmony_ci CSO_BIT_STREAM_OUTPUTS | 1770bf215546Sopenharmony_ci (st->active_queries ? CSO_BIT_PAUSE_QUERIES : 0) | 1771bf215546Sopenharmony_ci CSO_BIT_SAMPLE_MASK | 1772bf215546Sopenharmony_ci CSO_BIT_MIN_SAMPLES | 1773bf215546Sopenharmony_ci CSO_BIT_RENDER_CONDITION | 1774bf215546Sopenharmony_ci CSO_BITS_ALL_SHADERS)); 1775bf215546Sopenharmony_ci 1776bf215546Sopenharmony_ci cso_set_sample_mask(cso, ~0); 1777bf215546Sopenharmony_ci cso_set_min_samples(cso, 1); 1778bf215546Sopenharmony_ci cso_set_render_condition(cso, NULL, FALSE, 0); 1779bf215546Sopenharmony_ci 1780bf215546Sopenharmony_ci /* Set up the sampler_view */ 1781bf215546Sopenharmony_ci { 1782bf215546Sopenharmony_ci struct pipe_sampler_view templ; 1783bf215546Sopenharmony_ci struct pipe_sampler_view *sampler_view; 1784bf215546Sopenharmony_ci struct pipe_sampler_state sampler = {0}; 1785bf215546Sopenharmony_ci sampler.normalized_coords = true; 1786bf215546Sopenharmony_ci const struct pipe_sampler_state *samplers[1] = {&sampler}; 1787bf215546Sopenharmony_ci unsigned level = texImage->TexObject->Attrib.MinLevel + texImage->Level; 1788bf215546Sopenharmony_ci unsigned max_layer = util_max_layer(texture, level); 1789bf215546Sopenharmony_ci 1790bf215546Sopenharmony_ci u_sampler_view_default_template(&templ, texture, src_format); 1791bf215546Sopenharmony_ci 1792bf215546Sopenharmony_ci templ.target = pipe_target; 1793bf215546Sopenharmony_ci templ.u.tex.first_level = level; 1794bf215546Sopenharmony_ci templ.u.tex.last_level = templ.u.tex.first_level; 1795bf215546Sopenharmony_ci 1796bf215546Sopenharmony_ci zoffset += texImage->Face + texImage->TexObject->Attrib.MinLayer; 1797bf215546Sopenharmony_ci templ.u.tex.first_layer = MIN2(zoffset, max_layer); 1798bf215546Sopenharmony_ci templ.u.tex.last_layer = MIN2(zoffset + depth - 1, max_layer); 1799bf215546Sopenharmony_ci 1800bf215546Sopenharmony_ci sampler_view = pipe->create_sampler_view(pipe, texture, &templ); 1801bf215546Sopenharmony_ci if (sampler_view == NULL) 1802bf215546Sopenharmony_ci goto fail; 1803bf215546Sopenharmony_ci 1804bf215546Sopenharmony_ci pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, true, &sampler_view); 1805bf215546Sopenharmony_ci sampler_view = NULL; 1806bf215546Sopenharmony_ci 1807bf215546Sopenharmony_ci cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 1, samplers); 1808bf215546Sopenharmony_ci } 1809bf215546Sopenharmony_ci 1810bf215546Sopenharmony_ci /* Set up destination image */ 1811bf215546Sopenharmony_ci { 1812bf215546Sopenharmony_ci struct pipe_image_view image; 1813bf215546Sopenharmony_ci 1814bf215546Sopenharmony_ci memset(&image, 0, sizeof(image)); 1815bf215546Sopenharmony_ci image.resource = addr.buffer; 1816bf215546Sopenharmony_ci image.format = dst_format; 1817bf215546Sopenharmony_ci image.access = PIPE_IMAGE_ACCESS_WRITE; 1818bf215546Sopenharmony_ci image.shader_access = PIPE_IMAGE_ACCESS_WRITE; 1819bf215546Sopenharmony_ci image.u.buf.offset = addr.first_element * addr.bytes_per_pixel; 1820bf215546Sopenharmony_ci image.u.buf.size = (addr.last_element - addr.first_element + 1) * 1821bf215546Sopenharmony_ci addr.bytes_per_pixel; 1822bf215546Sopenharmony_ci 1823bf215546Sopenharmony_ci pipe->set_shader_images(pipe, PIPE_SHADER_FRAGMENT, 0, 1, 0, &image); 1824bf215546Sopenharmony_ci } 1825bf215546Sopenharmony_ci 1826bf215546Sopenharmony_ci /* Set up no-attachment framebuffer */ 1827bf215546Sopenharmony_ci memset(&fb, 0, sizeof(fb)); 1828bf215546Sopenharmony_ci fb.width = texture->width0; 1829bf215546Sopenharmony_ci fb.height = texture->height0; 1830bf215546Sopenharmony_ci fb.layers = 1; 1831bf215546Sopenharmony_ci fb.samples = 1; 1832bf215546Sopenharmony_ci cso_set_framebuffer(cso, &fb); 1833bf215546Sopenharmony_ci 1834bf215546Sopenharmony_ci /* Any blend state would do. Set this just to prevent drivers having 1835bf215546Sopenharmony_ci * blend == NULL. 1836bf215546Sopenharmony_ci */ 1837bf215546Sopenharmony_ci cso_set_blend(cso, &st->pbo.upload_blend); 1838bf215546Sopenharmony_ci 1839bf215546Sopenharmony_ci cso_set_viewport_dims(cso, fb.width, fb.height, FALSE); 1840bf215546Sopenharmony_ci 1841bf215546Sopenharmony_ci { 1842bf215546Sopenharmony_ci struct pipe_depth_stencil_alpha_state dsa; 1843bf215546Sopenharmony_ci memset(&dsa, 0, sizeof(dsa)); 1844bf215546Sopenharmony_ci cso_set_depth_stencil_alpha(cso, &dsa); 1845bf215546Sopenharmony_ci } 1846bf215546Sopenharmony_ci 1847bf215546Sopenharmony_ci /* Set up the fragment shader */ 1848bf215546Sopenharmony_ci { 1849bf215546Sopenharmony_ci void *fs = st_pbo_get_download_fs(st, pipe_target, src_format, dst_format, addr.depth != 1); 1850bf215546Sopenharmony_ci if (!fs) 1851bf215546Sopenharmony_ci goto fail; 1852bf215546Sopenharmony_ci 1853bf215546Sopenharmony_ci cso_set_fragment_shader_handle(cso, fs); 1854bf215546Sopenharmony_ci } 1855bf215546Sopenharmony_ci 1856bf215546Sopenharmony_ci success = st_pbo_draw(st, &addr, fb.width, fb.height); 1857bf215546Sopenharmony_ci 1858bf215546Sopenharmony_ci /* Buffer written via shader images needs explicit synchronization. */ 1859bf215546Sopenharmony_ci pipe->memory_barrier(pipe, PIPE_BARRIER_IMAGE | PIPE_BARRIER_TEXTURE | PIPE_BARRIER_FRAMEBUFFER); 1860bf215546Sopenharmony_ci 1861bf215546Sopenharmony_cifail: 1862bf215546Sopenharmony_ci /* Unbind all because st/mesa won't do it if the current shader doesn't 1863bf215546Sopenharmony_ci * use them. 1864bf215546Sopenharmony_ci */ 1865bf215546Sopenharmony_ci cso_restore_state(cso, CSO_UNBIND_FS_SAMPLERVIEWS | CSO_UNBIND_FS_IMAGE0); 1866bf215546Sopenharmony_ci st->state.num_sampler_views[PIPE_SHADER_FRAGMENT] = 0; 1867bf215546Sopenharmony_ci 1868bf215546Sopenharmony_ci st->ctx->Array.NewVertexElements = true; 1869bf215546Sopenharmony_ci st->dirty |= ST_NEW_FS_CONSTANTS | 1870bf215546Sopenharmony_ci ST_NEW_FS_IMAGES | 1871bf215546Sopenharmony_ci ST_NEW_FS_SAMPLER_VIEWS | 1872bf215546Sopenharmony_ci ST_NEW_VERTEX_ARRAYS; 1873bf215546Sopenharmony_ci 1874bf215546Sopenharmony_ci return success; 1875bf215546Sopenharmony_ci} 1876bf215546Sopenharmony_ci 1877bf215546Sopenharmony_ci 1878bf215546Sopenharmony_civoid 1879bf215546Sopenharmony_cist_TexSubImage(struct gl_context *ctx, GLuint dims, 1880bf215546Sopenharmony_ci struct gl_texture_image *texImage, 1881bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 1882bf215546Sopenharmony_ci GLint width, GLint height, GLint depth, 1883bf215546Sopenharmony_ci GLenum format, GLenum type, const void *pixels, 1884bf215546Sopenharmony_ci const struct gl_pixelstore_attrib *unpack) 1885bf215546Sopenharmony_ci{ 1886bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 1887bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 1888bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 1889bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 1890bf215546Sopenharmony_ci struct pipe_resource *dst = texImage->pt; 1891bf215546Sopenharmony_ci struct pipe_resource *src = NULL; 1892bf215546Sopenharmony_ci struct pipe_resource src_templ; 1893bf215546Sopenharmony_ci struct pipe_transfer *transfer; 1894bf215546Sopenharmony_ci struct pipe_blit_info blit; 1895bf215546Sopenharmony_ci enum pipe_format src_format, dst_format; 1896bf215546Sopenharmony_ci mesa_format mesa_src_format; 1897bf215546Sopenharmony_ci GLenum gl_target = texImage->TexObject->Target; 1898bf215546Sopenharmony_ci unsigned bind; 1899bf215546Sopenharmony_ci GLubyte *map; 1900bf215546Sopenharmony_ci unsigned dstz = texImage->Face + texImage->TexObject->Attrib.MinLayer; 1901bf215546Sopenharmony_ci unsigned dst_level = 0; 1902bf215546Sopenharmony_ci bool throttled = false; 1903bf215546Sopenharmony_ci 1904bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 1905bf215546Sopenharmony_ci st_invalidate_readpix_cache(st); 1906bf215546Sopenharmony_ci 1907bf215546Sopenharmony_ci if (stObj->pt == texImage->pt) 1908bf215546Sopenharmony_ci dst_level = texImage->TexObject->Attrib.MinLevel + texImage->Level; 1909bf215546Sopenharmony_ci 1910bf215546Sopenharmony_ci assert(!_mesa_is_format_etc2(texImage->TexFormat) && 1911bf215546Sopenharmony_ci !_mesa_is_format_astc_2d(texImage->TexFormat) && 1912bf215546Sopenharmony_ci texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); 1913bf215546Sopenharmony_ci 1914bf215546Sopenharmony_ci if (!dst) 1915bf215546Sopenharmony_ci goto fallback; 1916bf215546Sopenharmony_ci 1917bf215546Sopenharmony_ci /* Try texture_subdata, which should be the fastest memcpy path. */ 1918bf215546Sopenharmony_ci if (pixels && 1919bf215546Sopenharmony_ci !unpack->BufferObj && 1920bf215546Sopenharmony_ci _mesa_texstore_can_use_memcpy(ctx, texImage->_BaseFormat, 1921bf215546Sopenharmony_ci texImage->TexFormat, format, type, 1922bf215546Sopenharmony_ci unpack)) { 1923bf215546Sopenharmony_ci struct pipe_box box; 1924bf215546Sopenharmony_ci unsigned stride, layer_stride; 1925bf215546Sopenharmony_ci void *data; 1926bf215546Sopenharmony_ci 1927bf215546Sopenharmony_ci stride = _mesa_image_row_stride(unpack, width, format, type); 1928bf215546Sopenharmony_ci layer_stride = _mesa_image_image_stride(unpack, width, height, format, 1929bf215546Sopenharmony_ci type); 1930bf215546Sopenharmony_ci data = _mesa_image_address(dims, unpack, pixels, width, height, format, 1931bf215546Sopenharmony_ci type, 0, 0, 0); 1932bf215546Sopenharmony_ci 1933bf215546Sopenharmony_ci /* Convert to Gallium coordinates. */ 1934bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 1935bf215546Sopenharmony_ci zoffset = yoffset; 1936bf215546Sopenharmony_ci yoffset = 0; 1937bf215546Sopenharmony_ci depth = height; 1938bf215546Sopenharmony_ci height = 1; 1939bf215546Sopenharmony_ci layer_stride = stride; 1940bf215546Sopenharmony_ci } 1941bf215546Sopenharmony_ci 1942bf215546Sopenharmony_ci util_throttle_memory_usage(pipe, &st->throttle, 1943bf215546Sopenharmony_ci (uint64_t) width * height * depth * 1944bf215546Sopenharmony_ci util_format_get_blocksize(dst->format)); 1945bf215546Sopenharmony_ci 1946bf215546Sopenharmony_ci u_box_3d(xoffset, yoffset, zoffset + dstz, width, height, depth, &box); 1947bf215546Sopenharmony_ci pipe->texture_subdata(pipe, dst, dst_level, 0, 1948bf215546Sopenharmony_ci &box, data, stride, layer_stride); 1949bf215546Sopenharmony_ci return; 1950bf215546Sopenharmony_ci } 1951bf215546Sopenharmony_ci 1952bf215546Sopenharmony_ci if (!st->prefer_blit_based_texture_transfer) { 1953bf215546Sopenharmony_ci goto fallback; 1954bf215546Sopenharmony_ci } 1955bf215546Sopenharmony_ci 1956bf215546Sopenharmony_ci /* XXX Fallback for depth-stencil formats due to an incomplete stencil 1957bf215546Sopenharmony_ci * blit implementation in some drivers. */ 1958bf215546Sopenharmony_ci if (format == GL_DEPTH_STENCIL) { 1959bf215546Sopenharmony_ci goto fallback; 1960bf215546Sopenharmony_ci } 1961bf215546Sopenharmony_ci 1962bf215546Sopenharmony_ci /* If the base internal format and the texture format don't match, 1963bf215546Sopenharmony_ci * we can't use blit-based TexSubImage. */ 1964bf215546Sopenharmony_ci if (texImage->_BaseFormat != 1965bf215546Sopenharmony_ci _mesa_get_format_base_format(texImage->TexFormat)) { 1966bf215546Sopenharmony_ci goto fallback; 1967bf215546Sopenharmony_ci } 1968bf215546Sopenharmony_ci 1969bf215546Sopenharmony_ci 1970bf215546Sopenharmony_ci /* See if the destination format is supported. */ 1971bf215546Sopenharmony_ci if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL) 1972bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 1973bf215546Sopenharmony_ci else 1974bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 1975bf215546Sopenharmony_ci 1976bf215546Sopenharmony_ci /* For luminance and intensity, only the red channel is stored 1977bf215546Sopenharmony_ci * in the destination. */ 1978bf215546Sopenharmony_ci dst_format = util_format_linear(dst->format); 1979bf215546Sopenharmony_ci dst_format = util_format_luminance_to_red(dst_format); 1980bf215546Sopenharmony_ci dst_format = util_format_intensity_to_red(dst_format); 1981bf215546Sopenharmony_ci 1982bf215546Sopenharmony_ci if (!dst_format || 1983bf215546Sopenharmony_ci !screen->is_format_supported(screen, dst_format, dst->target, 1984bf215546Sopenharmony_ci dst->nr_samples, dst->nr_storage_samples, 1985bf215546Sopenharmony_ci bind)) { 1986bf215546Sopenharmony_ci goto fallback; 1987bf215546Sopenharmony_ci } 1988bf215546Sopenharmony_ci 1989bf215546Sopenharmony_ci if (unpack->BufferObj) { 1990bf215546Sopenharmony_ci if (try_pbo_upload(ctx, dims, texImage, format, type, dst_format, 1991bf215546Sopenharmony_ci xoffset, yoffset, zoffset, 1992bf215546Sopenharmony_ci width, height, depth, pixels, unpack)) 1993bf215546Sopenharmony_ci return; 1994bf215546Sopenharmony_ci } 1995bf215546Sopenharmony_ci 1996bf215546Sopenharmony_ci /* See if the texture format already matches the format and type, 1997bf215546Sopenharmony_ci * in which case the memcpy-based fast path will likely be used and 1998bf215546Sopenharmony_ci * we don't have to blit. */ 1999bf215546Sopenharmony_ci if (_mesa_format_matches_format_and_type(texImage->TexFormat, format, 2000bf215546Sopenharmony_ci type, unpack->SwapBytes, NULL)) { 2001bf215546Sopenharmony_ci goto fallback; 2002bf215546Sopenharmony_ci } 2003bf215546Sopenharmony_ci 2004bf215546Sopenharmony_ci /* Choose the source format. */ 2005bf215546Sopenharmony_ci src_format = st_choose_matching_format(st, PIPE_BIND_SAMPLER_VIEW, 2006bf215546Sopenharmony_ci format, type, unpack->SwapBytes); 2007bf215546Sopenharmony_ci if (!src_format) { 2008bf215546Sopenharmony_ci goto fallback; 2009bf215546Sopenharmony_ci } 2010bf215546Sopenharmony_ci 2011bf215546Sopenharmony_ci mesa_src_format = st_pipe_format_to_mesa_format(src_format); 2012bf215546Sopenharmony_ci 2013bf215546Sopenharmony_ci /* There is no reason to do this if we cannot use memcpy for the temporary 2014bf215546Sopenharmony_ci * source texture at least. This also takes transfer ops into account, 2015bf215546Sopenharmony_ci * etc. */ 2016bf215546Sopenharmony_ci if (!_mesa_texstore_can_use_memcpy(ctx, 2017bf215546Sopenharmony_ci _mesa_get_format_base_format(mesa_src_format), 2018bf215546Sopenharmony_ci mesa_src_format, format, type, unpack)) { 2019bf215546Sopenharmony_ci goto fallback; 2020bf215546Sopenharmony_ci } 2021bf215546Sopenharmony_ci 2022bf215546Sopenharmony_ci /* TexSubImage only sets a single cubemap face. */ 2023bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_CUBE_MAP) { 2024bf215546Sopenharmony_ci gl_target = GL_TEXTURE_2D; 2025bf215546Sopenharmony_ci } 2026bf215546Sopenharmony_ci /* TexSubImage can specify subsets of cube map array faces 2027bf215546Sopenharmony_ci * so we need to upload via 2D array instead */ 2028bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_CUBE_MAP_ARRAY) { 2029bf215546Sopenharmony_ci gl_target = GL_TEXTURE_2D_ARRAY; 2030bf215546Sopenharmony_ci } 2031bf215546Sopenharmony_ci 2032bf215546Sopenharmony_ci /* Initialize the source texture description. */ 2033bf215546Sopenharmony_ci memset(&src_templ, 0, sizeof(src_templ)); 2034bf215546Sopenharmony_ci src_templ.target = gl_target_to_pipe(gl_target); 2035bf215546Sopenharmony_ci src_templ.format = src_format; 2036bf215546Sopenharmony_ci src_templ.bind = PIPE_BIND_SAMPLER_VIEW; 2037bf215546Sopenharmony_ci src_templ.usage = PIPE_USAGE_STAGING; 2038bf215546Sopenharmony_ci 2039bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(gl_target, width, height, depth, 2040bf215546Sopenharmony_ci &src_templ.width0, &src_templ.height0, 2041bf215546Sopenharmony_ci &src_templ.depth0, &src_templ.array_size); 2042bf215546Sopenharmony_ci 2043bf215546Sopenharmony_ci /* Check for NPOT texture support. */ 2044bf215546Sopenharmony_ci if (!screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES) && 2045bf215546Sopenharmony_ci (!util_is_power_of_two_or_zero(src_templ.width0) || 2046bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(src_templ.height0) || 2047bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(src_templ.depth0))) { 2048bf215546Sopenharmony_ci goto fallback; 2049bf215546Sopenharmony_ci } 2050bf215546Sopenharmony_ci 2051bf215546Sopenharmony_ci util_throttle_memory_usage(pipe, &st->throttle, 2052bf215546Sopenharmony_ci (uint64_t) width * height * depth * 2053bf215546Sopenharmony_ci util_format_get_blocksize(src_templ.format)); 2054bf215546Sopenharmony_ci throttled = true; 2055bf215546Sopenharmony_ci 2056bf215546Sopenharmony_ci /* Create the source texture. */ 2057bf215546Sopenharmony_ci src = screen->resource_create(screen, &src_templ); 2058bf215546Sopenharmony_ci if (!src) { 2059bf215546Sopenharmony_ci goto fallback; 2060bf215546Sopenharmony_ci } 2061bf215546Sopenharmony_ci 2062bf215546Sopenharmony_ci /* Map source pixels. */ 2063bf215546Sopenharmony_ci pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, 2064bf215546Sopenharmony_ci format, type, pixels, unpack, 2065bf215546Sopenharmony_ci "glTexSubImage"); 2066bf215546Sopenharmony_ci if (!pixels) { 2067bf215546Sopenharmony_ci /* This is a GL error. */ 2068bf215546Sopenharmony_ci pipe_resource_reference(&src, NULL); 2069bf215546Sopenharmony_ci return; 2070bf215546Sopenharmony_ci } 2071bf215546Sopenharmony_ci 2072bf215546Sopenharmony_ci /* From now on, we need the gallium representation of dimensions. */ 2073bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 2074bf215546Sopenharmony_ci zoffset = yoffset; 2075bf215546Sopenharmony_ci yoffset = 0; 2076bf215546Sopenharmony_ci depth = height; 2077bf215546Sopenharmony_ci height = 1; 2078bf215546Sopenharmony_ci } 2079bf215546Sopenharmony_ci 2080bf215546Sopenharmony_ci map = pipe_texture_map_3d(pipe, src, 0, PIPE_MAP_WRITE, 0, 0, 0, 2081bf215546Sopenharmony_ci width, height, depth, &transfer); 2082bf215546Sopenharmony_ci if (!map) { 2083bf215546Sopenharmony_ci _mesa_unmap_teximage_pbo(ctx, unpack); 2084bf215546Sopenharmony_ci pipe_resource_reference(&src, NULL); 2085bf215546Sopenharmony_ci goto fallback; 2086bf215546Sopenharmony_ci } 2087bf215546Sopenharmony_ci 2088bf215546Sopenharmony_ci /* Upload pixels (just memcpy). */ 2089bf215546Sopenharmony_ci { 2090bf215546Sopenharmony_ci const uint bytesPerRow = width * util_format_get_blocksize(src_format); 2091bf215546Sopenharmony_ci GLuint row, slice; 2092bf215546Sopenharmony_ci 2093bf215546Sopenharmony_ci for (slice = 0; slice < (unsigned) depth; slice++) { 2094bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 2095bf215546Sopenharmony_ci /* 1D array textures. 2096bf215546Sopenharmony_ci * We need to convert gallium coords to GL coords. 2097bf215546Sopenharmony_ci */ 2098bf215546Sopenharmony_ci void *src = _mesa_image_address2d(unpack, pixels, 2099bf215546Sopenharmony_ci width, depth, format, 2100bf215546Sopenharmony_ci type, slice, 0); 2101bf215546Sopenharmony_ci memcpy(map, src, bytesPerRow); 2102bf215546Sopenharmony_ci } 2103bf215546Sopenharmony_ci else { 2104bf215546Sopenharmony_ci ubyte *slice_map = map; 2105bf215546Sopenharmony_ci 2106bf215546Sopenharmony_ci for (row = 0; row < (unsigned) height; row++) { 2107bf215546Sopenharmony_ci void *src = _mesa_image_address(dims, unpack, pixels, 2108bf215546Sopenharmony_ci width, height, format, 2109bf215546Sopenharmony_ci type, slice, row, 0); 2110bf215546Sopenharmony_ci memcpy(slice_map, src, bytesPerRow); 2111bf215546Sopenharmony_ci slice_map += transfer->stride; 2112bf215546Sopenharmony_ci } 2113bf215546Sopenharmony_ci } 2114bf215546Sopenharmony_ci map += transfer->layer_stride; 2115bf215546Sopenharmony_ci } 2116bf215546Sopenharmony_ci } 2117bf215546Sopenharmony_ci 2118bf215546Sopenharmony_ci pipe_texture_unmap(pipe, transfer); 2119bf215546Sopenharmony_ci _mesa_unmap_teximage_pbo(ctx, unpack); 2120bf215546Sopenharmony_ci 2121bf215546Sopenharmony_ci /* Blit. */ 2122bf215546Sopenharmony_ci memset(&blit, 0, sizeof(blit)); 2123bf215546Sopenharmony_ci blit.src.resource = src; 2124bf215546Sopenharmony_ci blit.src.level = 0; 2125bf215546Sopenharmony_ci blit.src.format = src_format; 2126bf215546Sopenharmony_ci blit.dst.resource = dst; 2127bf215546Sopenharmony_ci blit.dst.level = dst_level; 2128bf215546Sopenharmony_ci blit.dst.format = dst_format; 2129bf215546Sopenharmony_ci blit.src.box.x = blit.src.box.y = blit.src.box.z = 0; 2130bf215546Sopenharmony_ci blit.dst.box.x = xoffset; 2131bf215546Sopenharmony_ci blit.dst.box.y = yoffset; 2132bf215546Sopenharmony_ci blit.dst.box.z = zoffset + dstz; 2133bf215546Sopenharmony_ci blit.src.box.width = blit.dst.box.width = width; 2134bf215546Sopenharmony_ci blit.src.box.height = blit.dst.box.height = height; 2135bf215546Sopenharmony_ci blit.src.box.depth = blit.dst.box.depth = depth; 2136bf215546Sopenharmony_ci blit.mask = st_get_blit_mask(format, texImage->_BaseFormat); 2137bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 2138bf215546Sopenharmony_ci blit.scissor_enable = FALSE; 2139bf215546Sopenharmony_ci 2140bf215546Sopenharmony_ci st->pipe->blit(st->pipe, &blit); 2141bf215546Sopenharmony_ci 2142bf215546Sopenharmony_ci pipe_resource_reference(&src, NULL); 2143bf215546Sopenharmony_ci return; 2144bf215546Sopenharmony_ci 2145bf215546Sopenharmony_cifallback: 2146bf215546Sopenharmony_ci if (!throttled) { 2147bf215546Sopenharmony_ci util_throttle_memory_usage(pipe, &st->throttle, 2148bf215546Sopenharmony_ci (uint64_t) width * height * depth * 2149bf215546Sopenharmony_ci _mesa_get_format_bytes(texImage->TexFormat)); 2150bf215546Sopenharmony_ci } 2151bf215546Sopenharmony_ci _mesa_store_texsubimage(ctx, dims, texImage, xoffset, yoffset, zoffset, 2152bf215546Sopenharmony_ci width, height, depth, format, type, pixels, 2153bf215546Sopenharmony_ci unpack); 2154bf215546Sopenharmony_ci} 2155bf215546Sopenharmony_ci 2156bf215546Sopenharmony_ci 2157bf215546Sopenharmony_civoid 2158bf215546Sopenharmony_cist_TexImage(struct gl_context * ctx, GLuint dims, 2159bf215546Sopenharmony_ci struct gl_texture_image *texImage, 2160bf215546Sopenharmony_ci GLenum format, GLenum type, const void *pixels, 2161bf215546Sopenharmony_ci const struct gl_pixelstore_attrib *unpack) 2162bf215546Sopenharmony_ci{ 2163bf215546Sopenharmony_ci assert(dims == 1 || dims == 2 || dims == 3); 2164bf215546Sopenharmony_ci 2165bf215546Sopenharmony_ci prep_teximage(ctx, texImage, format, type); 2166bf215546Sopenharmony_ci 2167bf215546Sopenharmony_ci if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0) 2168bf215546Sopenharmony_ci return; 2169bf215546Sopenharmony_ci 2170bf215546Sopenharmony_ci /* allocate storage for texture data */ 2171bf215546Sopenharmony_ci if (!st_AllocTextureImageBuffer(ctx, texImage)) { 2172bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD(internalformat=%s)", 2173bf215546Sopenharmony_ci dims, _mesa_enum_to_string(texImage->InternalFormat)); 2174bf215546Sopenharmony_ci 2175bf215546Sopenharmony_ci return; 2176bf215546Sopenharmony_ci } 2177bf215546Sopenharmony_ci 2178bf215546Sopenharmony_ci st_TexSubImage(ctx, dims, texImage, 0, 0, 0, 2179bf215546Sopenharmony_ci texImage->Width, texImage->Height, texImage->Depth, 2180bf215546Sopenharmony_ci format, type, pixels, unpack); 2181bf215546Sopenharmony_ci} 2182bf215546Sopenharmony_ci 2183bf215546Sopenharmony_cistatic bool 2184bf215546Sopenharmony_cist_try_pbo_compressed_texsubimage(struct gl_context *ctx, 2185bf215546Sopenharmony_ci struct pipe_resource *buf, 2186bf215546Sopenharmony_ci intptr_t buf_offset, 2187bf215546Sopenharmony_ci const struct st_pbo_addresses *addr_tmpl, 2188bf215546Sopenharmony_ci struct pipe_resource *texture, 2189bf215546Sopenharmony_ci const struct pipe_surface *surface_templ) 2190bf215546Sopenharmony_ci{ 2191bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2192bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 2193bf215546Sopenharmony_ci struct st_pbo_addresses addr; 2194bf215546Sopenharmony_ci struct pipe_surface *surface = NULL; 2195bf215546Sopenharmony_ci bool success; 2196bf215546Sopenharmony_ci 2197bf215546Sopenharmony_ci addr = *addr_tmpl; 2198bf215546Sopenharmony_ci if (!st_pbo_addresses_setup(st, buf, buf_offset, &addr)) 2199bf215546Sopenharmony_ci return false; 2200bf215546Sopenharmony_ci 2201bf215546Sopenharmony_ci surface = pipe->create_surface(pipe, texture, surface_templ); 2202bf215546Sopenharmony_ci if (!surface) 2203bf215546Sopenharmony_ci return false; 2204bf215546Sopenharmony_ci 2205bf215546Sopenharmony_ci success = try_pbo_upload_common(ctx, surface, &addr, surface_templ->format); 2206bf215546Sopenharmony_ci 2207bf215546Sopenharmony_ci pipe_surface_reference(&surface, NULL); 2208bf215546Sopenharmony_ci 2209bf215546Sopenharmony_ci return success; 2210bf215546Sopenharmony_ci} 2211bf215546Sopenharmony_ci 2212bf215546Sopenharmony_civoid 2213bf215546Sopenharmony_cist_CompressedTexSubImage(struct gl_context *ctx, GLuint dims, 2214bf215546Sopenharmony_ci struct gl_texture_image *texImage, 2215bf215546Sopenharmony_ci GLint x, GLint y, GLint z, 2216bf215546Sopenharmony_ci GLsizei w, GLsizei h, GLsizei d, 2217bf215546Sopenharmony_ci GLenum format, GLsizei imageSize, const void *data) 2218bf215546Sopenharmony_ci{ 2219bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2220bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 2221bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 2222bf215546Sopenharmony_ci struct pipe_resource *buf; 2223bf215546Sopenharmony_ci struct pipe_resource *texture = stImage->pt; 2224bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 2225bf215546Sopenharmony_ci struct pipe_resource *dst = stImage->pt; 2226bf215546Sopenharmony_ci struct pipe_surface templ; 2227bf215546Sopenharmony_ci struct compressed_pixelstore store; 2228bf215546Sopenharmony_ci struct st_pbo_addresses addr; 2229bf215546Sopenharmony_ci enum pipe_format copy_format; 2230bf215546Sopenharmony_ci unsigned bw, bh, level, max_layer; 2231bf215546Sopenharmony_ci int layer; 2232bf215546Sopenharmony_ci intptr_t buf_offset; 2233bf215546Sopenharmony_ci bool success = false; 2234bf215546Sopenharmony_ci 2235bf215546Sopenharmony_ci /* Check basic pre-conditions for PBO upload */ 2236bf215546Sopenharmony_ci if (!st->prefer_blit_based_texture_transfer) { 2237bf215546Sopenharmony_ci goto fallback; 2238bf215546Sopenharmony_ci } 2239bf215546Sopenharmony_ci 2240bf215546Sopenharmony_ci if (!ctx->Unpack.BufferObj) 2241bf215546Sopenharmony_ci goto fallback; 2242bf215546Sopenharmony_ci 2243bf215546Sopenharmony_ci if (st_compressed_format_fallback(st, texImage->TexFormat)) 2244bf215546Sopenharmony_ci goto fallback; 2245bf215546Sopenharmony_ci 2246bf215546Sopenharmony_ci if (!dst) { 2247bf215546Sopenharmony_ci goto fallback; 2248bf215546Sopenharmony_ci } 2249bf215546Sopenharmony_ci 2250bf215546Sopenharmony_ci if (!st->pbo.upload_enabled || 2251bf215546Sopenharmony_ci !screen->get_param(screen, PIPE_CAP_SURFACE_REINTERPRET_BLOCKS)) { 2252bf215546Sopenharmony_ci goto fallback; 2253bf215546Sopenharmony_ci } 2254bf215546Sopenharmony_ci 2255bf215546Sopenharmony_ci /* Choose the pipe format for the upload. */ 2256bf215546Sopenharmony_ci addr.bytes_per_pixel = util_format_get_blocksize(dst->format); 2257bf215546Sopenharmony_ci bw = util_format_get_blockwidth(dst->format); 2258bf215546Sopenharmony_ci bh = util_format_get_blockheight(dst->format); 2259bf215546Sopenharmony_ci 2260bf215546Sopenharmony_ci switch (addr.bytes_per_pixel) { 2261bf215546Sopenharmony_ci case 8: 2262bf215546Sopenharmony_ci copy_format = PIPE_FORMAT_R16G16B16A16_UINT; 2263bf215546Sopenharmony_ci break; 2264bf215546Sopenharmony_ci case 16: 2265bf215546Sopenharmony_ci copy_format = PIPE_FORMAT_R32G32B32A32_UINT; 2266bf215546Sopenharmony_ci break; 2267bf215546Sopenharmony_ci default: 2268bf215546Sopenharmony_ci goto fallback; 2269bf215546Sopenharmony_ci } 2270bf215546Sopenharmony_ci 2271bf215546Sopenharmony_ci if (!screen->is_format_supported(screen, copy_format, PIPE_BUFFER, 0, 0, 2272bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)) { 2273bf215546Sopenharmony_ci goto fallback; 2274bf215546Sopenharmony_ci } 2275bf215546Sopenharmony_ci 2276bf215546Sopenharmony_ci if (!screen->is_format_supported(screen, copy_format, dst->target, 2277bf215546Sopenharmony_ci dst->nr_samples, dst->nr_storage_samples, 2278bf215546Sopenharmony_ci PIPE_BIND_RENDER_TARGET)) { 2279bf215546Sopenharmony_ci goto fallback; 2280bf215546Sopenharmony_ci } 2281bf215546Sopenharmony_ci 2282bf215546Sopenharmony_ci /* Interpret the pixelstore settings. */ 2283bf215546Sopenharmony_ci _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat, w, h, d, 2284bf215546Sopenharmony_ci &ctx->Unpack, &store); 2285bf215546Sopenharmony_ci assert(store.CopyBytesPerRow % addr.bytes_per_pixel == 0); 2286bf215546Sopenharmony_ci assert(store.SkipBytes % addr.bytes_per_pixel == 0); 2287bf215546Sopenharmony_ci 2288bf215546Sopenharmony_ci /* Compute the offset into the buffer */ 2289bf215546Sopenharmony_ci buf_offset = (intptr_t)data + store.SkipBytes; 2290bf215546Sopenharmony_ci 2291bf215546Sopenharmony_ci if (buf_offset % addr.bytes_per_pixel) { 2292bf215546Sopenharmony_ci goto fallback; 2293bf215546Sopenharmony_ci } 2294bf215546Sopenharmony_ci 2295bf215546Sopenharmony_ci buf_offset = buf_offset / addr.bytes_per_pixel; 2296bf215546Sopenharmony_ci 2297bf215546Sopenharmony_ci buf = ctx->Unpack.BufferObj->buffer; 2298bf215546Sopenharmony_ci 2299bf215546Sopenharmony_ci addr.xoffset = x / bw; 2300bf215546Sopenharmony_ci addr.yoffset = y / bh; 2301bf215546Sopenharmony_ci addr.width = store.CopyBytesPerRow / addr.bytes_per_pixel; 2302bf215546Sopenharmony_ci addr.height = store.CopyRowsPerSlice; 2303bf215546Sopenharmony_ci addr.depth = d; 2304bf215546Sopenharmony_ci addr.pixels_per_row = store.TotalBytesPerRow / addr.bytes_per_pixel; 2305bf215546Sopenharmony_ci addr.image_height = store.TotalRowsPerSlice; 2306bf215546Sopenharmony_ci 2307bf215546Sopenharmony_ci /* Set up the surface. */ 2308bf215546Sopenharmony_ci level = stObj->pt != stImage->pt 2309bf215546Sopenharmony_ci ? 0 : texImage->TexObject->Attrib.MinLevel + texImage->Level; 2310bf215546Sopenharmony_ci max_layer = util_max_layer(texture, level); 2311bf215546Sopenharmony_ci layer = z + texImage->Face + texImage->TexObject->Attrib.MinLayer; 2312bf215546Sopenharmony_ci 2313bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 2314bf215546Sopenharmony_ci templ.format = copy_format; 2315bf215546Sopenharmony_ci templ.u.tex.level = level; 2316bf215546Sopenharmony_ci templ.u.tex.first_layer = MIN2(layer, max_layer); 2317bf215546Sopenharmony_ci templ.u.tex.last_layer = MIN2(layer + d - 1, max_layer); 2318bf215546Sopenharmony_ci 2319bf215546Sopenharmony_ci if (st_try_pbo_compressed_texsubimage(ctx, buf, buf_offset, &addr, 2320bf215546Sopenharmony_ci texture, &templ)) 2321bf215546Sopenharmony_ci return; 2322bf215546Sopenharmony_ci 2323bf215546Sopenharmony_ci /* Some drivers can re-interpret surfaces but only one layer at a time. 2324bf215546Sopenharmony_ci * Fall back to doing a single try_pbo_upload_common per layer. 2325bf215546Sopenharmony_ci */ 2326bf215546Sopenharmony_ci while (layer <= max_layer) { 2327bf215546Sopenharmony_ci templ.u.tex.first_layer = MIN2(layer, max_layer); 2328bf215546Sopenharmony_ci templ.u.tex.last_layer = templ.u.tex.first_layer; 2329bf215546Sopenharmony_ci if (!st_try_pbo_compressed_texsubimage(ctx, buf, buf_offset, &addr, 2330bf215546Sopenharmony_ci texture, &templ)) 2331bf215546Sopenharmony_ci goto fallback; 2332bf215546Sopenharmony_ci 2333bf215546Sopenharmony_ci /* By incrementing layer here, we ensure the fallback only uploads 2334bf215546Sopenharmony_ci * layers we failed to upload. 2335bf215546Sopenharmony_ci */ 2336bf215546Sopenharmony_ci buf_offset += addr.pixels_per_row * addr.image_height; 2337bf215546Sopenharmony_ci layer++; 2338bf215546Sopenharmony_ci addr.depth--; 2339bf215546Sopenharmony_ci } 2340bf215546Sopenharmony_ci 2341bf215546Sopenharmony_ci if (success) 2342bf215546Sopenharmony_ci return; 2343bf215546Sopenharmony_ci 2344bf215546Sopenharmony_cifallback: 2345bf215546Sopenharmony_ci _mesa_store_compressed_texsubimage(ctx, dims, texImage, 2346bf215546Sopenharmony_ci x, y, z, w, h, d, 2347bf215546Sopenharmony_ci format, imageSize, data); 2348bf215546Sopenharmony_ci} 2349bf215546Sopenharmony_ci 2350bf215546Sopenharmony_ci 2351bf215546Sopenharmony_civoid 2352bf215546Sopenharmony_cist_CompressedTexImage(struct gl_context *ctx, GLuint dims, 2353bf215546Sopenharmony_ci struct gl_texture_image *texImage, 2354bf215546Sopenharmony_ci GLsizei imageSize, const void *data) 2355bf215546Sopenharmony_ci{ 2356bf215546Sopenharmony_ci prep_teximage(ctx, texImage, GL_NONE, GL_NONE); 2357bf215546Sopenharmony_ci 2358bf215546Sopenharmony_ci /* only 2D and 3D compressed images are supported at this time */ 2359bf215546Sopenharmony_ci if (dims == 1) { 2360bf215546Sopenharmony_ci _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call"); 2361bf215546Sopenharmony_ci return; 2362bf215546Sopenharmony_ci } 2363bf215546Sopenharmony_ci 2364bf215546Sopenharmony_ci /* This is pretty simple, because unlike the general texstore path we don't 2365bf215546Sopenharmony_ci * have to worry about the usual image unpacking or image transfer 2366bf215546Sopenharmony_ci * operations. 2367bf215546Sopenharmony_ci */ 2368bf215546Sopenharmony_ci assert(texImage); 2369bf215546Sopenharmony_ci assert(texImage->Width > 0); 2370bf215546Sopenharmony_ci assert(texImage->Height > 0); 2371bf215546Sopenharmony_ci assert(texImage->Depth > 0); 2372bf215546Sopenharmony_ci 2373bf215546Sopenharmony_ci /* allocate storage for texture data */ 2374bf215546Sopenharmony_ci if (!st_AllocTextureImageBuffer(ctx, texImage)) { 2375bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims); 2376bf215546Sopenharmony_ci return; 2377bf215546Sopenharmony_ci } 2378bf215546Sopenharmony_ci 2379bf215546Sopenharmony_ci st_CompressedTexSubImage(ctx, dims, texImage, 2380bf215546Sopenharmony_ci 0, 0, 0, 2381bf215546Sopenharmony_ci texImage->Width, texImage->Height, texImage->Depth, 2382bf215546Sopenharmony_ci texImage->TexFormat, 2383bf215546Sopenharmony_ci imageSize, data); 2384bf215546Sopenharmony_ci} 2385bf215546Sopenharmony_ci 2386bf215546Sopenharmony_ci 2387bf215546Sopenharmony_ci/** 2388bf215546Sopenharmony_ci * Called via ctx->Driver.GetTexSubImage() 2389bf215546Sopenharmony_ci * 2390bf215546Sopenharmony_ci * This uses a blit to copy the texture to a texture format which matches 2391bf215546Sopenharmony_ci * the format and type combo and then a fast read-back is done using memcpy. 2392bf215546Sopenharmony_ci * We can do arbitrary X/Y/Z/W/0/1 swizzling here as long as there is 2393bf215546Sopenharmony_ci * a format which matches the swizzling. 2394bf215546Sopenharmony_ci * 2395bf215546Sopenharmony_ci * If such a format isn't available, it falls back to _mesa_GetTexImage_sw. 2396bf215546Sopenharmony_ci * 2397bf215546Sopenharmony_ci * NOTE: Drivers usually do a blit to convert between tiled and linear 2398bf215546Sopenharmony_ci * texture layouts during texture uploads/downloads, so the blit 2399bf215546Sopenharmony_ci * we do here should be free in such cases. 2400bf215546Sopenharmony_ci */ 2401bf215546Sopenharmony_civoid 2402bf215546Sopenharmony_cist_GetTexSubImage(struct gl_context * ctx, 2403bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 2404bf215546Sopenharmony_ci GLsizei width, GLsizei height, GLint depth, 2405bf215546Sopenharmony_ci GLenum format, GLenum type, void * pixels, 2406bf215546Sopenharmony_ci struct gl_texture_image *texImage) 2407bf215546Sopenharmony_ci{ 2408bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2409bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 2410bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 2411bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 2412bf215546Sopenharmony_ci struct pipe_resource *src = stObj->pt; 2413bf215546Sopenharmony_ci struct pipe_resource *dst = NULL; 2414bf215546Sopenharmony_ci enum pipe_format dst_format, src_format; 2415bf215546Sopenharmony_ci GLenum gl_target = texImage->TexObject->Target; 2416bf215546Sopenharmony_ci enum pipe_texture_target pipe_target; 2417bf215546Sopenharmony_ci struct pipe_blit_info blit; 2418bf215546Sopenharmony_ci unsigned bind; 2419bf215546Sopenharmony_ci boolean done = FALSE; 2420bf215546Sopenharmony_ci 2421bf215546Sopenharmony_ci assert(!_mesa_is_format_etc2(texImage->TexFormat) && 2422bf215546Sopenharmony_ci !_mesa_is_format_astc_2d(texImage->TexFormat) && 2423bf215546Sopenharmony_ci texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); 2424bf215546Sopenharmony_ci 2425bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 2426bf215546Sopenharmony_ci 2427bf215546Sopenharmony_ci /* GetTexImage only returns a single face for cubemaps. */ 2428bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_CUBE_MAP) { 2429bf215546Sopenharmony_ci gl_target = GL_TEXTURE_2D; 2430bf215546Sopenharmony_ci } 2431bf215546Sopenharmony_ci pipe_target = gl_target_to_pipe(gl_target); 2432bf215546Sopenharmony_ci 2433bf215546Sopenharmony_ci if (!st->prefer_blit_based_texture_transfer && 2434bf215546Sopenharmony_ci !_mesa_is_format_compressed(texImage->TexFormat)) { 2435bf215546Sopenharmony_ci /* Try to avoid the non_blit_transfer if we're doing texture decompression here */ 2436bf215546Sopenharmony_ci goto non_blit_transfer; 2437bf215546Sopenharmony_ci } 2438bf215546Sopenharmony_ci 2439bf215546Sopenharmony_ci if (stImage->pt != stObj->pt) 2440bf215546Sopenharmony_ci goto non_blit_transfer; 2441bf215546Sopenharmony_ci 2442bf215546Sopenharmony_ci /* Handle non-finalized textures. */ 2443bf215546Sopenharmony_ci if (!stImage->pt || !src) { 2444bf215546Sopenharmony_ci goto cpu_transfer; 2445bf215546Sopenharmony_ci } 2446bf215546Sopenharmony_ci 2447bf215546Sopenharmony_ci /* XXX Fallback to _mesa_GetTexImage_sw for depth-stencil formats 2448bf215546Sopenharmony_ci * due to an incomplete stencil blit implementation in some drivers. */ 2449bf215546Sopenharmony_ci if (format == GL_DEPTH_STENCIL || format == GL_STENCIL_INDEX) { 2450bf215546Sopenharmony_ci goto non_blit_transfer; 2451bf215546Sopenharmony_ci } 2452bf215546Sopenharmony_ci 2453bf215546Sopenharmony_ci /* If the base internal format and the texture format don't match, we have 2454bf215546Sopenharmony_ci * to fall back to _mesa_GetTexImage_sw. */ 2455bf215546Sopenharmony_ci if (texImage->_BaseFormat != 2456bf215546Sopenharmony_ci _mesa_get_format_base_format(texImage->TexFormat)) { 2457bf215546Sopenharmony_ci goto non_blit_transfer; 2458bf215546Sopenharmony_ci } 2459bf215546Sopenharmony_ci 2460bf215546Sopenharmony_ci src_format = st_pbo_get_src_format(screen, stObj->surface_based ? stObj->surface_format : src->format, src); 2461bf215546Sopenharmony_ci if (src_format == PIPE_FORMAT_NONE) 2462bf215546Sopenharmony_ci goto non_blit_transfer; 2463bf215546Sopenharmony_ci 2464bf215546Sopenharmony_ci if (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL) 2465bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 2466bf215546Sopenharmony_ci else 2467bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 2468bf215546Sopenharmony_ci 2469bf215546Sopenharmony_ci dst_format = st_pbo_get_dst_format(ctx, pipe_target, src_format, util_format_is_compressed(src->format), 2470bf215546Sopenharmony_ci format, type, bind); 2471bf215546Sopenharmony_ci if (dst_format == PIPE_FORMAT_NONE) 2472bf215546Sopenharmony_ci goto non_blit_transfer; 2473bf215546Sopenharmony_ci 2474bf215546Sopenharmony_ci if (st->pbo.download_enabled && ctx->Pack.BufferObj) { 2475bf215546Sopenharmony_ci if (try_pbo_download(st, texImage, 2476bf215546Sopenharmony_ci src_format, dst_format, 2477bf215546Sopenharmony_ci xoffset, yoffset, zoffset, 2478bf215546Sopenharmony_ci width, height, depth, 2479bf215546Sopenharmony_ci &ctx->Pack, pixels)) 2480bf215546Sopenharmony_ci return; 2481bf215546Sopenharmony_ci } 2482bf215546Sopenharmony_ci 2483bf215546Sopenharmony_ci /* See if the texture format already matches the format and type, 2484bf215546Sopenharmony_ci * in which case the memcpy-based fast path will be used. */ 2485bf215546Sopenharmony_ci if (_mesa_format_matches_format_and_type(texImage->TexFormat, format, 2486bf215546Sopenharmony_ci type, ctx->Pack.SwapBytes, NULL)) 2487bf215546Sopenharmony_ci goto non_blit_transfer; 2488bf215546Sopenharmony_ci 2489bf215546Sopenharmony_ci dst = create_dst_texture(ctx, dst_format, pipe_target, width, height, depth, gl_target, bind); 2490bf215546Sopenharmony_ci if (!dst) 2491bf215546Sopenharmony_ci goto non_blit_transfer; 2492bf215546Sopenharmony_ci 2493bf215546Sopenharmony_ci /* From now on, we need the gallium representation of dimensions. */ 2494bf215546Sopenharmony_ci if (gl_target == GL_TEXTURE_1D_ARRAY) { 2495bf215546Sopenharmony_ci zoffset = yoffset; 2496bf215546Sopenharmony_ci yoffset = 0; 2497bf215546Sopenharmony_ci depth = height; 2498bf215546Sopenharmony_ci height = 1; 2499bf215546Sopenharmony_ci } 2500bf215546Sopenharmony_ci 2501bf215546Sopenharmony_ci assert(texImage->Face == 0 || 2502bf215546Sopenharmony_ci texImage->TexObject->Attrib.MinLayer == 0 || 2503bf215546Sopenharmony_ci zoffset == 0); 2504bf215546Sopenharmony_ci 2505bf215546Sopenharmony_ci memset(&blit, 0, sizeof(blit)); 2506bf215546Sopenharmony_ci blit.src.resource = src; 2507bf215546Sopenharmony_ci blit.src.level = texImage->Level + texImage->TexObject->Attrib.MinLevel; 2508bf215546Sopenharmony_ci blit.src.format = src_format; 2509bf215546Sopenharmony_ci blit.dst.resource = dst; 2510bf215546Sopenharmony_ci blit.dst.level = 0; 2511bf215546Sopenharmony_ci blit.dst.format = dst->format; 2512bf215546Sopenharmony_ci blit.src.box.x = xoffset; 2513bf215546Sopenharmony_ci blit.dst.box.x = 0; 2514bf215546Sopenharmony_ci blit.src.box.y = yoffset; 2515bf215546Sopenharmony_ci blit.dst.box.y = 0; 2516bf215546Sopenharmony_ci blit.src.box.z = texImage->Face + texImage->TexObject->Attrib.MinLayer + zoffset; 2517bf215546Sopenharmony_ci blit.dst.box.z = 0; 2518bf215546Sopenharmony_ci blit.src.box.width = blit.dst.box.width = width; 2519bf215546Sopenharmony_ci blit.src.box.height = blit.dst.box.height = height; 2520bf215546Sopenharmony_ci blit.src.box.depth = blit.dst.box.depth = depth; 2521bf215546Sopenharmony_ci blit.mask = st_get_blit_mask(texImage->_BaseFormat, format); 2522bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 2523bf215546Sopenharmony_ci blit.scissor_enable = FALSE; 2524bf215546Sopenharmony_ci 2525bf215546Sopenharmony_ci /* blit/render/decompress */ 2526bf215546Sopenharmony_ci st->pipe->blit(st->pipe, &blit); 2527bf215546Sopenharmony_ci 2528bf215546Sopenharmony_ci done = copy_to_staging_dest(ctx, dst, xoffset, yoffset, zoffset, width, height, 2529bf215546Sopenharmony_ci depth, format, type, pixels, texImage); 2530bf215546Sopenharmony_ci pipe_resource_reference(&dst, NULL); 2531bf215546Sopenharmony_ci 2532bf215546Sopenharmony_cinon_blit_transfer: 2533bf215546Sopenharmony_ci if (done) 2534bf215546Sopenharmony_ci return; 2535bf215546Sopenharmony_ci if (st->allow_compute_based_texture_transfer) { 2536bf215546Sopenharmony_ci if (st_GetTexSubImage_shader(ctx, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels, texImage)) 2537bf215546Sopenharmony_ci return; 2538bf215546Sopenharmony_ci } 2539bf215546Sopenharmony_cicpu_transfer: 2540bf215546Sopenharmony_ci _mesa_GetTexSubImage_sw(ctx, xoffset, yoffset, zoffset, 2541bf215546Sopenharmony_ci width, height, depth, 2542bf215546Sopenharmony_ci format, type, pixels, texImage); 2543bf215546Sopenharmony_ci} 2544bf215546Sopenharmony_ci 2545bf215546Sopenharmony_ci 2546bf215546Sopenharmony_ci/** 2547bf215546Sopenharmony_ci * Do a CopyTexSubImage operation using a read transfer from the source, 2548bf215546Sopenharmony_ci * a write transfer to the destination and get_tile()/put_tile() to access 2549bf215546Sopenharmony_ci * the pixels/texels. 2550bf215546Sopenharmony_ci * 2551bf215546Sopenharmony_ci * Note: srcY=0=TOP of renderbuffer 2552bf215546Sopenharmony_ci */ 2553bf215546Sopenharmony_cistatic void 2554bf215546Sopenharmony_cifallback_copy_texsubimage(struct gl_context *ctx, 2555bf215546Sopenharmony_ci struct gl_renderbuffer *rb, 2556bf215546Sopenharmony_ci struct gl_texture_image *stImage, 2557bf215546Sopenharmony_ci GLenum baseFormat, 2558bf215546Sopenharmony_ci GLint destX, GLint destY, GLint slice, 2559bf215546Sopenharmony_ci GLint srcX, GLint srcY, 2560bf215546Sopenharmony_ci GLsizei width, GLsizei height) 2561bf215546Sopenharmony_ci{ 2562bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2563bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 2564bf215546Sopenharmony_ci struct pipe_transfer *src_trans; 2565bf215546Sopenharmony_ci GLubyte *texDest; 2566bf215546Sopenharmony_ci enum pipe_map_flags transfer_usage; 2567bf215546Sopenharmony_ci void *map; 2568bf215546Sopenharmony_ci unsigned dst_width = width; 2569bf215546Sopenharmony_ci unsigned dst_height = height; 2570bf215546Sopenharmony_ci unsigned dst_depth = 1; 2571bf215546Sopenharmony_ci struct pipe_transfer *transfer; 2572bf215546Sopenharmony_ci 2573bf215546Sopenharmony_ci if (ST_DEBUG & DEBUG_FALLBACK) 2574bf215546Sopenharmony_ci debug_printf("%s: fallback processing\n", __func__); 2575bf215546Sopenharmony_ci 2576bf215546Sopenharmony_ci if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 2577bf215546Sopenharmony_ci srcY = rb->Height - srcY - height; 2578bf215546Sopenharmony_ci } 2579bf215546Sopenharmony_ci 2580bf215546Sopenharmony_ci map = pipe_texture_map(pipe, 2581bf215546Sopenharmony_ci rb->texture, 2582bf215546Sopenharmony_ci rb->surface->u.tex.level, 2583bf215546Sopenharmony_ci rb->surface->u.tex.first_layer, 2584bf215546Sopenharmony_ci PIPE_MAP_READ, 2585bf215546Sopenharmony_ci srcX, srcY, 2586bf215546Sopenharmony_ci width, height, &src_trans); 2587bf215546Sopenharmony_ci if (!map) { 2588bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); 2589bf215546Sopenharmony_ci return; 2590bf215546Sopenharmony_ci } 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci if ((baseFormat == GL_DEPTH_COMPONENT || 2593bf215546Sopenharmony_ci baseFormat == GL_DEPTH_STENCIL) && 2594bf215546Sopenharmony_ci util_format_is_depth_and_stencil(stImage->pt->format)) 2595bf215546Sopenharmony_ci transfer_usage = PIPE_MAP_READ_WRITE; 2596bf215546Sopenharmony_ci else 2597bf215546Sopenharmony_ci transfer_usage = PIPE_MAP_WRITE; 2598bf215546Sopenharmony_ci 2599bf215546Sopenharmony_ci texDest = st_texture_image_map(st, stImage, transfer_usage, 2600bf215546Sopenharmony_ci destX, destY, slice, 2601bf215546Sopenharmony_ci dst_width, dst_height, dst_depth, 2602bf215546Sopenharmony_ci &transfer); 2603bf215546Sopenharmony_ci if (!texDest) { 2604bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); 2605bf215546Sopenharmony_ci goto err; 2606bf215546Sopenharmony_ci } 2607bf215546Sopenharmony_ci 2608bf215546Sopenharmony_ci if (baseFormat == GL_DEPTH_COMPONENT || 2609bf215546Sopenharmony_ci baseFormat == GL_DEPTH_STENCIL) { 2610bf215546Sopenharmony_ci const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F || 2611bf215546Sopenharmony_ci ctx->Pixel.DepthBias != 0.0F); 2612bf215546Sopenharmony_ci GLint row, yStep; 2613bf215546Sopenharmony_ci uint *data; 2614bf215546Sopenharmony_ci 2615bf215546Sopenharmony_ci /* determine bottom-to-top vs. top-to-bottom order for src buffer */ 2616bf215546Sopenharmony_ci if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 2617bf215546Sopenharmony_ci srcY = height - 1; 2618bf215546Sopenharmony_ci yStep = -1; 2619bf215546Sopenharmony_ci } 2620bf215546Sopenharmony_ci else { 2621bf215546Sopenharmony_ci srcY = 0; 2622bf215546Sopenharmony_ci yStep = 1; 2623bf215546Sopenharmony_ci } 2624bf215546Sopenharmony_ci 2625bf215546Sopenharmony_ci data = malloc(width * sizeof(uint)); 2626bf215546Sopenharmony_ci 2627bf215546Sopenharmony_ci if (data) { 2628bf215546Sopenharmony_ci unsigned dst_stride = (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY ? 2629bf215546Sopenharmony_ci transfer->layer_stride : transfer->stride); 2630bf215546Sopenharmony_ci /* To avoid a large temp memory allocation, do copy row by row */ 2631bf215546Sopenharmony_ci for (row = 0; row < height; row++, srcY += yStep) { 2632bf215546Sopenharmony_ci util_format_unpack_z_32unorm(rb->texture->format, 2633bf215546Sopenharmony_ci data, (uint8_t *)map + src_trans->stride * srcY, 2634bf215546Sopenharmony_ci width); 2635bf215546Sopenharmony_ci if (scaleOrBias) { 2636bf215546Sopenharmony_ci _mesa_scale_and_bias_depth_uint(ctx, width, data); 2637bf215546Sopenharmony_ci } 2638bf215546Sopenharmony_ci 2639bf215546Sopenharmony_ci util_format_pack_z_32unorm(stImage->pt->format, 2640bf215546Sopenharmony_ci texDest + row * dst_stride, data, width); 2641bf215546Sopenharmony_ci } 2642bf215546Sopenharmony_ci } 2643bf215546Sopenharmony_ci else { 2644bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage()"); 2645bf215546Sopenharmony_ci } 2646bf215546Sopenharmony_ci 2647bf215546Sopenharmony_ci free(data); 2648bf215546Sopenharmony_ci } 2649bf215546Sopenharmony_ci else { 2650bf215546Sopenharmony_ci /* RGBA format */ 2651bf215546Sopenharmony_ci GLfloat *tempSrc = 2652bf215546Sopenharmony_ci malloc(width * height * 4 * sizeof(GLfloat)); 2653bf215546Sopenharmony_ci 2654bf215546Sopenharmony_ci if (tempSrc) { 2655bf215546Sopenharmony_ci const GLint dims = 2; 2656bf215546Sopenharmony_ci GLint dstRowStride; 2657bf215546Sopenharmony_ci struct gl_texture_image *texImage = stImage; 2658bf215546Sopenharmony_ci struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; 2659bf215546Sopenharmony_ci 2660bf215546Sopenharmony_ci if (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 2661bf215546Sopenharmony_ci unpack.Invert = GL_TRUE; 2662bf215546Sopenharmony_ci } 2663bf215546Sopenharmony_ci 2664bf215546Sopenharmony_ci if (stImage->pt->target == PIPE_TEXTURE_1D_ARRAY) { 2665bf215546Sopenharmony_ci dstRowStride = transfer->layer_stride; 2666bf215546Sopenharmony_ci } 2667bf215546Sopenharmony_ci else { 2668bf215546Sopenharmony_ci dstRowStride = transfer->stride; 2669bf215546Sopenharmony_ci } 2670bf215546Sopenharmony_ci 2671bf215546Sopenharmony_ci /* get float/RGBA image from framebuffer */ 2672bf215546Sopenharmony_ci /* XXX this usually involves a lot of int/float conversion. 2673bf215546Sopenharmony_ci * try to avoid that someday. 2674bf215546Sopenharmony_ci */ 2675bf215546Sopenharmony_ci pipe_get_tile_rgba(src_trans, map, 0, 0, width, height, 2676bf215546Sopenharmony_ci util_format_linear(rb->texture->format), 2677bf215546Sopenharmony_ci tempSrc); 2678bf215546Sopenharmony_ci 2679bf215546Sopenharmony_ci /* Store into texture memory. 2680bf215546Sopenharmony_ci * Note that this does some special things such as pixel transfer 2681bf215546Sopenharmony_ci * ops and format conversion. In particular, if the dest tex format 2682bf215546Sopenharmony_ci * is actually RGBA but the user created the texture as GL_RGB we 2683bf215546Sopenharmony_ci * need to fill-in/override the alpha channel with 1.0. 2684bf215546Sopenharmony_ci */ 2685bf215546Sopenharmony_ci _mesa_texstore(ctx, dims, 2686bf215546Sopenharmony_ci texImage->_BaseFormat, 2687bf215546Sopenharmony_ci texImage->TexFormat, 2688bf215546Sopenharmony_ci dstRowStride, 2689bf215546Sopenharmony_ci &texDest, 2690bf215546Sopenharmony_ci width, height, 1, 2691bf215546Sopenharmony_ci GL_RGBA, GL_FLOAT, tempSrc, /* src */ 2692bf215546Sopenharmony_ci &unpack); 2693bf215546Sopenharmony_ci } 2694bf215546Sopenharmony_ci else { 2695bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); 2696bf215546Sopenharmony_ci } 2697bf215546Sopenharmony_ci 2698bf215546Sopenharmony_ci free(tempSrc); 2699bf215546Sopenharmony_ci } 2700bf215546Sopenharmony_ci 2701bf215546Sopenharmony_ci st_texture_image_unmap(st, stImage, slice); 2702bf215546Sopenharmony_cierr: 2703bf215546Sopenharmony_ci pipe->texture_unmap(pipe, src_trans); 2704bf215546Sopenharmony_ci} 2705bf215546Sopenharmony_ci 2706bf215546Sopenharmony_ci 2707bf215546Sopenharmony_cistatic bool 2708bf215546Sopenharmony_cist_can_copyteximage_using_blit(const struct gl_texture_image *texImage, 2709bf215546Sopenharmony_ci const struct gl_renderbuffer *rb) 2710bf215546Sopenharmony_ci{ 2711bf215546Sopenharmony_ci GLenum tex_baseformat = _mesa_get_format_base_format(texImage->TexFormat); 2712bf215546Sopenharmony_ci 2713bf215546Sopenharmony_ci /* We don't blit to a teximage where the GL base format doesn't match the 2714bf215546Sopenharmony_ci * texture's chosen format, except in the case of a GL_RGB texture 2715bf215546Sopenharmony_ci * represented with GL_RGBA (where the alpha channel is just being 2716bf215546Sopenharmony_ci * dropped). 2717bf215546Sopenharmony_ci */ 2718bf215546Sopenharmony_ci if (texImage->_BaseFormat != tex_baseformat && 2719bf215546Sopenharmony_ci ((texImage->_BaseFormat != GL_RGB || tex_baseformat != GL_RGBA))) { 2720bf215546Sopenharmony_ci return false; 2721bf215546Sopenharmony_ci } 2722bf215546Sopenharmony_ci 2723bf215546Sopenharmony_ci /* We can't blit from a RB where the GL base format doesn't match the RB's 2724bf215546Sopenharmony_ci * chosen format (for example, GL RGB or ALPHA with rb->Format of an RGBA 2725bf215546Sopenharmony_ci * type, because the other channels will be undefined). 2726bf215546Sopenharmony_ci */ 2727bf215546Sopenharmony_ci if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) 2728bf215546Sopenharmony_ci return false; 2729bf215546Sopenharmony_ci 2730bf215546Sopenharmony_ci return true; 2731bf215546Sopenharmony_ci} 2732bf215546Sopenharmony_ci 2733bf215546Sopenharmony_ci 2734bf215546Sopenharmony_ci/** 2735bf215546Sopenharmony_ci * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. 2736bf215546Sopenharmony_ci * Note that the region to copy has already been clipped so we know we 2737bf215546Sopenharmony_ci * won't read from outside the source renderbuffer's bounds. 2738bf215546Sopenharmony_ci * 2739bf215546Sopenharmony_ci * Note: srcY=0=Bottom of renderbuffer (GL convention) 2740bf215546Sopenharmony_ci */ 2741bf215546Sopenharmony_civoid 2742bf215546Sopenharmony_cist_CopyTexSubImage(struct gl_context *ctx, GLuint dims, 2743bf215546Sopenharmony_ci struct gl_texture_image *texImage, 2744bf215546Sopenharmony_ci GLint destX, GLint destY, GLint slice, 2745bf215546Sopenharmony_ci struct gl_renderbuffer *rb, 2746bf215546Sopenharmony_ci GLint srcX, GLint srcY, GLsizei width, GLsizei height) 2747bf215546Sopenharmony_ci{ 2748bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 2749bf215546Sopenharmony_ci struct gl_texture_object *stObj = texImage->TexObject; 2750bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2751bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 2752bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 2753bf215546Sopenharmony_ci struct pipe_blit_info blit; 2754bf215546Sopenharmony_ci enum pipe_format dst_format; 2755bf215546Sopenharmony_ci GLboolean do_flip = (_mesa_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); 2756bf215546Sopenharmony_ci unsigned bind; 2757bf215546Sopenharmony_ci GLint srcY0, srcY1; 2758bf215546Sopenharmony_ci 2759bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 2760bf215546Sopenharmony_ci st_invalidate_readpix_cache(st); 2761bf215546Sopenharmony_ci 2762bf215546Sopenharmony_ci assert(!_mesa_is_format_etc2(texImage->TexFormat) && 2763bf215546Sopenharmony_ci !_mesa_is_format_astc_2d(texImage->TexFormat) && 2764bf215546Sopenharmony_ci texImage->TexFormat != MESA_FORMAT_ETC1_RGB8); 2765bf215546Sopenharmony_ci 2766bf215546Sopenharmony_ci if (!rb || !rb->surface || !stImage->pt) { 2767bf215546Sopenharmony_ci debug_printf("%s: null rb or stImage\n", __func__); 2768bf215546Sopenharmony_ci return; 2769bf215546Sopenharmony_ci } 2770bf215546Sopenharmony_ci 2771bf215546Sopenharmony_ci if (_mesa_texstore_needs_transfer_ops(ctx, texImage->_BaseFormat, 2772bf215546Sopenharmony_ci texImage->TexFormat)) { 2773bf215546Sopenharmony_ci goto fallback; 2774bf215546Sopenharmony_ci } 2775bf215546Sopenharmony_ci 2776bf215546Sopenharmony_ci if (!st_can_copyteximage_using_blit(texImage, rb)) { 2777bf215546Sopenharmony_ci goto fallback; 2778bf215546Sopenharmony_ci } 2779bf215546Sopenharmony_ci 2780bf215546Sopenharmony_ci /* Choose the destination format to match the TexImage behavior. */ 2781bf215546Sopenharmony_ci dst_format = util_format_linear(stImage->pt->format); 2782bf215546Sopenharmony_ci dst_format = util_format_luminance_to_red(dst_format); 2783bf215546Sopenharmony_ci dst_format = util_format_intensity_to_red(dst_format); 2784bf215546Sopenharmony_ci 2785bf215546Sopenharmony_ci /* See if the destination format is supported. */ 2786bf215546Sopenharmony_ci if (texImage->_BaseFormat == GL_DEPTH_STENCIL || 2787bf215546Sopenharmony_ci texImage->_BaseFormat == GL_DEPTH_COMPONENT) { 2788bf215546Sopenharmony_ci bind = PIPE_BIND_DEPTH_STENCIL; 2789bf215546Sopenharmony_ci } 2790bf215546Sopenharmony_ci else { 2791bf215546Sopenharmony_ci bind = PIPE_BIND_RENDER_TARGET; 2792bf215546Sopenharmony_ci } 2793bf215546Sopenharmony_ci 2794bf215546Sopenharmony_ci if (!dst_format || 2795bf215546Sopenharmony_ci !screen->is_format_supported(screen, dst_format, stImage->pt->target, 2796bf215546Sopenharmony_ci stImage->pt->nr_samples, 2797bf215546Sopenharmony_ci stImage->pt->nr_storage_samples, bind)) { 2798bf215546Sopenharmony_ci goto fallback; 2799bf215546Sopenharmony_ci } 2800bf215546Sopenharmony_ci 2801bf215546Sopenharmony_ci /* Y flipping for the main framebuffer. */ 2802bf215546Sopenharmony_ci if (do_flip) { 2803bf215546Sopenharmony_ci srcY1 = rb->Height - srcY - height; 2804bf215546Sopenharmony_ci srcY0 = srcY1 + height; 2805bf215546Sopenharmony_ci } 2806bf215546Sopenharmony_ci else { 2807bf215546Sopenharmony_ci srcY0 = srcY; 2808bf215546Sopenharmony_ci srcY1 = srcY0 + height; 2809bf215546Sopenharmony_ci } 2810bf215546Sopenharmony_ci 2811bf215546Sopenharmony_ci /* Blit the texture. 2812bf215546Sopenharmony_ci * This supports flipping, format conversions, and downsampling. 2813bf215546Sopenharmony_ci */ 2814bf215546Sopenharmony_ci memset(&blit, 0, sizeof(blit)); 2815bf215546Sopenharmony_ci blit.src.resource = rb->texture; 2816bf215546Sopenharmony_ci blit.src.format = util_format_linear(rb->surface->format); 2817bf215546Sopenharmony_ci blit.src.level = rb->surface->u.tex.level; 2818bf215546Sopenharmony_ci blit.src.box.x = srcX; 2819bf215546Sopenharmony_ci blit.src.box.y = srcY0; 2820bf215546Sopenharmony_ci blit.src.box.z = rb->surface->u.tex.first_layer; 2821bf215546Sopenharmony_ci blit.src.box.width = width; 2822bf215546Sopenharmony_ci blit.src.box.height = srcY1 - srcY0; 2823bf215546Sopenharmony_ci blit.src.box.depth = 1; 2824bf215546Sopenharmony_ci blit.dst.resource = stImage->pt; 2825bf215546Sopenharmony_ci blit.dst.format = dst_format; 2826bf215546Sopenharmony_ci blit.dst.level = stObj->pt != stImage->pt 2827bf215546Sopenharmony_ci ? 0 : texImage->Level + texImage->TexObject->Attrib.MinLevel; 2828bf215546Sopenharmony_ci blit.dst.box.x = destX; 2829bf215546Sopenharmony_ci blit.dst.box.y = destY; 2830bf215546Sopenharmony_ci blit.dst.box.z = stImage->Face + slice + 2831bf215546Sopenharmony_ci texImage->TexObject->Attrib.MinLayer; 2832bf215546Sopenharmony_ci blit.dst.box.width = width; 2833bf215546Sopenharmony_ci blit.dst.box.height = height; 2834bf215546Sopenharmony_ci blit.dst.box.depth = 1; 2835bf215546Sopenharmony_ci blit.mask = st_get_blit_mask(rb->_BaseFormat, texImage->_BaseFormat); 2836bf215546Sopenharmony_ci blit.filter = PIPE_TEX_FILTER_NEAREST; 2837bf215546Sopenharmony_ci pipe->blit(pipe, &blit); 2838bf215546Sopenharmony_ci return; 2839bf215546Sopenharmony_ci 2840bf215546Sopenharmony_cifallback: 2841bf215546Sopenharmony_ci /* software fallback */ 2842bf215546Sopenharmony_ci fallback_copy_texsubimage(ctx, 2843bf215546Sopenharmony_ci rb, stImage, texImage->_BaseFormat, 2844bf215546Sopenharmony_ci destX, destY, slice, 2845bf215546Sopenharmony_ci srcX, srcY, width, height); 2846bf215546Sopenharmony_ci} 2847bf215546Sopenharmony_ci 2848bf215546Sopenharmony_ci 2849bf215546Sopenharmony_ci/** 2850bf215546Sopenharmony_ci * Copy image data from stImage into the texture object 'stObj' at level 2851bf215546Sopenharmony_ci * 'dstLevel'. 2852bf215546Sopenharmony_ci */ 2853bf215546Sopenharmony_cistatic void 2854bf215546Sopenharmony_cicopy_image_data_to_texture(struct st_context *st, 2855bf215546Sopenharmony_ci struct gl_texture_object *stObj, 2856bf215546Sopenharmony_ci GLuint dstLevel, 2857bf215546Sopenharmony_ci struct gl_texture_image *stImage) 2858bf215546Sopenharmony_ci{ 2859bf215546Sopenharmony_ci /* debug checks */ 2860bf215546Sopenharmony_ci { 2861bf215546Sopenharmony_ci ASSERTED const struct gl_texture_image *dstImage = 2862bf215546Sopenharmony_ci stObj->Image[stImage->Face][dstLevel]; 2863bf215546Sopenharmony_ci assert(dstImage); 2864bf215546Sopenharmony_ci assert(dstImage->Width == stImage->Width); 2865bf215546Sopenharmony_ci assert(dstImage->Height == stImage->Height); 2866bf215546Sopenharmony_ci assert(dstImage->Depth == stImage->Depth); 2867bf215546Sopenharmony_ci } 2868bf215546Sopenharmony_ci 2869bf215546Sopenharmony_ci if (stImage->pt) { 2870bf215546Sopenharmony_ci /* Copy potentially with the blitter: 2871bf215546Sopenharmony_ci */ 2872bf215546Sopenharmony_ci GLuint src_level; 2873bf215546Sopenharmony_ci if (stImage->pt->last_level == 0) 2874bf215546Sopenharmony_ci src_level = 0; 2875bf215546Sopenharmony_ci else 2876bf215546Sopenharmony_ci src_level = stImage->Level; 2877bf215546Sopenharmony_ci 2878bf215546Sopenharmony_ci assert(src_level <= stImage->pt->last_level); 2879bf215546Sopenharmony_ci assert(u_minify(stImage->pt->width0, src_level) == stImage->Width); 2880bf215546Sopenharmony_ci assert(stImage->pt->target == PIPE_TEXTURE_1D_ARRAY || 2881bf215546Sopenharmony_ci u_minify(stImage->pt->height0, src_level) == stImage->Height); 2882bf215546Sopenharmony_ci assert(stImage->pt->target == PIPE_TEXTURE_2D_ARRAY || 2883bf215546Sopenharmony_ci stImage->pt->target == PIPE_TEXTURE_CUBE_ARRAY || 2884bf215546Sopenharmony_ci u_minify(stImage->pt->depth0, src_level) == stImage->Depth); 2885bf215546Sopenharmony_ci 2886bf215546Sopenharmony_ci st_texture_image_copy(st->pipe, 2887bf215546Sopenharmony_ci stObj->pt, dstLevel, /* dest texture, level */ 2888bf215546Sopenharmony_ci stImage->pt, src_level, /* src texture, level */ 2889bf215546Sopenharmony_ci stImage->Face); 2890bf215546Sopenharmony_ci 2891bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, NULL); 2892bf215546Sopenharmony_ci } 2893bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, stObj->pt); 2894bf215546Sopenharmony_ci} 2895bf215546Sopenharmony_ci 2896bf215546Sopenharmony_ci 2897bf215546Sopenharmony_ci/** 2898bf215546Sopenharmony_ci * Called during state validation. When this function is finished, 2899bf215546Sopenharmony_ci * the texture object should be ready for rendering. 2900bf215546Sopenharmony_ci * \return GL_TRUE for success, GL_FALSE for failure (out of mem) 2901bf215546Sopenharmony_ci */ 2902bf215546Sopenharmony_ciGLboolean 2903bf215546Sopenharmony_cist_finalize_texture(struct gl_context *ctx, 2904bf215546Sopenharmony_ci struct pipe_context *pipe, 2905bf215546Sopenharmony_ci struct gl_texture_object *tObj, 2906bf215546Sopenharmony_ci GLuint cubeMapFace) 2907bf215546Sopenharmony_ci{ 2908bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 2909bf215546Sopenharmony_ci const GLuint nr_faces = _mesa_num_tex_faces(tObj->Target); 2910bf215546Sopenharmony_ci GLuint face; 2911bf215546Sopenharmony_ci const struct gl_texture_image *firstImage; 2912bf215546Sopenharmony_ci enum pipe_format firstImageFormat; 2913bf215546Sopenharmony_ci unsigned ptWidth; 2914bf215546Sopenharmony_ci uint16_t ptHeight, ptDepth, ptLayers, ptNumSamples; 2915bf215546Sopenharmony_ci 2916bf215546Sopenharmony_ci if (tObj->Immutable) 2917bf215546Sopenharmony_ci return GL_TRUE; 2918bf215546Sopenharmony_ci 2919bf215546Sopenharmony_ci if (tObj->_MipmapComplete) 2920bf215546Sopenharmony_ci tObj->lastLevel = tObj->_MaxLevel; 2921bf215546Sopenharmony_ci else if (tObj->_BaseComplete) 2922bf215546Sopenharmony_ci tObj->lastLevel = tObj->Attrib.BaseLevel; 2923bf215546Sopenharmony_ci 2924bf215546Sopenharmony_ci /* Skip the loop over images in the common case of no images having 2925bf215546Sopenharmony_ci * changed. But if the GL_BASE_LEVEL or GL_MAX_LEVEL change to something we 2926bf215546Sopenharmony_ci * haven't looked at, then we do need to look at those new images. 2927bf215546Sopenharmony_ci */ 2928bf215546Sopenharmony_ci if (!tObj->needs_validation && 2929bf215546Sopenharmony_ci tObj->Attrib.BaseLevel >= tObj->validated_first_level && 2930bf215546Sopenharmony_ci tObj->lastLevel <= tObj->validated_last_level) { 2931bf215546Sopenharmony_ci return GL_TRUE; 2932bf215546Sopenharmony_ci } 2933bf215546Sopenharmony_ci 2934bf215546Sopenharmony_ci /* If this texture comes from a window system, there is nothing else to do. */ 2935bf215546Sopenharmony_ci if (tObj->surface_based) { 2936bf215546Sopenharmony_ci return GL_TRUE; 2937bf215546Sopenharmony_ci } 2938bf215546Sopenharmony_ci 2939bf215546Sopenharmony_ci firstImage = st_texture_image_const(tObj->Image[cubeMapFace] 2940bf215546Sopenharmony_ci [tObj->Attrib.BaseLevel]); 2941bf215546Sopenharmony_ci if (!firstImage) 2942bf215546Sopenharmony_ci return false; 2943bf215546Sopenharmony_ci 2944bf215546Sopenharmony_ci /* If both firstImage and tObj point to a texture which can contain 2945bf215546Sopenharmony_ci * all active images, favour firstImage. Note that because of the 2946bf215546Sopenharmony_ci * completeness requirement, we know that the image dimensions 2947bf215546Sopenharmony_ci * will match. 2948bf215546Sopenharmony_ci */ 2949bf215546Sopenharmony_ci if (firstImage->pt && 2950bf215546Sopenharmony_ci firstImage->pt != tObj->pt && 2951bf215546Sopenharmony_ci (!tObj->pt || firstImage->pt->last_level >= tObj->pt->last_level)) { 2952bf215546Sopenharmony_ci pipe_resource_reference(&tObj->pt, firstImage->pt); 2953bf215546Sopenharmony_ci st_texture_release_all_sampler_views(st, tObj); 2954bf215546Sopenharmony_ci } 2955bf215546Sopenharmony_ci 2956bf215546Sopenharmony_ci /* Find gallium format for the Mesa texture */ 2957bf215546Sopenharmony_ci firstImageFormat = 2958bf215546Sopenharmony_ci st_mesa_format_to_pipe_format(st, firstImage->TexFormat); 2959bf215546Sopenharmony_ci 2960bf215546Sopenharmony_ci /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ 2961bf215546Sopenharmony_ci { 2962bf215546Sopenharmony_ci unsigned width; 2963bf215546Sopenharmony_ci uint16_t height, depth; 2964bf215546Sopenharmony_ci 2965bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(tObj->Target, 2966bf215546Sopenharmony_ci firstImage->Width2, 2967bf215546Sopenharmony_ci firstImage->Height2, 2968bf215546Sopenharmony_ci firstImage->Depth2, 2969bf215546Sopenharmony_ci &width, &height, &depth, &ptLayers); 2970bf215546Sopenharmony_ci 2971bf215546Sopenharmony_ci /* If we previously allocated a pipe texture and its sizes are 2972bf215546Sopenharmony_ci * compatible, use them. 2973bf215546Sopenharmony_ci */ 2974bf215546Sopenharmony_ci if (tObj->pt && 2975bf215546Sopenharmony_ci u_minify(tObj->pt->width0, firstImage->Level) == width && 2976bf215546Sopenharmony_ci u_minify(tObj->pt->height0, firstImage->Level) == height && 2977bf215546Sopenharmony_ci u_minify(tObj->pt->depth0, firstImage->Level) == depth) { 2978bf215546Sopenharmony_ci ptWidth = tObj->pt->width0; 2979bf215546Sopenharmony_ci ptHeight = tObj->pt->height0; 2980bf215546Sopenharmony_ci ptDepth = tObj->pt->depth0; 2981bf215546Sopenharmony_ci } else { 2982bf215546Sopenharmony_ci /* Otherwise, compute a new level=0 size that is compatible with the 2983bf215546Sopenharmony_ci * base level image. 2984bf215546Sopenharmony_ci */ 2985bf215546Sopenharmony_ci ptWidth = width > 1 ? width << firstImage->Level : 1; 2986bf215546Sopenharmony_ci ptHeight = height > 1 ? height << firstImage->Level : 1; 2987bf215546Sopenharmony_ci ptDepth = depth > 1 ? depth << firstImage->Level : 1; 2988bf215546Sopenharmony_ci 2989bf215546Sopenharmony_ci /* If the base level image is 1x1x1, we still need to ensure that the 2990bf215546Sopenharmony_ci * resulting pipe texture ends up with the required number of levels 2991bf215546Sopenharmony_ci * in total. 2992bf215546Sopenharmony_ci */ 2993bf215546Sopenharmony_ci if (ptWidth == 1 && ptHeight == 1 && ptDepth == 1) { 2994bf215546Sopenharmony_ci ptWidth <<= firstImage->Level; 2995bf215546Sopenharmony_ci 2996bf215546Sopenharmony_ci if (tObj->Target == GL_TEXTURE_CUBE_MAP || 2997bf215546Sopenharmony_ci tObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) 2998bf215546Sopenharmony_ci ptHeight = ptWidth; 2999bf215546Sopenharmony_ci } 3000bf215546Sopenharmony_ci 3001bf215546Sopenharmony_ci /* At this point, the texture may be incomplete (mismatched cube 3002bf215546Sopenharmony_ci * face sizes, for example). If that's the case, give up, but 3003bf215546Sopenharmony_ci * don't return GL_FALSE as that would raise an incorrect 3004bf215546Sopenharmony_ci * GL_OUT_OF_MEMORY error. See Piglit fbo-incomplete-texture-03 test. 3005bf215546Sopenharmony_ci */ 3006bf215546Sopenharmony_ci if (!tObj->_BaseComplete) { 3007bf215546Sopenharmony_ci _mesa_test_texobj_completeness(ctx, tObj); 3008bf215546Sopenharmony_ci if (!tObj->_BaseComplete) { 3009bf215546Sopenharmony_ci return TRUE; 3010bf215546Sopenharmony_ci } 3011bf215546Sopenharmony_ci } 3012bf215546Sopenharmony_ci } 3013bf215546Sopenharmony_ci 3014bf215546Sopenharmony_ci ptNumSamples = firstImage->NumSamples; 3015bf215546Sopenharmony_ci } 3016bf215546Sopenharmony_ci 3017bf215546Sopenharmony_ci /* If we already have a gallium texture, check that it matches the texture 3018bf215546Sopenharmony_ci * object's format, target, size, num_levels, etc. 3019bf215546Sopenharmony_ci */ 3020bf215546Sopenharmony_ci if (tObj->pt) { 3021bf215546Sopenharmony_ci if (tObj->pt->target != gl_target_to_pipe(tObj->Target) || 3022bf215546Sopenharmony_ci tObj->pt->format != firstImageFormat || 3023bf215546Sopenharmony_ci tObj->pt->last_level < tObj->lastLevel || 3024bf215546Sopenharmony_ci tObj->pt->width0 != ptWidth || 3025bf215546Sopenharmony_ci tObj->pt->height0 != ptHeight || 3026bf215546Sopenharmony_ci tObj->pt->depth0 != ptDepth || 3027bf215546Sopenharmony_ci tObj->pt->nr_samples != ptNumSamples || 3028bf215546Sopenharmony_ci tObj->pt->array_size != ptLayers) 3029bf215546Sopenharmony_ci { 3030bf215546Sopenharmony_ci /* The gallium texture does not match the Mesa texture so delete the 3031bf215546Sopenharmony_ci * gallium texture now. We'll make a new one below. 3032bf215546Sopenharmony_ci */ 3033bf215546Sopenharmony_ci pipe_resource_reference(&tObj->pt, NULL); 3034bf215546Sopenharmony_ci st_texture_release_all_sampler_views(st, tObj); 3035bf215546Sopenharmony_ci st->dirty |= ST_NEW_FRAMEBUFFER; 3036bf215546Sopenharmony_ci } 3037bf215546Sopenharmony_ci } 3038bf215546Sopenharmony_ci 3039bf215546Sopenharmony_ci /* May need to create a new gallium texture: 3040bf215546Sopenharmony_ci */ 3041bf215546Sopenharmony_ci if (!tObj->pt) { 3042bf215546Sopenharmony_ci GLuint bindings = default_bindings(st, firstImageFormat); 3043bf215546Sopenharmony_ci 3044bf215546Sopenharmony_ci tObj->pt = st_texture_create(st, 3045bf215546Sopenharmony_ci gl_target_to_pipe(tObj->Target), 3046bf215546Sopenharmony_ci firstImageFormat, 3047bf215546Sopenharmony_ci tObj->lastLevel, 3048bf215546Sopenharmony_ci ptWidth, 3049bf215546Sopenharmony_ci ptHeight, 3050bf215546Sopenharmony_ci ptDepth, 3051bf215546Sopenharmony_ci ptLayers, ptNumSamples, 3052bf215546Sopenharmony_ci bindings, 3053bf215546Sopenharmony_ci false); 3054bf215546Sopenharmony_ci 3055bf215546Sopenharmony_ci if (!tObj->pt) { 3056bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 3057bf215546Sopenharmony_ci return GL_FALSE; 3058bf215546Sopenharmony_ci } 3059bf215546Sopenharmony_ci } 3060bf215546Sopenharmony_ci 3061bf215546Sopenharmony_ci /* Pull in any images not in the object's texture: 3062bf215546Sopenharmony_ci */ 3063bf215546Sopenharmony_ci for (face = 0; face < nr_faces; face++) { 3064bf215546Sopenharmony_ci GLuint level; 3065bf215546Sopenharmony_ci for (level = tObj->Attrib.BaseLevel; level <= tObj->lastLevel; level++) { 3066bf215546Sopenharmony_ci struct gl_texture_image *stImage = 3067bf215546Sopenharmony_ci tObj->Image[face][level]; 3068bf215546Sopenharmony_ci 3069bf215546Sopenharmony_ci /* Need to import images in main memory or held in other textures. 3070bf215546Sopenharmony_ci */ 3071bf215546Sopenharmony_ci if (stImage && tObj->pt != stImage->pt) { 3072bf215546Sopenharmony_ci GLuint height; 3073bf215546Sopenharmony_ci GLuint depth; 3074bf215546Sopenharmony_ci 3075bf215546Sopenharmony_ci if (tObj->Target != GL_TEXTURE_1D_ARRAY) 3076bf215546Sopenharmony_ci height = u_minify(ptHeight, level); 3077bf215546Sopenharmony_ci else 3078bf215546Sopenharmony_ci height = ptLayers; 3079bf215546Sopenharmony_ci 3080bf215546Sopenharmony_ci if (tObj->Target == GL_TEXTURE_3D) 3081bf215546Sopenharmony_ci depth = u_minify(ptDepth, level); 3082bf215546Sopenharmony_ci else if (tObj->Target == GL_TEXTURE_CUBE_MAP) 3083bf215546Sopenharmony_ci depth = 1; 3084bf215546Sopenharmony_ci else 3085bf215546Sopenharmony_ci depth = ptLayers; 3086bf215546Sopenharmony_ci 3087bf215546Sopenharmony_ci if (level == 0 || 3088bf215546Sopenharmony_ci (stImage->Width == u_minify(ptWidth, level) && 3089bf215546Sopenharmony_ci stImage->Height == height && 3090bf215546Sopenharmony_ci stImage->Depth == depth)) { 3091bf215546Sopenharmony_ci /* src image fits expected dest mipmap level size */ 3092bf215546Sopenharmony_ci copy_image_data_to_texture(st, tObj, level, stImage); 3093bf215546Sopenharmony_ci } 3094bf215546Sopenharmony_ci } 3095bf215546Sopenharmony_ci } 3096bf215546Sopenharmony_ci } 3097bf215546Sopenharmony_ci 3098bf215546Sopenharmony_ci tObj->validated_first_level = tObj->Attrib.BaseLevel; 3099bf215546Sopenharmony_ci tObj->validated_last_level = tObj->lastLevel; 3100bf215546Sopenharmony_ci tObj->needs_validation = false; 3101bf215546Sopenharmony_ci 3102bf215546Sopenharmony_ci return GL_TRUE; 3103bf215546Sopenharmony_ci} 3104bf215546Sopenharmony_ci 3105bf215546Sopenharmony_ci 3106bf215546Sopenharmony_ci/** 3107bf215546Sopenharmony_ci * Allocate a new pipe_resource object 3108bf215546Sopenharmony_ci * width0, height0, depth0 are the dimensions of the level 0 image 3109bf215546Sopenharmony_ci * (the highest resolution). last_level indicates how many mipmap levels 3110bf215546Sopenharmony_ci * to allocate storage for. For non-mipmapped textures, this will be zero. 3111bf215546Sopenharmony_ci */ 3112bf215546Sopenharmony_cistatic struct pipe_resource * 3113bf215546Sopenharmony_cist_texture_create_from_memory(struct st_context *st, 3114bf215546Sopenharmony_ci struct gl_memory_object *memObj, 3115bf215546Sopenharmony_ci GLuint64 offset, 3116bf215546Sopenharmony_ci enum pipe_texture_target target, 3117bf215546Sopenharmony_ci enum pipe_format format, 3118bf215546Sopenharmony_ci GLuint last_level, 3119bf215546Sopenharmony_ci GLuint width0, 3120bf215546Sopenharmony_ci GLuint height0, 3121bf215546Sopenharmony_ci GLuint depth0, 3122bf215546Sopenharmony_ci GLuint layers, 3123bf215546Sopenharmony_ci GLuint nr_samples, 3124bf215546Sopenharmony_ci GLuint bind) 3125bf215546Sopenharmony_ci{ 3126bf215546Sopenharmony_ci struct pipe_resource pt, *newtex; 3127bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 3128bf215546Sopenharmony_ci 3129bf215546Sopenharmony_ci assert(target < PIPE_MAX_TEXTURE_TYPES); 3130bf215546Sopenharmony_ci assert(width0 > 0); 3131bf215546Sopenharmony_ci assert(height0 > 0); 3132bf215546Sopenharmony_ci assert(depth0 > 0); 3133bf215546Sopenharmony_ci if (target == PIPE_TEXTURE_CUBE) 3134bf215546Sopenharmony_ci assert(layers == 6); 3135bf215546Sopenharmony_ci 3136bf215546Sopenharmony_ci DBG("%s target %d format %s last_level %d\n", __func__, 3137bf215546Sopenharmony_ci (int) target, util_format_name(format), last_level); 3138bf215546Sopenharmony_ci 3139bf215546Sopenharmony_ci assert(format); 3140bf215546Sopenharmony_ci assert(screen->is_format_supported(screen, format, target, 0, 0, 3141bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)); 3142bf215546Sopenharmony_ci 3143bf215546Sopenharmony_ci memset(&pt, 0, sizeof(pt)); 3144bf215546Sopenharmony_ci pt.target = target; 3145bf215546Sopenharmony_ci pt.format = format; 3146bf215546Sopenharmony_ci pt.last_level = last_level; 3147bf215546Sopenharmony_ci pt.width0 = width0; 3148bf215546Sopenharmony_ci pt.height0 = height0; 3149bf215546Sopenharmony_ci pt.depth0 = depth0; 3150bf215546Sopenharmony_ci pt.array_size = layers; 3151bf215546Sopenharmony_ci pt.usage = PIPE_USAGE_DEFAULT; 3152bf215546Sopenharmony_ci pt.bind = bind; 3153bf215546Sopenharmony_ci /* only set this for OpenGL textures, not renderbuffers */ 3154bf215546Sopenharmony_ci pt.flags = PIPE_RESOURCE_FLAG_TEXTURING_MORE_LIKELY; 3155bf215546Sopenharmony_ci if (memObj->TextureTiling == GL_LINEAR_TILING_EXT) 3156bf215546Sopenharmony_ci pt.bind |= PIPE_BIND_LINEAR; 3157bf215546Sopenharmony_ci 3158bf215546Sopenharmony_ci pt.nr_samples = nr_samples; 3159bf215546Sopenharmony_ci pt.nr_storage_samples = nr_samples; 3160bf215546Sopenharmony_ci 3161bf215546Sopenharmony_ci newtex = screen->resource_from_memobj(screen, &pt, memObj->memory, offset); 3162bf215546Sopenharmony_ci 3163bf215546Sopenharmony_ci assert(!newtex || pipe_is_referenced(&newtex->reference)); 3164bf215546Sopenharmony_ci 3165bf215546Sopenharmony_ci return newtex; 3166bf215546Sopenharmony_ci} 3167bf215546Sopenharmony_ci 3168bf215546Sopenharmony_ci 3169bf215546Sopenharmony_ci/** 3170bf215546Sopenharmony_ci * Allocate texture memory for a whole mipmap stack. 3171bf215546Sopenharmony_ci * Note: for multisample textures if the requested sample count is not 3172bf215546Sopenharmony_ci * supported, we search for the next higher supported sample count. 3173bf215546Sopenharmony_ci */ 3174bf215546Sopenharmony_cistatic GLboolean 3175bf215546Sopenharmony_cist_texture_storage(struct gl_context *ctx, 3176bf215546Sopenharmony_ci struct gl_texture_object *texObj, 3177bf215546Sopenharmony_ci GLsizei levels, GLsizei width, 3178bf215546Sopenharmony_ci GLsizei height, GLsizei depth, 3179bf215546Sopenharmony_ci struct gl_memory_object *memObj, 3180bf215546Sopenharmony_ci GLuint64 offset) 3181bf215546Sopenharmony_ci{ 3182bf215546Sopenharmony_ci const GLuint numFaces = _mesa_num_tex_faces(texObj->Target); 3183bf215546Sopenharmony_ci struct gl_texture_image *texImage = texObj->Image[0][0]; 3184bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3185bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 3186bf215546Sopenharmony_ci unsigned ptWidth, bindings; 3187bf215546Sopenharmony_ci uint16_t ptHeight, ptDepth, ptLayers; 3188bf215546Sopenharmony_ci enum pipe_format fmt; 3189bf215546Sopenharmony_ci GLint level; 3190bf215546Sopenharmony_ci GLuint num_samples = texImage->NumSamples; 3191bf215546Sopenharmony_ci 3192bf215546Sopenharmony_ci assert(levels > 0); 3193bf215546Sopenharmony_ci 3194bf215546Sopenharmony_ci texObj->lastLevel = levels - 1; 3195bf215546Sopenharmony_ci 3196bf215546Sopenharmony_ci fmt = st_mesa_format_to_pipe_format(st, texImage->TexFormat); 3197bf215546Sopenharmony_ci 3198bf215546Sopenharmony_ci bindings = default_bindings(st, fmt); 3199bf215546Sopenharmony_ci 3200bf215546Sopenharmony_ci if (memObj) { 3201bf215546Sopenharmony_ci memObj->TextureTiling = texObj->TextureTiling; 3202bf215546Sopenharmony_ci bindings |= PIPE_BIND_SHARED; 3203bf215546Sopenharmony_ci } 3204bf215546Sopenharmony_ci 3205bf215546Sopenharmony_ci if (num_samples > 0) { 3206bf215546Sopenharmony_ci /* Find msaa sample count which is actually supported. For example, 3207bf215546Sopenharmony_ci * if the user requests 1x but only 4x or 8x msaa is supported, we'll 3208bf215546Sopenharmony_ci * choose 4x here. 3209bf215546Sopenharmony_ci */ 3210bf215546Sopenharmony_ci enum pipe_texture_target ptarget = gl_target_to_pipe(texObj->Target); 3211bf215546Sopenharmony_ci boolean found = FALSE; 3212bf215546Sopenharmony_ci 3213bf215546Sopenharmony_ci if (ctx->Const.MaxSamples > 1 && num_samples == 1) { 3214bf215546Sopenharmony_ci /* don't try num_samples = 1 with drivers that support real msaa */ 3215bf215546Sopenharmony_ci num_samples = 2; 3216bf215546Sopenharmony_ci } 3217bf215546Sopenharmony_ci 3218bf215546Sopenharmony_ci for (; num_samples <= ctx->Const.MaxSamples; num_samples++) { 3219bf215546Sopenharmony_ci if (screen->is_format_supported(screen, fmt, ptarget, 3220bf215546Sopenharmony_ci num_samples, num_samples, 3221bf215546Sopenharmony_ci PIPE_BIND_SAMPLER_VIEW)) { 3222bf215546Sopenharmony_ci /* Update the sample count in gl_texture_image as well. */ 3223bf215546Sopenharmony_ci texImage->NumSamples = num_samples; 3224bf215546Sopenharmony_ci found = TRUE; 3225bf215546Sopenharmony_ci break; 3226bf215546Sopenharmony_ci } 3227bf215546Sopenharmony_ci } 3228bf215546Sopenharmony_ci 3229bf215546Sopenharmony_ci if (!found) { 3230bf215546Sopenharmony_ci return GL_FALSE; 3231bf215546Sopenharmony_ci } 3232bf215546Sopenharmony_ci } 3233bf215546Sopenharmony_ci 3234bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(texObj->Target, 3235bf215546Sopenharmony_ci width, height, depth, 3236bf215546Sopenharmony_ci &ptWidth, &ptHeight, &ptDepth, &ptLayers); 3237bf215546Sopenharmony_ci 3238bf215546Sopenharmony_ci pipe_resource_reference(&texObj->pt, NULL); 3239bf215546Sopenharmony_ci 3240bf215546Sopenharmony_ci if (memObj) { 3241bf215546Sopenharmony_ci texObj->pt = st_texture_create_from_memory(st, 3242bf215546Sopenharmony_ci memObj, 3243bf215546Sopenharmony_ci offset, 3244bf215546Sopenharmony_ci gl_target_to_pipe(texObj->Target), 3245bf215546Sopenharmony_ci fmt, 3246bf215546Sopenharmony_ci levels - 1, 3247bf215546Sopenharmony_ci ptWidth, 3248bf215546Sopenharmony_ci ptHeight, 3249bf215546Sopenharmony_ci ptDepth, 3250bf215546Sopenharmony_ci ptLayers, num_samples, 3251bf215546Sopenharmony_ci bindings); 3252bf215546Sopenharmony_ci } 3253bf215546Sopenharmony_ci else { 3254bf215546Sopenharmony_ci texObj->pt = st_texture_create(st, 3255bf215546Sopenharmony_ci gl_target_to_pipe(texObj->Target), 3256bf215546Sopenharmony_ci fmt, 3257bf215546Sopenharmony_ci levels - 1, 3258bf215546Sopenharmony_ci ptWidth, 3259bf215546Sopenharmony_ci ptHeight, 3260bf215546Sopenharmony_ci ptDepth, 3261bf215546Sopenharmony_ci ptLayers, num_samples, 3262bf215546Sopenharmony_ci bindings, 3263bf215546Sopenharmony_ci texObj->IsSparse); 3264bf215546Sopenharmony_ci } 3265bf215546Sopenharmony_ci 3266bf215546Sopenharmony_ci if (!texObj->pt) 3267bf215546Sopenharmony_ci return GL_FALSE; 3268bf215546Sopenharmony_ci 3269bf215546Sopenharmony_ci /* Set image resource pointers */ 3270bf215546Sopenharmony_ci for (level = 0; level < levels; level++) { 3271bf215546Sopenharmony_ci GLuint face; 3272bf215546Sopenharmony_ci for (face = 0; face < numFaces; face++) { 3273bf215546Sopenharmony_ci struct gl_texture_image *stImage = 3274bf215546Sopenharmony_ci texObj->Image[face][level]; 3275bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, texObj->pt); 3276bf215546Sopenharmony_ci 3277bf215546Sopenharmony_ci compressed_tex_fallback_allocate(st, stImage); 3278bf215546Sopenharmony_ci } 3279bf215546Sopenharmony_ci } 3280bf215546Sopenharmony_ci 3281bf215546Sopenharmony_ci /* Update gl_texture_object for texture parameter query. */ 3282bf215546Sopenharmony_ci texObj->NumSparseLevels = texObj->pt->nr_sparse_levels; 3283bf215546Sopenharmony_ci 3284bf215546Sopenharmony_ci /* The texture is in a validated state, so no need to check later. */ 3285bf215546Sopenharmony_ci texObj->needs_validation = false; 3286bf215546Sopenharmony_ci texObj->validated_first_level = 0; 3287bf215546Sopenharmony_ci texObj->validated_last_level = levels - 1; 3288bf215546Sopenharmony_ci 3289bf215546Sopenharmony_ci return GL_TRUE; 3290bf215546Sopenharmony_ci} 3291bf215546Sopenharmony_ci 3292bf215546Sopenharmony_ci/** 3293bf215546Sopenharmony_ci * Called via ctx->Driver.AllocTextureStorage() to allocate texture memory 3294bf215546Sopenharmony_ci * for a whole mipmap stack. 3295bf215546Sopenharmony_ci */ 3296bf215546Sopenharmony_ciGLboolean 3297bf215546Sopenharmony_cist_AllocTextureStorage(struct gl_context *ctx, 3298bf215546Sopenharmony_ci struct gl_texture_object *texObj, 3299bf215546Sopenharmony_ci GLsizei levels, GLsizei width, 3300bf215546Sopenharmony_ci GLsizei height, GLsizei depth) 3301bf215546Sopenharmony_ci{ 3302bf215546Sopenharmony_ci return st_texture_storage(ctx, texObj, levels, 3303bf215546Sopenharmony_ci width, height, depth, 3304bf215546Sopenharmony_ci NULL, 0); 3305bf215546Sopenharmony_ci} 3306bf215546Sopenharmony_ci 3307bf215546Sopenharmony_ci 3308bf215546Sopenharmony_ciGLboolean 3309bf215546Sopenharmony_cist_TestProxyTexImage(struct gl_context *ctx, GLenum target, 3310bf215546Sopenharmony_ci GLuint numLevels, GLint level, 3311bf215546Sopenharmony_ci mesa_format format, GLuint numSamples, 3312bf215546Sopenharmony_ci GLint width, GLint height, GLint depth) 3313bf215546Sopenharmony_ci{ 3314bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3315bf215546Sopenharmony_ci 3316bf215546Sopenharmony_ci if (width == 0 || height == 0 || depth == 0) { 3317bf215546Sopenharmony_ci /* zero-sized images are legal, and always fit! */ 3318bf215546Sopenharmony_ci return GL_TRUE; 3319bf215546Sopenharmony_ci } 3320bf215546Sopenharmony_ci 3321bf215546Sopenharmony_ci if (st->screen->can_create_resource) { 3322bf215546Sopenharmony_ci /* Ask the gallium driver if the texture is too large */ 3323bf215546Sopenharmony_ci struct gl_texture_object *texObj = 3324bf215546Sopenharmony_ci _mesa_get_current_tex_object(ctx, target); 3325bf215546Sopenharmony_ci struct pipe_resource pt; 3326bf215546Sopenharmony_ci 3327bf215546Sopenharmony_ci /* Setup the pipe_resource object 3328bf215546Sopenharmony_ci */ 3329bf215546Sopenharmony_ci memset(&pt, 0, sizeof(pt)); 3330bf215546Sopenharmony_ci 3331bf215546Sopenharmony_ci pt.target = gl_target_to_pipe(target); 3332bf215546Sopenharmony_ci pt.format = st_mesa_format_to_pipe_format(st, format); 3333bf215546Sopenharmony_ci pt.nr_samples = numSamples; 3334bf215546Sopenharmony_ci pt.nr_storage_samples = numSamples; 3335bf215546Sopenharmony_ci 3336bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(target, 3337bf215546Sopenharmony_ci width, height, depth, 3338bf215546Sopenharmony_ci &pt.width0, &pt.height0, 3339bf215546Sopenharmony_ci &pt.depth0, &pt.array_size); 3340bf215546Sopenharmony_ci 3341bf215546Sopenharmony_ci if (numLevels > 0) { 3342bf215546Sopenharmony_ci /* For immutable textures we know the final number of mip levels */ 3343bf215546Sopenharmony_ci pt.last_level = numLevels - 1; 3344bf215546Sopenharmony_ci } 3345bf215546Sopenharmony_ci else if (level == 0 && (texObj->Sampler.Attrib.MinFilter == GL_LINEAR || 3346bf215546Sopenharmony_ci texObj->Sampler.Attrib.MinFilter == GL_NEAREST)) { 3347bf215546Sopenharmony_ci /* assume just one mipmap level */ 3348bf215546Sopenharmony_ci pt.last_level = 0; 3349bf215546Sopenharmony_ci } 3350bf215546Sopenharmony_ci else { 3351bf215546Sopenharmony_ci /* assume a full set of mipmaps */ 3352bf215546Sopenharmony_ci pt.last_level = util_logbase2(MAX4(width, height, depth, 0)); 3353bf215546Sopenharmony_ci } 3354bf215546Sopenharmony_ci 3355bf215546Sopenharmony_ci return st->screen->can_create_resource(st->screen, &pt); 3356bf215546Sopenharmony_ci } 3357bf215546Sopenharmony_ci else { 3358bf215546Sopenharmony_ci /* Use core Mesa fallback */ 3359bf215546Sopenharmony_ci return _mesa_test_proxy_teximage(ctx, target, numLevels, level, format, 3360bf215546Sopenharmony_ci numSamples, width, height, depth); 3361bf215546Sopenharmony_ci } 3362bf215546Sopenharmony_ci} 3363bf215546Sopenharmony_ci 3364bf215546Sopenharmony_ciGLboolean 3365bf215546Sopenharmony_cist_TextureView(struct gl_context *ctx, 3366bf215546Sopenharmony_ci struct gl_texture_object *texObj, 3367bf215546Sopenharmony_ci struct gl_texture_object *origTexObj) 3368bf215546Sopenharmony_ci{ 3369bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3370bf215546Sopenharmony_ci struct gl_texture_object *orig = origTexObj; 3371bf215546Sopenharmony_ci struct gl_texture_object *tex = texObj; 3372bf215546Sopenharmony_ci struct gl_texture_image *image = texObj->Image[0][0]; 3373bf215546Sopenharmony_ci 3374bf215546Sopenharmony_ci const int numFaces = _mesa_num_tex_faces(texObj->Target); 3375bf215546Sopenharmony_ci const int numLevels = texObj->Attrib.NumLevels; 3376bf215546Sopenharmony_ci 3377bf215546Sopenharmony_ci int face; 3378bf215546Sopenharmony_ci int level; 3379bf215546Sopenharmony_ci 3380bf215546Sopenharmony_ci pipe_resource_reference(&tex->pt, orig->pt); 3381bf215546Sopenharmony_ci 3382bf215546Sopenharmony_ci /* Set image resource pointers */ 3383bf215546Sopenharmony_ci for (level = 0; level < numLevels; level++) { 3384bf215546Sopenharmony_ci for (face = 0; face < numFaces; face++) { 3385bf215546Sopenharmony_ci struct gl_texture_image *stImage = 3386bf215546Sopenharmony_ci texObj->Image[face][level]; 3387bf215546Sopenharmony_ci struct gl_texture_image *origImage = 3388bf215546Sopenharmony_ci origTexObj->Image[face][level]; 3389bf215546Sopenharmony_ci pipe_resource_reference(&stImage->pt, tex->pt); 3390bf215546Sopenharmony_ci if (origImage && 3391bf215546Sopenharmony_ci origImage->compressed_data) { 3392bf215546Sopenharmony_ci pipe_reference(NULL, 3393bf215546Sopenharmony_ci &origImage->compressed_data->reference); 3394bf215546Sopenharmony_ci stImage->compressed_data = origImage->compressed_data; 3395bf215546Sopenharmony_ci } 3396bf215546Sopenharmony_ci } 3397bf215546Sopenharmony_ci } 3398bf215546Sopenharmony_ci 3399bf215546Sopenharmony_ci tex->surface_based = GL_TRUE; 3400bf215546Sopenharmony_ci tex->surface_format = 3401bf215546Sopenharmony_ci st_mesa_format_to_pipe_format(st_context(ctx), image->TexFormat); 3402bf215546Sopenharmony_ci 3403bf215546Sopenharmony_ci tex->lastLevel = numLevels - 1; 3404bf215546Sopenharmony_ci 3405bf215546Sopenharmony_ci /* free texture sampler views. They need to be recreated when we 3406bf215546Sopenharmony_ci * change the texture view parameters. 3407bf215546Sopenharmony_ci */ 3408bf215546Sopenharmony_ci st_texture_release_all_sampler_views(st, tex); 3409bf215546Sopenharmony_ci 3410bf215546Sopenharmony_ci /* The texture is in a validated state, so no need to check later. */ 3411bf215546Sopenharmony_ci tex->needs_validation = false; 3412bf215546Sopenharmony_ci tex->validated_first_level = 0; 3413bf215546Sopenharmony_ci tex->validated_last_level = numLevels - 1; 3414bf215546Sopenharmony_ci 3415bf215546Sopenharmony_ci return GL_TRUE; 3416bf215546Sopenharmony_ci} 3417bf215546Sopenharmony_ci 3418bf215546Sopenharmony_ci 3419bf215546Sopenharmony_ci/** 3420bf215546Sopenharmony_ci * Find the mipmap level in 'pt' which matches the level described by 3421bf215546Sopenharmony_ci * 'texImage'. 3422bf215546Sopenharmony_ci */ 3423bf215546Sopenharmony_cistatic unsigned 3424bf215546Sopenharmony_cifind_mipmap_level(const struct gl_texture_image *texImage, 3425bf215546Sopenharmony_ci const struct pipe_resource *pt) 3426bf215546Sopenharmony_ci{ 3427bf215546Sopenharmony_ci const GLenum target = texImage->TexObject->Target; 3428bf215546Sopenharmony_ci GLint texWidth = texImage->Width; 3429bf215546Sopenharmony_ci GLint texHeight = texImage->Height; 3430bf215546Sopenharmony_ci GLint texDepth = texImage->Depth; 3431bf215546Sopenharmony_ci unsigned level, w; 3432bf215546Sopenharmony_ci uint16_t h, d, layers; 3433bf215546Sopenharmony_ci 3434bf215546Sopenharmony_ci st_gl_texture_dims_to_pipe_dims(target, texWidth, texHeight, texDepth, 3435bf215546Sopenharmony_ci &w, &h, &d, &layers); 3436bf215546Sopenharmony_ci 3437bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 3438bf215546Sopenharmony_ci if (u_minify(pt->width0, level) == w && 3439bf215546Sopenharmony_ci u_minify(pt->height0, level) == h && 3440bf215546Sopenharmony_ci u_minify(pt->depth0, level) == d) { 3441bf215546Sopenharmony_ci return level; 3442bf215546Sopenharmony_ci } 3443bf215546Sopenharmony_ci } 3444bf215546Sopenharmony_ci 3445bf215546Sopenharmony_ci /* If we get here, there must be some sort of inconsistency between 3446bf215546Sopenharmony_ci * the Mesa texture object/images and the gallium resource. 3447bf215546Sopenharmony_ci */ 3448bf215546Sopenharmony_ci debug_printf("Inconsistent textures in find_mipmap_level()\n"); 3449bf215546Sopenharmony_ci 3450bf215546Sopenharmony_ci return texImage->Level; 3451bf215546Sopenharmony_ci} 3452bf215546Sopenharmony_ci 3453bf215546Sopenharmony_ci 3454bf215546Sopenharmony_civoid 3455bf215546Sopenharmony_cist_ClearTexSubImage(struct gl_context *ctx, 3456bf215546Sopenharmony_ci struct gl_texture_image *texImage, 3457bf215546Sopenharmony_ci GLint xoffset, GLint yoffset, GLint zoffset, 3458bf215546Sopenharmony_ci GLsizei width, GLsizei height, GLsizei depth, 3459bf215546Sopenharmony_ci const void *clearValue) 3460bf215546Sopenharmony_ci{ 3461bf215546Sopenharmony_ci static const char zeros[16] = {0}; 3462bf215546Sopenharmony_ci struct gl_texture_object *texObj = texImage->TexObject; 3463bf215546Sopenharmony_ci struct gl_texture_image *stImage = texImage; 3464bf215546Sopenharmony_ci struct pipe_resource *pt = stImage->pt; 3465bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3466bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 3467bf215546Sopenharmony_ci unsigned level; 3468bf215546Sopenharmony_ci struct pipe_box box; 3469bf215546Sopenharmony_ci 3470bf215546Sopenharmony_ci if (!pt) 3471bf215546Sopenharmony_ci return; 3472bf215546Sopenharmony_ci 3473bf215546Sopenharmony_ci st_flush_bitmap_cache(st); 3474bf215546Sopenharmony_ci st_invalidate_readpix_cache(st); 3475bf215546Sopenharmony_ci 3476bf215546Sopenharmony_ci u_box_3d(xoffset, yoffset, zoffset + texImage->Face, 3477bf215546Sopenharmony_ci width, height, depth, &box); 3478bf215546Sopenharmony_ci 3479bf215546Sopenharmony_ci if (pt->target == PIPE_TEXTURE_1D_ARRAY) { 3480bf215546Sopenharmony_ci box.z = box.y; 3481bf215546Sopenharmony_ci box.depth = box.height; 3482bf215546Sopenharmony_ci box.y = 0; 3483bf215546Sopenharmony_ci box.height = 1; 3484bf215546Sopenharmony_ci } 3485bf215546Sopenharmony_ci 3486bf215546Sopenharmony_ci if (texObj->Immutable) { 3487bf215546Sopenharmony_ci /* The texture object has to be consistent (no "loose", per-image 3488bf215546Sopenharmony_ci * gallium resources). If this texture is a view into another 3489bf215546Sopenharmony_ci * texture, we have to apply the MinLevel/Layer offsets. If this is 3490bf215546Sopenharmony_ci * not a texture view, the offsets will be zero. 3491bf215546Sopenharmony_ci */ 3492bf215546Sopenharmony_ci assert(stImage->pt == texObj->pt); 3493bf215546Sopenharmony_ci level = texImage->Level + texObj->Attrib.MinLevel; 3494bf215546Sopenharmony_ci box.z += texObj->Attrib.MinLayer; 3495bf215546Sopenharmony_ci } 3496bf215546Sopenharmony_ci else { 3497bf215546Sopenharmony_ci /* Texture level sizes may be inconsistent. We my have "loose", 3498bf215546Sopenharmony_ci * per-image gallium resources. The texImage->Level may not match 3499bf215546Sopenharmony_ci * the gallium resource texture level. 3500bf215546Sopenharmony_ci */ 3501bf215546Sopenharmony_ci level = find_mipmap_level(texImage, pt); 3502bf215546Sopenharmony_ci } 3503bf215546Sopenharmony_ci 3504bf215546Sopenharmony_ci assert(level <= pt->last_level); 3505bf215546Sopenharmony_ci 3506bf215546Sopenharmony_ci pipe->clear_texture(pipe, pt, level, &box, clearValue ? clearValue : zeros); 3507bf215546Sopenharmony_ci} 3508bf215546Sopenharmony_ci 3509bf215546Sopenharmony_ci 3510bf215546Sopenharmony_ciGLboolean 3511bf215546Sopenharmony_cist_SetTextureStorageForMemoryObject(struct gl_context *ctx, 3512bf215546Sopenharmony_ci struct gl_texture_object *texObj, 3513bf215546Sopenharmony_ci struct gl_memory_object *memObj, 3514bf215546Sopenharmony_ci GLsizei levels, GLsizei width, 3515bf215546Sopenharmony_ci GLsizei height, GLsizei depth, 3516bf215546Sopenharmony_ci GLuint64 offset) 3517bf215546Sopenharmony_ci{ 3518bf215546Sopenharmony_ci return st_texture_storage(ctx, texObj, levels, 3519bf215546Sopenharmony_ci width, height, depth, 3520bf215546Sopenharmony_ci memObj, offset); 3521bf215546Sopenharmony_ci} 3522bf215546Sopenharmony_ci 3523bf215546Sopenharmony_ciGLboolean 3524bf215546Sopenharmony_cist_GetSparseTextureVirtualPageSize(struct gl_context *ctx, 3525bf215546Sopenharmony_ci GLenum target, mesa_format format, 3526bf215546Sopenharmony_ci unsigned index, int *x, int *y, int *z) 3527bf215546Sopenharmony_ci{ 3528bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3529bf215546Sopenharmony_ci struct pipe_screen *screen = st->screen; 3530bf215546Sopenharmony_ci enum pipe_texture_target ptarget = gl_target_to_pipe(target); 3531bf215546Sopenharmony_ci enum pipe_format pformat = st_mesa_format_to_pipe_format(st, format); 3532bf215546Sopenharmony_ci bool multi_sample = _mesa_is_multisample_target(target); 3533bf215546Sopenharmony_ci 3534bf215546Sopenharmony_ci /* Get an XYZ page size combination specified by index. */ 3535bf215546Sopenharmony_ci return !!screen->get_sparse_texture_virtual_page_size( 3536bf215546Sopenharmony_ci screen, ptarget, multi_sample, pformat, index, 1, x, y, z); 3537bf215546Sopenharmony_ci} 3538bf215546Sopenharmony_ci 3539bf215546Sopenharmony_civoid 3540bf215546Sopenharmony_cist_TexturePageCommitment(struct gl_context *ctx, 3541bf215546Sopenharmony_ci struct gl_texture_object *tex_obj, 3542bf215546Sopenharmony_ci int level, int xoffset, int yoffset, int zoffset, 3543bf215546Sopenharmony_ci int width, int height, int depth, bool commit) 3544bf215546Sopenharmony_ci{ 3545bf215546Sopenharmony_ci struct st_context *st = st_context(ctx); 3546bf215546Sopenharmony_ci struct pipe_context *pipe = st->pipe; 3547bf215546Sopenharmony_ci struct pipe_box box; 3548bf215546Sopenharmony_ci 3549bf215546Sopenharmony_ci u_box_3d(xoffset, yoffset, zoffset, width, height, depth, &box); 3550bf215546Sopenharmony_ci 3551bf215546Sopenharmony_ci if (!pipe->resource_commit(pipe, tex_obj->pt, level, &box, commit)) { 3552bf215546Sopenharmony_ci _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexPageCommitmentARB(out of memory)"); 3553bf215546Sopenharmony_ci return; 3554bf215546Sopenharmony_ci } 3555bf215546Sopenharmony_ci} 3556