st_cb_texture.c revision a7b818d53a95b549bbff942a9cb91272e0799dd5
124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**************************************************************************
224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * All Rights Reserved.
524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Permission is hereby granted, free of charge, to any person obtaining a
724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * copy of this software and associated documentation files (the
824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * "Software"), to deal in the Software without restriction, including
924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * without limitation the rights to use, copy, modify, merge, publish,
1024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * distribute, sub license, and/or sell copies of the Software, and to
1124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * permit persons to whom the Software is furnished to do so, subject to
1224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * the following conditions:
1324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
1424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The above copyright notice and this permission notice (including the
1524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * next paragraph) shall be included in all copies or substantial portions
1624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * of the Software.
1724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
1824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
2624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian **************************************************************************/
2724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
2824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/imports.h"
29b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#if FEATURE_convolution
3024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/convolve.h"
31b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
3224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/enums.h"
3324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/image.h"
3424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/macros.h"
352440ff74d69a8caf49b05a960b4c7e282a96565eBrian#include "main/mipmap.h"
36cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul#include "main/pixel.h"
3724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texcompress.h"
3824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texformat.h"
3924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/teximage.h"
4024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texobj.h"
4124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "main/texstore.h"
4224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_context.h"
44b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian#include "state_tracker/st_cb_fbo.h"
4524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "state_tracker/st_cb_texture.h"
46f8ab24760d0d3f07e9ee81c98207ddf92dfe74daBrian#include "state_tracker/st_format.h"
4702250c855fbec5299a2d6118fefa0523ec73654cMichel Dänzer#include "state_tracker/st_public.h"
48753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer#include "state_tracker/st_texture.h"
4962abcb9aacc33218d0143a743c738435794b32a9Brian#include "state_tracker/st_gen_mipmap.h"
5024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#include "pipe/p_context.h"
52b245840b86cf877c9b8d666edf229364a84f1deaBrian#include "pipe/p_defines.h"
5311a80160fd60d1eb1541b49128c659526a5d8ac8Michel Dänzer#include "pipe/p_inlines.h"
546acd63a4980951727939c0dd545a0324965b3834José Fonseca#include "util/p_tile.h"
553c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer#include "util/u_blit.h"
5624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define DBG if (0) printf
5924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
6024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
6124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic INLINE struct st_texture_image *
6224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_texture_image(struct gl_texture_image *img)
6324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
6424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (struct st_texture_image *) img;
6524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
6624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
6724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
681c5f27a18b775b3784fcd265d60e0affa0b31581Michel Dänzerstatic enum pipe_texture_target
695390a43ce06b27f6d54bc5f237aa305b6948f2afBriangl_target_to_pipe(GLenum target)
705390a43ce06b27f6d54bc5f237aa305b6948f2afBrian{
715390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   switch (target) {
725390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_1D:
735390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_1D;
745390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
755390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_2D:
765390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_RECTANGLE_NV:
775390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_2D;
785390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
795390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_3D:
805390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_3D;
815390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
825390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   case GL_TEXTURE_CUBE_MAP_ARB:
835390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return PIPE_TEXTURE_CUBE;
845390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
855390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   default:
865390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      assert(0);
875390a43ce06b27f6d54bc5f237aa305b6948f2afBrian      return 0;
885390a43ce06b27f6d54bc5f237aa305b6948f2afBrian   }
895390a43ce06b27f6d54bc5f237aa305b6948f2afBrian}
905390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
915390a43ce06b27f6d54bc5f237aa305b6948f2afBrian
92afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
93afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Return nominal bytes per texel for a compressed format, 0 for non-compressed
94afc54983370033b65e3a7cbb29bd9c87156f0881Brian * format.
95afc54983370033b65e3a7cbb29bd9c87156f0881Brian */
9624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
9714b98343309fdcff3514f05020303f7b40e83a4aBriancompressed_num_bytes(GLuint mesaFormat)
9824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
9924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch(mesaFormat) {
1005b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_fxt1
10124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_FXT1:
10224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_FXT1:
1035b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
1045b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#if FEATURE_texture_s3tc
10524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGB_DXT1:
10624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT1:
107afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 2;
10824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT3:
10924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case MESA_FORMAT_RGBA_DXT5:
110afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 4;
1115b51cc020efc5519bc7cc34f6fcb4138eab76e0aBrian Paul#endif
11224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
113afc54983370033b65e3a7cbb29bd9c87156f0881Brian      return 0;
11424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
11524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
11624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
11724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1184e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureImage() */
11924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_image *
12024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureImage(GLcontext * ctx)
12124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
12224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
12324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   (void) ctx;
12424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image);
12524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
12624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1284e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.NewTextureObject() */
12924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic struct gl_texture_object *
13024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
13124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
13224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object);
13324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
13524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_initialize_texture_object(&obj->base, name, target);
13624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return &obj->base;
13824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
13924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1404e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.DeleteTextureImage() */
14124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
14224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_DeleteTextureObject(GLcontext *ctx,
1436f715dcc219071e574e363a9db4365c9c31ebbd3Brian                       struct gl_texture_object *texObj)
14424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
14524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_object *stObj = st_texture_object(texObj);
146753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt)
147f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
14824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_delete_texture_object(ctx, texObj);
15024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
15124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1534e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/** called via ctx->Driver.FreeTexImageData() */
15424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
15524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
15624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
15724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
15824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
15924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
16024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
161753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
162f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
16324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
16424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
16524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->Data) {
16624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      free(texImage->Data);
16724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
16824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
16924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
17024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
17124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1724e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
17324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * From linux kernel i386 header files, copes with odd sizes better
17424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * than COPY_DWORDS would:
17524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * XXX Put this in src/mesa/main/imports.h ???
17624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
17724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#if defined(i386) || defined(__i386__)
17824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic INLINE void *
17924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian__memcpy(void *to, const void *from, size_t n)
18024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
18124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int d0, d1, d2;
18224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   __asm__ __volatile__("rep ; movsl\n\t"
18324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "testb $2,%b4\n\t"
18424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 1f\n\t"
18524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsw\n"
18624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "1:\ttestb $1,%b4\n\t"
18724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "je 2f\n\t"
18824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
18924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
19024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                        :"memory");
19124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return (to);
19224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
19324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#else
19424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#define __memcpy(a,b,c) memcpy(a,b,c)
19524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian#endif
19624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
19724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1984e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
1994e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * The system memcpy (at least on ubuntu 5.10) has problems copying
20024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * to agp (writecombined) memory from a source which isn't 64-byte
20124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * aligned - there is a 4x performance falloff.
20224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The x86 __memcpy is immune to this but is slightly slower
20424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * (10%-ish) than the system memcpy.
20524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
20724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * isn't much faster than x86_memcpy for agp copies.
20824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
20924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * TODO: switch dynamically.
21024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
21124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void *
21224df8f895fe8807aa2ba058e71bd40adfc01d21eBriando_memcpy(void *dest, const void *src, size_t n)
21324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
21424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
21524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return __memcpy(dest, src, n);
21624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
21724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
21824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return memcpy(dest, src, n);
21924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
22024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
22124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
22224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic int
22324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianlogbase2(int n)
22424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
2254e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLint i = 1, log2 = 0;
22624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   while (n > i) {
22724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      i *= 2;
22824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      log2++;
22924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
23024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return log2;
23124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
23224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
23324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
234f52f5136e6eed23e55098681e5b082cc452136d6Brian/**
235f52f5136e6eed23e55098681e5b082cc452136d6Brian * Allocate a pipe_texture object for the given st_texture_object using
236f52f5136e6eed23e55098681e5b082cc452136d6Brian * the given st_texture_image to guess the mipmap size/levels.
237f52f5136e6eed23e55098681e5b082cc452136d6Brian *
238f52f5136e6eed23e55098681e5b082cc452136d6Brian * [comments...]
239f52f5136e6eed23e55098681e5b082cc452136d6Brian * Otherwise, store it in memory if (Border != 0) or (any dimension ==
24024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * 1).
24124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
242753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, if max_level >= level >= min_level, create texture with
243753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * space for images from min_level down to max_level.
24424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian *
245753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Otherwise, create texture with space for images from (level 0)..(1x1).
246753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer * Consider pruning this texture at a validation if the saving is worth it.
24724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
24824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
249753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerguess_and_alloc_texture(struct st_context *st,
250753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			struct st_texture_object *stObj,
251afc54983370033b65e3a7cbb29bd9c87156f0881Brian			const struct st_texture_image *stImage)
25224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
25324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint firstLevel;
25424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint lastLevel;
25545cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint width = stImage->base.Width2;  /* size w/out border */
25645cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint height = stImage->base.Height2;
25745cc35e77600af8628393475405160e26d56d421Brian Paul   GLuint depth = stImage->base.Depth2;
25824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint i, comp_byte = 0;
259a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   enum pipe_format fmt;
26024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
26124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s\n", __FUNCTION__);
26224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
263f52f5136e6eed23e55098681e5b082cc452136d6Brian   assert(!stObj->pt);
264f52f5136e6eed23e55098681e5b082cc452136d6Brian
26545cc35e77600af8628393475405160e26d56d421Brian Paul   if (stObj->pt &&
2666c534b830c6f5427c391c5225c34561141c201baMichal Krol       (GLint) stImage->level > stObj->base.BaseLevel &&
26714b98343309fdcff3514f05020303f7b40e83a4aBrian       (stImage->base.Width == 1 ||
26814b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target != GL_TEXTURE_1D &&
26914b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Height == 1) ||
27014b98343309fdcff3514f05020303f7b40e83a4aBrian        (stObj->base.Target == GL_TEXTURE_3D &&
27114b98343309fdcff3514f05020303f7b40e83a4aBrian         stImage->base.Depth == 1)))
27224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
27324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
27424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* If this image disrespects BaseLevel, allocate from level zero.
27524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Usually BaseLevel == 0, so it's unlikely to happen.
27624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
2776c534b830c6f5427c391c5225c34561141c201baMichal Krol   if ((GLint) stImage->level < stObj->base.BaseLevel)
27824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = 0;
27924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else
28014b98343309fdcff3514f05020303f7b40e83a4aBrian      firstLevel = stObj->base.BaseLevel;
28124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
28224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
28324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Figure out image dimensions at start level.
28424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
28514b98343309fdcff3514f05020303f7b40e83a4aBrian   for (i = stImage->level; i > firstLevel; i--) {
28645cc35e77600af8628393475405160e26d56d421Brian Paul      if (width != 1)
28745cc35e77600af8628393475405160e26d56d421Brian Paul         width <<= 1;
28824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (height != 1)
28924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         height <<= 1;
29024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (depth != 1)
29124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         depth <<= 1;
29224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
29324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
294296378b6c8b205048244746e260739448c4ee590Brian Paul   if (width == 0 || height == 0 || depth == 0) {
295296378b6c8b205048244746e260739448c4ee590Brian Paul      /* no texture needed */
296296378b6c8b205048244746e260739448c4ee590Brian Paul      return;
297296378b6c8b205048244746e260739448c4ee590Brian Paul   }
298296378b6c8b205048244746e260739448c4ee590Brian Paul
29924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Guess a reasonable value for lastLevel.  This is probably going
30024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * to be wrong fairly often and might mean that we have to look at
30124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * resizable buffers, or require that buffers implement lazy
30224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * pagetable arrangements.
30324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
30414b98343309fdcff3514f05020303f7b40e83a4aBrian   if ((stObj->base.MinFilter == GL_NEAREST ||
30514b98343309fdcff3514f05020303f7b40e83a4aBrian        stObj->base.MinFilter == GL_LINEAR) &&
30614b98343309fdcff3514f05020303f7b40e83a4aBrian       stImage->level == firstLevel) {
30724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel;
30824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
30924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
310f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2width = logbase2(width);
311f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2height = logbase2(height);
312f52f5136e6eed23e55098681e5b082cc452136d6Brian      GLuint l2depth = logbase2(depth);
31324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
31424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
31524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
31614b98343309fdcff3514f05020303f7b40e83a4aBrian   if (stImage->base.IsCompressed)
31714b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
318f52f5136e6eed23e55098681e5b082cc452136d6Brian
319a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger   fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
320753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   stObj->pt = st_texture_create(st,
3215390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 gl_target_to_pipe(stObj->base.Target),
322a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 fmt,
3235390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 lastLevel,
3245390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 width,
3255390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 height,
3265390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                 depth,
327a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                 comp_byte,
328a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                 ( (pf_is_depth_stencil(fmt) ?
329a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
330a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                   PIPE_TEXTURE_USAGE_RENDER_TARGET) |
331a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                   PIPE_TEXTURE_USAGE_SAMPLER ));
33224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
33324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s - success\n", __FUNCTION__);
33424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
33524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
33624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
337212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian/**
338212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Adjust pixel unpack params and image dimensions to strip off the
339212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * texture border.
340212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * Gallium doesn't support texture borders.  They've seldem been used
341212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * and seldom been implemented correctly anyway.
342212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian * \param unpackNew  returns the new pixel unpack parameters
343212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian */
344212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstatic void
345212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brianstrip_texture_border(GLint border,
346212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     GLint *width, GLint *height, GLint *depth,
347212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     const struct gl_pixelstore_attrib *unpack,
348212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                     struct gl_pixelstore_attrib *unpackNew)
349212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian{
350212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(border > 0);  /* sanity check */
351212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
352212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *unpackNew = *unpack;
353212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
354212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (unpackNew->RowLength == 0)
355212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->RowLength = *width;
356212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
357212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && unpackNew->ImageHeight == 0)
358212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->ImageHeight = *height;
359212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
360212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   unpackNew->SkipPixels += border;
361212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height)
362212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipRows += border;
363212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth)
364212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpackNew->SkipImages += border;
365212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
366212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   assert(*width >= 3);
367212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   *width = *width - 2 * border;
368212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (height && *height >= 3)
369212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *height = *height - 2 * border;
370212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (depth && *depth >= 3)
371212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      *depth = *depth - 2 * border;
372212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian}
373212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
37424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
3754e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul/**
3764e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do glTexImage1/2/3D().
3774e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul */
37824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
37924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage(GLcontext * ctx,
380afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint dims,
381afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum target, GLint level,
382afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint internalFormat,
383afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint width, GLint height, GLint depth,
384afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLint border,
385afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLenum format, GLenum type, const void *pixels,
386afc54983370033b65e3a7cbb29bd9c87156f0881Brian            const struct gl_pixelstore_attrib *unpack,
387afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_object *texObj,
388afc54983370033b65e3a7cbb29bd9c87156f0881Brian            struct gl_texture_image *texImage,
389afc54983370033b65e3a7cbb29bd9c87156f0881Brian            GLsizei imageSize, int compressed)
39024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
39114b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(texObj);
39214b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_image *stImage = st_texture_image(texImage);
393212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   GLint postConvWidth, postConvHeight;
39424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLint texelBytes, sizeInBytes;
39524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
396212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   struct gl_pixelstore_attrib unpackNB;
39724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
39824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
39924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
40024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
401212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   /* gallium does not support texture borders, strip it off */
402212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   if (border) {
403212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      strip_texture_border(border, &width, &height, &depth,
404212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian                           unpack, &unpackNB);
405212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      unpack = &unpackNB;
40621989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Width = width;
40721989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Height = height;
40821989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Depth = depth;
40921989edd55409d72ee55187f4f9062496ca3fbf8Brian Paul      texImage->Border = 0;
410212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian      border = 0;
411212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   }
412212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
413212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvWidth = width;
414212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian   postConvHeight = height;
415212b27d33f94eeb25ba9cbc58f9e41295a29d2c9Brian
416cfe9e66f2bc596c43760911e7c1604bb32cdee28Brian   stImage->face = _mesa_tex_target_to_face(target);
41714b98343309fdcff3514f05020303f7b40e83a4aBrian   stImage->level = level;
41824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
419b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#if FEATURE_convolution
42024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
42124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
42224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                         &postConvHeight);
42324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
424b19e8f720bb2f4d360f5497b64901fc48321f172Brian Paul#endif
42524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
42624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* choose the texture format */
42724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
428afc54983370033b65e3a7cbb29bd9c87156f0881Brian                                                format, type);
42924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
43024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_set_fetch_functions(texImage, dims);
43124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
43224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (texImage->TexFormat->TexelBytes == 0) {
43324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* must be a compressed format */
43424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = 0;
43524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->IsCompressed = GL_TRUE;
43624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->CompressedSize =
43724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
43824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->Height, texImage->Depth,
43924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   texImage->TexFormat->MesaFormat);
440afc54983370033b65e3a7cbb29bd9c87156f0881Brian   }
441afc54983370033b65e3a7cbb29bd9c87156f0881Brian   else {
44224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texelBytes = texImage->TexFormat->TexelBytes;
44324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
44424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Minimum pitch of 32 bytes */
44524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (postConvWidth * texelBytes < 32) {
44624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 postConvWidth = 32 / texelBytes;
44724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	 texImage->RowStride = postConvWidth;
44824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
44924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4507585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /* we'll set RowStride elsewhere when the texture is a "mapped" state */
4517585b4ceb8fed862c07f50af8030a6f0eb8a8321Brian      /*assert(texImage->RowStride == postConvWidth);*/
45224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
45324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
45424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Release the reference to a potentially orphaned buffer.
45524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * Release any old malloced memory.
45624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
457753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
458f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
45924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(!texImage->Data);
46024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
46124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else if (texImage->Data) {
46224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(texImage->Data);
46324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
46424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4654da1cdf78fa3b954840650fa46cf72da5daf149fBrian   /* If this is the only mipmap level in the texture, could call
46624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * bmBufferData with NULL data to free the old block and avoid
46724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * waiting on any outstanding fences.
46824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
469753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
470d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer       (stObj->teximage_realloc ||
471d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer        (/*stObj->pt->first_level == level &&*/
472d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->last_level == level &&
473d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         stObj->pt->target != PIPE_TEXTURE_CUBE &&
474d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer         !st_texture_match_image(stObj->pt, &stImage->base,
475d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer                                 stImage->face, stImage->level)))) {
47624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
47724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      DBG("release it\n");
478f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stObj->pt, NULL);
479753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(!stObj->pt);
480d4074c509b5d28be0a2ec51d40329e1aed7047efMichel Dänzer      stObj->teximage_realloc = FALSE;
48124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
48224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
483753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
484753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      guess_and_alloc_texture(ctx->st, stObj, stImage);
485753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!stObj->pt) {
4863b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
4873b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         return;
48824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
48924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
49024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
491753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   assert(!stImage->pt);
49224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
493753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stObj->pt &&
494753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       st_texture_match_image(stObj->pt, &stImage->base,
49514b98343309fdcff3514f05020303f7b40e83a4aBrian                                 stImage->face, stImage->level)) {
49624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
4974da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stImage->pt, stObj->pt);
498753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(stImage->pt);
49924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
50024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
501753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stImage->pt)
502753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      DBG("XXX: Image did not fit into texture - storing in local memory!\n");
50324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
504987d59bb83e9e08192563e5f1b52949c5511053cMichel Dänzer   /* st_CopyTexImage calls this function with pixels == NULL, with
505753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer    * the expectation that the texture will be set up but nothing
50624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * more will be done.  This is where those calls return:
50724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
50824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
50924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
51024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      unpack,
51124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian						      "glCompressedTexImage");
51224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   } else {
51324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
51424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   format, type,
51524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian					   pixels, unpack, "glTexImage");
51624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
51724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
51824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
51924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
520753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
521c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
522c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_WRITE);
5232a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      if (stImage->surface)
5244ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca         dstRowStride = stImage->surface->stride;
52524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
52624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
52724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Allocate regular memory and store the image there temporarily.   */
52824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (texImage->IsCompressed) {
52924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = texImage->CompressedSize;
53024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride =
53124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian            _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
53224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         assert(dims != 3);
53324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
53424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
53524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         dstRowStride = postConvWidth * texelBytes;
53624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         sizeInBytes = depth * dstRowStride * postConvHeight;
53724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
53824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
53924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = malloc(sizeInBytes);
54024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
54124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
5422a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   if (!texImage->Data) {
5432a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
5442a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      return;
5452a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul   }
5462a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul
54724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
54824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       width, height, depth, width * texelBytes, dstRowStride);
54924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
55024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Copy data.  Would like to know when it's ok for us to eg. use
55124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * the blitter to copy.  Or, use the hardware to do the format
55224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * conversion and copy:
55324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
55424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (compressed) {
555afc54983370033b65e3a7cbb29bd9c87156f0881Brian      memcpy(texImage->Data, pixels, imageSize);
55624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
557753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   else {
558753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
559753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						       format, type);
560753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      int i;
5615823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian      const GLubyte *src = (const GLubyte *) pixels;
562753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
563753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      for (i = 0; i++ < depth;) {
564753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (!texImage->TexFormat->StoreImage(ctx, dims,
565753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->_BaseFormat,
566753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->TexFormat,
567753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->Data,
568753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      0, 0, 0, /* dstX/Y/Zoffset */
569753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      dstRowStride,
570753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      texImage->ImageOffsets,
571753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					      width, height, 1,
5725823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					      format, type, src, unpack)) {
573753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
574753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
575753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
576753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 if (stImage->pt && i < depth) {
577c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    st_texture_image_unmap(ctx->st, stImage);
578c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	    texImage->Data = st_texture_image_map(ctx->st, stImage, i,
579c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                                  PIPE_BUFFER_USAGE_CPU_WRITE);
5805823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	    src += srcImageStride;
581753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer	 }
582753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
58324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
58424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
58524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, unpack);
58624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
587753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
588c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
58924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
59024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
59124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
59362abcb9aacc33218d0143a743c738435794b32a9Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
59424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
59524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
59624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
59824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
59924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage3D(GLcontext * ctx,
6004e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6014e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6024e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint depth,
6034e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint border,
6044e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6054e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6064e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6074e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
60824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
60924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 3, target, level,
61024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, depth, border,
61124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
61224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
61324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
61424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
61524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
61624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage2D(GLcontext * ctx,
6174e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6184e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6194e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint height, GLint border,
6204e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6214e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6224e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6234e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
62424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
62524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
62624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, height, 1, border,
62724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
62824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
62924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
63024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
63124df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
63224df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexImage1D(GLcontext * ctx,
6334e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum target, GLint level,
6344e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint internalFormat,
6354e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLint width, GLint border,
6364e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              GLenum format, GLenum type, const void *pixels,
6374e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              const struct gl_pixelstore_attrib *unpack,
6384e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_object *texObj,
6394e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul              struct gl_texture_image *texImage)
64024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
64124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 1, target, level,
64224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 internalFormat, width, 1, 1, border,
64324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 format, type, pixels, unpack, texObj, texImage, 0, 0);
64424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
64524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
64624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
64724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
6484e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
6494e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint internalFormat,
6504e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLint width, GLint height, GLint border,
6514e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        GLsizei imageSize, const GLvoid *data,
6524e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_object *texObj,
6534e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                        struct gl_texture_image *texImage)
65424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
65524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_TexImage(ctx, 2, target, level,
65624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 internalFormat, width, height, 1, border,
65724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian		 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
65824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
65924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
66024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
66124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
66224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Need to map texture image into memory before copying image data,
66324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * then unmap it.
66424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
66524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
66624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
66724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 GLenum format, GLenum type, GLvoid * pixels,
66824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_object *texObj,
66924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                 struct gl_texture_image *texImage, int compressed)
67024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
67124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
6724e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
6734e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    texImage->Width,
6744e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul						    texImage->Height,
6754e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                                    format, type);
676753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint depth;
6776c534b830c6f5427c391c5225c34561141c201baMichal Krol   GLuint i;
6785823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   GLubyte *dest;
67924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
68024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map */
681753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
68224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Image is stored in hardware format in a buffer managed by the
68324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * kernel.  Need to explicitly map and unmap it.
68424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
685c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
686c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_READ);
6874ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca      texImage->RowStride = stImage->surface->stride / stImage->pt->block.size;
68824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
68924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   else {
69024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Otherwise, the image should actually be stored in
691753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       * texImage->Data.  This is pretty confusing for
69224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * everybody, I'd much prefer to separate the two functions of
69324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * texImage->Data - storage for texture images in main memory
69424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * and access (ie mappings) of images.  In other words, we'd
69524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * create a new texImage->Map field and leave Data simply for
69624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       * storage.
69724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
698753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      assert(texImage->Data);
69924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
70024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
701753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   depth = texImage->Depth;
702753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = 1;
70324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
7045823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   dest = (GLubyte *) pixels;
7055823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
706753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
707753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (compressed) {
7085823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_compressed_teximage(ctx, target, level, dest,
709753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer				       texObj, texImage);
710753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      } else {
7115823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 _mesa_get_teximage(ctx, target, level, format, type, dest,
712753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			    texObj, texImage);
713753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
714753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
715753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
716c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
717c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, i,
718c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                               PIPE_BUFFER_USAGE_CPU_READ);
7195823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 dest += dstImageStride;
720753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
72124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
722753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
723753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   texImage->Depth = depth;
72424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
72524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Unmap */
726753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
727c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
728753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      texImage->Data = NULL;
72924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
73024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
73124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
73324df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
73424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
7354e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, GLvoid * pixels,
7364e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7374e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
73824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
73924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, format, type, pixels,
74024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    texObj, texImage, 0);
74124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
74224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
74424df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
74524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
7464e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         GLvoid *pixels,
7474e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         const struct gl_texture_object *texObj,
7484e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                         const struct gl_texture_image *texImage)
74924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
75024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   st_get_tex_image(ctx, target, level, 0, 0, pixels,
75124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_object *) texObj,
75224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                    (struct gl_texture_image *) texImage, 1);
75324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
75424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
75524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
75624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
75724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
75824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubimage(GLcontext * ctx,
7594e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint dims,
7604e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum target, GLint level,
7614e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint xoffset, GLint yoffset, GLint zoffset,
7624e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLint width, GLint height, GLint depth,
7634e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               GLenum format, GLenum type, const void *pixels,
7644e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               const struct gl_pixelstore_attrib *packing,
7654e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_object *texObj,
7664e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               struct gl_texture_image *texImage)
76724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
76824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *stImage = st_texture_image(texImage);
76924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   GLuint dstRowStride;
770753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
771753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer						    format, type);
772753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   int i;
7735823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   const GLubyte *src;
77424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
77524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
77624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       _mesa_lookup_enum_by_nr(target),
77724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       level, xoffset, yoffset, width, height);
77824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
77924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   pixels =
78024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
78124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                                  type, pixels, packing, "glTexSubImage2D");
78224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (!pixels)
78324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
78424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
78524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Map buffer if necessary.  Need to lock to prevent other contexts
78624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * from uploading the buffer under us.
78724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
788753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
789c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset,
790c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                            PIPE_BUFFER_USAGE_CPU_WRITE);
7912a39dbe7364af5444b1eb43650dfc31ed09257dcBrian Paul      if (stImage->surface)
7924ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca         dstRowStride = stImage->surface->stride;
793753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   }
794753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
7959b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   if (!texImage->Data) {
7969b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
7979b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul      return;
7989b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul   }
7999b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul
8005823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian   src = (const GLubyte *) pixels;
8015823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian
802753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   for (i = 0; i++ < depth;) {
803753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
804753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->TexFormat,
805753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->Data,
806753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   xoffset, yoffset, 0,
807753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   dstRowStride,
808753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   texImage->ImageOffsets,
809753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer					   width, height, 1,
8105823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian					   format, type, src, packing)) {
8119b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
812753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
813753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer
814753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      if (stImage->pt && i < depth) {
8159b44f5a7550d8ede2eda763770e927df4c15cc8eBrian Paul         /* map next slice of 3D texture */
816c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 st_texture_image_unmap(ctx->st, stImage);
817c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell	 texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
818c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                               PIPE_BUFFER_USAGE_CPU_WRITE);
8195823f99d0fbc054b87aeb1bc15d413d3eadd27a8Brian	 src += srcImageStride;
820753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      }
82124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
82224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
82324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
8243ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
82524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
82624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
82724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   _mesa_unmap_teximage_pbo(ctx, packing);
82824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
829753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
830c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell      st_texture_image_unmap(ctx->st, stImage);
83124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      texImage->Data = NULL;
83224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
83324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
83424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
83524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
83624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
83724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
83824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage3D(GLcontext * ctx,
83924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
84024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
84124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset, GLint zoffset,
84224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height, GLsizei depth,
84324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
84424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
84524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
84624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
84724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
84824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
849b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 3, target, level,
850b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, zoffset,
851b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, depth,
852b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
85324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
85424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
85524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
85624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
85724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage2D(GLcontext * ctx,
85824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
85924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
86024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset, GLint yoffset,
86124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width, GLsizei height,
86224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
86324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
86424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
86524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
86624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
86724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
868b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 2, target, level,
869b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, yoffset, 0,
870b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, height, 1,
871b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
87224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
87324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
87424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
87524df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
87624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_TexSubImage1D(GLcontext * ctx,
87724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum target,
87824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint level,
87924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLint xoffset,
88024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLsizei width,
88124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   GLenum format, GLenum type,
88224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const GLvoid * pixels,
88324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   const struct gl_pixelstore_attrib *packing,
88424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_object *texObj,
88524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                   struct gl_texture_image *texImage)
88624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
887b245840b86cf877c9b8d666edf229364a84f1deaBrian   st_TexSubimage(ctx, 1, target, level,
888b245840b86cf877c9b8d666edf229364a84f1deaBrian                  xoffset, 0, 0,
889b245840b86cf877c9b8d666edf229364a84f1deaBrian                  width, 1, 1,
890b245840b86cf877c9b8d666edf229364a84f1deaBrian                  format, type, pixels, packing, texObj, texImage);
89124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
89224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
89524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
896038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian * Return 0 for GL_TEXTURE_CUBE_MAP_POSITIVE_X,
897038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian *        1 for GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
898038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian *        etc.
899038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian * XXX duplicated from main/teximage.c
900038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian */
901038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic uint
902038cb561eb094af2f2ba06e18e61246fc0c87c3cBriantexture_face(GLenum target)
903038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
904038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
905038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian       target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
906038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
907038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   else
908038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      return 0;
909038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
910038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
911038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
912038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
913038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian/**
914b859cdf6f191b4d8b56537c8dc30082a7e2d94b3Michel Dänzer * Do a CopyTexSubImage operation by mapping the source surface and
915b859cdf6f191b4d8b56537c8dc30082a7e2d94b3Michel Dänzer * dest surface and using 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;
932038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const uint face = texture_face(target);
933753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   struct pipe_texture *pt = stImage->pt;
934038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct pipe_surface *src_surf, *dest_surf;
935038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
936f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   /* We'd use strb->surface, here but it's created for GPU read/write only */
937f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   src_surf = pipe->screen->get_tex_surface( pipe->screen,
938f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             strb->texture,
939f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             0, 0, 0,
940f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul                                             PIPE_BUFFER_USAGE_CPU_READ);
941f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul
942c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell   dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ,
943c9ed86a96483063f3d6789ed16645a3dca77d726Keith Whitwell                                       PIPE_BUFFER_USAGE_CPU_WRITE);
944038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
945cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   assert(width <= MAX_WIDTH);
946038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
947cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (baseFormat == GL_DEPTH_COMPONENT) {
948cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
949cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul                                     ctx->Pixel.DepthBias != 0.0F);
95027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLint row, yStep;
951cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
95227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* determine bottom-to-top vs. top-to-bottom order for src buffer */
95327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
95427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         srcY = strb->Base.Height - 1 - srcY;
95527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = -1;
95627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
95727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
95827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         yStep = 1;
95927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
96027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
96127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      /* To avoid a large temp memory allocation, do copy row by row */
962275b09f2569c8bea5dcca1643c93aa6a43d7e2a2Brian Paul      for (row = 0; row < height; row++, srcY += yStep, destY++) {
963cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         uint data[MAX_WIDTH];
96436dd89c8a7f2a911e8f7f18d1edcaf982a75a438José Fonseca         pipe_get_tile_z(src_surf, srcX, srcY, width, 1, data);
965cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         if (scaleOrBias) {
966cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul            _mesa_scale_and_bias_depth_uint(ctx, width, data);
967cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
96836dd89c8a7f2a911e8f7f18d1edcaf982a75a438José Fonseca         pipe_put_tile_z(dest_surf, destX, destY, width, 1, data);
969cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      }
970cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   }
971cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   else {
972cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      /* RGBA format */
97327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLfloat *tempSrc =
97427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
97527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      GLvoid *texDest =
97627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         st_texture_image_map(ctx->st, stImage, 0,PIPE_BUFFER_USAGE_CPU_WRITE);
97727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
97827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc && texDest) {
97927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         const GLint dims = 2;
98027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_texture_image *texImage = &stImage->base;
98127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         GLint dstRowStride = stImage->surface->stride;
98227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
98327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
98427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
98527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            /* need to invert src */
98627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            srcY = strb->Base.Height - srcY - height;
98727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul            unpack.Invert = GL_TRUE;
988cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         }
98927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
99027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* get float/RGBA image from framebuffer */
99127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* XXX this usually involves a lot of int/float conversion.
99227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * try to avoid that someday.
99327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
99427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         pipe_get_tile_rgba(src_surf, srcX, srcY, width, height, tempSrc);
99527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
99627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         /* Store into texture memory.
99727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * Note that this does some special things such as pixel transfer
99827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * ops and format conversion.  In particular, if the dest tex format
99927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * is actually RGBA but the user created the texture as GL_RGB we
100027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          * need to fill-in/override the alpha channel with 1.0.
100127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul          */
100227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         texImage->TexFormat->StoreImage(ctx, dims,
100327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->_BaseFormat,
100427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->TexFormat,
100527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texDest,
100627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         destX, destY, destZ,
100727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         dstRowStride,
100827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         texImage->ImageOffsets,
100927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         width, height, 1,
101027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         GL_RGBA, GL_FLOAT, tempSrc, /* src */
101127858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                         &unpack);
101227858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      }
101327858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      else {
101427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
10155c83f1371978472fbe4bba8f686733c6b519874aBrian      }
101627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
101727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (tempSrc)
101827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         _mesa_free(tempSrc);
101927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (texDest)
102027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         st_texture_image_unmap(ctx->st, stImage);
10215c83f1371978472fbe4bba8f686733c6b519874aBrian   }
1022d0279fc4b38c72356a341173317bcd45d9093f45Michel Dänzer
1023d0279fc4b38c72356a341173317bcd45d9093f45Michel Dänzer   screen->tex_surface_release(screen, &dest_surf);
1024f3048ad90ed2e4583f0f7aaf35a0f4aa581942ddBrian Paul   screen->tex_surface_release(screen, &src_surf);
1025038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
1026038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1027038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
1028038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian/**
10294e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
10304e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note that the region to copy has already been clipped so we know we
10314e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * won't read from outside the source renderbuffer's bounds.
1032c6717a86420d7141013165f7acd50b3c3f751756Brian *
10334e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul * Note: srcY=0=Bottom of renderbuffer (GL convention)
103424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
1035038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
10364e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paulst_copy_texsubimage(GLcontext *ctx,
1037038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLenum target, GLint level,
1038038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint destX, GLint destY, GLint destZ,
1039038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLint srcX, GLint srcY,
1040038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                    GLsizei width, GLsizei height)
104124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1042038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_unit *texUnit =
1043038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1044038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_object *texObj =
1045038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_object(ctx, texUnit, target);
1046038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct gl_texture_image *texImage =
1047038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      _mesa_select_tex_image(ctx, texObj, target, level);
1048038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   struct st_texture_image *stImage = st_texture_image(texImage);
10494e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   const GLenum texBaseFormat = texImage->InternalFormat;
1050b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct gl_framebuffer *fb = ctx->ReadBuffer;
1051b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct st_renderbuffer *strb;
1052b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian   struct pipe_context *pipe = ctx->st->pipe;
10536f715dcc219071e574e363a9db4365c9c31ebbd3Brian   struct pipe_screen *screen = pipe->screen;
105427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   enum pipe_format dest_format, src_format;
1055cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   GLboolean use_fallback = GL_TRUE;
105627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul   GLboolean matching_base_formats;
105724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
105889e9d6b6db933c870443714c3d7c9539d117cddfBrian Paul   st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL);
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;
1092b27498c7cad7dae4e3b3ef9517b9c0aef58f73f6Brian
10933c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer      if (src_format == dest_format) {
10944e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* use surface_copy() / blit */
1095a479bf62353b6517841e620122112e7565d2391cBrian Paul         boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
109627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
109727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
109827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
109927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
110027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
1101a479bf62353b6517841e620122112e7565d2391cBrian Paul         pipe->surface_copy(pipe,
1102a479bf62353b6517841e620122112e7565d2391cBrian Paul                            do_flip,
1103a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* dest */
1104a479bf62353b6517841e620122112e7565d2391cBrian Paul                            dest_surface,
1105a479bf62353b6517841e620122112e7565d2391cBrian Paul                            destX, destY,
1106a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* src */
1107a479bf62353b6517841e620122112e7565d2391cBrian Paul                            strb->surface,
1108a479bf62353b6517841e620122112e7565d2391cBrian Paul                            srcX, srcY,
1109a479bf62353b6517841e620122112e7565d2391cBrian Paul                            /* size */
1110a479bf62353b6517841e620122112e7565d2391cBrian Paul                            width, height);
1111a479bf62353b6517841e620122112e7565d2391cBrian Paul         use_fallback = GL_FALSE;
1112cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul      }
11134e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      else if (screen->is_format_supported(screen, src_format,
11148aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11158aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_SAMPLER,
11168aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0) &&
11174e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul               screen->is_format_supported(screen, dest_format,
11188aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_2D,
11198aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           PIPE_TEXTURE_USAGE_RENDER_TARGET,
11208aafc03b260ab8923f1b373f7effa75bcdb40a72José Fonseca                                           0)) {
11214e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         /* draw textured quad to do the copy */
1122a479bf62353b6517841e620122112e7565d2391cBrian Paul         boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
1123a479bf62353b6517841e620122112e7565d2391cBrian Paul         int srcY0, srcY1;
112427858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
112527858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         dest_surface = screen->get_tex_surface(screen, stImage->pt,
112627858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                stImage->face, stImage->level,
112727858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                destZ,
112827858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul                                                PIPE_BUFFER_USAGE_GPU_WRITE);
112927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul
1130a479bf62353b6517841e620122112e7565d2391cBrian Paul         if (do_flip) {
1131a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = strb->Base.Height - srcY - height;
1132a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY1 + height;
1133a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
1134a479bf62353b6517841e620122112e7565d2391cBrian Paul         else {
1135a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY0 = srcY;
1136a479bf62353b6517841e620122112e7565d2391cBrian Paul            srcY1 = srcY0 + height;
1137a479bf62353b6517841e620122112e7565d2391cBrian Paul         }
11383c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer         util_blit_pixels(ctx->st->blit,
11393c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          strb->surface,
1140a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX, srcY0,
1141a479bf62353b6517841e620122112e7565d2391cBrian Paul                          srcX + width, srcY1,
11423c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          dest_surface,
1143a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX, destY,
1144a479bf62353b6517841e620122112e7565d2391cBrian Paul                          destX + width, destY + height,
11453c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer                          0.0, PIPE_TEX_MIPFILTER_NEAREST);
1146cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul         use_fallback = GL_FALSE;
11473c0dc8242b64518d5635263ba65b39afa919dd86Michel Dänzer      }
114879931e38abc62286151121a3f59127e296144551Michel Dänzer
114927858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul      if (dest_surface)
115027858226dc4eb3e64d980ba8530c2fd2e39218cfBrian Paul         pipe_surface_reference(&dest_surface, NULL);
1151038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1152cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul
1153cc94863429d8a6cef8dbf861e78701a458d30f5aBrian Paul   if (use_fallback) {
11544e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul      /* software fallback */
1155038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian      fallback_copy_texsubimage(ctx, target, level,
11564e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                                strb, stImage, texBaseFormat,
1157038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                destX, destY, destZ,
1158038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                                srcX, srcY, width, height);
1159038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   }
1160038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
116124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
11623ccbaa977f96eaa849093875dd0944f744ee1e21Brian      ctx->Driver.GenerateMipmap(ctx, target, texObj);
116324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
116424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
116524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
116624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1167038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
116824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
116924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
117024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
117124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLint border)
117224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
117324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
117424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
117524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
117624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
117724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
117824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
117924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1180038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#if 0
118124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (border)
118224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      goto fail;
1183038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian#endif
118424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1185753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
118624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
118724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
118824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
118924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, border,
119024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
119124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
119224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
11934e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
11944e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
11954e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, 1);  /* src X, Y, size */
119624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
119724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
119824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
119924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
120024df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
120124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLenum internalFormat,
120224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint x, GLint y, GLsizei width, GLsizei height,
120324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                  GLint border)
120424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
120524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_unit *texUnit =
120624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
120724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_object *texObj =
120824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_object(ctx, texUnit, target);
120924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct gl_texture_image *texImage =
121024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_select_tex_image(ctx, texObj, target, level);
121124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1212753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Setup or redefine the texture object, texture and texture
121324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * image.  Don't populate yet.
121424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
121524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
121624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          width, height, border,
121724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          GL_RGBA, CHAN_TYPE, NULL,
121824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                          &ctx->DefaultPacking, texObj, texImage);
121924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
12204e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12214e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       0, 0, 0,  /* destX,Y,Z */
12224e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
122324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
122424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
122524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
122624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
122724df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
122824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint x, GLint y, GLsizei width)
122924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1230038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint yoffset = 0, zoffset = 0;
1231038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLsizei height = 1;
12324e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12334e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12344e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
123524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
123624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
123824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
123924df8f895fe8807aa2ba058e71bd40adfc01d21eBrianst_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
124024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint xoffset, GLint yoffset,
124124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
124224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1243038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   const GLint zoffset = 0;
12444e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12454e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12464e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
1247038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian}
124824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
124924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1250038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianstatic void
1251038cb561eb094af2f2ba06e18e61246fc0c87c3cBrianst_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
1252038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint xoffset, GLint yoffset, GLint zoffset,
1253038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian                     GLint x, GLint y, GLsizei width, GLsizei height)
1254038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian{
12554e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul   st_copy_texsubimage(ctx, target, level,
12564e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       xoffset, yoffset, zoffset,  /* destX,Y,Z */
12574e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                       x, y, width, height);  /* src X, Y, size */
125824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
125924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
126024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
126124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian/**
126224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * Compute which mipmap levels that really need to be sent to the hardware.
126324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * This depends on the base image size, GL_TEXTURE_MIN_LOD,
126424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
126524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
126624df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
126714b98343309fdcff3514f05020303f7b40e83a4aBriancalculate_first_last_level(struct st_texture_object *stObj)
126824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
126914b98343309fdcff3514f05020303f7b40e83a4aBrian   struct gl_texture_object *tObj = &stObj->base;
127024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* These must be signed values.  MinLod and MaxLod can be negative numbers,
127224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * and having firstLevel and lastLevel as signed prevents the need for
127324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * extra sign checks.
127424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
127524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int firstLevel;
127624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int lastLevel;
127724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
127824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* Yes, this looks overly complicated, but it's all needed.
127924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
128024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   switch (tObj->Target) {
128124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_1D:
128224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_2D:
128324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_3D:
128424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_CUBE_MAP:
128524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
128624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
128724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
128824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         firstLevel = lastLevel = tObj->BaseLevel;
128924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
129024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      else {
12914da1cdf78fa3b954840650fa46cf72da5daf149fBrian         firstLevel = 0;
12924e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul         lastLevel = MIN2(tObj->MaxLevel,
12934e070f10c0a2af8a563eadf7fdb09b11d9067a99Brian Paul                          (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
129424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
129524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
129624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_RECTANGLE_NV:
129724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   case GL_TEXTURE_4D_SGIS:
129824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      firstLevel = lastLevel = 0;
129924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      break;
130024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   default:
130124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      return;
130224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
130324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130414b98343309fdcff3514f05020303f7b40e83a4aBrian   stObj->lastLevel = lastLevel;
130524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
130624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
130824df8f895fe8807aa2ba058e71bd40adfc01d21eBrianstatic void
1309753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzercopy_image_data_to_texture(struct st_context *st,
1310753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_object *stObj,
13114da1cdf78fa3b954840650fa46cf72da5daf149fBrian                           GLuint dstLevel,
1312753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer			   struct st_texture_image *stImage)
131324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
1314753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (stImage->pt) {
131524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* Copy potentially with the blitter:
131624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1317753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_copy(st->pipe,
13184da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stObj->pt, dstLevel,  /* dest texture, level */
13194da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->pt, /* src texture */
13204da1cdf78fa3b954840650fa46cf72da5daf149fBrian                            stImage->face
132128b315dc1aed36bebadfacbd55e481e7baacfcb5Brian                            );
132224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1323f8dce51083042b4d3fabf48524835290b6725682Brian Paul      pipe_texture_reference(&stImage->pt, NULL);
132424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
13254c50969334844bc9aa622176c3ebcbc733394f78Brian Paul   else if (stImage->base.Data) {
132624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      assert(stImage->base.Data != NULL);
132724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
132824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      /* More straightforward upload.
132924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian       */
1330753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      st_texture_image_data(st->pipe,
1331753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer                               stObj->pt,
133224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->face,
1333c2497879f127251994064a0e0c24901782adae9eBrian Paul                               dstLevel,
133424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.Data,
13354ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.RowStride *
13364ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size,
133724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian                               stImage->base.RowStride *
13384ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stImage->base.Height *
13394ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca                               stObj->pt->block.size);
134024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      _mesa_align_free(stImage->base.Data);
134124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      stImage->base.Data = NULL;
134224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
134324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13444da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian   pipe_texture_reference(&stImage->pt, stObj->pt);
134524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
134624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
134724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1348afc54983370033b65e3a7cbb29bd9c87156f0881Brian/**
1349afc54983370033b65e3a7cbb29bd9c87156f0881Brian * Called during state validation.  When this function is finished,
1350afc54983370033b65e3a7cbb29bd9c87156f0881Brian * the texture object should be ready for rendering.
13513b3774b1227743147159676795b542c0eb7c2bdfBrian Paul * \return GL_TRUE for success, GL_FALSE for failure (out of mem)
135224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian */
135314b98343309fdcff3514f05020303f7b40e83a4aBrianGLboolean
1354753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzerst_finalize_texture(GLcontext *ctx,
1355c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct pipe_context *pipe,
1356c3af68dc5022715cc8f126b7df12f3f5248aefe7Keith Whitwell		    struct gl_texture_object *tObj,
1357753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer		    GLboolean *needFlush)
135824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
135914b98343309fdcff3514f05020303f7b40e83a4aBrian   struct st_texture_object *stObj = st_texture_object(tObj);
1360afc54983370033b65e3a7cbb29bd9c87156f0881Brian   const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
136124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int comp_byte = 0;
136224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   int cpp;
13634da1cdf78fa3b954840650fa46cf72da5daf149fBrian   GLuint face;
136424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   struct st_texture_image *firstImage;
136524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
136624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   *needFlush = GL_FALSE;
136724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
136824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* We know/require this is true by now:
136924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
137014b98343309fdcff3514f05020303f7b40e83a4aBrian   assert(stObj->base._Complete);
137124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1372753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* What levels must the texture include at a minimum?
137324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
137414b98343309fdcff3514f05020303f7b40e83a4aBrian   calculate_first_last_level(stObj);
13754da1cdf78fa3b954840650fa46cf72da5daf149fBrian   firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
137624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1377753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* If both firstImage and stObj point to a texture which can contain
137824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * all active images, favour firstImage.  Note that because of the
137924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * completeness requirement, we know that the image dimensions
138024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    * will match.
138124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1382753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (firstImage->pt &&
1383753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt != stObj->pt &&
1384753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer       firstImage->pt->last_level >= stObj->lastLevel) {
138524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13864da19dbcaa9f3e2d20fffd0145bf0bc756dd7542Brian      pipe_texture_reference(&stObj->pt, firstImage->pt);
138724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
138824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
13894ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca   /* FIXME: determine format block instead of cpp */
139024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   if (firstImage->base.IsCompressed) {
139114b98343309fdcff3514f05020303f7b40e83a4aBrian      comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
139224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      cpp = comp_byte;
139324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
13945cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   else {
13955cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian      cpp = firstImage->base.TexFormat->TexelBytes;
13965cb0d749b07be4ecbf4d4d7cde18aecdfe2dba38Brian   }
139724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1398ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* If we already have a gallium texture, check that it matches the texture
1399ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul    * object's format, target, size, num_levels, etc.
140024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1401809dd9089bae70cf35cea6a75258e700e7455738Brian Paul   if (stObj->pt) {
1402809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      const enum pipe_format fmt =
1403809dd9089bae70cf35cea6a75258e700e7455738Brian Paul         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1404809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
1405809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->format != fmt ||
1406809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->last_level < stObj->lastLevel ||
1407809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->width[0] != firstImage->base.Width2 ||
1408809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->height[0] != firstImage->base.Height2 ||
1409809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->depth[0] != firstImage->base.Depth2 ||
14104ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.size != cpp ||
14114ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.width != 1 ||
14124ddd65967915ca4846f2831bc676c878a29dae4aJosé Fonseca          stObj->pt->block.height != 1 ||
1413809dd9089bae70cf35cea6a75258e700e7455738Brian Paul          stObj->pt->compressed != firstImage->base.IsCompressed) {
1414809dd9089bae70cf35cea6a75258e700e7455738Brian Paul         pipe_texture_release(&stObj->pt);
14151a82d9648b3db780e58e4966924157542d148c58Brian Paul         ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
1416809dd9089bae70cf35cea6a75258e700e7455738Brian Paul      }
141724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
141824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1419ce509401738e7073de94a2b7fc41461c52a73da0Brian Paul   /* May need to create a new gallium texture:
142024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
1421753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   if (!stObj->pt) {
1422a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger      const enum pipe_format fmt =
1423a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger         st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
1424753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer      stObj->pt = st_texture_create(ctx->st,
14255390a43ce06b27f6d54bc5f237aa305b6948f2afBrian                                    gl_target_to_pipe(stObj->base.Target),
1426a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    fmt,
1427b245840b86cf877c9b8d666edf229364a84f1deaBrian                                    stObj->lastLevel,
142845cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Width2,
142945cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Height2,
143045cc35e77600af8628393475405160e26d56d421Brian Paul                                    firstImage->base.Depth2,
1431a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                    comp_byte,
1432a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                    ( (pf_is_depth_stencil(fmt) ?
1433a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
1434a1f95a8bf64f863289b6759caeec76d7e054400eRoland Scheidegger                                      PIPE_TEXTURE_USAGE_RENDER_TARGET) |
1435a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell                                      PIPE_TEXTURE_USAGE_SAMPLER ));
1436a73ae3d5eb8419feab5aea26573aa41b72f941ebKeith Whitwell
14373b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      if (!stObj->pt) {
14383b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
14393b3774b1227743147159676795b542c0eb7c2bdfBrian Paul         return GL_FALSE;
14403b3774b1227743147159676795b542c0eb7c2bdfBrian Paul      }
144124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
144224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1443753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer   /* Pull in any images not in the object's texture:
144424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian    */
144524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   for (face = 0; face < nr_faces; face++) {
14464da1cdf78fa3b954840650fa46cf72da5daf149fBrian      GLuint level;
14474da1cdf78fa3b954840650fa46cf72da5daf149fBrian      for (level = 0; level <= stObj->lastLevel; level++) {
144824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         struct st_texture_image *stImage =
14494da1cdf78fa3b954840650fa46cf72da5daf149fBrian            st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
145024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
1451753db0d8407147393a7b0622ae3fa28f68d0353dMichel Dänzer         /* Need to import images in main memory or held in other textures.
145224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian          */
1453a34b43b3f4817268ef4b3f186203b5fbafc7214eBrian         if (stImage && stObj->pt != stImage->pt) {
14544da1cdf78fa3b954840650fa46cf72da5daf149fBrian            copy_image_data_to_texture(ctx->st, stObj, level, stImage);
145524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian	    *needFlush = GL_TRUE;
145624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian         }
145724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian      }
145824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   }
145924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
146024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   return GL_TRUE;
146124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
146224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
146324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
14648f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul/**
14658f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * Returns pointer to a default/dummy texture.
14668f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * This is typically used when the current shader has tex/sample instructions
14678f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul * but the user has not provided a (any) texture(s).
14688f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul */
14698f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulstruct gl_texture_object *
14708f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paulst_get_default_texture(struct st_context *st)
14718f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul{
14728f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   if (!st->default_texture) {
14738f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      static const GLenum target = GL_TEXTURE_2D;
14748f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      GLubyte pixels[16][16][4];
14758f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_object *texObj;
14768f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      struct gl_texture_image *texImg;
14778f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
1478a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      /* init image to gray */
1479a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul      memset(pixels, 127, sizeof(pixels));
1480a7b818d53a95b549bbff942a9cb91272e0799dd5Brian Paul
14818f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
14828f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14838f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
14848f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14858f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      _mesa_init_teximage_fields(st->ctx, target, texImg,
14868f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 16, 16, 1, 0,  /* w, h, d, border */
14878f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                                 GL_RGBA);
14888f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14898f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st_TexImage(st->ctx, 2, target,
14908f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, GL_RGBA,    /* level, intformat */
14918f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  16, 16, 1, 0,  /* w, h, d, border */
14928f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  GL_RGBA, GL_UNSIGNED_BYTE, pixels,
14938f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  &st->ctx->DefaultPacking,
14948f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  texObj, texImg,
14958f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul                  0, 0);
14968f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
14978f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MinFilter = GL_NEAREST;
14988f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->MagFilter = GL_NEAREST;
14998f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      texObj->_Complete = GL_TRUE;
15008f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15018f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul      st->default_texture = texObj;
15028f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   }
15038f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul   return st->default_texture;
15048f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul}
15058f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15068f6d9e12be0be086ca2aab0b56dff8d2181addd9Brian Paul
15076da9234fd437f97267e7831f034c78b31156d939Brianvoid
15086da9234fd437f97267e7831f034c78b31156d939Brianst_init_texture_functions(struct dd_function_table *functions)
150924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian{
151024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->ChooseTextureFormat = st_ChooseTextureFormat;
151124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage1D = st_TexImage1D;
151224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage2D = st_TexImage2D;
151324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexImage3D = st_TexImage3D;
151424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage1D = st_TexSubImage1D;
151524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage2D = st_TexSubImage2D;
151624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TexSubImage3D = st_TexSubImage3D;
151724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage1D = st_CopyTexImage1D;
151824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexImage2D = st_CopyTexImage2D;
151924df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
152024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
1521038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian   functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
152262abcb9aacc33218d0143a743c738435794b32a9Brian   functions->GenerateMipmap = st_generate_mipmap;
1523038cb561eb094af2f2ba06e18e61246fc0c87c3cBrian
152424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetTexImage = st_GetTexImage;
152524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
152624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   /* compressed texture functions */
152724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->CompressedTexImage2D = st_CompressedTexImage2D;
152824df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->GetCompressedTexImage = st_GetCompressedTexImage;
1529f32c51277498887b348133ebcd947dbc8acce756Roland Scheidegger   functions->CompressedTextureSize = _mesa_compressed_texture_size;
153024df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
153124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureObject = st_NewTextureObject;
153224df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->NewTextureImage = st_NewTextureImage;
153324df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->DeleteTexture = st_DeleteTextureObject;
153424df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->FreeTexImageData = st_FreeTextureImageData;
153524df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->UpdateTexturePalette = 0;
153624df8f895fe8807aa2ba058e71bd40adfc01d21eBrian
153724df8f895fe8807aa2ba058e71bd40adfc01d21eBrian   functions->TextureMemCpy = do_memcpy;
1538f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian
1539f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   /* XXX Temporary until we can query pipe's texture sizes */
1540f8549e8f4f8bdfebcb4e0a2754df59b3fe4fdff7Brian   functions->TestProxyTexImage = _mesa_test_proxy_teximage;
154124df8f895fe8807aa2ba058e71bd40adfc01d21eBrian}
1542