00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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;
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
00268
00269
00270 if ((GLint) stImage->level < stObj->base.BaseLevel)
00271 firstLevel = 0;
00272 else
00273 firstLevel = stObj->base.BaseLevel;
00274
00275
00276
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
00289 return;
00290 }
00291
00292
00293
00294
00295
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);
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
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
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
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
00438 if (postConvWidth * texelBytes < 32) {
00439 postConvWidth = 32 / texelBytes;
00440 texImage->RowStride = postConvWidth;
00441 }
00442
00443
00444
00445 }
00446
00447
00448
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
00460 return;
00461 }
00462
00463
00464
00465
00466
00467 if (stObj->pt &&
00468 (stObj->teximage_realloc ||
00469 (
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
00485
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
00510
00511
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
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
00556
00557
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,
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
00686 if (stImage->pt) {
00687
00688
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
00696
00697
00698
00699
00700
00701
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
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
00791
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
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
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
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
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
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
00991 srcY = strb->Base.Height - srcY - height;
00992 unpack.Invert = GL_TRUE;
00993 }
00994
00995
00996
00997
00998
00999 pipe_get_tile_rgba(src_surf, srcX, srcY, width, height, tempSrc);
01000
01001
01002
01003
01004
01005
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,
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
01064 st_finish(ctx->st);
01065
01066
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
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
01087
01088
01089
01090
01091
01092
01093 matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat);
01094
01095 if (matching_base_formats && ctx->_ImageTransferState == 0x0) {
01096
01097 struct pipe_surface *dest_surface = NULL;
01098
01099 if (src_format == dest_format) {
01100
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
01111 pipe->surface_copy(pipe,
01112 do_flip,
01113
01114 dest_surface,
01115 destX, destY,
01116
01117 strb->surface,
01118 srcX, srcY,
01119
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
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
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
01196
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,
01205 x, y, width, 1);
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
01223
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,
01232 x, y, width, height);
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,
01244 x, y, width, height);
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,
01256 x, y, width, height);
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,
01267 x, y, width, height);
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
01282
01283
01284
01285 int firstLevel;
01286 int lastLevel;
01287
01288
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
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
01326
01327 st_texture_image_copy(st->pipe,
01328 stObj->pt, dstLevel,
01329 stImage->pt,
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
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
01379
01380 assert(stObj->base._Complete);
01381
01382
01383
01384 calculate_first_last_level(stObj);
01385 firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
01386
01387
01388
01389
01390
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
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
01409
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
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
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
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
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,
01497 GL_RGBA);
01498
01499 st_TexImage(st->ctx, 2, target,
01500 0, GL_RGBA,
01501 16, 16, 1, 0,
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
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
01550 functions->TestProxyTexImage = _mesa_test_proxy_teximage;
01551 }