st_cb_texture.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 #include "main/imports.h"
00029 #if FEATURE_convolve
00030 #include "main/convolve.h"
00031 #endif
00032 #include "main/enums.h"
00033 #include "main/image.h"
00034 #include "main/macros.h"
00035 #include "main/mipmap.h"
00036 #include "main/pixel.h"
00037 #include "main/texcompress.h"
00038 #include "main/texformat.h"
00039 #include "main/teximage.h"
00040 #include "main/texobj.h"
00041 #include "main/texstore.h"
00042 
00043 #include "state_tracker/st_context.h"
00044 #include "state_tracker/st_cb_fbo.h"
00045 #include "state_tracker/st_cb_texture.h"
00046 #include "state_tracker/st_format.h"
00047 #include "state_tracker/st_public.h"
00048 #include "state_tracker/st_texture.h"
00049 #include "state_tracker/st_gen_mipmap.h"
00050 
00051 #include "pipe/p_context.h"
00052 #include "pipe/p_defines.h"
00053 #include "pipe/p_inlines.h"
00054 #include "util/u_tile.h"
00055 #include "util/u_blit.h"
00056 
00057 
00058 #define DBG if (0) printf
00059 
00060 
00061 static enum pipe_texture_target
00062 gl_target_to_pipe(GLenum target)
00063 {
00064    switch (target) {
00065    case GL_TEXTURE_1D:
00066       return PIPE_TEXTURE_1D;
00067 
00068    case GL_TEXTURE_2D:
00069    case GL_TEXTURE_RECTANGLE_NV:
00070       return PIPE_TEXTURE_2D;
00071 
00072    case GL_TEXTURE_3D:
00073       return PIPE_TEXTURE_3D;
00074 
00075    case GL_TEXTURE_CUBE_MAP_ARB:
00076       return PIPE_TEXTURE_CUBE;
00077 
00078    default:
00079       assert(0);
00080       return 0;
00081    }
00082 }
00083 
00084 
00089 static int
00090 compressed_num_bytes(GLuint mesaFormat)
00091 {
00092    switch(mesaFormat) {
00093 #if FEATURE_texture_fxt1
00094    case MESA_FORMAT_RGB_FXT1:
00095    case MESA_FORMAT_RGBA_FXT1:
00096 #endif
00097 #if FEATURE_texture_s3tc
00098    case MESA_FORMAT_RGB_DXT1:
00099    case MESA_FORMAT_RGBA_DXT1:
00100       return 2;
00101    case MESA_FORMAT_RGBA_DXT3:
00102    case MESA_FORMAT_RGBA_DXT5:
00103       return 4;
00104 #endif
00105    default:
00106       return 0;
00107    }
00108 }
00109 
00110 
00112 static struct gl_texture_image *
00113 st_NewTextureImage(GLcontext * ctx)
00114 {
00115    DBG("%s\n", __FUNCTION__);
00116    (void) ctx;
00117    return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image);
00118 }
00119 
00120 
00122 static struct gl_texture_object *
00123 st_NewTextureObject(GLcontext * ctx, GLuint name, GLenum target)
00124 {
00125    struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object);
00126 
00127    DBG("%s\n", __FUNCTION__);
00128    _mesa_initialize_texture_object(&obj->base, name, target);
00129 
00130    return &obj->base;
00131 }
00132 
00134 static void 
00135 st_DeleteTextureObject(GLcontext *ctx,
00136                        struct gl_texture_object *texObj)
00137 {
00138    struct st_texture_object *stObj = st_texture_object(texObj);
00139    if (stObj->pt)
00140       pipe_texture_reference(&stObj->pt, NULL);
00141 
00142    _mesa_delete_texture_object(ctx, texObj);
00143 }
00144 
00145 
00147 static void
00148 st_FreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage)
00149 {
00150    struct st_texture_image *stImage = st_texture_image(texImage);
00151 
00152    DBG("%s\n", __FUNCTION__);
00153 
00154    if (stImage->pt) {
00155       pipe_texture_reference(&stImage->pt, NULL);
00156    }
00157 
00158    if (texImage->Data) {
00159       _mesa_align_free(texImage->Data);
00160       texImage->Data = NULL;
00161    }
00162 }
00163 
00164 
00170 #if defined(i386) || defined(__i386__)
00171 static INLINE void *
00172 __memcpy(void *to, const void *from, size_t n)
00173 {
00174    int d0, d1, d2;
00175    __asm__ __volatile__("rep ; movsl\n\t"
00176                         "testb $2,%b4\n\t"
00177                         "je 1f\n\t"
00178                         "movsw\n"
00179                         "1:\ttestb $1,%b4\n\t"
00180                         "je 2f\n\t"
00181                         "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
00182                         :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
00183                         :"memory");
00184    return (to);
00185 }
00186 #else
00187 #define __memcpy(a,b,c) memcpy(a,b,c)
00188 #endif
00189 
00190 
00204 static void *
00205 do_memcpy(void *dest, const void *src, size_t n)
00206 {
00207    if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) {
00208       return __memcpy(dest, src, n);
00209    }
00210    else
00211       return memcpy(dest, src, n);
00212 }
00213 
00214 
00215 static int
00216 logbase2(int n)
00217 {
00218    GLint i = 1, log2 = 0;
00219    while (n > i) {
00220       i *= 2;
00221       log2++;
00222    }
00223    return log2;
00224 }
00225 
00226 
00241 static void
00242 guess_and_alloc_texture(struct st_context *st,
00243                         struct st_texture_object *stObj,
00244                         const struct st_texture_image *stImage)
00245 {
00246    GLuint firstLevel;
00247    GLuint lastLevel;
00248    GLuint width = stImage->base.Width2;  /* size w/out border */
00249    GLuint height = stImage->base.Height2;
00250    GLuint depth = stImage->base.Depth2;
00251    GLuint i, comp_byte = 0;
00252    enum pipe_format fmt;
00253 
00254    DBG("%s\n", __FUNCTION__);
00255 
00256    assert(!stObj->pt);
00257 
00258    if (stObj->pt &&
00259        (GLint) stImage->level > stObj->base.BaseLevel &&
00260        (stImage->base.Width == 1 ||
00261         (stObj->base.Target != GL_TEXTURE_1D &&
00262          stImage->base.Height == 1) ||
00263         (stObj->base.Target == GL_TEXTURE_3D &&
00264          stImage->base.Depth == 1)))
00265       return;
00266 
00267    /* If this image disrespects BaseLevel, allocate from level zero.
00268     * Usually BaseLevel == 0, so it's unlikely to happen.
00269     */
00270    if ((GLint) stImage->level < stObj->base.BaseLevel)
00271       firstLevel = 0;
00272    else
00273       firstLevel = stObj->base.BaseLevel;
00274 
00275 
00276    /* Figure out image dimensions at start level. 
00277     */
00278    for (i = stImage->level; i > firstLevel; i--) {
00279       if (width != 1)
00280          width <<= 1;
00281       if (height != 1)
00282          height <<= 1;
00283       if (depth != 1)
00284          depth <<= 1;
00285    }
00286 
00287    if (width == 0 || height == 0 || depth == 0) {
00288       /* no texture needed */
00289       return;
00290    }
00291 
00292    /* Guess a reasonable value for lastLevel.  This is probably going
00293     * to be wrong fairly often and might mean that we have to look at
00294     * resizable buffers, or require that buffers implement lazy
00295     * pagetable arrangements.
00296     */
00297    if ((stObj->base.MinFilter == GL_NEAREST ||
00298         stObj->base.MinFilter == GL_LINEAR) &&
00299        stImage->level == firstLevel) {
00300       lastLevel = firstLevel;
00301    }
00302    else {
00303       GLuint l2width = logbase2(width);
00304       GLuint l2height = logbase2(height);
00305       GLuint l2depth = logbase2(depth);
00306       lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth);
00307    }
00308 
00309    if (stImage->base.IsCompressed)
00310       comp_byte = compressed_num_bytes(stImage->base.TexFormat->MesaFormat);
00311 
00312    fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat);
00313    stObj->pt = st_texture_create(st,
00314                                  gl_target_to_pipe(stObj->base.Target),
00315                                  fmt,
00316                                  lastLevel,
00317                                  width,
00318                                  height,
00319                                  depth,
00320                                  comp_byte,
00321                                  ( (pf_is_depth_stencil(fmt) ?
00322                                    PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
00323                                    PIPE_TEXTURE_USAGE_RENDER_TARGET) |
00324                                    PIPE_TEXTURE_USAGE_SAMPLER ));
00325 
00326    DBG("%s - success\n", __FUNCTION__);
00327 }
00328 
00329 
00337 static void
00338 strip_texture_border(GLint border,
00339                      GLint *width, GLint *height, GLint *depth,
00340                      const struct gl_pixelstore_attrib *unpack,
00341                      struct gl_pixelstore_attrib *unpackNew)
00342 {
00343    assert(border > 0);  /* sanity check */
00344 
00345    *unpackNew = *unpack;
00346 
00347    if (unpackNew->RowLength == 0)
00348       unpackNew->RowLength = *width;
00349 
00350    if (depth && unpackNew->ImageHeight == 0)
00351       unpackNew->ImageHeight = *height;
00352 
00353    unpackNew->SkipPixels += border;
00354    if (height)
00355       unpackNew->SkipRows += border;
00356    if (depth)
00357       unpackNew->SkipImages += border;
00358 
00359    assert(*width >= 3);
00360    *width = *width - 2 * border;
00361    if (height && *height >= 3)
00362       *height = *height - 2 * border;
00363    if (depth && *depth >= 3)
00364       *depth = *depth - 2 * border;
00365 }
00366 
00367 
00371 static void
00372 st_TexImage(GLcontext * ctx,
00373             GLint dims,
00374             GLenum target, GLint level,
00375             GLint internalFormat,
00376             GLint width, GLint height, GLint depth,
00377             GLint border,
00378             GLenum format, GLenum type, const void *pixels,
00379             const struct gl_pixelstore_attrib *unpack,
00380             struct gl_texture_object *texObj,
00381             struct gl_texture_image *texImage,
00382             GLsizei imageSize, int compressed)
00383 {
00384    struct st_texture_object *stObj = st_texture_object(texObj);
00385    struct st_texture_image *stImage = st_texture_image(texImage);
00386    GLint postConvWidth, postConvHeight;
00387    GLint texelBytes, sizeInBytes;
00388    GLuint dstRowStride;
00389    struct gl_pixelstore_attrib unpackNB;
00390 
00391    DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
00392        _mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
00393 
00394    /* gallium does not support texture borders, strip it off */
00395    if (border) {
00396       strip_texture_border(border, &width, &height, &depth,
00397                            unpack, &unpackNB);
00398       unpack = &unpackNB;
00399       texImage->Width = width;
00400       texImage->Height = height;
00401       texImage->Depth = depth;
00402       texImage->Border = 0;
00403       border = 0;
00404    }
00405 
00406    postConvWidth = width;
00407    postConvHeight = height;
00408 
00409    stImage->face = _mesa_tex_target_to_face(target);
00410    stImage->level = level;
00411 
00412 #if FEATURE_convolve
00413    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
00414       _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
00415                                          &postConvHeight);
00416    }
00417 #endif
00418 
00419    /* choose the texture format */
00420    texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat,
00421                                                 format, type);
00422 
00423    _mesa_set_fetch_functions(texImage, dims);
00424 
00425    if (texImage->TexFormat->TexelBytes == 0) {
00426       /* must be a compressed format */
00427       texelBytes = 0;
00428       texImage->IsCompressed = GL_TRUE;
00429       texImage->CompressedSize =
00430          ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
00431                                            texImage->Height, texImage->Depth,
00432                                            texImage->TexFormat->MesaFormat);
00433    }
00434    else {
00435       texelBytes = texImage->TexFormat->TexelBytes;
00436       
00437       /* Minimum pitch of 32 bytes */
00438       if (postConvWidth * texelBytes < 32) {
00439          postConvWidth = 32 / texelBytes;
00440          texImage->RowStride = postConvWidth;
00441       }
00442       
00443       /* we'll set RowStride elsewhere when the texture is a "mapped" state */
00444       /*assert(texImage->RowStride == postConvWidth);*/
00445    }
00446 
00447    /* Release the reference to a potentially orphaned buffer.   
00448     * Release any old malloced memory.
00449     */
00450    if (stImage->pt) {
00451       pipe_texture_reference(&stImage->pt, NULL);
00452       assert(!texImage->Data);
00453    }
00454    else if (texImage->Data) {
00455       _mesa_align_free(texImage->Data);
00456    }
00457 
00458    if (width == 0 || height == 0 || depth == 0) {
00459       /* stop after freeing old image */
00460       return;
00461    }
00462 
00463    /* If this is the only mipmap level in the texture, could call
00464     * bmBufferData with NULL data to free the old block and avoid
00465     * waiting on any outstanding fences.
00466     */
00467    if (stObj->pt &&
00468        (stObj->teximage_realloc ||
00469         (/*stObj->pt->first_level == level &&*/
00470          stObj->pt->last_level == level &&
00471          stObj->pt->target != PIPE_TEXTURE_CUBE &&
00472          !st_texture_match_image(stObj->pt, &stImage->base,
00473                                  stImage->face, stImage->level)))) {
00474 
00475       DBG("release it\n");
00476       pipe_texture_reference(&stObj->pt, NULL);
00477       assert(!stObj->pt);
00478       stObj->teximage_realloc = FALSE;
00479    }
00480 
00481    if (!stObj->pt) {
00482       guess_and_alloc_texture(ctx->st, stObj, stImage);
00483       if (!stObj->pt) {
00484          /* Probably out of memory.
00485           * Try flushing any pending rendering, then retry.
00486           */
00487          st_finish(ctx->st);
00488          guess_and_alloc_texture(ctx->st, stObj, stImage);
00489          if (!stObj->pt) {
00490             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
00491             return;
00492          }
00493       }
00494    }
00495 
00496    assert(!stImage->pt);
00497 
00498    if (stObj->pt &&
00499        st_texture_match_image(stObj->pt, &stImage->base,
00500                                  stImage->face, stImage->level)) {
00501 
00502       pipe_texture_reference(&stImage->pt, stObj->pt);
00503       assert(stImage->pt);
00504    }
00505 
00506    if (!stImage->pt)
00507       DBG("XXX: Image did not fit into texture - storing in local memory!\n");
00508 
00509    /* st_CopyTexImage calls this function with pixels == NULL, with
00510     * the expectation that the texture will be set up but nothing
00511     * more will be done.  This is where those calls return:
00512     */
00513    if (compressed) {
00514       pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
00515                                                       unpack,
00516                                                       "glCompressedTexImage");
00517    } else {
00518       pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
00519                                            format, type,
00520                                            pixels, unpack, "glTexImage");
00521    }
00522    if (!pixels)
00523       return;
00524 
00525    if (stImage->pt) {
00526       texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
00527                                             PIPE_BUFFER_USAGE_CPU_WRITE);
00528       if (stImage->surface)
00529          dstRowStride = stImage->surface->stride;
00530    }
00531    else {
00532       /* Allocate regular memory and store the image there temporarily.   */
00533       if (texImage->IsCompressed) {
00534          sizeInBytes = texImage->CompressedSize;
00535          dstRowStride =
00536             _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
00537          assert(dims != 3);
00538       }
00539       else {
00540          dstRowStride = postConvWidth * texelBytes;
00541          sizeInBytes = depth * dstRowStride * postConvHeight;
00542       }
00543 
00544       texImage->Data = _mesa_align_malloc(sizeInBytes, 16);
00545    }
00546 
00547    if (!texImage->Data) {
00548       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
00549       return;
00550    }
00551 
00552    DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
00553        width, height, depth, width * texelBytes, dstRowStride);
00554 
00555    /* Copy data.  Would like to know when it's ok for us to eg. use
00556     * the blitter to copy.  Or, use the hardware to do the format
00557     * conversion and copy:
00558     */
00559    if (compressed) {
00560       memcpy(texImage->Data, pixels, imageSize);
00561    }
00562    else {
00563       GLuint srcImageStride = _mesa_image_image_stride(unpack, width, height,
00564                                                        format, type);
00565       int i;
00566       const GLubyte *src = (const GLubyte *) pixels;
00567 
00568       for (i = 0; i++ < depth;) {
00569          if (!texImage->TexFormat->StoreImage(ctx, dims, 
00570                                               texImage->_BaseFormat, 
00571                                               texImage->TexFormat, 
00572                                               texImage->Data,
00573                                               0, 0, 0, /* dstX/Y/Zoffset */
00574                                               dstRowStride,
00575                                               texImage->ImageOffsets,
00576                                               width, height, 1,
00577                                               format, type, src, unpack)) {
00578             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
00579          }
00580 
00581          if (stImage->pt && i < depth) {
00582             st_texture_image_unmap(ctx->st, stImage);
00583             texImage->Data = st_texture_image_map(ctx->st, stImage, i,
00584                                                   PIPE_BUFFER_USAGE_CPU_WRITE);
00585             src += srcImageStride;
00586          }
00587       }
00588    }
00589 
00590    _mesa_unmap_teximage_pbo(ctx, unpack);
00591 
00592    if (stImage->pt) {
00593       st_texture_image_unmap(ctx->st, stImage);
00594       texImage->Data = NULL;
00595    }
00596 
00597    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
00598       ctx->Driver.GenerateMipmap(ctx, target, texObj);
00599    }
00600 }
00601 
00602 
00603 static void
00604 st_TexImage3D(GLcontext * ctx,
00605               GLenum target, GLint level,
00606               GLint internalFormat,
00607               GLint width, GLint height, GLint depth,
00608               GLint border,
00609               GLenum format, GLenum type, const void *pixels,
00610               const struct gl_pixelstore_attrib *unpack,
00611               struct gl_texture_object *texObj,
00612               struct gl_texture_image *texImage)
00613 {
00614    st_TexImage(ctx, 3, target, level,
00615                  internalFormat, width, height, depth, border,
00616                  format, type, pixels, unpack, texObj, texImage, 0, 0);
00617 }
00618 
00619 
00620 static void
00621 st_TexImage2D(GLcontext * ctx,
00622               GLenum target, GLint level,
00623               GLint internalFormat,
00624               GLint width, GLint height, GLint border,
00625               GLenum format, GLenum type, const void *pixels,
00626               const struct gl_pixelstore_attrib *unpack,
00627               struct gl_texture_object *texObj,
00628               struct gl_texture_image *texImage)
00629 {
00630    st_TexImage(ctx, 2, target, level,
00631                  internalFormat, width, height, 1, border,
00632                  format, type, pixels, unpack, texObj, texImage, 0, 0);
00633 }
00634 
00635 
00636 static void
00637 st_TexImage1D(GLcontext * ctx,
00638               GLenum target, GLint level,
00639               GLint internalFormat,
00640               GLint width, GLint border,
00641               GLenum format, GLenum type, const void *pixels,
00642               const struct gl_pixelstore_attrib *unpack,
00643               struct gl_texture_object *texObj,
00644               struct gl_texture_image *texImage)
00645 {
00646    st_TexImage(ctx, 1, target, level,
00647                  internalFormat, width, 1, 1, border,
00648                  format, type, pixels, unpack, texObj, texImage, 0, 0);
00649 }
00650 
00651 
00652 static void
00653 st_CompressedTexImage2D(GLcontext *ctx, GLenum target, GLint level,
00654                         GLint internalFormat,
00655                         GLint width, GLint height, GLint border,
00656                         GLsizei imageSize, const GLvoid *data,
00657                         struct gl_texture_object *texObj,
00658                         struct gl_texture_image *texImage)
00659 {
00660    st_TexImage(ctx, 2, target, level,
00661                  internalFormat, width, height, 1, border,
00662                  0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1);
00663 }
00664 
00665 
00670 static void
00671 st_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
00672                  GLenum format, GLenum type, GLvoid * pixels,
00673                  struct gl_texture_object *texObj,
00674                  struct gl_texture_image *texImage, int compressed)
00675 {
00676    struct st_texture_image *stImage = st_texture_image(texImage);
00677    GLuint dstImageStride = _mesa_image_image_stride(&ctx->Pack,
00678                                                     texImage->Width,
00679                                                     texImage->Height,
00680                                                     format, type);
00681    GLuint depth;
00682    GLuint i;
00683    GLubyte *dest;
00684 
00685    /* Map */
00686    if (stImage->pt) {
00687       /* Image is stored in hardware format in a buffer managed by the
00688        * kernel.  Need to explicitly map and unmap it.
00689        */
00690       texImage->Data = st_texture_image_map(ctx->st, stImage, 0,
00691                                             PIPE_BUFFER_USAGE_CPU_READ);
00692       texImage->RowStride = stImage->surface->stride / stImage->pt->block.size;
00693    }
00694    else {
00695       /* Otherwise, the image should actually be stored in
00696        * texImage->Data.  This is pretty confusing for
00697        * everybody, I'd much prefer to separate the two functions of
00698        * texImage->Data - storage for texture images in main memory
00699        * and access (ie mappings) of images.  In other words, we'd
00700        * create a new texImage->Map field and leave Data simply for
00701        * storage.
00702        */
00703       assert(texImage->Data);
00704    }
00705 
00706    depth = texImage->Depth;
00707    texImage->Depth = 1;
00708 
00709    dest = (GLubyte *) pixels;
00710 
00711    for (i = 0; i++ < depth;) {
00712       if (compressed) {
00713          _mesa_get_compressed_teximage(ctx, target, level, dest,
00714                                        texObj, texImage);
00715       } else {
00716          _mesa_get_teximage(ctx, target, level, format, type, dest,
00717                             texObj, texImage);
00718       }
00719 
00720       if (stImage->pt && i < depth) {
00721          st_texture_image_unmap(ctx->st, stImage);
00722          texImage->Data = st_texture_image_map(ctx->st, stImage, i,
00723                                                PIPE_BUFFER_USAGE_CPU_READ);
00724          dest += dstImageStride;
00725       }
00726    }
00727 
00728    texImage->Depth = depth;
00729 
00730    /* Unmap */
00731    if (stImage->pt) {
00732       st_texture_image_unmap(ctx->st, stImage);
00733       texImage->Data = NULL;
00734    }
00735 }
00736 
00737 
00738 static void
00739 st_GetTexImage(GLcontext * ctx, GLenum target, GLint level,
00740                GLenum format, GLenum type, GLvoid * pixels,
00741                struct gl_texture_object *texObj,
00742                struct gl_texture_image *texImage)
00743 {
00744    st_get_tex_image(ctx, target, level, format, type, pixels,
00745                     texObj, texImage, 0);
00746 }
00747 
00748 
00749 static void
00750 st_GetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
00751                          GLvoid *pixels,
00752                          const struct gl_texture_object *texObj,
00753                          const struct gl_texture_image *texImage)
00754 {
00755    st_get_tex_image(ctx, target, level, 0, 0, pixels,
00756                     (struct gl_texture_object *) texObj,
00757                     (struct gl_texture_image *) texImage, 1);
00758 }
00759 
00760 
00761 
00762 static void
00763 st_TexSubimage(GLcontext * ctx,
00764                GLint dims,
00765                GLenum target, GLint level,
00766                GLint xoffset, GLint yoffset, GLint zoffset,
00767                GLint width, GLint height, GLint depth,
00768                GLenum format, GLenum type, const void *pixels,
00769                const struct gl_pixelstore_attrib *packing,
00770                struct gl_texture_object *texObj,
00771                struct gl_texture_image *texImage)
00772 {
00773    struct st_texture_image *stImage = st_texture_image(texImage);
00774    GLuint dstRowStride;
00775    GLuint srcImageStride = _mesa_image_image_stride(packing, width, height,
00776                                                     format, type);
00777    int i;
00778    const GLubyte *src;
00779 
00780    DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
00781        _mesa_lookup_enum_by_nr(target),
00782        level, xoffset, yoffset, width, height);
00783 
00784    pixels =
00785       _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
00786                                   type, pixels, packing, "glTexSubImage2D");
00787    if (!pixels)
00788       return;
00789 
00790    /* Map buffer if necessary.  Need to lock to prevent other contexts
00791     * from uploading the buffer under us.
00792     */
00793    if (stImage->pt) {
00794       texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset, 
00795                                             PIPE_BUFFER_USAGE_CPU_WRITE);
00796       if (stImage->surface)
00797          dstRowStride = stImage->surface->stride;
00798    }
00799 
00800    if (!texImage->Data) {
00801       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
00802       return;
00803    }
00804 
00805    src = (const GLubyte *) pixels;
00806 
00807    for (i = 0; i++ < depth;) {
00808       if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
00809                                            texImage->TexFormat,
00810                                            texImage->Data,
00811                                            xoffset, yoffset, 0,
00812                                            dstRowStride,
00813                                            texImage->ImageOffsets,
00814                                            width, height, 1,
00815                                            format, type, src, packing)) {
00816          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
00817       }
00818 
00819       if (stImage->pt && i < depth) {
00820          /* map next slice of 3D texture */
00821          st_texture_image_unmap(ctx->st, stImage);
00822          texImage->Data = st_texture_image_map(ctx->st, stImage, zoffset + i,
00823                                                PIPE_BUFFER_USAGE_CPU_WRITE);
00824          src += srcImageStride;
00825       }
00826    }
00827 
00828    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
00829       ctx->Driver.GenerateMipmap(ctx, target, texObj);
00830    }
00831 
00832    _mesa_unmap_teximage_pbo(ctx, packing);
00833 
00834    if (stImage->pt) {
00835       st_texture_image_unmap(ctx->st, stImage);
00836       texImage->Data = NULL;
00837    }
00838 }
00839 
00840 
00841 
00842 static void
00843 st_TexSubImage3D(GLcontext * ctx,
00844                    GLenum target,
00845                    GLint level,
00846                    GLint xoffset, GLint yoffset, GLint zoffset,
00847                    GLsizei width, GLsizei height, GLsizei depth,
00848                    GLenum format, GLenum type,
00849                    const GLvoid * pixels,
00850                    const struct gl_pixelstore_attrib *packing,
00851                    struct gl_texture_object *texObj,
00852                    struct gl_texture_image *texImage)
00853 {
00854    st_TexSubimage(ctx, 3, target, level,
00855                   xoffset, yoffset, zoffset,
00856                   width, height, depth,
00857                   format, type, pixels, packing, texObj, texImage);
00858 }
00859 
00860 
00861 static void
00862 st_TexSubImage2D(GLcontext * ctx,
00863                    GLenum target,
00864                    GLint level,
00865                    GLint xoffset, GLint yoffset,
00866                    GLsizei width, GLsizei height,
00867                    GLenum format, GLenum type,
00868                    const GLvoid * pixels,
00869                    const struct gl_pixelstore_attrib *packing,
00870                    struct gl_texture_object *texObj,
00871                    struct gl_texture_image *texImage)
00872 {
00873    st_TexSubimage(ctx, 2, target, level,
00874                   xoffset, yoffset, 0,
00875                   width, height, 1,
00876                   format, type, pixels, packing, texObj, texImage);
00877 }
00878 
00879 
00880 static void
00881 st_TexSubImage1D(GLcontext * ctx,
00882                    GLenum target,
00883                    GLint level,
00884                    GLint xoffset,
00885                    GLsizei width,
00886                    GLenum format, GLenum type,
00887                    const GLvoid * pixels,
00888                    const struct gl_pixelstore_attrib *packing,
00889                    struct gl_texture_object *texObj,
00890                    struct gl_texture_image *texImage)
00891 {
00892    st_TexSubimage(ctx, 1, target, level,
00893                   xoffset, 0, 0,
00894                   width, 1, 1,
00895                   format, type, pixels, packing, texObj, texImage);
00896 }
00897 
00898 
00899 
00906 static uint
00907 texture_face(GLenum target)
00908 {
00909    if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
00910        target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
00911       return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
00912    else
00913       return 0;
00914 }
00915 
00916 
00917 
00924 static void
00925 fallback_copy_texsubimage(GLcontext *ctx,
00926                           GLenum target,
00927                           GLint level,
00928                           struct st_renderbuffer *strb,
00929                           struct st_texture_image *stImage,
00930                           GLenum baseFormat,
00931                           GLint destX, GLint destY, GLint destZ,
00932                           GLint srcX, GLint srcY,
00933                           GLsizei width, GLsizei height)
00934 {
00935    struct pipe_context *pipe = ctx->st->pipe;
00936    struct pipe_screen *screen = pipe->screen;
00937    const uint face = texture_face(target);
00938    struct pipe_texture *pt = stImage->pt;
00939    struct pipe_surface *src_surf, *dest_surf;
00940 
00941    /* We'd use strb->surface, here but it's created for GPU read/write only */
00942    src_surf = pipe->screen->get_tex_surface( pipe->screen,
00943                                              strb->texture,
00944                                              0, 0, 0,
00945                                              PIPE_BUFFER_USAGE_CPU_READ);
00946 
00947    dest_surf = screen->get_tex_surface(screen, pt, face, level, destZ,
00948                                        PIPE_BUFFER_USAGE_CPU_WRITE);
00949 
00950    assert(width <= MAX_WIDTH);
00951 
00952    if (baseFormat == GL_DEPTH_COMPONENT) {
00953       const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
00954                                      ctx->Pixel.DepthBias != 0.0F);
00955       GLint row, yStep;
00956 
00957       /* determine bottom-to-top vs. top-to-bottom order for src buffer */
00958       if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
00959          srcY = strb->Base.Height - 1 - srcY;
00960          yStep = -1;
00961       }
00962       else {
00963          yStep = 1;
00964       }
00965 
00966       /* To avoid a large temp memory allocation, do copy row by row */
00967       for (row = 0; row < height; row++, srcY += yStep, destY++) {
00968          uint data[MAX_WIDTH];
00969          pipe_get_tile_z(src_surf, srcX, srcY, width, 1, data);
00970          if (scaleOrBias) {
00971             _mesa_scale_and_bias_depth_uint(ctx, width, data);
00972          }
00973          pipe_put_tile_z(dest_surf, destX, destY, width, 1, data);
00974       }
00975    }
00976    else {
00977       /* RGBA format */
00978       GLfloat *tempSrc =
00979          (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat));
00980       GLvoid *texDest =
00981          st_texture_image_map(ctx->st, stImage, 0,PIPE_BUFFER_USAGE_CPU_WRITE);
00982 
00983       if (tempSrc && texDest) {
00984          const GLint dims = 2;
00985          struct gl_texture_image *texImage = &stImage->base;
00986          GLint dstRowStride = stImage->surface->stride;
00987          struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
00988 
00989          if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
00990             /* need to invert src */
00991             srcY = strb->Base.Height - srcY - height;
00992             unpack.Invert = GL_TRUE;
00993          }
00994 
00995          /* get float/RGBA image from framebuffer */
00996          /* XXX this usually involves a lot of int/float conversion.
00997           * try to avoid that someday.
00998           */
00999          pipe_get_tile_rgba(src_surf, srcX, srcY, width, height, tempSrc);
01000 
01001          /* Store into texture memory.
01002           * Note that this does some special things such as pixel transfer
01003           * ops and format conversion.  In particular, if the dest tex format
01004           * is actually RGBA but the user created the texture as GL_RGB we
01005           * need to fill-in/override the alpha channel with 1.0.
01006           */
01007          texImage->TexFormat->StoreImage(ctx, dims,
01008                                          texImage->_BaseFormat, 
01009                                          texImage->TexFormat, 
01010                                          texDest,
01011                                          destX, destY, destZ,
01012                                          dstRowStride,
01013                                          texImage->ImageOffsets,
01014                                          width, height, 1,
01015                                          GL_RGBA, GL_FLOAT, tempSrc, /* src */
01016                                          &unpack);
01017       }
01018       else {
01019          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
01020       }
01021 
01022       if (tempSrc)
01023          _mesa_free(tempSrc);
01024       if (texDest)
01025          st_texture_image_unmap(ctx->st, stImage);
01026    }
01027 
01028    screen->tex_surface_release(screen, &dest_surf);
01029    screen->tex_surface_release(screen, &src_surf);
01030 }
01031 
01032 
01040 static void
01041 st_copy_texsubimage(GLcontext *ctx,
01042                     GLenum target, GLint level,
01043                     GLint destX, GLint destY, GLint destZ,
01044                     GLint srcX, GLint srcY,
01045                     GLsizei width, GLsizei height)
01046 {
01047    struct gl_texture_unit *texUnit =
01048       &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
01049    struct gl_texture_object *texObj =
01050       _mesa_select_tex_object(ctx, texUnit, target);
01051    struct gl_texture_image *texImage =
01052       _mesa_select_tex_image(ctx, texObj, target, level);
01053    struct st_texture_image *stImage = st_texture_image(texImage);
01054    const GLenum texBaseFormat = texImage->InternalFormat;
01055    struct gl_framebuffer *fb = ctx->ReadBuffer;
01056    struct st_renderbuffer *strb;
01057    struct pipe_context *pipe = ctx->st->pipe;
01058    struct pipe_screen *screen = pipe->screen;
01059    enum pipe_format dest_format, src_format;
01060    GLboolean use_fallback = GL_TRUE;
01061    GLboolean matching_base_formats;
01062 
01063    /* any rendering in progress must complete before we grab the fb image */
01064    st_finish(ctx->st);
01065 
01066    /* determine if copying depth or color data */
01067    if (texBaseFormat == GL_DEPTH_COMPONENT) {
01068       strb = st_renderbuffer(fb->_DepthBuffer);
01069    }
01070    else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) {
01071       strb = st_renderbuffer(fb->_StencilBuffer);
01072    }
01073    else {
01074       /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
01075       strb = st_renderbuffer(fb->_ColorReadBuffer);
01076    }
01077 
01078    assert(strb);
01079    assert(strb->surface);
01080    assert(stImage->pt);
01081 
01082    src_format = strb->surface->format;
01083    dest_format = stImage->pt->format;
01084 
01085    /*
01086     * Determine if the src framebuffer and dest texture have the same
01087     * base format.  We need this to detect a case such as the framebuffer
01088     * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
01089     * texture format stores RGBA we need to set A=1 (overriding the
01090     * framebuffer's alpha values).  We can't do that with the blit or
01091     * textured-quad paths.
01092     */
01093    matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
01094 
01095    if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
01096       /* try potential hardware path */
01097       struct pipe_surface *dest_surface = NULL;
01098 
01099       if (src_format == dest_format) {
01100          /* use surface_copy() / blit */
01101          boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
01102 
01103          dest_surface = screen->get_tex_surface(screen, stImage->pt,
01104                                                 stImage->face, stImage->level,
01105                                                 destZ,
01106                                                 PIPE_BUFFER_USAGE_GPU_WRITE);
01107          if (do_flip)
01108             srcY = strb->surface->height - srcY - height;
01109 
01110          /* for surface_copy(), y=0=top, always */
01111          pipe->surface_copy(pipe,
01112                             do_flip,
01113                             /* dest */
01114                             dest_surface,
01115                             destX, destY,
01116                             /* src */
01117                             strb->surface,
01118                             srcX, srcY,
01119                             /* size */
01120                             width, height);
01121          use_fallback = GL_FALSE;
01122       }
01123       else if (screen->is_format_supported(screen, src_format,
01124                                            PIPE_TEXTURE_2D, 
01125                                            PIPE_TEXTURE_USAGE_SAMPLER,
01126                                            0) &&
01127                screen->is_format_supported(screen, dest_format,
01128                                            PIPE_TEXTURE_2D, 
01129                                            PIPE_TEXTURE_USAGE_RENDER_TARGET,
01130                                            0)) {
01131          /* draw textured quad to do the copy */
01132          boolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
01133          int srcY0, srcY1;
01134 
01135          dest_surface = screen->get_tex_surface(screen, stImage->pt,
01136                                                 stImage->face, stImage->level,
01137                                                 destZ,
01138                                                 PIPE_BUFFER_USAGE_GPU_WRITE);
01139 
01140          if (do_flip) {
01141             srcY1 = strb->Base.Height - srcY - height;
01142             srcY0 = srcY1 + height;
01143          }
01144          else {
01145             srcY0 = srcY;
01146             srcY1 = srcY0 + height;
01147          }
01148          util_blit_pixels(ctx->st->blit,
01149                           strb->surface,
01150                           srcX, srcY0,
01151                           srcX + width, srcY1,
01152                           dest_surface,
01153                           destX, destY,
01154                           destX + width, destY + height,
01155                           0.0, PIPE_TEX_MIPFILTER_NEAREST);
01156          use_fallback = GL_FALSE;
01157       }
01158 
01159       if (dest_surface)
01160          pipe_surface_reference(&dest_surface, NULL);
01161    }
01162 
01163    if (use_fallback) {
01164       /* software fallback */
01165       fallback_copy_texsubimage(ctx, target, level,
01166                                 strb, stImage, texBaseFormat,
01167                                 destX, destY, destZ,
01168                                 srcX, srcY, width, height);
01169    }
01170 
01171    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
01172       ctx->Driver.GenerateMipmap(ctx, target, texObj);
01173    }
01174 }
01175 
01176 
01177 
01178 static void
01179 st_CopyTexImage1D(GLcontext * ctx, GLenum target, GLint level,
01180                   GLenum internalFormat,
01181                   GLint x, GLint y, GLsizei width, GLint border)
01182 {
01183    struct gl_texture_unit *texUnit =
01184       &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
01185    struct gl_texture_object *texObj =
01186       _mesa_select_tex_object(ctx, texUnit, target);
01187    struct gl_texture_image *texImage =
01188       _mesa_select_tex_image(ctx, texObj, target, level);
01189 
01190 #if 0
01191    if (border)
01192       goto fail;
01193 #endif
01194 
01195    /* Setup or redefine the texture object, texture and texture
01196     * image.  Don't populate yet.  
01197     */
01198    ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
01199                           width, border,
01200                           GL_RGBA, CHAN_TYPE, NULL,
01201                           &ctx->DefaultPacking, texObj, texImage);
01202 
01203    st_copy_texsubimage(ctx, target, level,
01204                        0, 0, 0,  /* destX,Y,Z */
01205                        x, y, width, 1);  /* src X, Y, size */
01206 }
01207 
01208 
01209 static void
01210 st_CopyTexImage2D(GLcontext * ctx, GLenum target, GLint level,
01211                   GLenum internalFormat,
01212                   GLint x, GLint y, GLsizei width, GLsizei height,
01213                   GLint border)
01214 {
01215    struct gl_texture_unit *texUnit =
01216       &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
01217    struct gl_texture_object *texObj =
01218       _mesa_select_tex_object(ctx, texUnit, target);
01219    struct gl_texture_image *texImage =
01220       _mesa_select_tex_image(ctx, texObj, target, level);
01221 
01222    /* Setup or redefine the texture object, texture and texture
01223     * image.  Don't populate yet.  
01224     */
01225    ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
01226                           width, height, border,
01227                           GL_RGBA, CHAN_TYPE, NULL,
01228                           &ctx->DefaultPacking, texObj, texImage);
01229 
01230    st_copy_texsubimage(ctx, target, level,
01231                        0, 0, 0,  /* destX,Y,Z */
01232                        x, y, width, height);  /* src X, Y, size */
01233 }
01234 
01235 
01236 static void
01237 st_CopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
01238                      GLint xoffset, GLint x, GLint y, GLsizei width)
01239 {
01240    const GLint yoffset = 0, zoffset = 0;
01241    const GLsizei height = 1;
01242    st_copy_texsubimage(ctx, target, level,
01243                        xoffset, yoffset, zoffset,  /* destX,Y,Z */
01244                        x, y, width, height);  /* src X, Y, size */
01245 }
01246 
01247 
01248 static void
01249 st_CopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
01250                      GLint xoffset, GLint yoffset,
01251                      GLint x, GLint y, GLsizei width, GLsizei height)
01252 {
01253    const GLint zoffset = 0;
01254    st_copy_texsubimage(ctx, target, level,
01255                        xoffset, yoffset, zoffset,  /* destX,Y,Z */
01256                        x, y, width, height);  /* src X, Y, size */
01257 }
01258 
01259 
01260 static void
01261 st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
01262                      GLint xoffset, GLint yoffset, GLint zoffset,
01263                      GLint x, GLint y, GLsizei width, GLsizei height)
01264 {
01265    st_copy_texsubimage(ctx, target, level,
01266                        xoffset, yoffset, zoffset,  /* destX,Y,Z */
01267                        x, y, width, height);  /* src X, Y, size */
01268 }
01269 
01270 
01276 static void
01277 calculate_first_last_level(struct st_texture_object *stObj)
01278 {
01279    struct gl_texture_object *tObj = &stObj->base;
01280 
01281    /* These must be signed values.  MinLod and MaxLod can be negative numbers,
01282     * and having firstLevel and lastLevel as signed prevents the need for
01283     * extra sign checks.
01284     */
01285    int firstLevel;
01286    int lastLevel;
01287 
01288    /* Yes, this looks overly complicated, but it's all needed.
01289     */
01290    switch (tObj->Target) {
01291    case GL_TEXTURE_1D:
01292    case GL_TEXTURE_2D:
01293    case GL_TEXTURE_3D:
01294    case GL_TEXTURE_CUBE_MAP:
01295       if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
01296          /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
01297           */
01298          firstLevel = lastLevel = tObj->BaseLevel;
01299       }
01300       else {
01301          firstLevel = 0;
01302          lastLevel = MIN2(tObj->MaxLevel,
01303                           (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2);
01304       }
01305       break;
01306    case GL_TEXTURE_RECTANGLE_NV:
01307    case GL_TEXTURE_4D_SGIS:
01308       firstLevel = lastLevel = 0;
01309       break;
01310    default:
01311       return;
01312    }
01313 
01314    stObj->lastLevel = lastLevel;
01315 }
01316 
01317 
01318 static void
01319 copy_image_data_to_texture(struct st_context *st,
01320                            struct st_texture_object *stObj,
01321                            GLuint dstLevel,
01322                            struct st_texture_image *stImage)
01323 {
01324    if (stImage->pt) {
01325       /* Copy potentially with the blitter:
01326        */
01327       st_texture_image_copy(st->pipe,
01328                             stObj->pt, dstLevel,  /* dest texture, level */
01329                             stImage->pt, /* src texture */
01330                             stImage->face
01331                             );
01332 
01333       pipe_texture_reference(&stImage->pt, NULL);
01334    }
01335    else if (stImage->base.Data) {
01336       assert(stImage->base.Data != NULL);
01337 
01338       /* More straightforward upload.  
01339        */
01340       st_texture_image_data(st->pipe,
01341                                stObj->pt,
01342                                stImage->face,
01343                                dstLevel,
01344                                stImage->base.Data,
01345                                stImage->base.RowStride * 
01346                                stObj->pt->block.size,
01347                                stImage->base.RowStride *
01348                                stImage->base.Height *
01349                                stObj->pt->block.size);
01350       _mesa_align_free(stImage->base.Data);
01351       stImage->base.Data = NULL;
01352    }
01353 
01354    pipe_texture_reference(&stImage->pt, stObj->pt);
01355 }
01356 
01357 
01363 GLboolean
01364 st_finalize_texture(GLcontext *ctx,
01365                     struct pipe_context *pipe,
01366                     struct gl_texture_object *tObj,
01367                     GLboolean *needFlush)
01368 {
01369    struct st_texture_object *stObj = st_texture_object(tObj);
01370    const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
01371    int comp_byte = 0;
01372    int cpp;
01373    GLuint face;
01374    struct st_texture_image *firstImage;
01375 
01376    *needFlush = GL_FALSE;
01377 
01378    /* We know/require this is true by now: 
01379     */
01380    assert(stObj->base._Complete);
01381 
01382    /* What levels must the texture include at a minimum?
01383     */
01384    calculate_first_last_level(stObj);
01385    firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
01386 
01387    /* If both firstImage and stObj point to a texture which can contain
01388     * all active images, favour firstImage.  Note that because of the
01389     * completeness requirement, we know that the image dimensions
01390     * will match.
01391     */
01392    if (firstImage->pt &&
01393        firstImage->pt != stObj->pt &&
01394        firstImage->pt->last_level >= stObj->lastLevel) {
01395 
01396       pipe_texture_reference(&stObj->pt, firstImage->pt);
01397    }
01398 
01399    /* FIXME: determine format block instead of cpp */
01400    if (firstImage->base.IsCompressed) {
01401       comp_byte = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat);
01402       cpp = comp_byte;
01403    }
01404    else {
01405       cpp = firstImage->base.TexFormat->TexelBytes;
01406    }
01407 
01408    /* If we already have a gallium texture, check that it matches the texture
01409     * object's format, target, size, num_levels, etc.
01410     */
01411    if (stObj->pt) {
01412       const enum pipe_format fmt =
01413          st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
01414       if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
01415           stObj->pt->format != fmt ||
01416           stObj->pt->last_level < stObj->lastLevel ||
01417           stObj->pt->width[0] != firstImage->base.Width2 ||
01418           stObj->pt->height[0] != firstImage->base.Height2 ||
01419           stObj->pt->depth[0] != firstImage->base.Depth2 ||
01420           stObj->pt->block.size != cpp ||
01421           stObj->pt->block.width != 1 ||
01422           stObj->pt->block.height != 1 ||
01423           stObj->pt->compressed != firstImage->base.IsCompressed) {
01424          pipe_texture_release(&stObj->pt);
01425          ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER;
01426       }
01427    }
01428 
01429    /* May need to create a new gallium texture:
01430     */
01431    if (!stObj->pt) {
01432       const enum pipe_format fmt =
01433          st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat);
01434       stObj->pt = st_texture_create(ctx->st,
01435                                     gl_target_to_pipe(stObj->base.Target),
01436                                     fmt,
01437                                     stObj->lastLevel,
01438                                     firstImage->base.Width2,
01439                                     firstImage->base.Height2,
01440                                     firstImage->base.Depth2,
01441                                     comp_byte,
01442                                     ( (pf_is_depth_stencil(fmt) ?
01443                                       PIPE_TEXTURE_USAGE_DEPTH_STENCIL :
01444                                       PIPE_TEXTURE_USAGE_RENDER_TARGET) |
01445                                       PIPE_TEXTURE_USAGE_SAMPLER ));
01446 
01447       if (!stObj->pt) {
01448          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
01449          return GL_FALSE;
01450       }
01451    }
01452 
01453    /* Pull in any images not in the object's texture:
01454     */
01455    for (face = 0; face < nr_faces; face++) {
01456       GLuint level;
01457       for (level = 0; level <= stObj->lastLevel; level++) {
01458          struct st_texture_image *stImage =
01459             st_texture_image(stObj->base.Image[face][stObj->base.BaseLevel + level]);
01460 
01461          /* Need to import images in main memory or held in other textures.
01462           */
01463          if (stImage && stObj->pt != stImage->pt) {
01464             copy_image_data_to_texture(ctx->st, stObj, level, stImage);
01465             *needFlush = GL_TRUE;
01466          }
01467       }
01468    }
01469 
01470    return GL_TRUE;
01471 }
01472 
01473 
01479 struct gl_texture_object *
01480 st_get_default_texture(struct st_context *st)
01481 {
01482    if (!st->default_texture) {
01483       static const GLenum target = GL_TEXTURE_2D;
01484       GLubyte pixels[16][16][4];
01485       struct gl_texture_object *texObj;
01486       struct gl_texture_image *texImg;
01487 
01488       /* init image to gray */
01489       memset(pixels, 127, sizeof(pixels));
01490 
01491       texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
01492 
01493       texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
01494 
01495       _mesa_init_teximage_fields(st->ctx, target, texImg,
01496                                  16, 16, 1, 0,  /* w, h, d, border */
01497                                  GL_RGBA);
01498 
01499       st_TexImage(st->ctx, 2, target,
01500                   0, GL_RGBA,    /* level, intformat */
01501                   16, 16, 1, 0,  /* w, h, d, border */
01502                   GL_RGBA, GL_UNSIGNED_BYTE, pixels,
01503                   &st->ctx->DefaultPacking,
01504                   texObj, texImg,
01505                   0, 0);
01506 
01507       texObj->MinFilter = GL_NEAREST;
01508       texObj->MagFilter = GL_NEAREST;
01509       texObj->_Complete = GL_TRUE;
01510 
01511       st->default_texture = texObj;
01512    }
01513    return st->default_texture;
01514 }
01515 
01516 
01517 void
01518 st_init_texture_functions(struct dd_function_table *functions)
01519 {
01520    functions->ChooseTextureFormat = st_ChooseTextureFormat;
01521    functions->TexImage1D = st_TexImage1D;
01522    functions->TexImage2D = st_TexImage2D;
01523    functions->TexImage3D = st_TexImage3D;
01524    functions->TexSubImage1D = st_TexSubImage1D;
01525    functions->TexSubImage2D = st_TexSubImage2D;
01526    functions->TexSubImage3D = st_TexSubImage3D;
01527    functions->CopyTexImage1D = st_CopyTexImage1D;
01528    functions->CopyTexImage2D = st_CopyTexImage2D;
01529    functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
01530    functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
01531    functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
01532    functions->GenerateMipmap = st_generate_mipmap;
01533 
01534    functions->GetTexImage = st_GetTexImage;
01535 
01536    /* compressed texture functions */
01537    functions->CompressedTexImage2D = st_CompressedTexImage2D;
01538    functions->GetCompressedTexImage = st_GetCompressedTexImage;
01539    functions->CompressedTextureSize = _mesa_compressed_texture_size;
01540 
01541    functions->NewTextureObject = st_NewTextureObject;
01542    functions->NewTextureImage = st_NewTextureImage;
01543    functions->DeleteTexture = st_DeleteTextureObject;
01544    functions->FreeTexImageData = st_FreeTextureImageData;
01545    functions->UpdateTexturePalette = 0;
01546 
01547    functions->TextureMemCpy = do_memcpy;
01548 
01549    /* XXX Temporary until we can query pipe's texture sizes */
01550    functions->TestProxyTexImage = _mesa_test_proxy_teximage;
01551 }

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4