st_cb_texture.c revision f500f3a72c6be61ff9b8e1166f734e408d00aded
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
28f2c023291a1f2887294d2aac504f8b82857ad092Brian Paul#include "main/mfeatures.h"
29d055b2c001a0fb233f98c10d124b43dd2448059eBrian#if FEATURE_convolve
3024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/convolve.h"
31b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
3224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/enums.h"
3324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/image.h"
34f2c023291a1f2887294d2aac504f8b82857ad092Brian Paul#include "main/imports.h"
3524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/macros.h"
362440ff74d69a8caf49b05a960b4c7e282a96565eBrian#include "main/mipmap.h"
37cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul#include "main/pixel.h"
3824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texcompress.h"
3924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texformat.h"
4024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/teximage.h"
4124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texobj.h"
4224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texstore.h"
4324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_context.h"
45b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian#include "state_tracker/st_cb_fbo.h"
4624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_cb_texture.h"
47f8ab24760d0d3f07e9ee81c98207ddf92dfe74daBrian#include "state_tracker/st_format.h"
4802250c855fbec5299a2d6118fefa0523ec73654cMichel Dänzer#include "state_tracker/st_public.h"
49753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer#include "state_tracker/st_texture.h"
5062abcb9aacc33218d0143a743c738435794b32a9Brian#include "state_tracker/st_gen_mipmap.h"
5124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "pipe/p_context.h"
53b245840b86cf877c9b8d666edf229364a84f1deaBrian#include "pipe/p_defines.h"
5411a80160fd60d1eb1541b49128c659526a5d8ac8Michel Dänzer#include "pipe/p_inlines.h"
554f25420bdd834e81a3e22733304efc5261c2998aBrian Paul#include "util/u_tile.h"
563c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer#include "util/u_blit.h"
5724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define DBG if (0) printf
6024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
6124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
621c5f27a18b775b3784fcd265d60e0affa0b31581Michel Dänzerstatic enum pipe_texture_target
635390a43ce06b27f6d54bc5f237aa305b6948f2afBriangl_target_to_pipe(GLenum target)
645390a43ce06b27f6d54bc5f237aa305b6948f2afBrian{
655390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   switch (target) {
665390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_1D:
675390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_1D;
685390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
695390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_2D:
705390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_RECTANGLE_NV:
715390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_2D;
725390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
735390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_3D:
745390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_3D;
755390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
765390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_CUBE_MAP_ARB:
775390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_CUBE;
785390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
795390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   default:
805390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      assert(0);
815390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return 0;
825390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   }
835390a43ce06b27f6d54bc5f237aa305b6948f2afBrian}
845390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
855390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
86afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
87afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Return nominal bytes per texel for a compressed format, 0 for non-compressed
88afc54983370033b65e3a7cbb29bd9c87156f0881Brian * format.
89afc54983370033b65e3a7cbb29bd9c87156f0881Brian */
9024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
9114b98343309fdcff3514f05020303f7b40e83a4aBriancompressed_num_bytes(GLuint mesaFormat)
9224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
9324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch(mesaFormat) {
945b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_fxt1
9524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_FXT1:
9624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_FXT1:
975b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
985b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_s3tc
9924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_DXT1:
10024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT1:
101afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 2;
10224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT3:
10324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT5:
104afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 4;
1055b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
10624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
107afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 0;
10824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
10924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
11024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
11124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1124e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureImage() */
11324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_image *
11424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureImage(GLcontext * ctx)
11524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
11624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
11724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   (void) ctx;
118f1a59a6dd7b7b0523db191d82b3af1a841c6475dBrian Paul   return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image);
11924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
12024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1224e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureObject() */
12324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_object *
12424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
12524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
126f1a59a6dd7b7b0523db191d82b3af1a841c6475dBrian Paul   struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object);
12724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
12924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_initialize_texture_object(&obj->base, name, target);
13024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return &obj->base;
13224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
13324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1344e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.DeleteTextureImage() */
13524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
13624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_DeleteTextureObject(GLcontext *ctx,
1376f715dcc219071e574e363a9db4365c9c31ebbd3Brian                       struct gl_texture_object *texObj)
13824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
13924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_object *stObj = st_texture_object(texObj);
140753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt)
141f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
14224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_delete_texture_object(ctx, texObj);
14424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
14524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1474e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.FreeTexImageData() */
14824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
14924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
15024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
15124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
15224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
15424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
155753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
156f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
15724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
15824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->Data) {
1608d6ef125ac6044438db5b89d6d310ccfc4b8140aBrian Paul      _mesa_align_free(texImage->Data);
16124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
16224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
16324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
16424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
16524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1664e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
16724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * From linux kernel i386 header files, copes with odd sizes better
16824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * than COPY_DWORDS would:
16924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * XXX Put this in src/mesa/main/imports.h ???
17024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
17124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#if defined(i386) || defined(__i386__)
17224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic INLINE void *
17324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian__memcpy(void *to, const void *from, size_t n)
17424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
17524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int d0, d1, d2;
17624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   __asm__ __volatile__("rep ; movsl\n\t"
17724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "testb $2,%b4\n\t"
17824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 1f\n\t"
17924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsw\n"
18024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "1:\ttestb $1,%b4\n\t"
18124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 2f\n\t"
18224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
18324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
18424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"memory");
18524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (to);
18624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
18724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#else
18824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define __memcpy(a,b,c) memcpy(a,b,c)
18924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#endif
19024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
19124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1924e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
1934e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * The system memcpy (at least on ubuntu 5.10) has problems copying
19424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * to agp (writecombined) memory from a source which isn't 64-byte
19524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * aligned - there is a 4x performance falloff.
19624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
19724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The x86 __memcpy is immune to this but is slightly slower
19824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * (10%-ish) than the system memcpy.
19924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
20124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * isn't much faster than x86_memcpy for agp copies.
20224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * TODO: switch dynamically.
20424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
20524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void *
20624df8f895fe8807aa2ba058e71bd40adfc01d21eBriando_memcpy(void *dest, const void *src, size_t n)
20724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
208799f55803d15602b10d2bb97ff62792f05ce4de3Brian Paul   if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) {
20924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return __memcpy(dest, src, n);
21024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
21124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
21224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return memcpy(dest, src, n);
21324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
21424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
21524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
21624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
21724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianlogbase2(int n)
21824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
2194e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLint i = 1, log2 = 0;
22024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   while (n > i) {
22124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      i *= 2;
22224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      log2++;
22324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
22424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return log2;
22524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
22624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
22724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
228f52f5136e6eed23e55098681e5b082cc452136d6Brian/**
229f52f5136e6eed23e55098681e5b082cc452136d6Brian * Allocate a pipe_texture object for the given st_texture_object using
230f52f5136e6eed23e55098681e5b082cc452136d6Brian * the given st_texture_image to guess the mipmap size/levels.
231f52f5136e6eed23e55098681e5b082cc452136d6Brian *
232f52f5136e6eed23e55098681e5b082cc452136d6Brian * [comments...]
233f52f5136e6eed23e55098681e5b082cc452136d6Brian * Otherwise, store it in memory if (Border != 0) or (any dimension ==
23424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * 1).
23524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
236753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, if max_level >= level >= min_level, create texture with
237753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * space for images from min_level down to max_level.
23824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
239753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, create texture with space for images from (level 0)..(1x1).
240753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Consider pruning this texture at a validation if the saving is worth it.
24124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
24224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
243753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerguess_and_alloc_texture(struct st_context *st,
244753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			struct st_texture_object *stObj,
245afc54983370033b65e3a7cbb29bd9c87156f0881Brian			const struct st_texture_image *stImage)
24624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
24724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint firstLevel;
24824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint lastLevel;
24945cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint width = stImage->base.Width2;  /* size w/out border */
25045cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint height = stImage->base.Height2;
25145cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint depth = stImage->base.Depth2;
25224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint i, comp_byte = 0;
253a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   enum pipe_format fmt;
25424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
25524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
25624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
257f52f5136e6eed23e55098681e5b082cc452136d6Brian   assert(!stObj->pt);
258f52f5136e6eed23e55098681e5b082cc452136d6Brian
25945cc35e77600af8628393475405160e26d56d421Brian Paul   if (stObj->pt &&
2606c534b830c6f5427c391c5225c34561141c201baMichal Krol       (GLint) stImage->level > stObj->base.BaseLevel &&
26114b98343309fdcff3514f05020303f7b40e83a4aBrian       (stImage->base.Width == 1 ||
26214b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target != GL_TEXTURE_1D &&
26314b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Height == 1) ||
26414b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target == GL_TEXTURE_3D &&
26514b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Depth == 1)))
26624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
26724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
26824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* If this image disrespects BaseLevel, allocate from level zero.
26924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Usually BaseLevel == 0, so it's unlikely to happen.
27024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
2716c534b830c6f5427c391c5225c34561141c201baMichal Krol   if ((GLint) stImage->level < stObj->base.BaseLevel)
27224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = 0;
27324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
27414b98343309fdcff3514f05020303f7b40e83a4aBrian      firstLevel = stObj->base.BaseLevel;
27524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
27624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
27724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Figure out image dimensions at start level.
27824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
27914b98343309fdcff3514f05020303f7b40e83a4aBrian   for (i = stImage->level; i > firstLevel; i--) {
28045cc35e77600af8628393475405160e26d56d421Brian Paul      if (width != 1)
28145cc35e77600af8628393475405160e26d56d421Brian Paul         width <<= 1;
28224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (height != 1)
28324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         height <<= 1;
28424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (depth != 1)
28524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         depth <<= 1;
28624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
28724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
288296378b6c8b205048244746e260739448c4ee590Brian Paul   if (width == 0 || height == 0 || depth == 0) {
289296378b6c8b205048244746e260739448c4ee590Brian Paul      /* no texture needed */
290296378b6c8b205048244746e260739448c4ee590Brian Paul      return;
291296378b6c8b205048244746e260739448c4ee590Brian Paul   }
292296378b6c8b205048244746e260739448c4ee590Brian Paul
29324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Guess a reasonable value for lastLevel.  This is probably going
29424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * to be wrong fairly often and might mean that we have to look at
29524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * resizable buffers, or require that buffers implement lazy
29624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * pagetable arrangements.
29724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
29814b98343309fdcff3514f05020303f7b40e83a4aBrian   if ((stObj->base.MinFilter == GL_NEAREST ||
29914b98343309fdcff3514f05020303f7b40e83a4aBrian        stObj->base.MinFilter == GL_LINEAR) &&
30014b98343309fdcff3514f05020303f7b40e83a4aBrian       stImage->level == firstLevel) {
30124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel;
30224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
30324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
304f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2width = logbase2(width);
305f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2height = logbase2(height);
306f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2depth = logbase2(depth);
30724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
30824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
30924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
31014b98343309fdcff3514f05020303f7b40e83a4aBrian   if (stImage->base.IsCompressed)
31114b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
312f52f5136e6eed23e55098681e5b082cc452136d6Brian
313a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
314753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   stObj->pt = st_texture_create(st,
3155390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 gl_target_to_pipe(stObj->base.Target),
316a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 fmt,
3175390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 lastLevel,
3185390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 width,
3195390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 height,
3205390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 depth,
321a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                 comp_byte,
322a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 ( (pf_is_depth_stencil(fmt) ?
323a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
324a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_RENDER_TARGET) |
325a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                   PIPE_TEXTURE_USAGE_SAMPLER ));
32624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
32724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s - success\n", __FUNCTION__);
32824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
32924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
33024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
331212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian/**
332212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Adjust pixel unpack params and image dimensions to strip off the
333212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * texture border.
334212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Gallium doesn't support texture borders.  They've seldem been used
335212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * and seldom been implemented correctly anyway.
336212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * \param unpackNew  returns the new pixel unpack parameters
337212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian */
338212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstatic void
339212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstrip_texture_border(GLint border,
340212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     GLint *width, GLint *height, GLint *depth,
341212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     const struct gl_pixelstore_attrib *unpack,
342212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     struct gl_pixelstore_attrib *unpackNew)
343212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian{
344212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(border > 0);  /* sanity check */
345212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
346212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *unpackNew = *unpack;
347212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
348212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (unpackNew->RowLength == 0)
349212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->RowLength = *width;
350212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
351212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && unpackNew->ImageHeight == 0)
352212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->ImageHeight = *height;
353212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
354212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   unpackNew->SkipPixels += border;
355212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height)
356212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipRows += border;
357212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth)
358212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipImages += border;
359212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
360212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(*width >= 3);
361212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *width = *width - 2 * border;
362212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height && *height >= 3)
363212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *height = *height - 2 * border;
364212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && *depth >= 3)
365212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *depth = *depth - 2 * border;
366212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian}
367212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
36824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
3694e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
3704e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do glTexImage1/2/3D().
3714e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul */
37224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
37324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage(GLcontext * ctx,
374afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint dims,
375afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum target, GLint level,
376afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint internalFormat,
377afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint width, GLint height, GLint depth,
378afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint border,
379afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum format, GLenum type, const void *pixels,
380afc54983370033b65e3a7cbb29bd9c87156f0881Brian            const struct gl_pixelstore_attrib *unpack,
381afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_object *texObj,
382afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_image *texImage,
383afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLsizei imageSize, int compressed)
38424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
38514b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(texObj);
38614b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_image *stImage = st_texture_image(texImage);
387212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   GLint postConvWidth, postConvHeight;
38824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLint texelBytes, sizeInBytes;
38924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
390212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   struct gl_pixelstore_attrib unpackNB;
39124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
39224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
39324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
39424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
395212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   /* gallium does not support texture borders, strip it off */
396212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (border) {
397212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      strip_texture_border(border, &width, &height, &depth,
398212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                           unpack, &unpackNB);
399212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpack = &unpackNB;
40021989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Width = width;
40121989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Height = height;
40221989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Depth = depth;
40321989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Border = 0;
404212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      border = 0;
405212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   }
406212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
407212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvWidth = width;
408212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvHeight = height;
409212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
410cfe9e66f2bc596c43760911e7c1604bb32cdee28Brian   stImage->face = _mesa_tex_target_to_face(target);
41114b98343309fdcff3514f05020303f7b40e83a4aBrian   stImage->level = level;
41224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
413d055b2c001a0fb233f98c10d124b43dd2448059eBrian#if FEATURE_convolve
41424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
41524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
41624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                         &postConvHeight);
41724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
418b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
41924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* choose the texture format */
42124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
422afc54983370033b65e3a7cbb29bd9c87156f0881Brian                                                format, type);
42324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_set_fetch_functions(texImage, dims);
42524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->TexFormat->TexelBytes == 0) {
42724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* must be a compressed format */
42824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = 0;
42924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->IsCompressed = GL_TRUE;
43024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->CompressedSize =
43124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
43224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->Height, texImage->Depth,
43324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->TexFormat->MesaFormat);
434afc54983370033b65e3a7cbb29bd9c87156f0881Brian   }
435afc54983370033b65e3a7cbb29bd9c87156f0881Brian   else {
43624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = texImage->TexFormat->TexelBytes;
43724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
43824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Minimum pitch of 32 bytes */
43924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (postConvWidth * texelBytes < 32) {
44024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 postConvWidth = 32 / texelBytes;
44124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 texImage->RowStride = postConvWidth;
44224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
44324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4447585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /* we'll set RowStride elsewhere when the texture is a "mapped" state */
4457585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /*assert(texImage->RowStride == postConvWidth);*/
44624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
44724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
44824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Release the reference to a potentially orphaned buffer.
44924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Release any old malloced memory.
45024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
451753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
452f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
45324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(!texImage->Data);
45424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
45524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else if (texImage->Data) {
45624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(texImage->Data);
45724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
45824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
45937607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul   if (width == 0 || height == 0 || depth == 0) {
46037607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul      /* stop after freeing old image */
46137607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul      return;
46237607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul   }
46337607aeaf8b0fd35213635ba1c3743b6e059d48fBrian Paul
4644da1cdf78fa3b954840650fa46cf72da5daf149fBrian   /* If this is the only mipmap level in the texture, could call
46524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * bmBufferData with NULL data to free the old block and avoid
46624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * waiting on any outstanding fences.
46724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
468753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
469d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer       (stObj->teximage_realloc ||
470d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer        (/*stObj->pt->first_level == level &&*/
471d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->last_level == level &&
472d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->target != PIPE_TEXTURE_CUBE &&
473d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         !st_texture_match_image(stObj->pt, &stImage->base,
474d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer                                 stImage->face, stImage->level)))) {
47524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
47624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      DBG("release it\n");
477f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
478753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(!stObj->pt);
479d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer      stObj->teximage_realloc = FALSE;
48024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
48124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
482753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
483753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      guess_and_alloc_texture(ctx->st, stObj, stImage);
484753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!stObj->pt) {
4858d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         /* Probably out of memory.
4868d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul          * Try flushing any pending rendering, then retry.
4878d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul          */
4888d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         st_finish(ctx->st);
4898d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         guess_and_alloc_texture(ctx->st, stObj, stImage);
4908d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         if (!stObj->pt) {
4918d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
4928d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul            return;
4938d249ca620f6995cc5824d95c29bda7043bbdf8cBrian Paul         }
49424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
49524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
49624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
497753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   assert(!stImage->pt);
49824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
499753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
500753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       st_texture_match_image(stObj->pt, &stImage->base,
50114b98343309fdcff3514f05020303f7b40e83a4aBrian                                 stImage->face, stImage->level)) {
50224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5034da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stImage->pt, stObj->pt);
504753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(stImage->pt);
50524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
50624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
507753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stImage->pt)
508753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      DBG("XXX: Image did not fit into texture - storing in local memory!\n");
50924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
510987d59bb83e9e08192563e5f1b52949c5511053cMichel Dänzer   /* st_CopyTexImage calls this function with pixels == NULL, with
511753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer    * the expectation that the texture will be set up but nothing
51224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * more will be done.  This is where those calls return:
51324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
51424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
51524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
51624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      unpack,
51724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      "glCompressedTexImage");
51824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   } else {
51924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
52024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   format, type,
52124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   pixels, unpack, "glTexImage");
52224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
52324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
52424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
52524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
526753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
527c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
5284617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            PIPE_TRANSFER_WRITE, 0, 0,
5294617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Width,
5304617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Height);
5314617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer      dstRowStride = stImage->transfer->stride;
53224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
53324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
53424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Allocate regular memory and store the image there temporarily.   */
53524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (texImage->IsCompressed) {
53624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = texImage->CompressedSize;
53724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride =
53824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian            _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
53924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         assert(dims != 3);
54024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
54124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
54224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride = postConvWidth * texelBytes;
54324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = depth * dstRowStride * postConvHeight;
54424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
54524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5468d6ef125ac6044438db5b89d6d310ccfc4b8140aBrian Paul      texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
54724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
54824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5492a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   if (!texImage->Data) {
5502a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
5512a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      return;
5522a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   }
5532a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul
55424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
55524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       width, height, depth, width * texelBytes, dstRowStride);
55624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
55724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Copy data.  Would like to know when it's ok for us to eg. use
55824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * the blitter to copy.  Or, use the hardware to do the format
55924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * conversion and copy:
56024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
56124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
562afc54983370033b65e3a7cbb29bd9c87156f0881Brian      memcpy(texImage->Data, pixels, imageSize);
56324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
564753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   else {
565753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
566753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						       format, type);
567753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      int i;
5685823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian      const GLubyte *src = (const GLubyte *) pixels;
569753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
570753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      for (i = 0; i++ < depth;) {
571753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (!texImage->TexFormat->StoreImage(ctx, dims,
572753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->_BaseFormat,
573753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->TexFormat,
574753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->Data,
575753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      0, 0, 0, /* dstX/Y/Zoffset */
576753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      dstRowStride,
577753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->ImageOffsets,
578753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      width, height, 1,
5795823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					      format, type, src, unpack)) {
580753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
581753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
582753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
583753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (stImage->pt && i < depth) {
584c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    st_texture_image_unmap(ctx->st, stImage);
585c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    texImage->Data = st_texture_image_map(ctx->st, stImage, i,
5864617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                                  PIPE_TRANSFER_WRITE, 0, 0,
5874617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                                  stImage->base.Width,
5884617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                                  stImage->base.Height);
5895823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	    src += srcImageStride;
590753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
591753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
59224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
59324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, unpack);
59524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
596753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
597c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
59824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
59924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
60024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
60124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
60262abcb9aacc33218d0143a743c738435794b32a9Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
60324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
60424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
60524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
60624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
60724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
60824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage3D(GLcontext * ctx,
6094e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6104e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6114e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint depth,
6124e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint border,
6134e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6144e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6154e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6164e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
61724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
61824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 3, target, level,
61924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, depth, border,
62024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
62124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
62224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
62324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
62424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
62524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage2D(GLcontext * ctx,
6264e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6274e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6284e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint border,
6294e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6304e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6314e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6324e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
63324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
63424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
63524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, 1, border,
63624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
63724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
63824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
63924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
64024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
64124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage1D(GLcontext * ctx,
6424e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6434e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6444e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint border,
6454e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6464e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6474e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6484e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
64924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
65024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 1, target, level,
65124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, 1, 1, border,
65224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
65324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
65424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
65524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
65624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
6574e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
6584e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint internalFormat,
6594e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint width, GLint height, GLint border,
6604e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLsizei imageSize, const GLvoid *data,
6614e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_object *texObj,
6624e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_image *texImage)
66324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
66424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
66524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 internalFormat, width, height, 1, border,
66624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
66724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
66824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
66924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
67024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
67124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Need to map texture image into memory before copying image data,
67224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * then unmap it.
67324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
67424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
67524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
67624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 GLenum format, GLenum type, GLvoid * pixels,
67724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_object *texObj,
67824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_image *texImage, int compressed)
67924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
68024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
6814e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
6824e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    texImage->Width,
6834e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul						    texImage->Height,
6844e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    format, type);
685753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint depth;
6866c534b830c6f5427c391c5225c34561141c201baMichal Krol   GLuint i;
6875823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   GLubyte *dest;
68824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
68924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map */
690753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
69124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Image is stored in hardware format in a buffer managed by the
69224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * kernel.  Need to explicitly map and unmap it.
69324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
694c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
6954617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            PIPE_TRANSFER_READ, 0, 0,
6964617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Width,
6974617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Height);
6984617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer      texImage->RowStride = stImage->transfer->stride / stImage->pt->block.size;
69924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
70024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
70124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Otherwise, the image should actually be stored in
702753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       * texImage->Data.  This is pretty confusing for
70324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * everybody, I'd much prefer to separate the two functions of
70424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * texImage->Data - storage for texture images in main memory
70524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * and access (ie mappings) of images.  In other words, we'd
70624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * create a new texImage->Map field and leave Data simply for
70724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * storage.
70824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
709753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(texImage->Data);
71024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
71124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
712753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   depth = texImage->Depth;
713753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = 1;
71424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
7155823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   dest = (GLubyte *) pixels;
7165823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
717753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
718753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (compressed) {
7195823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_compressed_teximage(ctx, target, level, dest,
720753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer				       texObj, texImage);
721753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      } else {
7225823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_teximage(ctx, target, level, format, type, dest,
723753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			    texObj, texImage);
724753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
725753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
726753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
727c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
728c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, i,
7294617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               PIPE_TRANSFER_READ, 0, 0,
7304617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               stImage->base.Width,
7314617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               stImage->base.Height);
7325823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 dest += dstImageStride;
733753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
73424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
735753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
736753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = depth;
73724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Unmap */
739753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
740c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
741753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      texImage->Data = NULL;
74224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
74324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
74424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
74724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
7484e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, GLvoid * pixels,
7494e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7504e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
75124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
75224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, format, type, pixels,
75324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    texObj, texImage, 0);
75424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
75524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
75624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
75724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
75824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
7594e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         GLvoid *pixels,
76047bf26845712bea756526fc159bdb355ceaef9c2Brian Paul                         struct gl_texture_object *texObj,
76147bf26845712bea756526fc159bdb355ceaef9c2Brian Paul                         struct gl_texture_image *texImage)
76224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
76324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, 0, 0, pixels,
76424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_object *) texObj,
76524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_image *) texImage, 1);
76624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
76724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
76824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
76924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
77024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
77124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubimage(GLcontext * ctx,
7724e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint dims,
7734e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum target, GLint level,
7744e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint xoffset, GLint yoffset, GLint zoffset,
7754e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint width, GLint height, GLint depth,
7764e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, const void *pixels,
7774e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               const struct gl_pixelstore_attrib *packing,
7784e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7794e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
78024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
78124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
78224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
783753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
784753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						    format, type);
785753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   int i;
7865823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   const GLubyte *src;
78724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
78824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
78924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target),
79024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       level, xoffset, yoffset, width, height);
79124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
79224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   pixels =
79324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
79424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                  type, pixels, packing, "glTexSubImage2D");
79524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
79624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
79724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
79824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map buffer if necessary.  Need to lock to prevent other contexts
79924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * from uploading the buffer under us.
80024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
801753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
802c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
8034617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            PIPE_TRANSFER_WRITE,
8044617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            xoffset, yoffset,
8054617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Width,
8064617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                            stImage->base.Height);
8074617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer      dstRowStride = stImage->transfer->stride;
808753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   }
809753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
8109b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   if (!texImage->Data) {
8119b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
8129b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      return;
8139b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   }
8149b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul
8155823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   src = (const GLubyte *) pixels;
8165823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
817753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
818753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
819753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->TexFormat,
820753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->Data,
8217c8836e9ef49d938aa55a1c385b95c6371c301f1Michel Dänzer					   0, 0, 0,
822753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   dstRowStride,
823753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->ImageOffsets,
824753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   width, height, 1,
8255823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					   format, type, src, packing)) {
8269b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
827753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
828753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
829753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
8309b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul         /* map next slice of 3D texture */
831c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
832c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
8334617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               PIPE_TRANSFER_WRITE,
8344617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               xoffset, yoffset,
8354617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               stImage->base.Width,
8364617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                               stImage->base.Height);
8375823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 src += srcImageStride;
838753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
83924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
84024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
84124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
8423ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
84324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
84424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
84524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, packing);
84624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
847753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
848c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
84924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
85024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
85124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
85224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
85324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
85424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
85524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
85624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage3D(GLcontext * ctx,
85724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
85824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
85924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset, GLint zoffset,
86024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height, GLsizei depth,
86124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
86224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
86324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
86424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
86524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
86624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
867b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 3, target, level,
868b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, zoffset,
869b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, depth,
870b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
87124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
87224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
87324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
87424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
87524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage2D(GLcontext * ctx,
87624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
87724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
87824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset,
87924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height,
88024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
88124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
88224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
88324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
88424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
88524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
886b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 2, target, level,
887b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, 0,
888b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, 1,
889b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
89024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
89124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
89424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage1D(GLcontext * ctx,
89524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
89624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
89724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset,
89824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width,
89924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
90024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
90124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
90224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
90324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
90424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
905b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 1, target, level,
906b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, 0, 0,
907b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, 1, 1,
908b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
90924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
91024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
91124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
91224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
91324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
9144617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer * Do a CopyTexSubImage operation using a read transfer from the source, a write
9154617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer * transfer to the destination and get_tile()/put_tile() to access the pixels/texels.
916c6717a86420d7141013165f7acd50b3c3f751756Brian *
917c6717a86420d7141013165f7acd50b3c3f751756Brian * Note: srcY=0=TOP of renderbuffer
918038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian */
919038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
920038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianfallback_copy_texsubimage(GLcontext *ctx,
921038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLenum target,
922038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint level,
923038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          struct st_renderbuffer *strb,
924038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          struct st_texture_image *stImage,
925038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLenum baseFormat,
926038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint destX, GLint destY, GLint destZ,
927038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLint srcX, GLint srcY,
928038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                          GLsizei width, GLsizei height)
929038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
930038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct pipe_context *pipe = ctx->st->pipe;
9316f715dcc219071e574e363a9db4365c9c31ebbd3Brian   struct pipe_screen *screen = pipe->screen;
9324617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   struct pipe_transfer *src_trans;
9334617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   GLvoid *texDest;
9344617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer
9354617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   assert(width <= MAX_WIDTH);
936038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
9374617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
9387c8836e9ef49d938aa55a1c385b95c6371c301f1Michel Dänzer      srcY = strb->Base.Height - srcY - height;
9394617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   }
940f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul
9415e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer   src_trans = screen->get_tex_transfer( screen,
9425e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer                                         strb->texture,
9435e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer                                         0, 0, 0,
9445e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer                                         PIPE_TRANSFER_READ,
9455e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer                                         srcX, srcY,
9465e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer                                         width, height);
947038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
9484617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   texDest = st_texture_image_map(ctx->st, stImage, 0, PIPE_TRANSFER_WRITE,
9494617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                  destX, destY, width, height);
950038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
951cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (baseFormat == GL_DEPTH_COMPONENT) {
952cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
953cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul                                     ctx->Pixel.DepthBias != 0.0F);
95427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLint row, yStep;
955cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
95627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* determine bottom-to-top vs. top-to-bottom order for src buffer */
95727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
9587c8836e9ef49d938aa55a1c385b95c6371c301f1Michel Dänzer         srcY = height - 1;
95927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = -1;
96027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
96127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
9624617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer         srcY = 0;
96327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = 1;
96427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
96527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
96627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* To avoid a large temp memory allocation, do copy row by row */
9674617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer      for (row = 0; row < height; row++, srcY += yStep) {
968cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         uint data[MAX_WIDTH];
9694617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer         pipe_get_tile_z(src_trans, 0, srcY, width, 1, data);
970cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         if (scaleOrBias) {
971cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul            _mesa_scale_and_bias_depth_uint(ctx, width, data);
972cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
9734617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer         pipe_put_tile_z(stImage->transfer, 0, row, 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
98127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc && texDest) {
98227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         const GLint dims = 2;
98327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_texture_image *texImage = &stImage->base;
9844617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer         GLint dstRowStride = stImage->transfer->stride;
98527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
98627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
98727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
98827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            unpack.Invert = GL_TRUE;
989cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
99027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
99127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* get float/RGBA image from framebuffer */
99227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* XXX this usually involves a lot of int/float conversion.
99327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * try to avoid that someday.
99427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
9954617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer         pipe_get_tile_rgba(src_trans, 0, 0, width, height, tempSrc);
99627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
99727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* Store into texture memory.
99827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * Note that this does some special things such as pixel transfer
99927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * ops and format conversion.  In particular, if the dest tex format
100027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * is actually RGBA but the user created the texture as GL_RGB we
100127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * need to fill-in/override the alpha channel with 1.0.
100227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
100327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         texImage->TexFormat->StoreImage(ctx, dims,
100427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->_BaseFormat,
100527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->TexFormat,
100627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texDest,
10074617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer                                         0, 0, 0,
100827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         dstRowStride,
100927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->ImageOffsets,
101027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         width, height, 1,
101127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         GL_RGBA, GL_FLOAT, tempSrc, /* src */
101227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         &unpack);
101327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
101427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
101527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
10165c83f1371978472fbe4bba8f686733c6b519874aBrian      }
101727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
101827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc)
101927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_free(tempSrc);
10205c83f1371978472fbe4bba8f686733c6b519874aBrian   }
1021d0279fc4b38c72356a341173317bcd45d9093f45Michel Dänzer
10224617981ec72f7985941bee4b03c534d97ff96bc6Michel Dänzer   st_texture_image_unmap(ctx->st, stImage);
10235e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer   screen->tex_transfer_destroy(src_trans);
1024038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
1025038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1026038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1027038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian/**
10284e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
10294e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note that the region to copy has already been clipped so we know we
10304e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * won't read from outside the source renderbuffer's bounds.
1031c6717a86420d7141013165f7acd50b3c3f751756Brian *
10324e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note: srcY=0=Bottom of renderbuffer (GL convention)
103324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
1034038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
10354e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_copy_texsubimage(GLcontext *ctx,
1036038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLenum target, GLint level,
1037038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint destX, GLint destY, GLint destZ,
1038038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint srcX, GLint srcY,
1039038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLsizei width, GLsizei height)
104024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1041038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_unit *texUnit =
1042038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1043038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_object *texObj =
1044038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_object(ctx, texUnit, target);
1045038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_image *texImage =
1046038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_image(ctx, texObj, target, level);
1047038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct st_texture_image *stImage = st_texture_image(texImage);
10484e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   const GLenum texBaseFormat = texImage->InternalFormat;
1049b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct gl_framebuffer *fb = ctx->ReadBuffer;
1050b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct st_renderbuffer *strb;
1051b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct pipe_context *pipe = ctx->st->pipe;
10526f715dcc219071e574e363a9db4365c9c31ebbd3Brian   struct pipe_screen *screen = pipe->screen;
105327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   enum pipe_format dest_format, src_format;
1054cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   GLboolean use_fallback = GL_TRUE;
105527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   GLboolean matching_base_formats;
105624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
105766682651b622be201b211d50c7311e0b81b2b4a5Brian Paul   /* any rendering in progress must complete before we grab the fb image */
105866682651b622be201b211d50c7311e0b81b2b4a5Brian Paul   st_finish(ctx->st);
1059a479bf62353b6517841e620122112e7565d2391cBrian Paul
1060b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   /* determine if copying depth or color data */
10614e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   if (texBaseFormat == GL_DEPTH_COMPONENT) {
1062b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_DepthBuffer);
106324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
10644e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
1065b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_StencilBuffer);
1066b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   }
1067b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   else {
10684e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
1069b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian      strb = st_renderbuffer(fb->_ColorReadBuffer);
1070b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   }
1071b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
1072b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   assert(strb);
1073b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   assert(strb->surface);
1074753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   assert(stImage->pt);
1075c6717a86420d7141013165f7acd50b3c3f751756Brian
1076b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   src_format = strb->surface->format;
1077753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   dest_format = stImage->pt->format;
1078b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
107927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   /*
108027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * Determine if the src framebuffer and dest texture have the same
108127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * base format.  We need this to detect a case such as the framebuffer
108227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
108327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * texture format stores RGBA we need to set A=1 (overriding the
108427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * framebuffer's alpha values).  We can't do that with the blit or
108527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    * textured-quad paths.
108627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul    */
108727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
108879931e38abc62286151121a3f59127e296144551Michel Dänzer
108927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
109027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* try potential hardware path */
109127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      struct pipe_surface *dest_surface = NULL;
1092f500f3a72c6be61ff9b8e1166f734e408d00adedJakob Bornecrantz      boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
1093b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
1094f500f3a72c6be61ff9b8e1166f734e408d00adedJakob Bornecrantz      if (src_format == dest_format && !do_flip) {
10954e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* use surface_copy() / blit */
1096f500f3a72c6be61ff9b8e1166f734e408d00adedJakob Bornecrantz
109727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
109827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
109927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
110027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
110127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
1102145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul
1103145a45e9d6807add8229f1fc9c63fbb6951b1b88Brian Paul         /* for surface_copy(), y=0=top, always */
1104a479bf62353b6517841e620122112e7565d2391cBrian Paul         pipe->surface_copy(pipe,
1105a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* dest */
1106a479bf62353b6517841e620122112e7565d2391cBrian Paul                            dest_surface,
1107a479bf62353b6517841e620122112e7565d2391cBrian Paul                            destX, destY,
1108a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* src */
1109a479bf62353b6517841e620122112e7565d2391cBrian Paul                            strb->surface,
1110a479bf62353b6517841e620122112e7565d2391cBrian Paul                            srcX, srcY,
1111a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* size */
1112a479bf62353b6517841e620122112e7565d2391cBrian Paul                            width, height);
1113a479bf62353b6517841e620122112e7565d2391cBrian Paul         use_fallback = GL_FALSE;
1114cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      }
11154e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      else if (screen->is_format_supported(screen, src_format,
11168aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11178aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_SAMPLER,
11188aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0) &&
11194e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               screen->is_format_supported(screen, dest_format,
11208aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11218aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_RENDER_TARGET,
11228aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0)) {
11234e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* draw textured quad to do the copy */
1124a479bf62353b6517841e620122112e7565d2391cBrian Paul         int srcY0, srcY1;
112527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
112627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
112727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
112827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
112927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
113027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
1131a479bf62353b6517841e620122112e7565d2391cBrian Paul         if (do_flip) {
1132a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = strb->Base.Height - srcY - height;
1133a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY1 + height;
1134a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
1135a479bf62353b6517841e620122112e7565d2391cBrian Paul         else {
1136a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY;
1137a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = srcY0 + height;
1138a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
11393c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer         util_blit_pixels(ctx->st->blit,
11403c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          strb->surface,
1141a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX, srcY0,
1142a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX + width, srcY1,
11433c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          dest_surface,
1144a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX, destY,
1145a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX + width, destY + height,
11463c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          0.0, PIPE_TEX_MIPFILTER_NEAREST);
1147cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         use_fallback = GL_FALSE;
11483c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer      }
114979931e38abc62286151121a3f59127e296144551Michel Dänzer
115027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (dest_surface)
115127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         pipe_surface_reference(&dest_surface, NULL);
1152038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1153cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
1154cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (use_fallback) {
11554e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      /* software fallback */
1156038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      fallback_copy_texsubimage(ctx, target, level,
11574e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                strb, stImage, texBaseFormat,
1158038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                destX, destY, destZ,
1159038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                srcX, srcY, width, height);
1160038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1161038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
116224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
11633ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
116424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
116524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
116624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
116724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1168038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
116924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
117024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
117124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
117224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLint border)
117324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
117424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
117524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
117624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
117724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
117824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
117924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
118024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1181038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#if 0
118224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (border)
118324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      goto fail;
1184038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#endif
118524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1186753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
118724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
118824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
118924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
119024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, border,
119124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
119224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
119324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
11944e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
11954e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
11964e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, 1);  /* src X, Y, size */
119724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
119824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
119924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
120024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
120124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
120224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
120324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLsizei height,
120424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint border)
120524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
120624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
120724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
120824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
120924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
121024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
121124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
121224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1213753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
121424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
121524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
121624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
121724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, height, border,
121824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
121924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
122024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12214e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12224e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
12234e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
122424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
122524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
122624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
122724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
122824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
122924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint x, GLint y, GLsizei width)
123024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1231038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint yoffset = 0, zoffset = 0;
1232038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLsizei height = 1;
12334e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12344e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12354e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
123624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
123724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
124024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
124124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint yoffset,
124224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
124324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1244038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint zoffset = 0;
12454e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12464e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12474e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
1248038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
124924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
125024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1251038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
1252038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianst_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
1253038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint xoffset, GLint yoffset, GLint zoffset,
1254038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
1255038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
12564e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12574e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12584e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
125924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
126024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
126124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
126224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
126324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Compute which mipmap levels that really need to be sent to the hardware.
126424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * This depends on the base image size, GL_TEXTURE_MIN_LOD,
126524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
126624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
126724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
126814b98343309fdcff3514f05020303f7b40e83a4aBriancalculate_first_last_level(struct st_texture_object *stObj)
126924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
127014b98343309fdcff3514f05020303f7b40e83a4aBrian   struct gl_texture_object *tObj = &stObj->base;
127124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* These must be signed values.  MinLod and MaxLod can be negative numbers,
127324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * and having firstLevel and lastLevel as signed prevents the need for
127424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * extra sign checks.
127524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
127624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int firstLevel;
127724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int lastLevel;
127824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Yes, this looks overly complicated, but it's all needed.
128024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
128124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch (tObj->Target) {
128224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_1D:
128324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_2D:
128424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_3D:
128524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_CUBE_MAP:
128624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
128724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
128824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
128924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         firstLevel = lastLevel = tObj->BaseLevel;
129024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
129124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
12924da1cdf78fa3b954840650fa46cf72da5daf149fBrian         firstLevel = 0;
12934e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         lastLevel = MIN2(tObj->MaxLevel,
12944e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                          (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
129524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
129624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
129724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_RECTANGLE_NV:
129824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_4D_SGIS:
129924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = lastLevel = 0;
130024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
130124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
130224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
130324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
130424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130514b98343309fdcff3514f05020303f7b40e83a4aBrian   stObj->lastLevel = lastLevel;
130624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
130724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
1310753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzercopy_image_data_to_texture(struct st_context *st,
1311753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_object *stObj,
13124da1cdf78fa3b954840650fa46cf72da5daf149fBrian                           GLuint dstLevel,
1313753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_image *stImage)
131424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1315753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
131624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Copy potentially with the blitter:
131724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1318753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_copy(st->pipe,
13194da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stObj->pt, dstLevel,  /* dest texture, level */
13204da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->pt, /* src texture */
13214da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->face
132228b315dc1aed36bebadfacbd55e481e7baacfcb5Brian                            );
132324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1324f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
132524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
13264c50969334844bc9aa622176c3ebcbc733394f78Brian Paul   else if (stImage->base.Data) {
132724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(stImage->base.Data != NULL);
132824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
132924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* More straightforward upload.
133024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1331753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_data(st->pipe,
1332753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer                               stObj->pt,
133324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->face,
1334c2497879f127251994064a0e0c24901782adae9eBrian Paul                               dstLevel,
133524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.Data,
13364ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.RowStride *
13374ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size,
133824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.RowStride *
13394ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.Height *
13404ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size);
134124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(stImage->base.Data);
134224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      stImage->base.Data = NULL;
134324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
134424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13454da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian   pipe_texture_reference(&stImage->pt, stObj->pt);
134624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
134724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
134824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1349afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
1350afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Called during state validation.  When this function is finished,
1351afc54983370033b65e3a7cbb29bd9c87156f0881Brian * the texture object should be ready for rendering.
13523b3774b1227743147159676795b542c0eb7c2bdfBrian Paul * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
135324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
135414b98343309fdcff3514f05020303f7b40e83a4aBrianGLboolean
1355753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerst_finalize_texture(GLcontext *ctx,
1356c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct pipe_context *pipe,
1357c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct gl_texture_object *tObj,
1358753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer		    GLboolean *needFlush)
135924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
136014b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(tObj);
1361afc54983370033b65e3a7cbb29bd9c87156f0881Brian   const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
136224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int comp_byte = 0;
136324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int cpp;
13644da1cdf78fa3b954840650fa46cf72da5daf149fBrian   GLuint face;
136524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *firstImage;
136624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
136724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   *needFlush = GL_FALSE;
136824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
136924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* We know/require this is true by now:
137024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
137114b98343309fdcff3514f05020303f7b40e83a4aBrian   assert(stObj->base._Complete);
137224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1373753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* What levels must the texture include at a minimum?
137424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
137514b98343309fdcff3514f05020303f7b40e83a4aBrian   calculate_first_last_level(stObj);
13764da1cdf78fa3b954840650fa46cf72da5daf149fBrian   firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
137724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1378753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* If both firstImage and stObj point to a texture which can contain
137924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * all active images, favour firstImage.  Note that because of the
138024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * completeness requirement, we know that the image dimensions
138124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * will match.
138224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1383753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (firstImage->pt &&
1384753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt != stObj->pt &&
1385753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt->last_level >= stObj->lastLevel) {
138624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13874da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stObj->pt, firstImage->pt);
138824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
138924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13904ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca   /* FIXME: determine format block instead of cpp */
139124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (firstImage->base.IsCompressed) {
139214b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
139324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      cpp = comp_byte;
139424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
13955cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   else {
13965cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian      cpp = firstImage->base.TexFormat->TexelBytes;
13975cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   }
139824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1399ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* If we already have a gallium texture, check that it matches the texture
1400ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul    * object's format, target, size, num_levels, etc.
140124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1402809dd9089bae70cf35cea6a75258e700e7455738Brian Paul   if (stObj->pt) {
1403809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      const enum pipe_format fmt =
1404809dd9089bae70cf35cea6a75258e700e7455738Brian Paul         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1405809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
1406809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->format != fmt ||
1407809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->last_level < stObj->lastLevel ||
1408809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->width[0] != firstImage->base.Width2 ||
1409809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->height[0] != firstImage->base.Height2 ||
1410809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->depth[0] != firstImage->base.Depth2 ||
1411dc6cc4f9da25725d0b8f6efe571a5430fb399de5José Fonseca          stObj->pt->block.size/stObj->pt->block.width != cpp || /* Nominal bytes per pixel */
1412809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->compressed != firstImage->base.IsCompressed) {
14135e27cd46c04a9e7b5904cc014bffd0f4daae31feMichel Dänzer         pipe_texture_reference(&stObj->pt, NULL);
14141a82d9648b3db780e58e4966924157542d148c58Brian Paul         ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
1415809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      }
141624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
141724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1418ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* May need to create a new gallium texture:
141924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1420753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
1421a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger      const enum pipe_format fmt =
1422a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1423753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      stObj->pt = st_texture_create(ctx->st,
14245390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                    gl_target_to_pipe(stObj->base.Target),
1425a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    fmt,
1426b245840b86cf877c9b8d666edf229364a84f1deaBrian                                    stObj->lastLevel,
142745cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Width2,
142845cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Height2,
142945cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Depth2,
1430a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                    comp_byte,
1431a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    ( (pf_is_depth_stencil(fmt) ?
1432a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
1433a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_RENDER_TARGET) |
1434a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                      PIPE_TEXTURE_USAGE_SAMPLER ));
1435a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell
14363b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      if (!stObj->pt) {
14373b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
14383b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         return GL_FALSE;
14393b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      }
144024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
144124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1442753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Pull in any images not in the object's texture:
144324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
144424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   for (face = 0; face < nr_faces; face++) {
14454da1cdf78fa3b954840650fa46cf72da5daf149fBrian      GLuint level;
14464da1cdf78fa3b954840650fa46cf72da5daf149fBrian      for (level = 0; level <= stObj->lastLevel; level++) {
144724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         struct st_texture_image *stImage =
14484da1cdf78fa3b954840650fa46cf72da5daf149fBrian            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
144924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1450753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer         /* Need to import images in main memory or held in other textures.
145124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
1452a34b43b3f4817268ef4b3f186203b5fbafc7214eBrian         if (stImage && stObj->pt != stImage->pt) {
14534da1cdf78fa3b954840650fa46cf72da5daf149fBrian            copy_image_data_to_texture(ctx->st, stObj, level, stImage);
145424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	    *needFlush = GL_TRUE;
145524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         }
145624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
145724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
145824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
145924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return GL_TRUE;
146024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
146124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
146224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14638f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul/**
14648f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * Returns pointer to a default/dummy texture.
14658f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * This is typically used when the current shader has tex/sample instructions
14668f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * but the user has not provided a (any) texture(s).
14678f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul */
14688f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulstruct gl_texture_object *
14698f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulst_get_default_texture(struct st_context *st)
14708f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul{
14718f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   if (!st->default_texture) {
14728f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      static const GLenum target = GL_TEXTURE_2D;
14738f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      GLubyte pixels[16][16][4];
14748f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_object *texObj;
14758f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_image *texImg;
14768f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
1477a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      /* init image to gray */
1478a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      memset(pixels, 127, sizeof(pixels));
1479a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul
14808f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
14818f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14828f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
14838f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14848f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      _mesa_init_teximage_fields(st->ctx, target, texImg,
14858f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 16, 16, 1, 0,  /* w, h, d, border */
14868f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 GL_RGBA);
14878f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14888f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st_TexImage(st->ctx, 2, target,
14898f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, GL_RGBA,    /* level, intformat */
14908f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  16, 16, 1, 0,  /* w, h, d, border */
14918f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  GL_RGBA, GL_UNSIGNED_BYTE, pixels,
14928f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  &st->ctx->DefaultPacking,
14938f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  texObj, texImg,
14948f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, 0);
14958f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14968f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MinFilter = GL_NEAREST;
14978f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MagFilter = GL_NEAREST;
14988f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->_Complete = GL_TRUE;
14998f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15008f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st->default_texture = texObj;
15018f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   }
15028f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   return st->default_texture;
15038f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul}
15048f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15058f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15066da9234fd437f97267e7831f034c78b31156d939Brianvoid
15076da9234fd437f97267e7831f034c78b31156d939Brianst_init_texture_functions(struct dd_function_table *functions)
150824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
150924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->ChooseTextureFormat = st_ChooseTextureFormat;
151024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage1D = st_TexImage1D;
151124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage2D = st_TexImage2D;
151224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage3D = st_TexImage3D;
151324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage1D = st_TexSubImage1D;
151424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage2D = st_TexSubImage2D;
151524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage3D = st_TexSubImage3D;
151624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage1D = st_CopyTexImage1D;
151724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage2D = st_CopyTexImage2D;
151824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
151924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
1520038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
152162abcb9aacc33218d0143a743c738435794b32a9Brian   functions->GenerateMipmap = st_generate_mipmap;
1522038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
152324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetTexImage = st_GetTexImage;
152424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
152524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* compressed texture functions */
152624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CompressedTexImage2D = st_CompressedTexImage2D;
152724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetCompressedTexImage = st_GetCompressedTexImage;
1528f32c51277498887b348133ebcd947dbc8acce756Roland Scheidegger   functions->CompressedTextureSize = _mesa_compressed_texture_size;
152924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
153024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureObject = st_NewTextureObject;
153124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureImage = st_NewTextureImage;
153224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->DeleteTexture = st_DeleteTextureObject;
153324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->FreeTexImageData = st_FreeTextureImageData;
153424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->UpdateTexturePalette = 0;
153524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
153624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TextureMemCpy = do_memcpy;
1537f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian
1538f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   /* XXX Temporary until we can query pipe's texture sizes */
1539f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   functions->TestProxyTexImage = _mesa_test_proxy_teximage;
154024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
1541