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