st_cb_texture.c revision 8d45bbc4221d83bc2bfd0295f56b0f6d35b16a99
112a1024d9d003afe1212cc48af04dac81c034299Karl Schultz/************************************************************************** 2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 3e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * All Rights Reserved. 559235bd5da794557613463bc942de0c634d2d961Brian Paul * 622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * Permission is hereby granted, free of charge, to any person obtaining a 7733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul * copy of this software and associated documentation files (the 822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * "Software"), to deal in the Software without restriction, including 9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * without limitation the rights to use, copy, modify, merge, publish, 10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * distribute, sub license, and/or sell copies of the Software, and to 11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * permit persons to whom the Software is furnished to do so, subject to 12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the following conditions: 13e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice (including the 1522144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * next paragraph) shall be included in all copies or substantial portions 16e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * of the Software. 17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 1822144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 26e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell **************************************************************************/ 27e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 28e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/mfeatures.h" 29e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/bufferobj.h" 30e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/enums.h" 31e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/fbobject.h" 32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/formats.h" 33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/image.h" 34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/imports.h" 35cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "main/macros.h" 36e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/mipmap.h" 37e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/pack.h" 38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/pbo.h" 39cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "main/pixeltransfer.h" 40cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "main/texcompress.h" 41cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "main/texfetch.h" 42e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/texgetimage.h" 43e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/teximage.h" 44e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/texobj.h" 45e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "main/texstore.h" 46e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 47cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell#include "state_tracker/st_debug.h" 48e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#include "state_tracker/st_context.h" 4959235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_cb_fbo.h" 5059235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_cb_flush.h" 5159235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_cb_texture.h" 5259235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_format.h" 5359235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_texture.h" 5459235bd5da794557613463bc942de0c634d2d961Brian Paul#include "state_tracker/st_gen_mipmap.h" 5512a1024d9d003afe1212cc48af04dac81c034299Karl Schultz#include "state_tracker/st_atom.h" 5659235bd5da794557613463bc942de0c634d2d961Brian Paul 5759235bd5da794557613463bc942de0c634d2d961Brian Paul#include "pipe/p_context.h" 5859235bd5da794557613463bc942de0c634d2d961Brian Paul#include "pipe/p_defines.h" 5959235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_inlines.h" 6059235bd5da794557613463bc942de0c634d2d961Brian Paul#include "pipe/p_shader_tokens.h" 6159235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_tile.h" 6259235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_blit.h" 6359235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_format.h" 6459235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_surface.h" 6559235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_sampler.h" 6659235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_math.h" 6759235bd5da794557613463bc942de0c634d2d961Brian Paul#include "util/u_box.h" 6859235bd5da794557613463bc942de0c634d2d961Brian Paul 6959235bd5da794557613463bc942de0c634d2d961Brian Paul#define DBG if (0) printf 7059235bd5da794557613463bc942de0c634d2d961Brian Paul 7159235bd5da794557613463bc942de0c634d2d961Brian Paul 7259235bd5da794557613463bc942de0c634d2d961Brian Paulstatic enum pipe_texture_target 7359235bd5da794557613463bc942de0c634d2d961Brian Paulgl_target_to_pipe(GLenum target) 7459235bd5da794557613463bc942de0c634d2d961Brian Paul{ 7559235bd5da794557613463bc942de0c634d2d961Brian Paul switch (target) { 7659235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_1D: 7759235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_1D; 7859235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_2D: 7959235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_2D; 8059235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_RECTANGLE_NV: 8159235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_RECT; 8259235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_3D: 8359235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_3D; 8459235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_CUBE_MAP_ARB: 8559235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_CUBE; 8659235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_1D_ARRAY_EXT: 8759235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_1D_ARRAY; 8859235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_2D_ARRAY_EXT: 8959235bd5da794557613463bc942de0c634d2d961Brian Paul return PIPE_TEXTURE_2D_ARRAY; 9059235bd5da794557613463bc942de0c634d2d961Brian Paul case GL_TEXTURE_BUFFER: 91e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return PIPE_BUFFER; 92e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell default: 93e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(0); 94e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return 0; 95e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 96e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 97e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 98e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 99e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** called via ctx->Driver.NewTextureImage() */ 100e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic struct gl_texture_image * 101e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellst_NewTextureImage(struct gl_context * ctx) 102e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 103e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("%s\n", __FUNCTION__); 104e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell (void) ctx; 105e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image); 106e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 107e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 108e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 109e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** called via ctx->Driver.NewTextureObject() */ 110e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic struct gl_texture_object * 111e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellst_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) 112e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 113e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object); 114e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 115e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("%s\n", __FUNCTION__); 116e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_initialize_texture_object(&obj->base, name, target); 117e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 118e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return &obj->base; 119e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 120e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 121e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** called via ctx->Driver.DeleteTextureObject() */ 122e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic void 123e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellst_DeleteTextureObject(struct gl_context *ctx, 124e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct gl_texture_object *texObj) 125e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 126e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_context *st = st_context(ctx); 127e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_texture_object *stObj = st_texture_object(texObj); 128e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->pt) 129e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_resource_reference(&stObj->pt, NULL); 130e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->sampler_view) { 131e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->sampler_view->context != st->pipe) { 132e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Take "ownership" of this texture sampler view by setting 133e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * its context pointer to this context. This avoids potential 134e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * crashes when the texture object is shared among contexts 135e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and the original/owner context has already been destroyed. 136e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 137e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->sampler_view->context = st->pipe; 138e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 139e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_sampler_view_reference(&stObj->sampler_view, NULL); 140e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 141e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_delete_texture_object(ctx, texObj); 14201915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul} 14301915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul 14401915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul 14501915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul/** called via ctx->Driver.FreeTexImageData() */ 14601915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paulstatic void 14701915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paulst_FreeTextureImageData(struct gl_context * ctx, struct gl_texture_image *texImage) 14801915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul{ 14901915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul struct st_texture_image *stImage = st_texture_image(texImage); 15001915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul 15101915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul DBG("%s\n", __FUNCTION__); 15201915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul 15301915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul if (stImage->pt) { 15401915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul pipe_resource_reference(&stImage->pt, NULL); 15501915e90e6912f06d43d443a09157f7bbc96ddc5Brian Paul } 156e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 157e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (texImage->Data) { 158e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_align_free(texImage->Data); 159e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Data = NULL; 160e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 161e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 162e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 163e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 164e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 165e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * From linux kernel i386 header files, copes with odd sizes better 166e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * than COPY_DWORDS would: 167e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * XXX Put this in src/mesa/main/imports.h ??? 168e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 169e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86) 170e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic INLINE void * 171e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell__memcpy(void *to, const void *from, size_t n) 172e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 173e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell int d0, d1, d2; 174e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell __asm__ __volatile__("rep ; movsl\n\t" 175e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "testb $2,%b4\n\t" 176e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "je 1f\n\t" 177e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "movsw\n" 178e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "1:\ttestb $1,%b4\n\t" 179e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "je 2f\n\t" 180e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2) 181e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from) 182e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell :"memory"); 183e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return (to); 184e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 185e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#else 186e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#define __memcpy(a,b,c) memcpy(a,b,c) 187e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#endif 188e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 189e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 190e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 191e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The system memcpy (at least on ubuntu 5.10) has problems copying 192e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to agp (writecombined) memory from a source which isn't 64-byte 193e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * aligned - there is a 4x performance falloff. 194e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 195e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The x86 __memcpy is immune to this but is slightly slower 196e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * (10%-ish) than the system memcpy. 197e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 198e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but 199e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * isn't much faster than x86_memcpy for agp copies. 200e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 201e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * TODO: switch dynamically. 202e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 203e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic void * 204e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwelldo_memcpy(void *dest, const void *src, size_t n) 205e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 206e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) { 207e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return __memcpy(dest, src, n); 208e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 209e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else 210e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return memcpy(dest, src, n); 211e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 212e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 213e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 214e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 215e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Return default texture resource binding bitmask for the given format. 216e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 217e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic GLuint 218e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwelldefault_bindings(struct st_context *st, enum pipe_format format) 219e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 220e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct pipe_screen *screen = st->pipe->screen; 221e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const unsigned target = PIPE_TEXTURE_2D; 222e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unsigned bindings; 223e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 224e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (util_format_is_depth_or_stencil(format)) 225e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL; 226e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else 227e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 228e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 229e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (screen->is_format_supported(screen, format, target, 0, bindings)) 230e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return bindings; 231e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 232e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Try non-sRGB. */ 233e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell format = util_format_linear(format); 234e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 235e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (screen->is_format_supported(screen, format, target, 0, bindings)) 236e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return bindings; 237e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else 238e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return PIPE_BIND_SAMPLER_VIEW; 239e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 240e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 241e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 242e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 243e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** Return number of image dimensions (1, 2 or 3) for a texture target. */ 244e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic GLuint 245e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellget_texture_dims(GLenum target) 246e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 247e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell switch (target) { 248e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_1D: 249e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_1D_ARRAY_EXT: 250e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_BUFFER: 251e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return 1; 252e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_2D: 253e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_ARB: 254e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 255e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 256e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 257e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 258e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 259e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 260f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul case GL_TEXTURE_RECTANGLE_NV: 261f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul case GL_TEXTURE_2D_ARRAY_EXT: 262f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul return 2; 263f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul case GL_TEXTURE_3D: 264f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul return 3; 265f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul default: 266e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(0 && "invalid texture target in get_texture_dims()"); 267e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return 1; 268e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 269e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 270e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 271e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 272e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 273e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Given the size of a mipmap image, try to compute the size of the level=0 274f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul * mipmap image. 275e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 276e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Note that this isn't always accurate for odd-sized, non-POW textures. 277e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * For example, if level=1 and width=40 then the level=0 width may be 80 or 81. 278e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 279e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * \return GL_TRUE for success, GL_FALSE for failure 280e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 281e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic GLboolean 282e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellguess_base_level_size(GLenum target, 283e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint width, GLuint height, GLuint depth, GLuint level, 284e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint *width0, GLuint *height0, GLuint *depth0) 285e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 286e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const GLuint dims = get_texture_dims(target); 287e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 288e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(width >= 1); 289e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(height >= 1); 290e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(depth >= 1); 291e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 292e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (level > 0) { 293e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Depending on the image's size, we can't always make a guess here */ 294e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if ((dims >= 1 && width == 1) || 295e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell (dims >= 2 && height == 1) || 296e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell (dims >= 3 && depth == 1)) { 297e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* we can't determine the image size at level=0 */ 298e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return GL_FALSE; 299e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 300e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 301e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* grow the image size until we hit level = 0 */ 302e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell while (level > 0) { 303e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (width > 1) 304e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell width <<= 1; 305e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (height > 1) 306e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell height <<= 1; 307e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (depth > 1) 308e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell depth <<= 1; 309e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell level--; 310e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 311e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 312e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 313e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *width0 = width; 314e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *height0 = height; 315e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *depth0 = depth; 316e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 317e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return GL_TRUE; 318e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 319e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 320e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 321e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 322e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Try to allocate a pipe_resource object for the given st_texture_object. 323e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 324e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * We use the given st_texture_image as a clue to determine the size of the 325e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * mipmap image at level=0. 326e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 327e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * \return GL_TRUE for success, GL_FALSE if out of memory. 328e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 329e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic GLboolean 330e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellguess_and_alloc_texture(struct st_context *st, 331e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_texture_object *stObj, 332e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const struct st_texture_image *stImage) 333e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 334e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint lastLevel, width, height, depth; 335e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint bindings; 336e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint ptWidth, ptHeight, ptDepth, ptLayers; 337e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell enum pipe_format fmt; 338e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 339e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("%s\n", __FUNCTION__); 340e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 341e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(!stObj->pt); 342e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 343e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (!guess_base_level_size(stObj->base.Target, 344e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->base.Width2, 345e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->base.Height2, 346e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->base.Depth2, 347e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->level, 348e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell &width, &height, &depth)) { 349e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* we can't determine the image size at level=0 */ 350e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->width0 = stObj->height0 = stObj->depth0 = 0; 351e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* this is not an out of memory error */ 352e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return GL_TRUE; 353e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 354e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 355e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* At this point, (width x height x depth) is the expected size of 356e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the level=0 mipmap image. 357e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 358e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 359e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Guess a reasonable value for lastLevel. With OpenGL we have no 360e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * idea how many mipmap levels will be in a texture until we start 361e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to render with it. Make an educated guess here but be prepared 362e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to re-allocating a texture buffer with space for more (or fewer) 363e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * mipmap levels later. 364e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 365e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if ((stObj->base.Sampler.MinFilter == GL_NEAREST || 366e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->base.Sampler.MinFilter == GL_LINEAR || 367e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->base._BaseFormat == GL_DEPTH_COMPONENT || 368e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) && 369e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell !stObj->base.GenerateMipmap && 370e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->level == 0) { 371e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* only alloc space for a single mipmap level */ 372e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell lastLevel = 0; 373e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 374e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 375e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* alloc space for a full mipmap */ 376e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint l2width = util_logbase2(width); 377e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint l2height = util_logbase2(height); 378e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint l2depth = util_logbase2(depth); 379e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell lastLevel = MAX2(MAX2(l2width, l2height), l2depth); 380e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 381e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 382e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Save the level=0 dimensions */ 383e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->width0 = width; 38408836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul stObj->height0 = height; 38559235bd5da794557613463bc942de0c634d2d961Brian Paul stObj->depth0 = depth; 386e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 387e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); 388e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 389e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell bindings = default_bindings(st, fmt); 390e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 391e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell st_gl_texture_dims_to_pipe_dims(stObj->base.Target, 392e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell width, height, depth, 393e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell &ptWidth, &ptHeight, &ptDepth, &ptLayers); 394e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 395e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->pt = st_texture_create(st, 396e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell gl_target_to_pipe(stObj->base.Target), 397e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell fmt, 398e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell lastLevel, 399e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell ptWidth, 400e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell ptHeight, 401e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell ptDepth, 402e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell ptLayers, 403e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell bindings); 404e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 405e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL)); 406e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 407e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return stObj->pt != NULL; 408e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 409e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 410e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 411e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 412e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Adjust pixel unpack params and image dimensions to strip off the 413e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * texture border. 414e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Gallium doesn't support texture borders. They've seldem been used 415e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and seldom been implemented correctly anyway. 416e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * \param unpackNew returns the new pixel unpack parameters 417e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 418e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic void 419e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstrip_texture_border(GLint border, 420e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint *width, GLint *height, GLint *depth, 421e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const struct gl_pixelstore_attrib *unpack, 422e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct gl_pixelstore_attrib *unpackNew) 423e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 424e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(border > 0); /* sanity check */ 425e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 426e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *unpackNew = *unpack; 427e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 428e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (unpackNew->RowLength == 0) 429e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpackNew->RowLength = *width; 430e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 431e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (depth && unpackNew->ImageHeight == 0) 432e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpackNew->ImageHeight = *height; 433e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 434e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpackNew->SkipPixels += border; 435e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (height) 436e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpackNew->SkipRows += border; 437e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (depth) 43808836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul unpackNew->SkipImages += border; 439e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 440e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(*width >= 3); 441e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *width = *width - 2 * border; 442e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (height && *height >= 3) 443e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *height = *height - 2 * border; 444e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (depth && *depth >= 3) 445e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *depth = *depth - 2 * border; 446e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell} 447e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 448e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 449e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/** 450e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Do glTexImage1/2/3D(). 451e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 452e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellstatic void 453e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwellst_TexImage(struct gl_context * ctx, 454e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint dims, 455e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLenum target, GLint level, 456e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint internalFormat, 457e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint width, GLint height, GLint depth, 458e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint border, 459e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLenum format, GLenum type, const void *pixels, 460e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const struct gl_pixelstore_attrib *unpack, 461e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct gl_texture_object *texObj, 462e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct gl_texture_image *texImage, 463e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLsizei imageSize, GLboolean compressed_src) 464e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{ 465e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_context *st = st_context(ctx); 466e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_texture_object *stObj = st_texture_object(texObj); 467e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct st_texture_image *stImage = st_texture_image(texImage); 468e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint dstRowStride = 0; 469e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell struct gl_pixelstore_attrib unpackNB; 470e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell enum pipe_transfer_usage transfer_usage = 0; 471e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 472e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, 473e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); 474e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 475e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* switch to "normal" */ 476e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->surface_based) { 477e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell gl_format texFormat; 478e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 479e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_clear_texture_object(ctx, texObj); 480e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_resource_reference(&stObj->pt, NULL); 481e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 482e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* oops, need to init this image again */ 483e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 484e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell internalFormat, format, type); 485e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 486e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_init_teximage_fields(ctx, target, texImage, 487e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell width, height, depth, border, 488e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell internalFormat, texFormat); 489e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 490e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stObj->surface_based = GL_FALSE; 491e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 492e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 493e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* gallium does not support texture borders, strip it off */ 494e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (border) { 495e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB); 496e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpack = &unpackNB; 497e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Width = width; 498e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Height = height; 499e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Depth = depth; 50008836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul texImage->Border = 0; 501e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell border = 0; 502e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 503e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 504e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(texImage->Width == width); 505e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(texImage->Height == height); 506e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(texImage->Depth == depth); 507e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 508e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 509e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->face = _mesa_tex_target_to_face(target); 510e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->level = level; 511e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 512e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_set_fetch_functions(texImage, dims); 513e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 514e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Release the reference to a potentially orphaned buffer. 515e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Release any old malloced memory. 516e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 517e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stImage->pt) { 518e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_resource_reference(&stImage->pt, NULL); 519e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(!texImage->Data); 520e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 521e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else if (texImage->Data) { 522e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_align_free(texImage->Data); 523e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 524e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 525e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* 526e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * See if the new image is somehow incompatible with the existing 527e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * mipmap. If so, free the old mipmap. 528e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 529e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->pt) { 530e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (level > (GLint) stObj->pt->last_level || 531e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell !st_texture_match_image(stObj->pt, &stImage->base, 532e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->face, stImage->level)) { 533e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("release it\n"); 534e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_resource_reference(&stObj->pt, NULL); 535e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(!stObj->pt); 536e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_sampler_view_reference(&stObj->sampler_view, NULL); 537e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 538e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 539e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 540e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (width == 0 || height == 0 || depth == 0) { 541e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* stop after freeing old image */ 542e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 543e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 544e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 545e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (!stObj->pt) { 546e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (!guess_and_alloc_texture(st, stObj, stImage)) { 547e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Probably out of memory. 548e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Try flushing any pending rendering, then retry. 549e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 55008836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul st_finish(st); 55159235bd5da794557613463bc942de0c634d2d961Brian Paul if (!guess_and_alloc_texture(st, stObj, stImage)) { 552e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 553e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell return; 554e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 555e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 556e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 557e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 558e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(!stImage->pt); 559e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 560e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Check if this texture image can live inside the texture object's buffer. 561e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * If so, store the image there. Otherwise the image will temporarily live 562e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in its own buffer. 563e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 564e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stObj->pt && 565e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell st_texture_match_image(stObj->pt, &stImage->base, 566e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell stImage->face, stImage->level)) { 567e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 568e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pipe_resource_reference(&stImage->pt, stObj->pt); 569e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell assert(stImage->pt); 570e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 571e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 572e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (!stImage->pt) 573e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("XXX: Image did not fit into texture - storing in local memory!\n"); 574e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 575e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Pixel data may come from regular user memory or a PBO. For the later, 576e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * do bounds checking and map the PBO to read pixels data from it. 577e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * 578e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * XXX we should try to use a GPU-accelerated path to copy the image data 579e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * from the PBO to the texture. 580e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 581e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (compressed_src) { 582e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, 583e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell unpack, 584e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell "glCompressedTexImage"); 585e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 586e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 587e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, 588e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell format, type, 589e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell pixels, unpack, "glTexImage"); 590e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 591e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 592e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* for a 1D array upload the image as a series of layer with height = 1 */ 593e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (target == GL_TEXTURE_1D_ARRAY) { 594e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell depth = height; 595e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell height = 1; 59608836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul } 597e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 598e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* 599e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Prepare to store the texture data. Either map the gallium texture buffer 600e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * memory or malloc space for it. 601e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */ 602e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stImage->pt) { 603e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (!pixels) { 604e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* We've allocated texture resource, but have no pixel data - all done. */ 605e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell goto done; 606e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 607e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 608e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Store the image in the gallium transfer object */ 609e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (format == GL_DEPTH_COMPONENT && 610e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell util_format_is_depth_and_stencil(stImage->pt->format)) 611e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell transfer_usage = PIPE_TRANSFER_READ_WRITE; 612e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else 613e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell transfer_usage = PIPE_TRANSFER_WRITE; 614e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 615e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Data = st_texture_image_map(st, stImage, 0, 616cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell transfer_usage, 0, 0, width, height); 617e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if(stImage->transfer) 618e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell dstRowStride = stImage->transfer->stride; 619e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 620e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 621e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Allocate regular memory and store the image there temporarily. */ 622e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLuint imageSize = _mesa_format_image_size(texImage->TexFormat, 623e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell width, height, depth); 624e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); 625cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell 626e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Data = _mesa_align_malloc(imageSize, 16); 627e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 62859235bd5da794557613463bc942de0c634d2d961Brian Paul 629cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell if (!texImage->Data) { 630461b99050811b345e77de01f4610e7c22a259141Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 631461b99050811b345e77de01f4610e7c22a259141Brian Paul return; 632cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell } 63359235bd5da794557613463bc942de0c634d2d961Brian Paul 634cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell if (!pixels) { 635cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell /* We've allocated texture memory, but have no pixel data - all done. */ 636cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell goto done; 637cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell } 638e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 639e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell DBG("Upload image %dx%dx%d row_len %x pitch %x\n", 640cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell width, height, depth, width, dstRowStride); 641e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 642e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* Copy user texture image into the texture buffer. 643cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell */ 644cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell if (compressed_src) { 645cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell const GLuint srcRowStride = 646cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell _mesa_format_row_stride(texImage->TexFormat, width); 647cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell if (dstRowStride == srcRowStride) { 648e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell memcpy(texImage->Data, pixels, imageSize); 649e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 650cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell else { 651e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell char *dst = texImage->Data; 652e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const char *src = pixels; 653cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell GLuint i, bw, bh, lines; 654e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); 65559235bd5da794557613463bc942de0c634d2d961Brian Paul lines = (height + bh - 1) / bh; 65659235bd5da794557613463bc942de0c634d2d961Brian Paul 65759235bd5da794557613463bc942de0c634d2d961Brian Paul for (i = 0; i < lines; ++i) { 65859235bd5da794557613463bc942de0c634d2d961Brian Paul memcpy(dst, src, srcRowStride); 65959235bd5da794557613463bc942de0c634d2d961Brian Paul dst += dstRowStride; 66059235bd5da794557613463bc942de0c634d2d961Brian Paul src += srcRowStride; 661e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 662cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0Keith Whitwell } 663e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell } 664e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell else { 665e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const GLuint srcImageStride = 666e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell _mesa_image_image_stride(unpack, width, height, format, type); 667e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell GLint i; 668e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell const GLubyte *src = (const GLubyte *) pixels; 669e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 670733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul for (i = 0; i < depth; i++) { 671733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (!_mesa_texstore(ctx, dims, 672e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->_BaseFormat, 673e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->TexFormat, 674733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul texImage->Data, 675733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 0, 0, 0, /* dstX/Y/Zoffset */ 676e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell dstRowStride, 677733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul texImage->ImageOffsets, 678733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul width, height, 1, 679e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell format, type, src, unpack)) { 680733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 681733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 682733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 683e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell if (stImage->pt && i + 1 < depth) { 684e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell /* unmap this slice */ 685733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul st_texture_image_unmap(st, stImage); 686733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul /* map next slice of 3D texture */ 687733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul texImage->Data = st_texture_image_map(st, stImage, i + 1, 688733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul transfer_usage, 0, 0, 689733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul width, height); 690733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul src += srcImageStride; 691733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 692733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 693733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 694733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 695733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Pauldone: 696733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul _mesa_unmap_teximage_pbo(ctx, unpack); 697733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul 698733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul if (stImage->pt && texImage->Data) { 699733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul st_texture_image_unmap(st, stImage); 700e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell texImage->Data = NULL; 701733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul } 702733a4b602bbbfda83ee03b7ae4f3737bbe659034Brian Paul} 703e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell 704 705static void 706st_TexImage3D(struct gl_context * ctx, 707 GLenum target, GLint level, 708 GLint internalFormat, 709 GLint width, GLint height, GLint depth, 710 GLint border, 711 GLenum format, GLenum type, const void *pixels, 712 const struct gl_pixelstore_attrib *unpack, 713 struct gl_texture_object *texObj, 714 struct gl_texture_image *texImage) 715{ 716 st_TexImage(ctx, 3, target, level, internalFormat, width, height, depth, 717 border, format, type, pixels, unpack, texObj, texImage, 718 0, GL_FALSE); 719} 720 721 722static void 723st_TexImage2D(struct gl_context * ctx, 724 GLenum target, GLint level, 725 GLint internalFormat, 726 GLint width, GLint height, GLint border, 727 GLenum format, GLenum type, const void *pixels, 728 const struct gl_pixelstore_attrib *unpack, 729 struct gl_texture_object *texObj, 730 struct gl_texture_image *texImage) 731{ 732 st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border, 733 format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE); 734} 735 736 737static void 738st_TexImage1D(struct gl_context * ctx, 739 GLenum target, GLint level, 740 GLint internalFormat, 741 GLint width, GLint border, 742 GLenum format, GLenum type, const void *pixels, 743 const struct gl_pixelstore_attrib *unpack, 744 struct gl_texture_object *texObj, 745 struct gl_texture_image *texImage) 746{ 747 st_TexImage(ctx, 1, target, level, internalFormat, width, 1, 1, border, 748 format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE); 749} 750 751 752static void 753st_CompressedTexImage2D(struct gl_context *ctx, GLenum target, GLint level, 754 GLint internalFormat, 755 GLint width, GLint height, GLint border, 756 GLsizei imageSize, const GLvoid *data, 757 struct gl_texture_object *texObj, 758 struct gl_texture_image *texImage) 759{ 760 st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border, 761 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE); 762} 763 764 765 766/** 767 * glGetTexImage() helper: decompress a compressed texture by rendering 768 * a textured quad. Store the results in the user's buffer. 769 */ 770static void 771decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level, 772 GLenum format, GLenum type, GLvoid *pixels, 773 struct gl_texture_object *texObj, 774 struct gl_texture_image *texImage) 775{ 776 struct st_context *st = st_context(ctx); 777 struct pipe_context *pipe = st->pipe; 778 struct st_texture_image *stImage = st_texture_image(texImage); 779 struct st_texture_object *stObj = st_texture_object(texObj); 780 struct pipe_sampler_view *src_view = 781 st_get_texture_sampler_view(stObj, pipe); 782 const GLuint width = texImage->Width; 783 const GLuint height = texImage->Height; 784 struct pipe_surface *dst_surface; 785 struct pipe_resource *dst_texture; 786 struct pipe_transfer *tex_xfer; 787 unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */ 788 PIPE_BIND_TRANSFER_READ); 789 790 /* create temp / dest surface */ 791 if (!util_create_rgba_surface(pipe, width, height, bind, 792 &dst_texture, &dst_surface)) { 793 _mesa_problem(ctx, "util_create_rgba_surface() failed " 794 "in decompress_with_blit()"); 795 return; 796 } 797 798 /* Disable conditional rendering. */ 799 if (st->render_condition) { 800 pipe->render_condition(pipe, NULL, 0); 801 } 802 803 /* blit/render/decompress */ 804 util_blit_pixels_tex(st->blit, 805 src_view, /* pipe_resource (src) */ 806 0, 0, /* src x0, y0 */ 807 width, height, /* src x1, y1 */ 808 dst_surface, /* pipe_surface (dst) */ 809 0, 0, /* dst x0, y0 */ 810 width, height, /* dst x1, y1 */ 811 0.0, /* z */ 812 PIPE_TEX_MIPFILTER_NEAREST); 813 814 /* Restore conditional rendering state. */ 815 if (st->render_condition) { 816 pipe->render_condition(pipe, st->render_condition, 817 st->condition_mode); 818 } 819 820 /* map the dst_surface so we can read from it */ 821 tex_xfer = pipe_get_transfer(pipe, 822 dst_texture, 0, 0, 823 PIPE_TRANSFER_READ, 824 0, 0, width, height); 825 826 pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels); 827 828 /* copy/pack data into user buffer */ 829 if (st_equal_formats(stImage->pt->format, format, type)) { 830 /* memcpy */ 831 const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format); 832 ubyte *map = pipe_transfer_map(pipe, tex_xfer); 833 GLuint row; 834 for (row = 0; row < height; row++) { 835 GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, 836 height, format, type, row, 0); 837 memcpy(dest, map, bytesPerRow); 838 map += tex_xfer->stride; 839 } 840 pipe_transfer_unmap(pipe, tex_xfer); 841 } 842 else { 843 /* format translation via floats */ 844 GLuint row; 845 enum pipe_format format = util_format_linear(dst_texture->format); 846 for (row = 0; row < height; row++) { 847 const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */ 848 GLfloat rgba[4 * MAX_WIDTH]; 849 GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, 850 height, format, type, row, 0); 851 852 if (ST_DEBUG & DEBUG_FALLBACK) 853 debug_printf("%s: fallback format translation\n", __FUNCTION__); 854 855 /* get float[4] rgba row from surface */ 856 pipe_get_tile_rgba_format(pipe, tex_xfer, 0, row, width, 1, 857 format, rgba); 858 859 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, 860 type, dest, &ctx->Pack, transferOps); 861 } 862 } 863 864 _mesa_unmap_pbo_dest(ctx, &ctx->Pack); 865 866 pipe->transfer_destroy(pipe, tex_xfer); 867 868 /* destroy the temp / dest surface */ 869 util_destroy_rgba_surface(dst_texture, dst_surface); 870} 871 872 873 874/** 875 * Need to map texture image into memory before copying image data, 876 * then unmap it. 877 */ 878static void 879st_get_tex_image(struct gl_context * ctx, GLenum target, GLint level, 880 GLenum format, GLenum type, GLvoid * pixels, 881 struct gl_texture_object *texObj, 882 struct gl_texture_image *texImage, GLboolean compressed_dst) 883{ 884 struct st_context *st = st_context(ctx); 885 struct st_texture_image *stImage = st_texture_image(texImage); 886 const GLuint dstImageStride = 887 _mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height, 888 format, type); 889 GLuint depth, i; 890 GLubyte *dest; 891 892 if (stImage->pt && 893 util_format_is_s3tc(stImage->pt->format) && 894 !compressed_dst) { 895 /* Need to decompress the texture. 896 * We'll do this by rendering a textured quad. 897 * Note that we only expect RGBA formats (no Z/depth formats). 898 */ 899 decompress_with_blit(ctx, target, level, format, type, pixels, 900 texObj, texImage); 901 return; 902 } 903 904 /* Map */ 905 if (stImage->pt) { 906 /* Image is stored in hardware format in a buffer managed by the 907 * kernel. Need to explicitly map and unmap it. 908 */ 909 texImage->Data = st_texture_image_map(st, stImage, 0, 910 PIPE_TRANSFER_READ, 0, 0, 911 stImage->base.Width, 912 stImage->base.Height); 913 /* compute stride in texels from stride in bytes */ 914 texImage->RowStride = stImage->transfer->stride 915 * util_format_get_blockwidth(stImage->pt->format) 916 / util_format_get_blocksize(stImage->pt->format); 917 } 918 else { 919 /* Otherwise, the image should actually be stored in 920 * texImage->Data. This is pretty confusing for 921 * everybody, I'd much prefer to separate the two functions of 922 * texImage->Data - storage for texture images in main memory 923 * and access (ie mappings) of images. In other words, we'd 924 * create a new texImage->Map field and leave Data simply for 925 * storage. 926 */ 927 assert(texImage->Data); 928 } 929 930 depth = texImage->Depth; 931 texImage->Depth = 1; 932 933 dest = (GLubyte *) pixels; 934 935 _mesa_set_fetch_functions(texImage, get_texture_dims(target)); 936 937 for (i = 0; i < depth; i++) { 938 if (compressed_dst) { 939 _mesa_get_compressed_teximage(ctx, target, level, dest, 940 texObj, texImage); 941 } 942 else { 943 _mesa_get_teximage(ctx, target, level, format, type, dest, 944 texObj, texImage); 945 } 946 947 if (stImage->pt && i + 1 < depth) { 948 /* unmap this slice */ 949 st_texture_image_unmap(st, stImage); 950 /* map next slice of 3D texture */ 951 texImage->Data = st_texture_image_map(st, stImage, i + 1, 952 PIPE_TRANSFER_READ, 0, 0, 953 stImage->base.Width, 954 stImage->base.Height); 955 dest += dstImageStride; 956 } 957 } 958 959 texImage->Depth = depth; 960 961 /* Unmap */ 962 if (stImage->pt) { 963 st_texture_image_unmap(st, stImage); 964 texImage->Data = NULL; 965 } 966} 967 968 969static void 970st_GetTexImage(struct gl_context * ctx, GLenum target, GLint level, 971 GLenum format, GLenum type, GLvoid * pixels, 972 struct gl_texture_object *texObj, 973 struct gl_texture_image *texImage) 974{ 975 st_get_tex_image(ctx, target, level, format, type, pixels, texObj, texImage, 976 GL_FALSE); 977} 978 979 980static void 981st_GetCompressedTexImage(struct gl_context *ctx, GLenum target, GLint level, 982 GLvoid *pixels, 983 struct gl_texture_object *texObj, 984 struct gl_texture_image *texImage) 985{ 986 st_get_tex_image(ctx, target, level, 0, 0, pixels, texObj, texImage, 987 GL_TRUE); 988} 989 990 991 992static void 993st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level, 994 GLint xoffset, GLint yoffset, GLint zoffset, 995 GLint width, GLint height, GLint depth, 996 GLenum format, GLenum type, const void *pixels, 997 const struct gl_pixelstore_attrib *packing, 998 struct gl_texture_object *texObj, 999 struct gl_texture_image *texImage) 1000{ 1001 struct st_context *st = st_context(ctx); 1002 struct st_texture_image *stImage = st_texture_image(texImage); 1003 GLuint dstRowStride; 1004 const GLuint srcImageStride = 1005 _mesa_image_image_stride(packing, width, height, format, type); 1006 GLint i; 1007 const GLubyte *src; 1008 /* init to silence warning only: */ 1009 enum pipe_transfer_usage transfer_usage = PIPE_TRANSFER_WRITE; 1010 1011 DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, 1012 _mesa_lookup_enum_by_nr(target), 1013 level, xoffset, yoffset, width, height); 1014 1015 pixels = 1016 _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, 1017 type, pixels, packing, "glTexSubImage2D"); 1018 if (!pixels) 1019 return; 1020 1021 /* for a 1D array upload the image as a series of layer with height = 1 */ 1022 if (target == GL_TEXTURE_1D_ARRAY) { 1023 depth = height; 1024 height = 1; 1025 } 1026 1027 /* Map buffer if necessary. Need to lock to prevent other contexts 1028 * from uploading the buffer under us. 1029 */ 1030 if (stImage->pt) { 1031 if (format == GL_DEPTH_COMPONENT && 1032 util_format_is_depth_and_stencil(stImage->pt->format)) 1033 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1034 else 1035 transfer_usage = PIPE_TRANSFER_WRITE; 1036 1037 texImage->Data = st_texture_image_map(st, stImage, zoffset, 1038 transfer_usage, 1039 xoffset, yoffset, 1040 width, height); 1041 } 1042 1043 if (!texImage->Data) { 1044 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); 1045 goto done; 1046 } 1047 1048 src = (const GLubyte *) pixels; 1049 dstRowStride = stImage->transfer->stride; 1050 1051 for (i = 0; i < depth; i++) { 1052 if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat, 1053 texImage->TexFormat, 1054 texImage->Data, 1055 0, 0, 0, 1056 dstRowStride, 1057 texImage->ImageOffsets, 1058 width, height, 1, 1059 format, type, src, packing)) { 1060 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); 1061 } 1062 1063 if (stImage->pt && i + 1 < depth) { 1064 /* unmap this slice */ 1065 st_texture_image_unmap(st, stImage); 1066 /* map next slice of 3D texture */ 1067 texImage->Data = st_texture_image_map(st, stImage, 1068 zoffset + i + 1, 1069 transfer_usage, 1070 xoffset, yoffset, 1071 width, height); 1072 src += srcImageStride; 1073 } 1074 } 1075 1076done: 1077 _mesa_unmap_teximage_pbo(ctx, packing); 1078 1079 if (stImage->pt && texImage->Data) { 1080 st_texture_image_unmap(st, stImage); 1081 texImage->Data = NULL; 1082 } 1083} 1084 1085 1086 1087static void 1088st_TexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, 1089 GLint xoffset, GLint yoffset, GLint zoffset, 1090 GLsizei width, GLsizei height, GLsizei depth, 1091 GLenum format, GLenum type, const GLvoid *pixels, 1092 const struct gl_pixelstore_attrib *packing, 1093 struct gl_texture_object *texObj, 1094 struct gl_texture_image *texImage) 1095{ 1096 st_TexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, 1097 width, height, depth, format, type, 1098 pixels, packing, texObj, texImage); 1099} 1100 1101 1102static void 1103st_TexSubImage2D(struct gl_context *ctx, GLenum target, GLint level, 1104 GLint xoffset, GLint yoffset, 1105 GLsizei width, GLsizei height, 1106 GLenum format, GLenum type, const GLvoid * pixels, 1107 const struct gl_pixelstore_attrib *packing, 1108 struct gl_texture_object *texObj, 1109 struct gl_texture_image *texImage) 1110{ 1111 st_TexSubimage(ctx, 2, target, level, xoffset, yoffset, 0, 1112 width, height, 1, format, type, 1113 pixels, packing, texObj, texImage); 1114} 1115 1116 1117static void 1118st_TexSubImage1D(struct gl_context *ctx, GLenum target, GLint level, 1119 GLint xoffset, GLsizei width, GLenum format, GLenum type, 1120 const GLvoid * pixels, 1121 const struct gl_pixelstore_attrib *packing, 1122 struct gl_texture_object *texObj, 1123 struct gl_texture_image *texImage) 1124{ 1125 st_TexSubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1, 1126 format, type, pixels, packing, texObj, texImage); 1127} 1128 1129 1130static void 1131st_CompressedTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level, 1132 GLint xoffset, GLsizei width, 1133 GLenum format, 1134 GLsizei imageSize, const GLvoid *data, 1135 struct gl_texture_object *texObj, 1136 struct gl_texture_image *texImage) 1137{ 1138 assert(0); 1139} 1140 1141 1142static void 1143st_CompressedTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level, 1144 GLint xoffset, GLint yoffset, 1145 GLsizei width, GLint height, 1146 GLenum format, 1147 GLsizei imageSize, const GLvoid *data, 1148 struct gl_texture_object *texObj, 1149 struct gl_texture_image *texImage) 1150{ 1151 struct st_context *st = st_context(ctx); 1152 struct st_texture_image *stImage = st_texture_image(texImage); 1153 int srcBlockStride; 1154 int dstBlockStride; 1155 int y; 1156 enum pipe_format pformat; 1157 1158 if (stImage->pt) { 1159 pformat = stImage->pt->format; 1160 1161 texImage->Data = st_texture_image_map(st, stImage, 0, 1162 PIPE_TRANSFER_WRITE, 1163 xoffset, yoffset, 1164 width, height); 1165 1166 srcBlockStride = util_format_get_stride(pformat, width); 1167 dstBlockStride = stImage->transfer->stride; 1168 } else { 1169 assert(stImage->pt); 1170 /* TODO find good values for block and strides */ 1171 /* TODO also adjust texImage->data for yoffset/xoffset */ 1172 return; 1173 } 1174 1175 if (!texImage->Data) { 1176 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage"); 1177 return; 1178 } 1179 1180 assert(xoffset % util_format_get_blockwidth(pformat) == 0); 1181 assert(yoffset % util_format_get_blockheight(pformat) == 0); 1182 1183 for (y = 0; y < height; y += util_format_get_blockheight(pformat)) { 1184 /* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */ 1185 const char *src = (const char*)data + srcBlockStride * util_format_get_nblocksy(pformat, y); 1186 char *dst = (char*)texImage->Data + dstBlockStride * util_format_get_nblocksy(pformat, y); 1187 memcpy(dst, src, util_format_get_stride(pformat, width)); 1188 } 1189 1190 if (stImage->pt) { 1191 st_texture_image_unmap(st, stImage); 1192 texImage->Data = NULL; 1193 } 1194} 1195 1196 1197static void 1198st_CompressedTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level, 1199 GLint xoffset, GLint yoffset, GLint zoffset, 1200 GLsizei width, GLint height, GLint depth, 1201 GLenum format, 1202 GLsizei imageSize, const GLvoid *data, 1203 struct gl_texture_object *texObj, 1204 struct gl_texture_image *texImage) 1205{ 1206 assert(0); 1207} 1208 1209 1210 1211/** 1212 * Do a CopyTexSubImage operation using a read transfer from the source, 1213 * a write transfer to the destination and get_tile()/put_tile() to access 1214 * the pixels/texels. 1215 * 1216 * Note: srcY=0=TOP of renderbuffer 1217 */ 1218static void 1219fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level, 1220 struct st_renderbuffer *strb, 1221 struct st_texture_image *stImage, 1222 GLenum baseFormat, 1223 GLint destX, GLint destY, GLint destZ, 1224 GLint srcX, GLint srcY, 1225 GLsizei width, GLsizei height) 1226{ 1227 struct st_context *st = st_context(ctx); 1228 struct pipe_context *pipe = st->pipe; 1229 struct pipe_transfer *src_trans; 1230 GLvoid *texDest; 1231 enum pipe_transfer_usage transfer_usage; 1232 1233 if (ST_DEBUG & DEBUG_FALLBACK) 1234 debug_printf("%s: fallback processing\n", __FUNCTION__); 1235 1236 assert(width <= MAX_WIDTH); 1237 1238 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1239 srcY = strb->Base.Height - srcY - height; 1240 } 1241 1242 src_trans = pipe_get_transfer(pipe, 1243 strb->texture, 1244 0, 0, 1245 PIPE_TRANSFER_READ, 1246 srcX, srcY, 1247 width, height); 1248 1249 if ((baseFormat == GL_DEPTH_COMPONENT || 1250 baseFormat == GL_DEPTH_STENCIL) && 1251 util_format_is_depth_and_stencil(stImage->pt->format)) 1252 transfer_usage = PIPE_TRANSFER_READ_WRITE; 1253 else 1254 transfer_usage = PIPE_TRANSFER_WRITE; 1255 1256 /* XXX this used to ignore destZ param */ 1257 texDest = st_texture_image_map(st, stImage, destZ, transfer_usage, 1258 destX, destY, width, height); 1259 1260 if (baseFormat == GL_DEPTH_COMPONENT || 1261 baseFormat == GL_DEPTH_STENCIL) { 1262 const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F || 1263 ctx->Pixel.DepthBias != 0.0F); 1264 GLint row, yStep; 1265 1266 /* determine bottom-to-top vs. top-to-bottom order for src buffer */ 1267 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1268 srcY = height - 1; 1269 yStep = -1; 1270 } 1271 else { 1272 srcY = 0; 1273 yStep = 1; 1274 } 1275 1276 /* To avoid a large temp memory allocation, do copy row by row */ 1277 for (row = 0; row < height; row++, srcY += yStep) { 1278 uint data[MAX_WIDTH]; 1279 pipe_get_tile_z(pipe, src_trans, 0, srcY, width, 1, data); 1280 if (scaleOrBias) { 1281 _mesa_scale_and_bias_depth_uint(ctx, width, data); 1282 } 1283 pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data); 1284 } 1285 } 1286 else { 1287 /* RGBA format */ 1288 GLfloat *tempSrc = 1289 (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat)); 1290 1291 if (tempSrc && texDest) { 1292 const GLint dims = 2; 1293 const GLint dstRowStride = stImage->transfer->stride; 1294 struct gl_texture_image *texImage = &stImage->base; 1295 struct gl_pixelstore_attrib unpack = ctx->DefaultPacking; 1296 1297 if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { 1298 unpack.Invert = GL_TRUE; 1299 } 1300 1301 /* get float/RGBA image from framebuffer */ 1302 /* XXX this usually involves a lot of int/float conversion. 1303 * try to avoid that someday. 1304 */ 1305 pipe_get_tile_rgba_format(pipe, src_trans, 0, 0, width, height, 1306 util_format_linear(strb->texture->format), 1307 tempSrc); 1308 1309 /* Store into texture memory. 1310 * Note that this does some special things such as pixel transfer 1311 * ops and format conversion. In particular, if the dest tex format 1312 * is actually RGBA but the user created the texture as GL_RGB we 1313 * need to fill-in/override the alpha channel with 1.0. 1314 */ 1315 _mesa_texstore(ctx, dims, 1316 texImage->_BaseFormat, 1317 texImage->TexFormat, 1318 texDest, 1319 0, 0, 0, 1320 dstRowStride, 1321 texImage->ImageOffsets, 1322 width, height, 1, 1323 GL_RGBA, GL_FLOAT, tempSrc, /* src */ 1324 &unpack); 1325 } 1326 else { 1327 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); 1328 } 1329 1330 if (tempSrc) 1331 free(tempSrc); 1332 } 1333 1334 st_texture_image_unmap(st, stImage); 1335 pipe->transfer_destroy(pipe, src_trans); 1336} 1337 1338 1339 1340/** 1341 * If the format of the src renderbuffer and the format of the dest 1342 * texture are compatible (in terms of blitting), return a TGSI writemask 1343 * to be used during the blit. 1344 * If the src/dest are incompatible, return 0. 1345 */ 1346static unsigned 1347compatible_src_dst_formats(struct gl_context *ctx, 1348 const struct gl_renderbuffer *src, 1349 const struct gl_texture_image *dst) 1350{ 1351 /* Get logical base formats for the src and dest. 1352 * That is, use the user-requested formats and not the actual, device- 1353 * chosen formats. 1354 * For example, the user may have requested an A8 texture but the 1355 * driver may actually be using an RGBA texture format. When we 1356 * copy/blit to that texture, we only want to copy the Alpha channel 1357 * and not the RGB channels. 1358 * 1359 * Similarly, when the src FBO was created an RGB format may have been 1360 * requested but the driver actually chose an RGBA format. In that case, 1361 * we don't want to copy the undefined Alpha channel to the dest texture 1362 * (it should be 1.0). 1363 */ 1364 const GLenum srcFormat = _mesa_base_fbo_format(ctx, src->InternalFormat); 1365 const GLenum dstFormat = _mesa_base_tex_format(ctx, dst->InternalFormat); 1366 1367 /** 1368 * XXX when we have red-only and red/green renderbuffers we'll need 1369 * to add more cases here (or implement a general-purpose routine that 1370 * queries the existance of the R,G,B,A channels in the src and dest). 1371 */ 1372 if (srcFormat == dstFormat) { 1373 /* This is the same as matching_base_formats, which should 1374 * always pass, as it did previously. 1375 */ 1376 return TGSI_WRITEMASK_XYZW; 1377 } 1378 else if (srcFormat == GL_RGB && dstFormat == GL_RGBA) { 1379 /* Make sure that A in the dest is 1. The actual src format 1380 * may be RGBA and have undefined A values. 1381 */ 1382 return TGSI_WRITEMASK_XYZ; 1383 } 1384 else if (srcFormat == GL_RGBA && dstFormat == GL_RGB) { 1385 /* Make sure that A in the dest is 1. The actual dst format 1386 * may be RGBA and will need A=1 to provide proper alpha values 1387 * when sampled later. 1388 */ 1389 return TGSI_WRITEMASK_XYZ; 1390 } 1391 else { 1392 if (ST_DEBUG & DEBUG_FALLBACK) 1393 debug_printf("%s failed for src %s, dst %s\n", 1394 __FUNCTION__, 1395 _mesa_lookup_enum_by_nr(srcFormat), 1396 _mesa_lookup_enum_by_nr(dstFormat)); 1397 1398 /* Otherwise fail. 1399 */ 1400 return 0; 1401 } 1402} 1403 1404 1405 1406/** 1407 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible. 1408 * Note that the region to copy has already been clipped so we know we 1409 * won't read from outside the source renderbuffer's bounds. 1410 * 1411 * Note: srcY=0=Bottom of renderbuffer (GL convention) 1412 */ 1413static void 1414st_copy_texsubimage(struct gl_context *ctx, 1415 GLenum target, GLint level, 1416 GLint destX, GLint destY, GLint destZ, 1417 GLint srcX, GLint srcY, 1418 GLsizei width, GLsizei height) 1419{ 1420 struct gl_texture_unit *texUnit = 1421 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1422 struct gl_texture_object *texObj = 1423 _mesa_select_tex_object(ctx, texUnit, target); 1424 struct gl_texture_image *texImage = 1425 _mesa_select_tex_image(ctx, texObj, target, level); 1426 struct st_texture_image *stImage = st_texture_image(texImage); 1427 const GLenum texBaseFormat = texImage->_BaseFormat; 1428 struct gl_framebuffer *fb = ctx->ReadBuffer; 1429 struct st_renderbuffer *strb; 1430 struct st_context *st = st_context(ctx); 1431 struct pipe_context *pipe = st->pipe; 1432 struct pipe_screen *screen = pipe->screen; 1433 enum pipe_format dest_format, src_format; 1434 GLboolean use_fallback = GL_TRUE; 1435 GLboolean matching_base_formats; 1436 GLuint format_writemask, sample_count; 1437 struct pipe_surface *dest_surface = NULL; 1438 GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); 1439 1440 /* make sure finalize_textures has been called? 1441 */ 1442 if (0) st_validate_state(st); 1443 1444 /* determine if copying depth or color data */ 1445 if (texBaseFormat == GL_DEPTH_COMPONENT || 1446 texBaseFormat == GL_DEPTH_STENCIL) { 1447 strb = st_renderbuffer(fb->_DepthBuffer); 1448 if (strb->Base.Wrapped) { 1449 strb = st_renderbuffer(strb->Base.Wrapped); 1450 } 1451 } 1452 else { 1453 /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ 1454 strb = st_renderbuffer(fb->_ColorReadBuffer); 1455 } 1456 1457 if (!strb || !strb->surface || !stImage->pt) { 1458 debug_printf("%s: null strb or stImage\n", __FUNCTION__); 1459 return; 1460 } 1461 1462 sample_count = strb->surface->texture->nr_samples; 1463 /* I believe this would be legal, presumably would need to do a resolve 1464 for color, and for depth/stencil spec says to just use one of the 1465 depth/stencil samples per pixel? Need some transfer clarifications. */ 1466 assert(sample_count < 2); 1467 1468 if (srcX < 0) { 1469 width -= -srcX; 1470 destX += -srcX; 1471 srcX = 0; 1472 } 1473 1474 if (srcY < 0) { 1475 height -= -srcY; 1476 destY += -srcY; 1477 srcY = 0; 1478 } 1479 1480 if (destX < 0) { 1481 width -= -destX; 1482 srcX += -destX; 1483 destX = 0; 1484 } 1485 1486 if (destY < 0) { 1487 height -= -destY; 1488 srcY += -destY; 1489 destY = 0; 1490 } 1491 1492 if (width < 0 || height < 0) 1493 return; 1494 1495 1496 assert(strb); 1497 assert(strb->surface); 1498 assert(stImage->pt); 1499 1500 src_format = strb->surface->format; 1501 dest_format = stImage->pt->format; 1502 1503 /* 1504 * Determine if the src framebuffer and dest texture have the same 1505 * base format. We need this to detect a case such as the framebuffer 1506 * being GL_RGBA but the texture being GL_RGB. If the actual hardware 1507 * texture format stores RGBA we need to set A=1 (overriding the 1508 * framebuffer's alpha values). We can't do that with the blit or 1509 * textured-quad paths. 1510 */ 1511 matching_base_formats = 1512 (_mesa_get_format_base_format(strb->Base.Format) == 1513 _mesa_get_format_base_format(texImage->TexFormat)); 1514 format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); 1515 1516 if (ctx->_ImageTransferState == 0x0) { 1517 1518 if (matching_base_formats && 1519 src_format == dest_format && 1520 !do_flip) 1521 { 1522 /* use surface_copy() / blit */ 1523 struct pipe_box src_box; 1524 u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, 1525 width, height, &src_box); 1526 1527 /* for resource_copy_region(), y=0=top, always */ 1528 pipe->resource_copy_region(pipe, 1529 /* dest */ 1530 stImage->pt, 1531 stImage->level, 1532 destX, destY, destZ + stImage->face, 1533 /* src */ 1534 strb->texture, 1535 strb->surface->u.tex.level, 1536 &src_box); 1537 use_fallback = GL_FALSE; 1538 } 1539 else if (format_writemask && 1540 texBaseFormat != GL_DEPTH_COMPONENT && 1541 texBaseFormat != GL_DEPTH_STENCIL && 1542 screen->is_format_supported(screen, src_format, 1543 PIPE_TEXTURE_2D, sample_count, 1544 PIPE_BIND_SAMPLER_VIEW) && 1545 screen->is_format_supported(screen, dest_format, 1546 PIPE_TEXTURE_2D, 0, 1547 PIPE_BIND_RENDER_TARGET)) { 1548 /* draw textured quad to do the copy */ 1549 GLint srcY0, srcY1; 1550 struct pipe_surface surf_tmpl; 1551 memset(&surf_tmpl, 0, sizeof(surf_tmpl)); 1552 surf_tmpl.format = util_format_linear(stImage->pt->format); 1553 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 1554 surf_tmpl.u.tex.level = stImage->level; 1555 surf_tmpl.u.tex.first_layer = stImage->face + destZ; 1556 surf_tmpl.u.tex.last_layer = stImage->face + destZ; 1557 1558 dest_surface = pipe->create_surface(pipe, stImage->pt, 1559 &surf_tmpl); 1560 1561 if (do_flip) { 1562 srcY1 = strb->Base.Height - srcY - height; 1563 srcY0 = srcY1 + height; 1564 } 1565 else { 1566 srcY0 = srcY; 1567 srcY1 = srcY0 + height; 1568 } 1569 1570 /* Disable conditional rendering. */ 1571 if (st->render_condition) { 1572 pipe->render_condition(pipe, NULL, 0); 1573 } 1574 1575 util_blit_pixels_writemask(st->blit, 1576 strb->texture, 1577 strb->surface->u.tex.level, 1578 srcX, srcY0, 1579 srcX + width, srcY1, 1580 strb->surface->u.tex.first_layer, 1581 dest_surface, 1582 destX, destY, 1583 destX + width, destY + height, 1584 0.0, PIPE_TEX_MIPFILTER_NEAREST, 1585 format_writemask); 1586 1587 /* Restore conditional rendering state. */ 1588 if (st->render_condition) { 1589 pipe->render_condition(pipe, st->render_condition, 1590 st->condition_mode); 1591 } 1592 1593 use_fallback = GL_FALSE; 1594 } 1595 1596 if (dest_surface) 1597 pipe_surface_reference(&dest_surface, NULL); 1598 } 1599 1600 if (use_fallback) { 1601 /* software fallback */ 1602 fallback_copy_texsubimage(ctx, target, level, 1603 strb, stImage, texBaseFormat, 1604 destX, destY, destZ, 1605 srcX, srcY, width, height); 1606 } 1607} 1608 1609 1610 1611static void 1612st_CopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level, 1613 GLenum internalFormat, 1614 GLint x, GLint y, GLsizei width, GLint border) 1615{ 1616 struct gl_texture_unit *texUnit = 1617 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1618 struct gl_texture_object *texObj = 1619 _mesa_select_tex_object(ctx, texUnit, target); 1620 struct gl_texture_image *texImage = 1621 _mesa_select_tex_image(ctx, texObj, target, level); 1622 1623 /* Setup or redefine the texture object, texture and texture 1624 * image. Don't populate yet. 1625 */ 1626 ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 1627 width, border, 1628 GL_RGBA, CHAN_TYPE, NULL, 1629 &ctx->DefaultPacking, texObj, texImage); 1630 1631 st_copy_texsubimage(ctx, target, level, 1632 0, 0, 0, /* destX,Y,Z */ 1633 x, y, width, 1); /* src X, Y, size */ 1634} 1635 1636 1637static void 1638st_CopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level, 1639 GLenum internalFormat, 1640 GLint x, GLint y, GLsizei width, GLsizei height, 1641 GLint border) 1642{ 1643 struct gl_texture_unit *texUnit = 1644 &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1645 struct gl_texture_object *texObj = 1646 _mesa_select_tex_object(ctx, texUnit, target); 1647 struct gl_texture_image *texImage = 1648 _mesa_select_tex_image(ctx, texObj, target, level); 1649 1650 /* Setup or redefine the texture object, texture and texture 1651 * image. Don't populate yet. 1652 */ 1653 ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 1654 width, height, border, 1655 GL_RGBA, CHAN_TYPE, NULL, 1656 &ctx->DefaultPacking, texObj, texImage); 1657 1658 st_copy_texsubimage(ctx, target, level, 1659 0, 0, 0, /* destX,Y,Z */ 1660 x, y, width, height); /* src X, Y, size */ 1661} 1662 1663 1664static void 1665st_CopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level, 1666 GLint xoffset, GLint x, GLint y, GLsizei width) 1667{ 1668 const GLint yoffset = 0, zoffset = 0; 1669 const GLsizei height = 1; 1670 st_copy_texsubimage(ctx, target, level, 1671 xoffset, yoffset, zoffset, /* destX,Y,Z */ 1672 x, y, width, height); /* src X, Y, size */ 1673} 1674 1675 1676static void 1677st_CopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level, 1678 GLint xoffset, GLint yoffset, 1679 GLint x, GLint y, GLsizei width, GLsizei height) 1680{ 1681 const GLint zoffset = 0; 1682 st_copy_texsubimage(ctx, target, level, 1683 xoffset, yoffset, zoffset, /* destX,Y,Z */ 1684 x, y, width, height); /* src X, Y, size */ 1685} 1686 1687 1688static void 1689st_CopyTexSubImage3D(struct gl_context * ctx, GLenum target, GLint level, 1690 GLint xoffset, GLint yoffset, GLint zoffset, 1691 GLint x, GLint y, GLsizei width, GLsizei height) 1692{ 1693 st_copy_texsubimage(ctx, target, level, 1694 xoffset, yoffset, zoffset, /* destX,Y,Z */ 1695 x, y, width, height); /* src X, Y, size */ 1696} 1697 1698 1699/** 1700 * Copy image data from stImage into the texture object 'stObj' at level 1701 * 'dstLevel'. 1702 */ 1703static void 1704copy_image_data_to_texture(struct st_context *st, 1705 struct st_texture_object *stObj, 1706 GLuint dstLevel, 1707 struct st_texture_image *stImage) 1708{ 1709 /* debug checks */ 1710 { 1711 const struct gl_texture_image *dstImage = 1712 stObj->base.Image[stImage->face][dstLevel]; 1713 assert(dstImage); 1714 assert(dstImage->Width == stImage->base.Width); 1715 assert(dstImage->Height == stImage->base.Height); 1716 assert(dstImage->Depth == stImage->base.Depth); 1717 } 1718 1719 if (stImage->pt) { 1720 /* Copy potentially with the blitter: 1721 */ 1722 st_texture_image_copy(st->pipe, 1723 stObj->pt, dstLevel, /* dest texture, level */ 1724 stImage->pt, stImage->level, /* src texture, level */ 1725 stImage->face); 1726 1727 pipe_resource_reference(&stImage->pt, NULL); 1728 } 1729 else if (stImage->base.Data) { 1730 st_texture_image_data(st, 1731 stObj->pt, 1732 stImage->face, 1733 dstLevel, 1734 stImage->base.Data, 1735 stImage->base.RowStride * 1736 util_format_get_blocksize(stObj->pt->format), 1737 stImage->base.RowStride * 1738 stImage->base.Height * 1739 util_format_get_blocksize(stObj->pt->format)); 1740 _mesa_align_free(stImage->base.Data); 1741 stImage->base.Data = NULL; 1742 } 1743 1744 pipe_resource_reference(&stImage->pt, stObj->pt); 1745} 1746 1747 1748/** 1749 * Called during state validation. When this function is finished, 1750 * the texture object should be ready for rendering. 1751 * \return GL_TRUE for success, GL_FALSE for failure (out of mem) 1752 */ 1753GLboolean 1754st_finalize_texture(struct gl_context *ctx, 1755 struct pipe_context *pipe, 1756 struct gl_texture_object *tObj) 1757{ 1758 struct st_context *st = st_context(ctx); 1759 struct st_texture_object *stObj = st_texture_object(tObj); 1760 const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 1761 GLuint face; 1762 struct st_texture_image *firstImage; 1763 enum pipe_format firstImageFormat; 1764 GLuint ptWidth, ptHeight, ptDepth, ptLayers; 1765 1766 if (stObj->base._Complete) { 1767 /* The texture is complete and we know exactly how many mipmap levels 1768 * are present/needed. This is conditional because we may be called 1769 * from the st_generate_mipmap() function when the texture object is 1770 * incomplete. In that case, we'll have set stObj->lastLevel before 1771 * we get here. 1772 */ 1773 if (stObj->base.Sampler.MinFilter == GL_LINEAR || 1774 stObj->base.Sampler.MinFilter == GL_NEAREST) 1775 stObj->lastLevel = stObj->base.BaseLevel; 1776 else 1777 stObj->lastLevel = stObj->base._MaxLevel; 1778 } 1779 1780 firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); 1781 assert(firstImage); 1782 1783 /* If both firstImage and stObj point to a texture which can contain 1784 * all active images, favour firstImage. Note that because of the 1785 * completeness requirement, we know that the image dimensions 1786 * will match. 1787 */ 1788 if (firstImage->pt && 1789 firstImage->pt != stObj->pt && 1790 (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) { 1791 pipe_resource_reference(&stObj->pt, firstImage->pt); 1792 pipe_sampler_view_reference(&stObj->sampler_view, NULL); 1793 } 1794 1795 /* Find gallium format for the Mesa texture */ 1796 firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); 1797 1798 /* Find size of level=0 Gallium mipmap image, plus number of texture layers */ 1799 { 1800 GLuint width, height, depth; 1801 if (!guess_base_level_size(stObj->base.Target, 1802 firstImage->base.Width2, 1803 firstImage->base.Height2, 1804 firstImage->base.Depth2, 1805 stObj->base.BaseLevel, 1806 &width, &height, &depth)) { 1807 width = stObj->width0; 1808 height = stObj->height0; 1809 depth = stObj->depth0; 1810 } 1811 /* convert GL dims to Gallium dims */ 1812 st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth, 1813 &ptWidth, &ptHeight, &ptDepth, &ptLayers); 1814 } 1815 1816 /* If we already have a gallium texture, check that it matches the texture 1817 * object's format, target, size, num_levels, etc. 1818 */ 1819 if (stObj->pt) { 1820 if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || 1821 !st_sampler_compat_formats(stObj->pt->format, firstImageFormat) || 1822 stObj->pt->last_level < stObj->lastLevel || 1823 stObj->pt->width0 != ptWidth || 1824 stObj->pt->height0 != ptHeight || 1825 stObj->pt->depth0 != ptDepth || 1826 stObj->pt->array_size != ptLayers) 1827 { 1828 /* The gallium texture does not match the Mesa texture so delete the 1829 * gallium texture now. We'll make a new one below. 1830 */ 1831 pipe_resource_reference(&stObj->pt, NULL); 1832 pipe_sampler_view_reference(&stObj->sampler_view, NULL); 1833 st->dirty.st |= ST_NEW_FRAMEBUFFER; 1834 } 1835 } 1836 1837 /* May need to create a new gallium texture: 1838 */ 1839 if (!stObj->pt) { 1840 GLuint bindings = default_bindings(st, firstImageFormat); 1841 1842 stObj->pt = st_texture_create(st, 1843 gl_target_to_pipe(stObj->base.Target), 1844 firstImageFormat, 1845 stObj->lastLevel, 1846 ptWidth, 1847 ptHeight, 1848 ptDepth, 1849 ptLayers, 1850 bindings); 1851 1852 if (!stObj->pt) { 1853 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 1854 return GL_FALSE; 1855 } 1856 } 1857 1858 /* Pull in any images not in the object's texture: 1859 */ 1860 for (face = 0; face < nr_faces; face++) { 1861 GLuint level; 1862 for (level = stObj->base.BaseLevel; level <= stObj->lastLevel; level++) { 1863 struct st_texture_image *stImage = 1864 st_texture_image(stObj->base.Image[face][level]); 1865 1866 /* Need to import images in main memory or held in other textures. 1867 */ 1868 if (stImage && stObj->pt != stImage->pt) { 1869 if (level == 0 || (stImage->base.Width == u_minify(stObj->width0, level) && 1870 stImage->base.Height == u_minify(stObj->height0, level) && 1871 stImage->base.Depth == u_minify(stObj->depth0, level))) { 1872 /* src image fits expected dest mipmap level size */ 1873 copy_image_data_to_texture(st, stObj, level, stImage); 1874 } 1875 } 1876 } 1877 } 1878 1879 return GL_TRUE; 1880} 1881 1882 1883/** 1884 * Returns pointer to a default/dummy texture. 1885 * This is typically used when the current shader has tex/sample instructions 1886 * but the user has not provided a (any) texture(s). 1887 */ 1888struct gl_texture_object * 1889st_get_default_texture(struct st_context *st) 1890{ 1891 if (!st->default_texture) { 1892 static const GLenum target = GL_TEXTURE_2D; 1893 GLubyte pixels[16][16][4]; 1894 struct gl_texture_object *texObj; 1895 struct gl_texture_image *texImg; 1896 GLuint i, j; 1897 1898 /* The ARB_fragment_program spec says (0,0,0,1) should be returned 1899 * when attempting to sample incomplete textures. 1900 */ 1901 for (i = 0; i < 16; i++) { 1902 for (j = 0; j < 16; j++) { 1903 pixels[i][j][0] = 0; 1904 pixels[i][j][1] = 0; 1905 pixels[i][j][2] = 0; 1906 pixels[i][j][3] = 255; 1907 } 1908 } 1909 1910 texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target); 1911 1912 texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0); 1913 1914 _mesa_init_teximage_fields(st->ctx, target, texImg, 1915 16, 16, 1, 0, /* w, h, d, border */ 1916 GL_RGBA, MESA_FORMAT_RGBA8888); 1917 1918 st_TexImage(st->ctx, 2, target, 1919 0, GL_RGBA, /* level, intformat */ 1920 16, 16, 1, 0, /* w, h, d, border */ 1921 GL_RGBA, GL_UNSIGNED_BYTE, pixels, 1922 &st->ctx->DefaultPacking, 1923 texObj, texImg, 1924 0, 0); 1925 1926 texObj->Sampler.MinFilter = GL_NEAREST; 1927 texObj->Sampler.MagFilter = GL_NEAREST; 1928 texObj->_Complete = GL_TRUE; 1929 1930 st->default_texture = texObj; 1931 } 1932 return st->default_texture; 1933} 1934 1935 1936void 1937st_init_texture_functions(struct dd_function_table *functions) 1938{ 1939 functions->ChooseTextureFormat = st_ChooseTextureFormat; 1940 functions->TexImage1D = st_TexImage1D; 1941 functions->TexImage2D = st_TexImage2D; 1942 functions->TexImage3D = st_TexImage3D; 1943 functions->TexSubImage1D = st_TexSubImage1D; 1944 functions->TexSubImage2D = st_TexSubImage2D; 1945 functions->TexSubImage3D = st_TexSubImage3D; 1946 functions->CompressedTexSubImage1D = st_CompressedTexSubImage1D; 1947 functions->CompressedTexSubImage2D = st_CompressedTexSubImage2D; 1948 functions->CompressedTexSubImage3D = st_CompressedTexSubImage3D; 1949 functions->CopyTexImage1D = st_CopyTexImage1D; 1950 functions->CopyTexImage2D = st_CopyTexImage2D; 1951 functions->CopyTexSubImage1D = st_CopyTexSubImage1D; 1952 functions->CopyTexSubImage2D = st_CopyTexSubImage2D; 1953 functions->CopyTexSubImage3D = st_CopyTexSubImage3D; 1954 functions->GenerateMipmap = st_generate_mipmap; 1955 1956 functions->GetTexImage = st_GetTexImage; 1957 1958 /* compressed texture functions */ 1959 functions->CompressedTexImage2D = st_CompressedTexImage2D; 1960 functions->GetCompressedTexImage = st_GetCompressedTexImage; 1961 1962 functions->NewTextureObject = st_NewTextureObject; 1963 functions->NewTextureImage = st_NewTextureImage; 1964 functions->DeleteTexture = st_DeleteTextureObject; 1965 functions->FreeTexImageData = st_FreeTextureImageData; 1966 1967 functions->TextureMemCpy = do_memcpy; 1968 1969 /* XXX Temporary until we can query pipe's texture sizes */ 1970 functions->TestProxyTexImage = _mesa_test_proxy_teximage; 1971} 1972