st_cb_texture.c revision 8d249ca620f6995cc5824d95c29bda7043bbdf8c
124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**************************************************************************
224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * All Rights Reserved.
524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Permission is hereby granted, free of charge, to any person obtaining a
724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * copy of this software and associated documentation files (the
824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * "Software"), to deal in the Software without restriction, including
924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * without limitation the rights to use, copy, modify, merge, publish,
1024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * distribute, sub license, and/or sell copies of the Software, and to
1124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * permit persons to whom the Software is furnished to do so, subject to
1224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * the following conditions:
1324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
1424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The above copyright notice and this permission notice (including the
1524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * next paragraph) shall be included in all copies or substantial portions
1624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * of the Software.
1724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
1824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
2624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian **************************************************************************/
2724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
2824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/imports.h"
29b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#if FEATURE_convolution
3024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/convolve.h"
31b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
3224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/enums.h"
3324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/image.h"
3424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/macros.h"
352440ff74d69a8caf49b05a960b4c7e282a96565eBrian#include "main/mipmap.h"
36cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul#include "main/pixel.h"
3724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texcompress.h"
3824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texformat.h"
3924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/teximage.h"
4024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texobj.h"
4124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texstore.h"
4224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_context.h"
44b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian#include "state_tracker/st_cb_fbo.h"
4524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_cb_texture.h"
46f8ab24760d0d3f07e9ee81c98207ddf92dfe74daBrian#include "state_tracker/st_format.h"
4702250c855fbec5299a2d6118fefa0523ec73654cMichel Dänzer#include "state_tracker/st_public.h"
48753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer#include "state_tracker/st_texture.h"
4962abcb9aacc33218d0143a743c738435794b32a9Brian#include "state_tracker/st_gen_mipmap.h"
5024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "pipe/p_context.h"
52b245840b86cf877c9b8d666edf229364a84f1deaBrian#include "pipe/p_defines.h"
5311a80160fd60d1eb1541b49128c659526a5d8ac8Michel Dänzer#include "pipe/p_inlines.h"
544f25420bdd834e81a3e22733304efc5261c2998aBrian Paul#include "util/u_tile.h"
553c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer#include "util/u_blit.h"
5624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define DBG if (0) printf
5924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
6024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
611c5f27a18b775b3784fcd265d60e0affa0b31581Michel Dänzerstatic enum pipe_texture_target
625390a43ce06b27f6d54bc5f237aa305b6948f2afBriangl_target_to_pipe(GLenum target)
635390a43ce06b27f6d54bc5f237aa305b6948f2afBrian{
645390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   switch (target) {
655390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_1D:
665390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_1D;
675390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
685390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_2D:
695390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_RECTANGLE_NV:
705390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_2D;
715390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
725390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_3D:
735390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_3D;
745390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
755390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_CUBE_MAP_ARB:
765390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_CUBE;
775390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
785390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   default:
795390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      assert(0);
805390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return 0;
815390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   }
825390a43ce06b27f6d54bc5f237aa305b6948f2afBrian}
835390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
845390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
85afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
86afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Return nominal bytes per texel for a compressed format, 0 for non-compressed
87afc54983370033b65e3a7cbb29bd9c87156f0881Brian * format.
88afc54983370033b65e3a7cbb29bd9c87156f0881Brian */
8924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
9014b98343309fdcff3514f05020303f7b40e83a4aBriancompressed_num_bytes(GLuint mesaFormat)
9124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
9224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch(mesaFormat) {
935b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_fxt1
9424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_FXT1:
9524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_FXT1:
965b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
975b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_s3tc
9824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_DXT1:
9924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT1:
100afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 2;
10124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT3:
10224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT5:
103afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 4;
1045b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
10524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
106afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 0;
10724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
10824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
10924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
11024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1114e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureImage() */
11224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_image *
11324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureImage(GLcontext * ctx)
11424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
11524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
11624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   (void) ctx;
11724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image);
11824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
11924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1214e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureObject() */
12224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_object *
12324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
12424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
12524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object);
12624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
12824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_initialize_texture_object(&obj->base, name, target);
12924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return &obj->base;
13124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
13224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1334e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.DeleteTextureImage() */
13424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
13524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_DeleteTextureObject(GLcontext *ctx,
1366f715dcc219071e574e363a9db4365c9c31ebbd3Brian                       struct gl_texture_object *texObj)
13724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
13824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_object *stObj = st_texture_object(texObj);
139753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt)
140f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
14124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_delete_texture_object(ctx, texObj);
14324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
14424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1464e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.FreeTexImageData() */
14724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
14824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
14924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
15024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
15124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
15324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
154753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
155f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
15624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
15724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->Data) {
15924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      free(texImage->Data);
16024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
16124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
16224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
16324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
16424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1654e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
16624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * From linux kernel i386 header files, copes with odd sizes better
16724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * than COPY_DWORDS would:
16824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * XXX Put this in src/mesa/main/imports.h ???
16924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
17024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#if defined(i386) || defined(__i386__)
17124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic INLINE void *
17224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian__memcpy(void *to, const void *from, size_t n)
17324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
17424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int d0, d1, d2;
17524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   __asm__ __volatile__("rep ; movsl\n\t"
17624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "testb $2,%b4\n\t"
17724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 1f\n\t"
17824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsw\n"
17924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "1:\ttestb $1,%b4\n\t"
18024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 2f\n\t"
18124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
18224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
18324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"memory");
18424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (to);
18524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
18624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#else
18724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define __memcpy(a,b,c) memcpy(a,b,c)
18824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#endif
18924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
19024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1914e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
1924e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * The system memcpy (at least on ubuntu 5.10) has problems copying
19324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * to agp (writecombined) memory from a source which isn't 64-byte
19424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * aligned - there is a 4x performance falloff.
19524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
19624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The x86 __memcpy is immune to this but is slightly slower
19724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * (10%-ish) than the system memcpy.
19824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
19924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
20024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * isn't much faster than x86_memcpy for agp copies.
20124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * TODO: switch dynamically.
20324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
20424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void *
20524df8f895fe8807aa2ba058e71bd40adfc01d21eBriando_memcpy(void *dest, const void *src, size_t n)
20624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
20724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
20824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return __memcpy(dest, src, n);
20924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
21024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
21124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return memcpy(dest, src, n);
21224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
21324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
21424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
21524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
21624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianlogbase2(int n)
21724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
2184e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLint i = 1, log2 = 0;
21924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   while (n > i) {
22024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      i *= 2;
22124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      log2++;
22224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
22324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return log2;
22424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
22524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
22624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
227f52f5136e6eed23e55098681e5b082cc452136d6Brian/**
228f52f5136e6eed23e55098681e5b082cc452136d6Brian * Allocate a pipe_texture object for the given st_texture_object using
229f52f5136e6eed23e55098681e5b082cc452136d6Brian * the given st_texture_image to guess the mipmap size/levels.
230f52f5136e6eed23e55098681e5b082cc452136d6Brian *
231f52f5136e6eed23e55098681e5b082cc452136d6Brian * [comments...]
232f52f5136e6eed23e55098681e5b082cc452136d6Brian * Otherwise, store it in memory if (Border != 0) or (any dimension ==
23324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * 1).
23424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
235753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, if max_level >= level >= min_level, create texture with
236753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * space for images from min_level down to max_level.
23724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
238753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, create texture with space for images from (level 0)..(1x1).
239753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Consider pruning this texture at a validation if the saving is worth it.
24024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
24124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
242753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerguess_and_alloc_texture(struct st_context *st,
243753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			struct st_texture_object *stObj,
244afc54983370033b65e3a7cbb29bd9c87156f0881Brian			const struct st_texture_image *stImage)
24524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
24624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint firstLevel;
24724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint lastLevel;
24845cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint width = stImage->base.Width2;  /* size w/out border */
24945cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint height = stImage->base.Height2;
25045cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint depth = stImage->base.Depth2;
25124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint i, comp_byte = 0;
252a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   enum pipe_format fmt;
25324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
25424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
25524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
256f52f5136e6eed23e55098681e5b082cc452136d6Brian   assert(!stObj->pt);
257f52f5136e6eed23e55098681e5b082cc452136d6Brian
25845cc35e77600af8628393475405160e26d56d421Brian Paul   if (stObj->pt &&
2596c534b830c6f5427c391c5225c34561141c201baMichal Krol       (GLint) stImage->level > stObj->base.BaseLevel &&
26014b98343309fdcff3514f05020303f7b40e83a4aBrian       (stImage->base.Width == 1 ||
26114b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target != GL_TEXTURE_1D &&
26214b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Height == 1) ||
26314b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target == GL_TEXTURE_3D &&
26414b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Depth == 1)))
26524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
26624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
26724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* If this image disrespects BaseLevel, allocate from level zero.
26824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Usually BaseLevel == 0, so it's unlikely to happen.
26924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
2706c534b830c6f5427c391c5225c34561141c201baMichal Krol   if ((GLint) stImage->level < stObj->base.BaseLevel)
27124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = 0;
27224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
27314b98343309fdcff3514f05020303f7b40e83a4aBrian      firstLevel = stObj->base.BaseLevel;
27424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
27524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
27624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Figure out image dimensions at start level.
27724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
27814b98343309fdcff3514f05020303f7b40e83a4aBrian   for (i = stImage->level; i > firstLevel; i--) {
27945cc35e77600af8628393475405160e26d56d421Brian Paul      if (width != 1)
28045cc35e77600af8628393475405160e26d56d421Brian Paul         width <<= 1;
28124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (height != 1)
28224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         height <<= 1;
28324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (depth != 1)
28424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         depth <<= 1;
28524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
28624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
287296378b6c8b205048244746e260739448c4ee590Brian Paul   if (width == 0 || height == 0 || depth == 0) {
288296378b6c8b205048244746e260739448c4ee590Brian Paul      /* no texture needed */
289296378b6c8b205048244746e260739448c4ee590Brian Paul      return;
290296378b6c8b205048244746e260739448c4ee590Brian Paul   }
291296378b6c8b205048244746e260739448c4ee590Brian Paul
29224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Guess a reasonable value for lastLevel.  This is probably going
29324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * to be wrong fairly often and might mean that we have to look at
29424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * resizable buffers, or require that buffers implement lazy
29524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * pagetable arrangements.
29624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
29714b98343309fdcff3514f05020303f7b40e83a4aBrian   if ((stObj->base.MinFilter == GL_NEAREST ||
29814b98343309fdcff3514f05020303f7b40e83a4aBrian        stObj->base.MinFilter == GL_LINEAR) &&
29914b98343309fdcff3514f05020303f7b40e83a4aBrian       stImage->level == firstLevel) {
30024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel;
30124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
30224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
303f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2width = logbase2(width);
304f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2height = logbase2(height);
305f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2depth = logbase2(depth);
30624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
30724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
30824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
30914b98343309fdcff3514f05020303f7b40e83a4aBrian   if (stImage->base.IsCompressed)
31014b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
311f52f5136e6eed23e55098681e5b082cc452136d6Brian
312a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
313753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   stObj->pt = st_texture_create(st,
3145390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 gl_target_to_pipe(stObj->base.Target),
315a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 fmt,
3165390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 lastLevel,
3175390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 width,
3185390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 height,
3195390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 depth,
320a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                 comp_byte,
321a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 ( (pf_is_depth_stencil(fmt) ?
322a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
323a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_RENDER_TARGET) |
324a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                   PIPE_TEXTURE_USAGE_SAMPLER ));
32524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
32624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s - success\n", __FUNCTION__);
32724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
32824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
32924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
330212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian/**
331212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Adjust pixel unpack params and image dimensions to strip off the
332212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * texture border.
333212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Gallium doesn't support texture borders.  They've seldem been used
334212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * and seldom been implemented correctly anyway.
335212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * \param unpackNew  returns the new pixel unpack parameters
336212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian */
337212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstatic void
338212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstrip_texture_border(GLint border,
339212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     GLint *width, GLint *height, GLint *depth,
340212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     const struct gl_pixelstore_attrib *unpack,
341212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     struct gl_pixelstore_attrib *unpackNew)
342212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian{
343212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(border > 0);  /* sanity check */
344212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
345212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *unpackNew = *unpack;
346212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
347212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (unpackNew->RowLength == 0)
348212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->RowLength = *width;
349212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
350212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && unpackNew->ImageHeight == 0)
351212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->ImageHeight = *height;
352212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
353212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   unpackNew->SkipPixels += border;
354212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height)
355212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipRows += border;
356212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth)
357212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipImages += border;
358212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
359212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(*width >= 3);
360212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *width = *width - 2 * border;
361212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height && *height >= 3)
362212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *height = *height - 2 * border;
363212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && *depth >= 3)
364212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *depth = *depth - 2 * border;
365212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian}
366212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
36724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
3684e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
3694e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do glTexImage1/2/3D().
3704e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul */
37124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
37224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage(GLcontext * ctx,
373afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint dims,
374afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum target, GLint level,
375afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint internalFormat,
376afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint width, GLint height, GLint depth,
377afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint border,
378afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum format, GLenum type, const void *pixels,
379afc54983370033b65e3a7cbb29bd9c87156f0881Brian            const struct gl_pixelstore_attrib *unpack,
380afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_object *texObj,
381afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_image *texImage,
382afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLsizei imageSize, int compressed)
38324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
38414b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(texObj);
38514b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_image *stImage = st_texture_image(texImage);
386212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   GLint postConvWidth, postConvHeight;
38724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLint texelBytes, sizeInBytes;
38824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
389212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   struct gl_pixelstore_attrib unpackNB;
39024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
39124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
39224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
39324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
394212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   /* gallium does not support texture borders, strip it off */
395212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (border) {
396212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      strip_texture_border(border, &width, &height, &depth,
397212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                           unpack, &unpackNB);
398212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpack = &unpackNB;
39921989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Width = width;
40021989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Height = height;
40121989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Depth = depth;
40221989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Border = 0;
403212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      border = 0;
404212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   }
405212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
406212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvWidth = width;
407212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvHeight = height;
408212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
409cfe9e66f2bc596c43760911e7c1604bb32cdee28Brian   stImage->face = _mesa_tex_target_to_face(target);
41014b98343309fdcff3514f05020303f7b40e83a4aBrian   stImage->level = level;
41124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
412b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#if FEATURE_convolution
41324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
41424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
41524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                         &postConvHeight);
41624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
417b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
41824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
41924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* choose the texture format */
42024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
421afc54983370033b65e3a7cbb29bd9c87156f0881Brian                                                format, type);
42224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_set_fetch_functions(texImage, dims);
42424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->TexFormat->TexelBytes == 0) {
42624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* must be a compressed format */
42724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = 0;
42824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->IsCompressed = GL_TRUE;
42924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->CompressedSize =
43024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
43124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->Height, texImage->Depth,
43224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->TexFormat->MesaFormat);
433afc54983370033b65e3a7cbb29bd9c87156f0881Brian   }
434afc54983370033b65e3a7cbb29bd9c87156f0881Brian   else {
43524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = texImage->TexFormat->TexelBytes;
43624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
43724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Minimum pitch of 32 bytes */
43824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (postConvWidth * texelBytes < 32) {
43924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 postConvWidth = 32 / texelBytes;
44024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 texImage->RowStride = postConvWidth;
44124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
44224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4437585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /* we'll set RowStride elsewhere when the texture is a "mapped" state */
4447585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /*assert(texImage->RowStride == postConvWidth);*/
44524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
44624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
44724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Release the reference to a potentially orphaned buffer.
44824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Release any old malloced memory.
44924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
450753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
451f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
45224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(!texImage->Data);
45324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
45424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else if (texImage->Data) {
45524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(texImage->Data);
45624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
45724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
45837607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul   if (width == 0 || height == 0 || depth == 0) {
45937607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul      /* stop after freeing old image */
46037607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul      return;
46137607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul   }
46237607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul
4634da1cdf78fa3b954840650fa46cf72da5daf149fBrian   /* If this is the only mipmap level in the texture, could call
46424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * bmBufferData with NULL data to free the old block and avoid
46524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * waiting on any outstanding fences.
46624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
467753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
468d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer       (stObj->teximage_realloc ||
469d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer        (/*stObj->pt->first_level == level &&*/
470d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->last_level == level &&
471d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->target != PIPE_TEXTURE_CUBE &&
472d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         !st_texture_match_image(stObj->pt, &stImage->base,
473d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer                                 stImage->face, stImage->level)))) {
47424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
47524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      DBG("release it\n");
476f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
477753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(!stObj->pt);
478d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer      stObj->teximage_realloc = FALSE;
47924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
48024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
481753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
482753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      guess_and_alloc_texture(ctx->st, stObj, stImage);
483753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!stObj->pt) {
4848d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         /* Probably out of memory.
4858d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul          * Try flushing any pending rendering, then retry.
4868d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul          */
4878d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         st_finish(ctx->st);
4888d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         guess_and_alloc_texture(ctx->st, stObj, stImage);
4898d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         if (!stObj->pt) {
4908d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
4918d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul            return;
4928d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         }
49324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
49424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
49524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
496753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   assert(!stImage->pt);
49724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
498753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
499753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       st_texture_match_image(stObj->pt, &stImage->base,
50014b98343309fdcff3514f05020303f7b40e83a4aBrian                                 stImage->face, stImage->level)) {
50124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5024da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stImage->pt, stObj->pt);
503753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(stImage->pt);
50424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
50524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
506753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stImage->pt)
507753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      DBG("XXX: Image did not fit into texture - storing in local memory!\n");
50824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
509987d59bb83e9e08192563e5f1b52949c5511053cMichel Dänzer   /* st_CopyTexImage calls this function with pixels == NULL, with
510753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer    * the expectation that the texture will be set up but nothing
51124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * more will be done.  This is where those calls return:
51224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
51324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
51424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
51524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      unpack,
51624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      "glCompressedTexImage");
51724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   } else {
51824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
51924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   format, type,
52024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   pixels, unpack, "glTexImage");
52124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
52224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
52324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
52424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
525753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
526c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
527c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_WRITE);
5282a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      if (stImage->surface)
5294ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca         dstRowStride = stImage->surface->stride;
53024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
53124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
53224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Allocate regular memory and store the image there temporarily.   */
53324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (texImage->IsCompressed) {
53424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = texImage->CompressedSize;
53524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride =
53624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian            _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
53724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         assert(dims != 3);
53824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
53924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
54024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride = postConvWidth * texelBytes;
54124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = depth * dstRowStride * postConvHeight;
54224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
54324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
54424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = malloc(sizeInBytes);
54524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
54624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5472a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   if (!texImage->Data) {
5482a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
5492a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      return;
5502a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   }
5512a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul
55224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
55324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       width, height, depth, width * texelBytes, dstRowStride);
55424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
55524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Copy data.  Would like to know when it's ok for us to eg. use
55624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * the blitter to copy.  Or, use the hardware to do the format
55724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * conversion and copy:
55824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
55924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
560afc54983370033b65e3a7cbb29bd9c87156f0881Brian      memcpy(texImage->Data, pixels, imageSize);
56124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
562753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   else {
563753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
564753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						       format, type);
565753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      int i;
5665823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian      const GLubyte *src = (const GLubyte *) pixels;
567753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
568753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      for (i = 0; i++ < depth;) {
569753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (!texImage->TexFormat->StoreImage(ctx, dims,
570753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->_BaseFormat,
571753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->TexFormat,
572753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->Data,
573753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      0, 0, 0, /* dstX/Y/Zoffset */
574753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      dstRowStride,
575753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->ImageOffsets,
576753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      width, height, 1,
5775823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					      format, type, src, unpack)) {
578753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
579753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
580753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
581753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (stImage->pt && i < depth) {
582c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    st_texture_image_unmap(ctx->st, stImage);
583c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    texImage->Data = st_texture_image_map(ctx->st, stImage, i,
584c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                                  PIPE_BUFFER_USAGE_CPU_WRITE);
5855823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	    src += srcImageStride;
586753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
587753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
58824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
58924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, unpack);
59124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
592753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
593c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
59424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
59524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
59624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
59862abcb9aacc33218d0143a743c738435794b32a9Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
59924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
60024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
60124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
60224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
60324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
60424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage3D(GLcontext * ctx,
6054e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6064e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6074e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint depth,
6084e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint border,
6094e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6104e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6114e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6124e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
61324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
61424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 3, target, level,
61524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, depth, border,
61624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
61724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
61824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
61924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
62024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
62124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage2D(GLcontext * ctx,
6224e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6234e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6244e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint border,
6254e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6264e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6274e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6284e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
62924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
63024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
63124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, 1, border,
63224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
63324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
63424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
63524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
63624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
63724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage1D(GLcontext * ctx,
6384e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6394e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6404e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint border,
6414e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6424e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6434e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6444e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
64524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
64624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 1, target, level,
64724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, 1, 1, border,
64824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
64924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
65024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
65124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
65224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
6534e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
6544e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint internalFormat,
6554e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint width, GLint height, GLint border,
6564e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLsizei imageSize, const GLvoid *data,
6574e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_object *texObj,
6584e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_image *texImage)
65924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
66024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
66124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 internalFormat, width, height, 1, border,
66224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
66324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
66424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
66524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
66624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
66724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Need to map texture image into memory before copying image data,
66824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * then unmap it.
66924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
67024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
67124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
67224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 GLenum format, GLenum type, GLvoid * pixels,
67324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_object *texObj,
67424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_image *texImage, int compressed)
67524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
67624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
6774e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
6784e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    texImage->Width,
6794e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul						    texImage->Height,
6804e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    format, type);
681753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint depth;
6826c534b830c6f5427c391c5225c34561141c201baMichal Krol   GLuint i;
6835823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   GLubyte *dest;
68424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
68524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map */
686753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
68724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Image is stored in hardware format in a buffer managed by the
68824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * kernel.  Need to explicitly map and unmap it.
68924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
690c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
691c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_READ);
6924ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca      texImage->RowStride = stImage->surface->stride / stImage->pt->block.size;
69324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
69424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
69524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Otherwise, the image should actually be stored in
696753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       * texImage->Data.  This is pretty confusing for
69724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * everybody, I'd much prefer to separate the two functions of
69824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * texImage->Data - storage for texture images in main memory
69924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * and access (ie mappings) of images.  In other words, we'd
70024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * create a new texImage->Map field and leave Data simply for
70124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * storage.
70224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
703753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(texImage->Data);
70424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
70524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
706753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   depth = texImage->Depth;
707753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = 1;
70824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
7095823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   dest = (GLubyte *) pixels;
7105823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
711753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
712753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (compressed) {
7135823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_compressed_teximage(ctx, target, level, dest,
714753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer				       texObj, texImage);
715753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      } else {
7165823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_teximage(ctx, target, level, format, type, dest,
717753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			    texObj, texImage);
718753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
719753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
720753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
721c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
722c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, i,
723c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                               PIPE_BUFFER_USAGE_CPU_READ);
7245823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 dest += dstImageStride;
725753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
72624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
727753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
728753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = depth;
72924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Unmap */
731753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
732c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
733753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      texImage->Data = NULL;
73424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
73524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
73624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
73924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
7404e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, GLvoid * pixels,
7414e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7424e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
74324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
74424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, format, type, pixels,
74524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    texObj, texImage, 0);
74624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
74724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
75024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
7514e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         GLvoid *pixels,
7524e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         const struct gl_texture_object *texObj,
7534e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         const struct gl_texture_image *texImage)
75424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
75524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, 0, 0, pixels,
75624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_object *) texObj,
75724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_image *) texImage, 1);
75824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
75924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
76024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
76124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
76224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
76324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubimage(GLcontext * ctx,
7644e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint dims,
7654e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum target, GLint level,
7664e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint xoffset, GLint yoffset, GLint zoffset,
7674e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint width, GLint height, GLint depth,
7684e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, const void *pixels,
7694e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               const struct gl_pixelstore_attrib *packing,
7704e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7714e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
77224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
77324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
77424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
775753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
776753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						    format, type);
777753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   int i;
7785823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   const GLubyte *src;
77924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
78024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
78124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target),
78224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       level, xoffset, yoffset, width, height);
78324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
78424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   pixels =
78524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
78624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                  type, pixels, packing, "glTexSubImage2D");
78724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
78824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
78924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
79024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map buffer if necessary.  Need to lock to prevent other contexts
79124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * from uploading the buffer under us.
79224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
793753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
794c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
795c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_WRITE);
7962a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      if (stImage->surface)
7974ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca         dstRowStride = stImage->surface->stride;
798753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   }
799753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
8009b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   if (!texImage->Data) {
8019b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
8029b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      return;
8039b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   }
8049b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul
8055823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   src = (const GLubyte *) pixels;
8065823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
807753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
808753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
809753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->TexFormat,
810753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->Data,
811753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   xoffset, yoffset, 0,
812753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   dstRowStride,
813753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->ImageOffsets,
814753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   width, height, 1,
8155823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					   format, type, src, packing)) {
8169b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
817753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
818753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
819753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
8209b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul         /* map next slice of 3D texture */
821c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
822c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
823c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                               PIPE_BUFFER_USAGE_CPU_WRITE);
8245823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 src += srcImageStride;
825753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
82624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
82724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
82824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
8293ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
83024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
83124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
83224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, packing);
83324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
834753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
835c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
83624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
83724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
83824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
83924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
84024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
84124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
84224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
84324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage3D(GLcontext * ctx,
84424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
84524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
84624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset, GLint zoffset,
84724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height, GLsizei depth,
84824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
84924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
85024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
85124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
85224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
85324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
854b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 3, target, level,
855b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, zoffset,
856b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, depth,
857b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
85824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
85924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
86024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
86124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
86224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage2D(GLcontext * ctx,
86324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
86424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
86524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset,
86624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height,
86724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
86824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
86924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
87024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
87124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
87224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
873b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 2, target, level,
874b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, 0,
875b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, 1,
876b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
87724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
87824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
87924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
88024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
88124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage1D(GLcontext * ctx,
88224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
88324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
88424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset,
88524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width,
88624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
88724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
88824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
88924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
89024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
89124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
892b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 1, target, level,
893b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, 0, 0,
894b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, 1, 1,
895b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
89624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
89724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
90024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
901038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian * Return 0 for GL_TEXTURE_CUBE_MAP_POSITIVE_X,
902038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian *        1 for GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
903038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian *        etc.
904038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian * XXX duplicated from main/teximage.c
905038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian */
906038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic uint
907038cb561eb094af2f2ba06e18e61246fc0c87c3cBriantexture_face(GLenum target)
908038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
909038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
910038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
911038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
912038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   else
913038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      return 0;
914038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
915038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
916038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
917038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
918038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian/**
919b859cdf6f191b4d8b56537c8dc30082a7e2d94b3Michel Dänzer * Do a CopyTexSubImage operation by mapping the source surface and
920b859cdf6f191b4d8b56537c8dc30082a7e2d94b3Michel Dänzer * dest surface and using get_tile()/put_tile() to access the pixels/texels.
921c6717a86420d7141013165f7acd50b3c3f751756Brian *
922c6717a86420d7141013165f7acd50b3c3f751756Brian * Note: srcY=0=TOP of renderbuffer
923038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian */
924038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
925038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianfallback_copy_texsubimage(GLcontext *ctx,
926038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLenum target,
927038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint level,
928038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          struct st_renderbuffer *strb,
929038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          struct st_texture_image *stImage,
930038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLenum baseFormat,
931038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint destX, GLint destY, GLint destZ,
932038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint srcX, GLint srcY,
933038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLsizei width, GLsizei height)
934038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
935038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct pipe_context *pipe = ctx->st->pipe;
9366f715dcc219071e574e363a9db4365c9c31ebbd3Brian   struct pipe_screen *screen = pipe->screen;
937038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const uint face = texture_face(target);
938753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   struct pipe_texture *pt = stImage->pt;
939038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct pipe_surface *src_surf, *dest_surf;
940038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
941f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   /* We'd use strb->surface, here but it's created for GPU read/write only */
942f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   src_surf = pipe->screen->get_tex_surface( pipe->screen,
943f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             strb->texture,
944f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             0, 0, 0,
945f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             PIPE_BUFFER_USAGE_CPU_READ);
946f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul
947c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell   dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ,
948c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                       PIPE_BUFFER_USAGE_CPU_WRITE);
949038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
950cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   assert(width <= MAX_WIDTH);
951038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
952cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (baseFormat == GL_DEPTH_COMPONENT) {
953cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
954cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul                                     ctx->Pixel.DepthBias != 0.0F);
95527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLint row, yStep;
956cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
95727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* determine bottom-to-top vs. top-to-bottom order for src buffer */
95827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
95927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         srcY = strb->Base.Height - 1 - srcY;
96027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = -1;
96127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
96227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
96327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = 1;
96427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
96527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
96627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* To avoid a large temp memory allocation, do copy row by row */
967275b09f2569c8bea5dcca1643c93aa6a43d7e2a2Brian Paul      for (row = 0; row < height; row++, srcY += yStep, destY++) {
968cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         uint data[MAX_WIDTH];
96936dd89c8a7f2a911e8f7f18d1edcaf982a75a438José Fonseca         pipe_get_tile_z(src_surf, srcX, srcY, width, 1, data);
970cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         if (scaleOrBias) {
971cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul            _mesa_scale_and_bias_depth_uint(ctx, width, data);
972cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
97336dd89c8a7f2a911e8f7f18d1edcaf982a75a438José Fonseca         pipe_put_tile_z(dest_surf, destX, destY, width, 1, data);
974cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      }
975cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   }
976cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   else {
977cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      /* RGBA format */
97827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLfloat *tempSrc =
97927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
98027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLvoid *texDest =
98127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         st_texture_image_map(ctx->st, stImage, 0,PIPE_BUFFER_USAGE_CPU_WRITE);
98227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
98327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc && texDest) {
98427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         const GLint dims = 2;
98527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_texture_image *texImage = &stImage->base;
98627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         GLint dstRowStride = stImage->surface->stride;
98727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
98827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
98927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
99027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            /* need to invert src */
99127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            srcY = strb->Base.Height - srcY - height;
99227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            unpack.Invert = GL_TRUE;
993cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
99427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
99527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* get float/RGBA image from framebuffer */
99627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* XXX this usually involves a lot of int/float conversion.
99727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * try to avoid that someday.
99827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
99927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         pipe_get_tile_rgba(src_surf, srcX, srcY, width, height, tempSrc);
100027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
100127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* Store into texture memory.
100227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * Note that this does some special things such as pixel transfer
100327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * ops and format conversion.  In particular, if the dest tex format
100427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * is actually RGBA but the user created the texture as GL_RGB we
100527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * need to fill-in/override the alpha channel with 1.0.
100627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
100727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         texImage->TexFormat->StoreImage(ctx, dims,
100827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->_BaseFormat,
100927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->TexFormat,
101027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texDest,
101127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         destX, destY, destZ,
101227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         dstRowStride,
101327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->ImageOffsets,
101427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         width, height, 1,
101527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         GL_RGBA, GL_FLOAT, tempSrc, /* src */
101627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         &unpack);
101727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
101827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
101927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
10205c83f1371978472fbe4bba8f686733c6b519874aBrian      }
102127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
102227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc)
102327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_free(tempSrc);
102427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (texDest)
102527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         st_texture_image_unmap(ctx->st, stImage);
10265c83f1371978472fbe4bba8f686733c6b519874aBrian   }
1027d0279fc4b38c72356a341173317bcd45d9093f45Michel Dänzer
1028d0279fc4b38c72356a341173317bcd45d9093f45Michel Dänzer   screen->tex_surface_release(screen, &dest_surf);
1029f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   screen->tex_surface_release(screen, &src_surf);
1030038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
1031038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1032038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1033038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian/**
10344e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
10354e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note that the region to copy has already been clipped so we know we
10364e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * won't read from outside the source renderbuffer's bounds.
1037c6717a86420d7141013165f7acd50b3c3f751756Brian *
10384e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note: srcY=0=Bottom of renderbuffer (GL convention)
103924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
1040038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
10414e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_copy_texsubimage(GLcontext *ctx,
1042038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLenum target, GLint level,
1043038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint destX, GLint destY, GLint destZ,
1044038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint srcX, GLint srcY,
1045038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLsizei width, GLsizei height)
104624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1047038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_unit *texUnit =
1048038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1049038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_object *texObj =
1050038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_object(ctx, texUnit, target);
1051038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_image *texImage =
1052038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_image(ctx, texObj, target, level);
1053038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct st_texture_image *stImage = st_texture_image(texImage);
10544e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   const GLenum texBaseFormat = texImage->InternalFormat;
1055b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct gl_framebuffer *fb = ctx->ReadBuffer;
1056b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct st_renderbuffer *strb;
1057b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct pipe_context *pipe = ctx->st->pipe;
10586f715dcc219071e574e363a9db4365c9c31ebbd3Brian   struct pipe_screen *screen = pipe->screen;
105927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   enum pipe_format dest_format, src_format;
1060cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   GLboolean use_fallback = GL_TRUE;
106127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   GLboolean matching_base_formats;
106224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
106366682651b622be201b211d50c7311e0b81b2b4a5Brian Paul   /* any rendering in progress must complete before we grab the fb image */
106466682651b622be201b211d50c7311e0b81b2b4a5Brian Paul   st_finish(ctx->st);
1065a479bf62353b6517841e620122112e7565d2391cBrian Paul
1066b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   /* determine if copying depth or color data */
10674e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   if (texBaseFormat == GL_DEPTH_COMPONENT) {
1068b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_DepthBuffer);
106924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
10704e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
1071b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_StencilBuffer);
1072b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   }
1073b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   else {
10744e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
1075b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_ColorReadBuffer);
1076b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   }
1077b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
1078b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   assert(strb);
1079b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   assert(strb->surface);
1080753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   assert(stImage->pt);
1081c6717a86420d7141013165f7acd50b3c3f751756Brian
1082b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   src_format = strb->surface->format;
1083753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   dest_format = stImage->pt->format;
1084b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
108527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   /*
108627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * Determine if the src framebuffer and dest texture have the same
108727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * base format.  We need this to detect a case such as the framebuffer
108827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
108927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * texture format stores RGBA we need to set A=1 (overriding the
109027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * framebuffer's alpha values).  We can't do that with the blit or
109127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * textured-quad paths.
109227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    */
109327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
109479931e38abc62286151121a3f59127e296144551Michel Dänzer
109527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
109627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* try potential hardware path */
109727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      struct pipe_surface *dest_surface = NULL;
1098b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
10993c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer      if (src_format == dest_format) {
11004e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* use surface_copy() / blit */
1101a479bf62353b6517841e620122112e7565d2391cBrian Paul         boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
110227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
110327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
110427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
110527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
110627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
1107145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul         if (do_flip)
1108145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul            srcY = strb->surface->height - srcY - height;
1109145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul
1110145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul         /* for surface_copy(), y=0=top, always */
1111a479bf62353b6517841e620122112e7565d2391cBrian Paul         pipe->surface_copy(pipe,
1112a479bf62353b6517841e620122112e7565d2391cBrian Paul                            do_flip,
1113a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* dest */
1114a479bf62353b6517841e620122112e7565d2391cBrian Paul                            dest_surface,
1115a479bf62353b6517841e620122112e7565d2391cBrian Paul                            destX, destY,
1116a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* src */
1117a479bf62353b6517841e620122112e7565d2391cBrian Paul                            strb->surface,
1118a479bf62353b6517841e620122112e7565d2391cBrian Paul                            srcX, srcY,
1119a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* size */
1120a479bf62353b6517841e620122112e7565d2391cBrian Paul                            width, height);
1121a479bf62353b6517841e620122112e7565d2391cBrian Paul         use_fallback = GL_FALSE;
1122cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      }
11234e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      else if (screen->is_format_supported(screen, src_format,
11248aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11258aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_SAMPLER,
11268aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0) &&
11274e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               screen->is_format_supported(screen, dest_format,
11288aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11298aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_RENDER_TARGET,
11308aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0)) {
11314e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* draw textured quad to do the copy */
1132a479bf62353b6517841e620122112e7565d2391cBrian Paul         boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
1133a479bf62353b6517841e620122112e7565d2391cBrian Paul         int srcY0, srcY1;
113427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
113527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
113627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
113727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
113827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
113927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
1140a479bf62353b6517841e620122112e7565d2391cBrian Paul         if (do_flip) {
1141a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = strb->Base.Height - srcY - height;
1142a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY1 + height;
1143a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
1144a479bf62353b6517841e620122112e7565d2391cBrian Paul         else {
1145a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY;
1146a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = srcY0 + height;
1147a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
11483c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer         util_blit_pixels(ctx->st->blit,
11493c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          strb->surface,
1150a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX, srcY0,
1151a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX + width, srcY1,
11523c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          dest_surface,
1153a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX, destY,
1154a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX + width, destY + height,
11553c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          0.0, PIPE_TEX_MIPFILTER_NEAREST);
1156cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         use_fallback = GL_FALSE;
11573c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer      }
115879931e38abc62286151121a3f59127e296144551Michel Dänzer
115927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (dest_surface)
116027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         pipe_surface_reference(&dest_surface, NULL);
1161038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1162cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
1163cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (use_fallback) {
11644e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      /* software fallback */
1165038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      fallback_copy_texsubimage(ctx, target, level,
11664e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                strb, stImage, texBaseFormat,
1167038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                destX, destY, destZ,
1168038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                srcX, srcY, width, height);
1169038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1170038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
117124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
11723ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
117324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
117424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
117524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
117624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1177038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
117824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
117924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
118024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
118124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLint border)
118224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
118324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
118424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
118524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
118624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
118724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
118824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
118924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1190038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#if 0
119124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (border)
119224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      goto fail;
1193038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#endif
119424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1195753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
119624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
119724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
119824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
119924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, border,
120024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
120124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
120224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12034e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12044e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
12054e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, 1);  /* src X, Y, size */
120624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
120724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
120824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
120924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
121024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
121124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
121224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLsizei height,
121324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint border)
121424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
121524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
121624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
121724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
121824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
121924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
122024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
122124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1222753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
122324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
122424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
122524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
122624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, height, border,
122724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
122824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
122924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12304e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12314e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
12324e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
123324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
123424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
123724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
123824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint x, GLint y, GLsizei width)
123924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1240038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint yoffset = 0, zoffset = 0;
1241038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLsizei height = 1;
12424e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12434e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12444e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
124524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
124624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
124724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
124824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
124924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
125024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint yoffset,
125124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
125224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1253038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint zoffset = 0;
12544e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12554e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12564e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
1257038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
125824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
125924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1260038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
1261038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianst_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
1262038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint xoffset, GLint yoffset, GLint zoffset,
1263038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
1264038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
12654e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12664e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12674e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
126824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
126924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
127224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Compute which mipmap levels that really need to be sent to the hardware.
127324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * This depends on the base image size, GL_TEXTURE_MIN_LOD,
127424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
127524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
127624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
127714b98343309fdcff3514f05020303f7b40e83a4aBriancalculate_first_last_level(struct st_texture_object *stObj)
127824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
127914b98343309fdcff3514f05020303f7b40e83a4aBrian   struct gl_texture_object *tObj = &stObj->base;
128024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
128124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* These must be signed values.  MinLod and MaxLod can be negative numbers,
128224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * and having firstLevel and lastLevel as signed prevents the need for
128324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * extra sign checks.
128424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
128524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int firstLevel;
128624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int lastLevel;
128724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
128824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Yes, this looks overly complicated, but it's all needed.
128924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
129024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch (tObj->Target) {
129124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_1D:
129224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_2D:
129324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_3D:
129424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_CUBE_MAP:
129524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
129624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
129724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
129824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         firstLevel = lastLevel = tObj->BaseLevel;
129924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
130024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
13014da1cdf78fa3b954840650fa46cf72da5daf149fBrian         firstLevel = 0;
13024e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         lastLevel = MIN2(tObj->MaxLevel,
13034e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                          (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
130424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
130524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
130624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_RECTANGLE_NV:
130724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_4D_SGIS:
130824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = lastLevel = 0;
130924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
131024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
131124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
131224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
131324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
131414b98343309fdcff3514f05020303f7b40e83a4aBrian   stObj->lastLevel = lastLevel;
131524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
131624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
131724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
131824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
1319753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzercopy_image_data_to_texture(struct st_context *st,
1320753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_object *stObj,
13214da1cdf78fa3b954840650fa46cf72da5daf149fBrian                           GLuint dstLevel,
1322753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_image *stImage)
132324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1324753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
132524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Copy potentially with the blitter:
132624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1327753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_copy(st->pipe,
13284da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stObj->pt, dstLevel,  /* dest texture, level */
13294da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->pt, /* src texture */
13304da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->face
133128b315dc1aed36bebadfacbd55e481e7baacfcb5Brian                            );
133224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1333f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
133424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
13354c50969334844bc9aa622176c3ebcbc733394f78Brian Paul   else if (stImage->base.Data) {
133624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(stImage->base.Data != NULL);
133724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
133824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* More straightforward upload.
133924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1340753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_data(st->pipe,
1341753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer                               stObj->pt,
134224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->face,
1343c2497879f127251994064a0e0c24901782adae9eBrian Paul                               dstLevel,
134424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.Data,
13454ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.RowStride *
13464ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size,
134724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.RowStride *
13484ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.Height *
13494ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size);
135024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(stImage->base.Data);
135124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      stImage->base.Data = NULL;
135224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
135324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13544da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian   pipe_texture_reference(&stImage->pt, stObj->pt);
135524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
135624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
135724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1358afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
1359afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Called during state validation.  When this function is finished,
1360afc54983370033b65e3a7cbb29bd9c87156f0881Brian * the texture object should be ready for rendering.
13613b3774b1227743147159676795b542c0eb7c2bdfBrian Paul * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
136224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
136314b98343309fdcff3514f05020303f7b40e83a4aBrianGLboolean
1364753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerst_finalize_texture(GLcontext *ctx,
1365c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct pipe_context *pipe,
1366c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct gl_texture_object *tObj,
1367753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer		    GLboolean *needFlush)
136824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
136914b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(tObj);
1370afc54983370033b65e3a7cbb29bd9c87156f0881Brian   const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
137124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int comp_byte = 0;
137224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int cpp;
13734da1cdf78fa3b954840650fa46cf72da5daf149fBrian   GLuint face;
137424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *firstImage;
137524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
137624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   *needFlush = GL_FALSE;
137724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
137824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* We know/require this is true by now:
137924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
138014b98343309fdcff3514f05020303f7b40e83a4aBrian   assert(stObj->base._Complete);
138124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1382753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* What levels must the texture include at a minimum?
138324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
138414b98343309fdcff3514f05020303f7b40e83a4aBrian   calculate_first_last_level(stObj);
13854da1cdf78fa3b954840650fa46cf72da5daf149fBrian   firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
138624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1387753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* If both firstImage and stObj point to a texture which can contain
138824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * all active images, favour firstImage.  Note that because of the
138924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * completeness requirement, we know that the image dimensions
139024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * will match.
139124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1392753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (firstImage->pt &&
1393753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt != stObj->pt &&
1394753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt->last_level >= stObj->lastLevel) {
139524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13964da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stObj->pt, firstImage->pt);
139724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
139824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13994ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca   /* FIXME: determine format block instead of cpp */
140024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (firstImage->base.IsCompressed) {
140114b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
140224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      cpp = comp_byte;
140324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
14045cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   else {
14055cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian      cpp = firstImage->base.TexFormat->TexelBytes;
14065cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   }
140724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1408ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* If we already have a gallium texture, check that it matches the texture
1409ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul    * object's format, target, size, num_levels, etc.
141024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1411809dd9089bae70cf35cea6a75258e700e7455738Brian Paul   if (stObj->pt) {
1412809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      const enum pipe_format fmt =
1413809dd9089bae70cf35cea6a75258e700e7455738Brian Paul         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1414809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
1415809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->format != fmt ||
1416809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->last_level < stObj->lastLevel ||
1417809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->width[0] != firstImage->base.Width2 ||
1418809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->height[0] != firstImage->base.Height2 ||
1419809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->depth[0] != firstImage->base.Depth2 ||
14204ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.size != cpp ||
14214ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.width != 1 ||
14224ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.height != 1 ||
1423809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->compressed != firstImage->base.IsCompressed) {
1424809dd9089bae70cf35cea6a75258e700e7455738Brian Paul         pipe_texture_release(&stObj->pt);
14251a82d9648b3db780e58e4966924157542d148c58Brian Paul         ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
1426809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      }
142724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
142824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1429ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* May need to create a new gallium texture:
143024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1431753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
1432a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger      const enum pipe_format fmt =
1433a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1434753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      stObj->pt = st_texture_create(ctx->st,
14355390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                    gl_target_to_pipe(stObj->base.Target),
1436a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    fmt,
1437b245840b86cf877c9b8d666edf229364a84f1deaBrian                                    stObj->lastLevel,
143845cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Width2,
143945cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Height2,
144045cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Depth2,
1441a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                    comp_byte,
1442a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    ( (pf_is_depth_stencil(fmt) ?
1443a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
1444a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_RENDER_TARGET) |
1445a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                      PIPE_TEXTURE_USAGE_SAMPLER ));
1446a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell
14473b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      if (!stObj->pt) {
14483b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
14493b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         return GL_FALSE;
14503b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      }
145124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
145224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1453753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Pull in any images not in the object's texture:
145424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
145524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   for (face = 0; face < nr_faces; face++) {
14564da1cdf78fa3b954840650fa46cf72da5daf149fBrian      GLuint level;
14574da1cdf78fa3b954840650fa46cf72da5daf149fBrian      for (level = 0; level <= stObj->lastLevel; level++) {
145824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         struct st_texture_image *stImage =
14594da1cdf78fa3b954840650fa46cf72da5daf149fBrian            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
146024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1461753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer         /* Need to import images in main memory or held in other textures.
146224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
1463a34b43b3f4817268ef4b3f186203b5fbafc7214eBrian         if (stImage && stObj->pt != stImage->pt) {
14644da1cdf78fa3b954840650fa46cf72da5daf149fBrian            copy_image_data_to_texture(ctx->st, stObj, level, stImage);
146524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	    *needFlush = GL_TRUE;
146624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         }
146724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
146824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
146924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
147024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return GL_TRUE;
147124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
147224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
147324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14748f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul/**
14758f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * Returns pointer to a default/dummy texture.
14768f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * This is typically used when the current shader has tex/sample instructions
14778f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * but the user has not provided a (any) texture(s).
14788f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul */
14798f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulstruct gl_texture_object *
14808f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulst_get_default_texture(struct st_context *st)
14818f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul{
14828f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   if (!st->default_texture) {
14838f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      static const GLenum target = GL_TEXTURE_2D;
14848f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      GLubyte pixels[16][16][4];
14858f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_object *texObj;
14868f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_image *texImg;
14878f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
1488a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      /* init image to gray */
1489a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      memset(pixels, 127, sizeof(pixels));
1490a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul
14918f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
14928f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14938f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
14948f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14958f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      _mesa_init_teximage_fields(st->ctx, target, texImg,
14968f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 16, 16, 1, 0,  /* w, h, d, border */
14978f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 GL_RGBA);
14988f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14998f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st_TexImage(st->ctx, 2, target,
15008f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, GL_RGBA,    /* level, intformat */
15018f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  16, 16, 1, 0,  /* w, h, d, border */
15028f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  GL_RGBA, GL_UNSIGNED_BYTE, pixels,
15038f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  &st->ctx->DefaultPacking,
15048f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  texObj, texImg,
15058f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, 0);
15068f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15078f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MinFilter = GL_NEAREST;
15088f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MagFilter = GL_NEAREST;
15098f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->_Complete = GL_TRUE;
15108f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15118f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st->default_texture = texObj;
15128f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   }
15138f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   return st->default_texture;
15148f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul}
15158f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15168f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15176da9234fd437f97267e7831f034c78b31156d939Brianvoid
15186da9234fd437f97267e7831f034c78b31156d939Brianst_init_texture_functions(struct dd_function_table *functions)
151924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
152024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->ChooseTextureFormat = st_ChooseTextureFormat;
152124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage1D = st_TexImage1D;
152224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage2D = st_TexImage2D;
152324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage3D = st_TexImage3D;
152424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage1D = st_TexSubImage1D;
152524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage2D = st_TexSubImage2D;
152624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage3D = st_TexSubImage3D;
152724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage1D = st_CopyTexImage1D;
152824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage2D = st_CopyTexImage2D;
152924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
153024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
1531038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
153262abcb9aacc33218d0143a743c738435794b32a9Brian   functions->GenerateMipmap = st_generate_mipmap;
1533038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
153424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetTexImage = st_GetTexImage;
153524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
153624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* compressed texture functions */
153724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CompressedTexImage2D = st_CompressedTexImage2D;
153824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetCompressedTexImage = st_GetCompressedTexImage;
1539f32c51277498887b348133ebcd947dbc8acce756Roland Scheidegger   functions->CompressedTextureSize = _mesa_compressed_texture_size;
154024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
154124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureObject = st_NewTextureObject;
154224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureImage = st_NewTextureImage;
154324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->DeleteTexture = st_DeleteTextureObject;
154424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->FreeTexImageData = st_FreeTextureImageData;
154524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->UpdateTexturePalette = 0;
154624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
154724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TextureMemCpy = do_memcpy;
1548f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian
1549f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   /* XXX Temporary until we can query pipe's texture sizes */
1550f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   functions->TestProxyTexImage = _mesa_test_proxy_teximage;
155124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
1552