Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.7
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (c) 2009 VMware, Inc.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /**
  28.  * Code for glGetTexImage() and glGetCompressedTexImage().
  29.  */
  30.  
  31.  
  32. #include "glheader.h"
  33. #include "bufferobj.h"
  34. #include "enums.h"
  35. #include "context.h"
  36. #include "formats.h"
  37. #include "image.h"
  38. #include "pack.h"
  39. #include "texgetimage.h"
  40. #include "teximage.h"
  41.  
  42.  
  43.  
  44. /**
  45.  * Can the given type represent negative values?
  46.  */
  47. static INLINE GLboolean
  48. type_with_negative_values(GLenum type)
  49. {
  50.    switch (type) {
  51.    case GL_BYTE:
  52.    case GL_SHORT:
  53.    case GL_INT:
  54.    case GL_FLOAT:
  55.    case GL_HALF_FLOAT_ARB:
  56.       return GL_TRUE;
  57.    default:
  58.       return GL_FALSE;
  59.    }
  60. }
  61.  
  62.  
  63. /**
  64.  * glGetTexImage for color index pixels.
  65.  */
  66. static void
  67. get_tex_color_index(struct gl_context *ctx, GLuint dimensions,
  68.                     GLenum format, GLenum type, GLvoid *pixels,
  69.                     const struct gl_texture_image *texImage)
  70. {
  71.    const GLint width = texImage->Width;
  72.    const GLint height = texImage->Height;
  73.    const GLint depth = texImage->Depth;
  74.    const GLuint indexBits =
  75.       _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
  76.    const GLbitfield transferOps = 0x0;
  77.    GLint img, row, col;
  78.  
  79.    for (img = 0; img < depth; img++) {
  80.       for (row = 0; row < height; row++) {
  81.          GLuint indexRow[MAX_WIDTH] = { 0 };
  82.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  83.                                           width, height, format, type,
  84.                                           img, row, 0);
  85.          assert(dest);
  86.  
  87.          if (indexBits == 8) {
  88.             const GLubyte *src = (const GLubyte *) texImage->Data;
  89.             src += width * (img * texImage->Height + row);
  90.             for (col = 0; col < width; col++) {
  91.                indexRow[col] = src[col];
  92.             }
  93.          }
  94.          else if (indexBits == 16) {
  95.             const GLushort *src = (const GLushort *) texImage->Data;
  96.             src += width * (img * texImage->Height + row);
  97.             for (col = 0; col < width; col++) {
  98.                indexRow[col] = src[col];
  99.             }
  100.          }
  101.          else {
  102.             _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage");
  103.          }
  104.          _mesa_pack_index_span(ctx, width, type, dest,
  105.                                indexRow, &ctx->Pack, transferOps);
  106.       }
  107.    }
  108. }
  109.  
  110.  
  111. /**
  112.  * glGetTexImage for depth/Z pixels.
  113.  */
  114. static void
  115. get_tex_depth(struct gl_context *ctx, GLuint dimensions,
  116.               GLenum format, GLenum type, GLvoid *pixels,
  117.               const struct gl_texture_image *texImage)
  118. {
  119.    const GLint width = texImage->Width;
  120.    const GLint height = texImage->Height;
  121.    const GLint depth = texImage->Depth;
  122.    GLint img, row, col;
  123.    GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
  124.  
  125.    if (!depthRow) {
  126.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  127.       return;
  128.    }
  129.  
  130.    for (img = 0; img < depth; img++) {
  131.       for (row = 0; row < height; row++) {
  132.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  133.                                           width, height, format, type,
  134.                                           img, row, 0);
  135.          assert(dest);
  136.  
  137.          for (col = 0; col < width; col++) {
  138.             texImage->FetchTexelf(texImage, col, row, img, depthRow + col);
  139.          }
  140.          _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
  141.       }
  142.    }
  143.  
  144.    free(depthRow);
  145. }
  146.  
  147.  
  148. /**
  149.  * glGetTexImage for depth/stencil pixels.
  150.  */
  151. static void
  152. get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
  153.                       GLenum format, GLenum type, GLvoid *pixels,
  154.                       const struct gl_texture_image *texImage)
  155. {
  156.    const GLint width = texImage->Width;
  157.    const GLint height = texImage->Height;
  158.    const GLint depth = texImage->Depth;
  159.    const GLuint *src = (const GLuint *) texImage->Data;
  160.    GLint img, row;
  161.  
  162.    for (img = 0; img < depth; img++) {
  163.       for (row = 0; row < height; row++) {
  164.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  165.                                           width, height, format, type,
  166.                                           img, row, 0);
  167.          memcpy(dest, src, width * sizeof(GLuint));
  168.          if (ctx->Pack.SwapBytes) {
  169.             _mesa_swap4((GLuint *) dest, width);
  170.          }
  171.  
  172.          src += width * row + width * height * img;
  173.       }
  174.    }
  175. }
  176.  
  177.  
  178. /**
  179.  * glGetTexImage for YCbCr pixels.
  180.  */
  181. static void
  182. get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
  183.               GLenum format, GLenum type, GLvoid *pixels,
  184.               const struct gl_texture_image *texImage)
  185. {
  186.    const GLint width = texImage->Width;
  187.    const GLint height = texImage->Height;
  188.    const GLint depth = texImage->Depth;
  189.    const GLint rowstride = texImage->RowStride;
  190.    const GLushort *src = (const GLushort *) texImage->Data;
  191.    GLint img, row;
  192.  
  193.    for (img = 0; img < depth; img++) {
  194.       for (row = 0; row < height; row++) {
  195.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  196.                                           width, height, format, type,
  197.                                           img, row, 0);
  198.          memcpy(dest, src, width * sizeof(GLushort));
  199.  
  200.          /* check for byte swapping */
  201.          if ((texImage->TexFormat == MESA_FORMAT_YCBCR
  202.               && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
  203.              (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
  204.               && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
  205.             if (!ctx->Pack.SwapBytes)
  206.                _mesa_swap2((GLushort *) dest, width);
  207.          }
  208.          else if (ctx->Pack.SwapBytes) {
  209.             _mesa_swap2((GLushort *) dest, width);
  210.          }
  211.  
  212.          src += rowstride;
  213.       }
  214.    }
  215. }
  216.  
  217.  
  218. #if FEATURE_EXT_texture_sRGB
  219.  
  220.  
  221. /**
  222.  * Convert a float value from linear space to a
  223.  * non-linear sRGB value in [0, 255].
  224.  * Not terribly efficient.
  225.  */
  226. static INLINE GLfloat
  227. linear_to_nonlinear(GLfloat cl)
  228. {
  229.    /* can't have values outside [0, 1] */
  230.    GLfloat cs;
  231.    if (cl < 0.0031308f) {
  232.       cs = 12.92f * cl;
  233.    }
  234.    else {
  235.       cs = (GLfloat)(1.055 * pow(cl, 0.41666) - 0.055);
  236.    }
  237.    return cs;
  238. }
  239.  
  240.  
  241. /**
  242.  * glGetTexImagefor sRGB pixels;
  243.  */
  244. static void
  245. get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
  246.              GLenum format, GLenum type, GLvoid *pixels,
  247.              const struct gl_texture_image *texImage)
  248. {
  249.    const GLint width = texImage->Width;
  250.    const GLint height = texImage->Height;
  251.    const GLint depth = texImage->Depth;
  252.    const GLbitfield transferOps = 0x0;
  253.    GLint img, row;
  254.    GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
  255.  
  256.    if (!rgba) {
  257.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  258.       return;
  259.    }
  260.  
  261.    for (img = 0; img < depth; img++) {
  262.       for (row = 0; row < height; row++) {
  263.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  264.                                           width, height, format, type,
  265.                                           img, row, 0);
  266.  
  267.          GLint col;
  268.  
  269.          /* convert row to RGBA format */
  270.          for (col = 0; col < width; col++) {
  271.             texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
  272.             if (texImage->_BaseFormat == GL_LUMINANCE) {
  273.                rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
  274.                rgba[col][GCOMP] = 0.0;
  275.                rgba[col][BCOMP] = 0.0;
  276.             }
  277.             else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
  278.                rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
  279.                rgba[col][GCOMP] = 0.0;
  280.                rgba[col][BCOMP] = 0.0;
  281.             }
  282.             else if (texImage->_BaseFormat == GL_RGB ||
  283.                      texImage->_BaseFormat == GL_RGBA) {
  284.                rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
  285.                rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
  286.                rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
  287.             }
  288.          }
  289.          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
  290.                                     format, type, dest,
  291.                                     &ctx->Pack, transferOps);
  292.       }
  293.    }
  294.  
  295.    free(rgba);
  296. }
  297.  
  298.  
  299. #else /* FEATURE_EXT_texture_sRGB */
  300.  
  301.  
  302. static INLINE void
  303. get_tex_srgb(struct gl_context *ctx, GLuint dimensions,
  304.              GLenum format, GLenum type, GLvoid *pixels,
  305.              const struct gl_texture_image *texImage)
  306. {
  307.    ASSERT_NO_FEATURE();
  308. }
  309.  
  310.  
  311. #endif /* FEATURE_EXT_texture_sRGB */
  312.  
  313.  
  314. /**
  315.  * glGetTexImagefor RGBA, Luminance, etc. pixels.
  316.  * This is the slow way since we use texture sampling.
  317.  */
  318. static void
  319. get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
  320.              GLenum format, GLenum type, GLvoid *pixels,
  321.              const struct gl_texture_image *texImage)
  322. {
  323.    const GLint width = texImage->Width;
  324.    const GLint height = texImage->Height;
  325.    const GLint depth = texImage->Depth;
  326.    /* Normally, no pixel transfer ops are performed during glGetTexImage.
  327.     * The only possible exception is component clamping to [0,1].
  328.     */
  329.    GLbitfield transferOps = 0x0;
  330.    GLint img, row;
  331.    GLfloat (*rgba)[4] = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
  332.  
  333.    if (!rgba) {
  334.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  335.       return;
  336.    }
  337.  
  338.    for (img = 0; img < depth; img++) {
  339.       for (row = 0; row < height; row++) {
  340.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  341.                                           width, height, format, type,
  342.                                           img, row, 0);
  343.          GLint col;
  344.          GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
  345.  
  346.          /* clamp does not apply to GetTexImage (final conversion)?
  347.           * Looks like we need clamp though when going from format
  348.           * containing negative values to unsigned format.
  349.           */
  350.          if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) {
  351.             transferOps |= IMAGE_CLAMP_BIT;
  352.          }
  353.          else if (!type_with_negative_values(type) &&
  354.                   (dataType == GL_FLOAT ||
  355.                    dataType == GL_SIGNED_NORMALIZED)) {
  356.             transferOps |= IMAGE_CLAMP_BIT;
  357.          }
  358.  
  359.          for (col = 0; col < width; col++) {
  360.             texImage->FetchTexelf(texImage, col, row, img, rgba[col]);
  361.             if (texImage->_BaseFormat == GL_ALPHA) {
  362.                rgba[col][RCOMP] = 0.0F;
  363.                rgba[col][GCOMP] = 0.0F;
  364.                rgba[col][BCOMP] = 0.0F;
  365.             }
  366.             else if (texImage->_BaseFormat == GL_LUMINANCE) {
  367.                rgba[col][GCOMP] = 0.0F;
  368.                rgba[col][BCOMP] = 0.0F;
  369.                rgba[col][ACOMP] = 1.0F;
  370.             }
  371.             else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
  372.                rgba[col][GCOMP] = 0.0F;
  373.                rgba[col][BCOMP] = 0.0F;
  374.             }
  375.             else if (texImage->_BaseFormat == GL_INTENSITY) {
  376.                rgba[col][GCOMP] = 0.0F;
  377.                rgba[col][BCOMP] = 0.0F;
  378.                rgba[col][ACOMP] = 1.0F;
  379.             }
  380.          }
  381.          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
  382.                                     format, type, dest,
  383.                                     &ctx->Pack, transferOps);
  384.       }
  385.    }
  386.  
  387.    free(rgba);
  388. }
  389.  
  390.  
  391. /**
  392.  * Try to do glGetTexImage() with simple memcpy().
  393.  * \return GL_TRUE if done, GL_FALSE otherwise
  394.  */
  395. static GLboolean
  396. get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels,
  397.                const struct gl_texture_object *texObj,
  398.                const struct gl_texture_image *texImage)
  399. {
  400.    GLboolean memCopy = GL_FALSE;
  401.  
  402.    /* Texture image should have been mapped already */
  403.    assert(texImage->Data);
  404.  
  405.    /*
  406.     * Check if the src/dst formats are compatible.
  407.     * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
  408.     * so we don't have to worry about those.
  409.     * XXX more format combinations could be supported here.
  410.     */
  411.    if ((texObj->Target == GL_TEXTURE_1D ||
  412.         texObj->Target == GL_TEXTURE_2D ||
  413.         texObj->Target == GL_TEXTURE_RECTANGLE ||
  414.         (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
  415.          texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
  416.       if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
  417.           format == GL_BGRA &&
  418.           type == GL_UNSIGNED_BYTE &&
  419.           !ctx->Pack.SwapBytes &&
  420.           _mesa_little_endian()) {
  421.          memCopy = GL_TRUE;
  422.       }
  423.       else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
  424.                format == GL_LUMINANCE_ALPHA &&
  425.                type == GL_UNSIGNED_BYTE &&
  426.                !ctx->Pack.SwapBytes &&
  427.                _mesa_little_endian()) {
  428.          memCopy = GL_TRUE;
  429.       }
  430.       else if (texImage->TexFormat == MESA_FORMAT_L8 &&
  431.                format == GL_LUMINANCE &&
  432.                type == GL_UNSIGNED_BYTE) {
  433.          memCopy = GL_TRUE;
  434.       }
  435.       else if (texImage->TexFormat == MESA_FORMAT_A8 &&
  436.                format == GL_ALPHA &&
  437.                type == GL_UNSIGNED_BYTE) {
  438.          memCopy = GL_TRUE;
  439.       }
  440.    }
  441.  
  442.    if (memCopy) {
  443.       const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
  444.       const GLuint bytesPerRow = texImage->Width * bpp;
  445.       GLubyte *dst =
  446.          _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
  447.                                texImage->Height, format, type, 0, 0);
  448.       const GLint dstRowStride =
  449.          _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
  450.       const GLubyte *src = texImage->Data;
  451.       const GLint srcRowStride = texImage->RowStride * bpp;
  452.       GLuint row;
  453.  
  454.       if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
  455.          memcpy(dst, src, bytesPerRow * texImage->Height);
  456.       }
  457.       else {
  458.          for (row = 0; row < texImage->Height; row++) {
  459.             memcpy(dst, src, bytesPerRow);
  460.             dst += dstRowStride;
  461.             src += srcRowStride;
  462.          }
  463.       }
  464.    }
  465.  
  466.    return memCopy;
  467. }
  468.  
  469.  
  470. /**
  471.  * This is the software fallback for Driver.GetTexImage().
  472.  * All error checking will have been done before this routine is called.
  473.  * The texture image must be mapped.
  474.  */
  475. void
  476. _mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level,
  477.                    GLenum format, GLenum type, GLvoid *pixels,
  478.                    struct gl_texture_object *texObj,
  479.                    struct gl_texture_image *texImage)
  480. {
  481.    GLuint dimensions;
  482.  
  483.    /* If we get here, the texture image should be mapped */
  484.    assert(texImage->Data);
  485.  
  486.    switch (target) {
  487.    case GL_TEXTURE_1D:
  488.       dimensions = 1;
  489.       break;
  490.    case GL_TEXTURE_3D:
  491.       dimensions = 3;
  492.       break;
  493.    default:
  494.       dimensions = 2;
  495.    }
  496.  
  497.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  498.       /* Packing texture image into a PBO.
  499.        * Map the (potentially) VRAM-based buffer into our process space so
  500.        * we can write into it with the code below.
  501.        * A hardware driver might use a sophisticated blit to move the
  502.        * texture data to the PBO if the PBO is in VRAM along with the texture.
  503.        */
  504.       GLubyte *buf = (GLubyte *)
  505.          ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
  506.                                GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
  507.       if (!buf) {
  508.          /* out of memory or other unexpected error */
  509.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
  510.          return;
  511.       }
  512.       /* <pixels> was an offset into the PBO.
  513.        * Now make it a real, client-side pointer inside the mapped region.
  514.        */
  515.       pixels = ADD_POINTERS(buf, pixels);
  516.    }
  517.  
  518.    if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) {
  519.       /* all done */
  520.    }
  521.    else if (format == GL_COLOR_INDEX) {
  522.       get_tex_color_index(ctx, dimensions, format, type, pixels, texImage);
  523.    }
  524.    else if (format == GL_DEPTH_COMPONENT) {
  525.       get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
  526.    }
  527.    else if (format == GL_DEPTH_STENCIL_EXT) {
  528.       get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
  529.    }
  530.    else if (format == GL_YCBCR_MESA) {
  531.       get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
  532.    }
  533.    else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) {
  534.       get_tex_srgb(ctx, dimensions, format, type, pixels, texImage);
  535.    }
  536.    else {
  537.       get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
  538.    }
  539.  
  540.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  541.       ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
  542.                               ctx->Pack.BufferObj);
  543.    }
  544. }
  545.  
  546.  
  547.  
  548. /**
  549.  * This is the software fallback for Driver.GetCompressedTexImage().
  550.  * All error checking will have been done before this routine is called.
  551.  */
  552. void
  553. _mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level,
  554.                               GLvoid *img,
  555.                               struct gl_texture_object *texObj,
  556.                               struct gl_texture_image *texImage)
  557. {
  558.    const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat,
  559.                                                      texImage->Width);
  560.    const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat,
  561.                                                             texImage->RowStride);
  562.    GLuint i;
  563.  
  564.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  565.       /* pack texture image into a PBO */
  566.       GLubyte *buf = (GLubyte *)
  567.          ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
  568.                                GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
  569.       if (!buf) {
  570.          /* out of memory or other unexpected error */
  571.          _mesa_error(ctx, GL_OUT_OF_MEMORY,
  572.                      "glGetCompresssedTexImage(map PBO failed)");
  573.          return;
  574.       }
  575.       img = ADD_POINTERS(buf, img);
  576.    }
  577.  
  578.    /* no pixelstore or pixel transfer, but respect stride */
  579.  
  580.    if (row_stride == row_stride_stored) {
  581.       const GLuint size = _mesa_format_image_size(texImage->TexFormat,
  582.                                                   texImage->Width,
  583.                                                   texImage->Height,
  584.                                                   texImage->Depth);
  585.       memcpy(img, texImage->Data, size);
  586.    }
  587.    else {
  588.       GLuint bw, bh;
  589.       _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
  590.       for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
  591.          memcpy((GLubyte *)img + i * row_stride,
  592.                 (GLubyte *)texImage->Data + i * row_stride_stored,
  593.                 row_stride);
  594.       }
  595.    }
  596.  
  597.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  598.       ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
  599.                               ctx->Pack.BufferObj);
  600.    }
  601. }
  602.  
  603.  
  604.  
  605. /**
  606.  * Do error checking for a glGetTexImage() call.
  607.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  608.  */
  609. static GLboolean
  610. getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
  611.                         GLenum format, GLenum type, GLvoid *pixels )
  612. {
  613.    struct gl_texture_object *texObj;
  614.    struct gl_texture_image *texImage;
  615.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  616.    GLenum baseFormat;
  617.  
  618.    if (maxLevels == 0) {
  619.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
  620.       return GL_TRUE;
  621.    }
  622.  
  623.    if (level < 0 || level >= maxLevels) {
  624.       _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
  625.       return GL_TRUE;
  626.    }
  627.  
  628.    if (_mesa_sizeof_packed_type(type) <= 0) {
  629.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
  630.       return GL_TRUE;
  631.    }
  632.  
  633.    if (_mesa_components_in_format(format) <= 0 ||
  634.        format == GL_STENCIL_INDEX) {
  635.       _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
  636.       return GL_TRUE;
  637.    }
  638.  
  639.    if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
  640.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
  641.       return GL_TRUE;
  642.    }
  643.  
  644.    if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
  645.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
  646.       return GL_TRUE;
  647.    }
  648.  
  649.    if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
  650.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
  651.       return GL_TRUE;
  652.    }
  653.  
  654.    if (!ctx->Extensions.EXT_packed_depth_stencil
  655.        && _mesa_is_depthstencil_format(format)) {
  656.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
  657.       return GL_TRUE;
  658.    }
  659.  
  660.    if (!ctx->Extensions.ATI_envmap_bumpmap
  661.        && _mesa_is_dudv_format(format)) {
  662.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
  663.       return GL_TRUE;
  664.    }
  665.  
  666.    texObj = _mesa_get_current_tex_object(ctx, target);
  667.  
  668.    if (!texObj || _mesa_is_proxy_texture(target)) {
  669.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
  670.       return GL_TRUE;
  671.    }
  672.  
  673.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  674.    if (!texImage) {
  675.       /* out of memory */
  676.       return GL_TRUE;
  677.    }
  678.  
  679.    baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  680.      
  681.    /* Make sure the requested image format is compatible with the
  682.     * texture's format.  Note that a color index texture can be converted
  683.     * to RGBA so that combo is allowed.
  684.     */
  685.    if (_mesa_is_color_format(format)
  686.        && !_mesa_is_color_format(baseFormat)
  687.        && !_mesa_is_index_format(baseFormat)) {
  688.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  689.       return GL_TRUE;
  690.    }
  691.    else if (_mesa_is_index_format(format)
  692.             && !_mesa_is_index_format(baseFormat)) {
  693.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  694.       return GL_TRUE;
  695.    }
  696.    else if (_mesa_is_depth_format(format)
  697.             && !_mesa_is_depth_format(baseFormat)
  698.             && !_mesa_is_depthstencil_format(baseFormat)) {
  699.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  700.       return GL_TRUE;
  701.    }
  702.    else if (_mesa_is_ycbcr_format(format)
  703.             && !_mesa_is_ycbcr_format(baseFormat)) {
  704.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  705.       return GL_TRUE;
  706.    }
  707.    else if (_mesa_is_depthstencil_format(format)
  708.             && !_mesa_is_depthstencil_format(baseFormat)) {
  709.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  710.       return GL_TRUE;
  711.    }
  712.    else if (_mesa_is_dudv_format(format)
  713.             && !_mesa_is_dudv_format(baseFormat)) {
  714.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  715.       return GL_TRUE;
  716.    }
  717.  
  718.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  719.       /* packing texture image into a PBO */
  720.       const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
  721.       if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
  722.                                      texImage->Height, texImage->Depth,
  723.                                      format, type, pixels)) {
  724.          _mesa_error(ctx, GL_INVALID_OPERATION,
  725.                      "glGetTexImage(out of bounds PBO write)");
  726.          return GL_TRUE;
  727.       }
  728.  
  729.       /* PBO should not be mapped */
  730.       if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
  731.          _mesa_error(ctx, GL_INVALID_OPERATION,
  732.                      "glGetTexImage(PBO is mapped)");
  733.          return GL_TRUE;
  734.       }
  735.    }
  736.  
  737.    return GL_FALSE;
  738. }
  739.  
  740.  
  741.  
  742. /**
  743.  * Get texture image.  Called by glGetTexImage.
  744.  *
  745.  * \param target texture target.
  746.  * \param level image level.
  747.  * \param format pixel data format for returned image.
  748.  * \param type pixel data type for returned image.
  749.  * \param pixels returned pixel data.
  750.  */
  751. void GLAPIENTRY
  752. _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
  753.                    GLenum type, GLvoid *pixels )
  754. {
  755.    struct gl_texture_object *texObj;
  756.    struct gl_texture_image *texImage;
  757.    GET_CURRENT_CONTEXT(ctx);
  758.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  759.  
  760.    if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
  761.       return;
  762.    }
  763.  
  764.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
  765.       /* not an error, do nothing */
  766.       return;
  767.    }
  768.  
  769.    texObj = _mesa_get_current_tex_object(ctx, target);
  770.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  771.  
  772.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  773.       _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
  774.                   " dstFmt=0x%x, dstType=0x%x\n",
  775.                   texObj->Name,
  776.                   _mesa_get_format_name(texImage->TexFormat),
  777.                   texImage->Width, texImage->Height,
  778.                   format, type);
  779.    }
  780.  
  781.    _mesa_lock_texture(ctx, texObj);
  782.    {
  783.       ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
  784.                               texObj, texImage);
  785.    }
  786.    _mesa_unlock_texture(ctx, texObj);
  787. }
  788.  
  789.  
  790.  
  791. /**
  792.  * Do error checking for a glGetCompressedTexImage() call.
  793.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  794.  */
  795. static GLboolean
  796. getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
  797.                                   GLvoid *img)
  798. {
  799.    struct gl_texture_object *texObj;
  800.    struct gl_texture_image *texImage;
  801.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  802.  
  803.    if (maxLevels == 0) {
  804.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
  805.                   target);
  806.       return GL_TRUE;
  807.    }
  808.  
  809.    if (level < 0 || level >= maxLevels) {
  810.       _mesa_error(ctx, GL_INVALID_VALUE,
  811.                   "glGetCompressedTexImageARB(bad level = %d)", level);
  812.       return GL_TRUE;
  813.    }
  814.  
  815.    if (_mesa_is_proxy_texture(target)) {
  816.       _mesa_error(ctx, GL_INVALID_ENUM,
  817.                   "glGetCompressedTexImageARB(bad target = %s)",
  818.                   _mesa_lookup_enum_by_nr(target));
  819.       return GL_TRUE;
  820.    }
  821.  
  822.    texObj = _mesa_get_current_tex_object(ctx, target);
  823.    if (!texObj) {
  824.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
  825.       return GL_TRUE;
  826.    }
  827.  
  828.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  829.  
  830.    if (!texImage) {
  831.       /* probably invalid mipmap level */
  832.       _mesa_error(ctx, GL_INVALID_VALUE,
  833.                   "glGetCompressedTexImageARB(level)");
  834.       return GL_TRUE;
  835.    }
  836.  
  837.    if (!_mesa_is_format_compressed(texImage->TexFormat)) {
  838.       _mesa_error(ctx, GL_INVALID_OPERATION,
  839.                   "glGetCompressedTexImageARB(texture is not compressed)");
  840.       return GL_TRUE;
  841.    }
  842.  
  843.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  844.       GLuint compressedSize;
  845.  
  846.       /* make sure PBO is not mapped */
  847.       if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
  848.          _mesa_error(ctx, GL_INVALID_OPERATION,
  849.                      "glGetCompressedTexImage(PBO is mapped)");
  850.          return GL_TRUE;
  851.       }
  852.  
  853.       compressedSize = _mesa_format_image_size(texImage->TexFormat,
  854.                                                texImage->Width,
  855.                                                texImage->Height,
  856.                                                texImage->Depth);
  857.  
  858.       /* do bounds checking on PBO write */
  859.       if ((const GLubyte *) img + compressedSize >
  860.           (const GLubyte *) ctx->Pack.BufferObj->Size) {
  861.          _mesa_error(ctx, GL_INVALID_OPERATION,
  862.                      "glGetCompressedTexImage(out of bounds PBO write)");
  863.          return GL_TRUE;
  864.       }
  865.    }
  866.  
  867.    return GL_FALSE;
  868. }
  869.  
  870.  
  871. void GLAPIENTRY
  872. _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
  873. {
  874.    struct gl_texture_object *texObj;
  875.    struct gl_texture_image *texImage;
  876.    GET_CURRENT_CONTEXT(ctx);
  877.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
  878.  
  879.    if (getcompressedteximage_error_check(ctx, target, level, img)) {
  880.       return;
  881.    }
  882.  
  883.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
  884.       /* not an error, do nothing */
  885.       return;
  886.    }
  887.  
  888.    texObj = _mesa_get_current_tex_object(ctx, target);
  889.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  890.  
  891.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  892.       _mesa_debug(ctx,
  893.                   "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
  894.                   texObj->Name,
  895.                   _mesa_get_format_name(texImage->TexFormat),
  896.                   texImage->Width, texImage->Height);
  897.    }
  898.  
  899.    _mesa_lock_texture(ctx, texObj);
  900.    {
  901.       ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
  902.                                         texObj, texImage);
  903.    }
  904.    _mesa_unlock_texture(ctx, texObj);
  905. }
  906.