Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  5.  * Copyright (c) 2009 VMware, Inc.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  21.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  22.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23.  * 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 "format_unpack.h"
  38. #include "glformats.h"
  39. #include "image.h"
  40. #include "mtypes.h"
  41. #include "pack.h"
  42. #include "pbo.h"
  43. #include "texcompress.h"
  44. #include "texgetimage.h"
  45. #include "teximage.h"
  46.  
  47.  
  48.  
  49. /**
  50.  * Can the given type represent negative values?
  51.  */
  52. static inline GLboolean
  53. type_needs_clamping(GLenum type)
  54. {
  55.    switch (type) {
  56.    case GL_BYTE:
  57.    case GL_SHORT:
  58.    case GL_INT:
  59.    case GL_FLOAT:
  60.    case GL_HALF_FLOAT_ARB:
  61.    case GL_UNSIGNED_INT_10F_11F_11F_REV:
  62.    case GL_UNSIGNED_INT_5_9_9_9_REV:
  63.       return GL_FALSE;
  64.    default:
  65.       return GL_TRUE;
  66.    }
  67. }
  68.  
  69.  
  70. /**
  71.  * glGetTexImage for depth/Z pixels.
  72.  */
  73. static void
  74. get_tex_depth(struct gl_context *ctx, GLuint dimensions,
  75.               GLenum format, GLenum type, GLvoid *pixels,
  76.               struct gl_texture_image *texImage)
  77. {
  78.    const GLint width = texImage->Width;
  79.    const GLint height = texImage->Height;
  80.    const GLint depth = texImage->Depth;
  81.    GLint img, row;
  82.    GLfloat *depthRow = malloc(width * sizeof(GLfloat));
  83.  
  84.    if (!depthRow) {
  85.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  86.       return;
  87.    }
  88.  
  89.    for (img = 0; img < depth; img++) {
  90.       GLubyte *srcMap;
  91.       GLint srcRowStride;
  92.  
  93.       /* map src texture buffer */
  94.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  95.                                   0, 0, width, height, GL_MAP_READ_BIT,
  96.                                   &srcMap, &srcRowStride);
  97.  
  98.       if (srcMap) {
  99.          for (row = 0; row < height; row++) {
  100.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  101.                                              width, height, format, type,
  102.                                              img, row, 0);
  103.             const GLubyte *src = srcMap + row * srcRowStride;
  104.             _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
  105.             _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
  106.          }
  107.  
  108.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  109.       }
  110.       else {
  111.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  112.          break;
  113.       }
  114.    }
  115.  
  116.    free(depthRow);
  117. }
  118.  
  119.  
  120. /**
  121.  * glGetTexImage for depth/stencil pixels.
  122.  */
  123. static void
  124. get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
  125.                       GLenum format, GLenum type, GLvoid *pixels,
  126.                       struct gl_texture_image *texImage)
  127. {
  128.    const GLint width = texImage->Width;
  129.    const GLint height = texImage->Height;
  130.    const GLint depth = texImage->Depth;
  131.    GLint img, row;
  132.  
  133.    for (img = 0; img < depth; img++) {
  134.       GLubyte *srcMap;
  135.       GLint rowstride;
  136.  
  137.       /* map src texture buffer */
  138.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  139.                                   0, 0, width, height, GL_MAP_READ_BIT,
  140.                                   &srcMap, &rowstride);
  141.  
  142.       if (srcMap) {
  143.          for (row = 0; row < height; row++) {
  144.             const GLubyte *src = srcMap + row * rowstride;
  145.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  146.                                              width, height, format, type,
  147.                                              img, row, 0);
  148.             /* XXX Z24_S8 vs. S8_Z24??? */
  149.             memcpy(dest, src, width * sizeof(GLuint));
  150.             if (ctx->Pack.SwapBytes) {
  151.                _mesa_swap4((GLuint *) dest, width);
  152.             }
  153.          }
  154.  
  155.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  156.       }
  157.       else {
  158.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  159.          break;
  160.       }
  161.    }
  162. }
  163.  
  164.  
  165. /**
  166.  * glGetTexImage for YCbCr pixels.
  167.  */
  168. static void
  169. get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
  170.               GLenum format, GLenum type, GLvoid *pixels,
  171.               struct gl_texture_image *texImage)
  172. {
  173.    const GLint width = texImage->Width;
  174.    const GLint height = texImage->Height;
  175.    const GLint depth = texImage->Depth;
  176.    GLint img, row;
  177.  
  178.    for (img = 0; img < depth; img++) {
  179.       GLubyte *srcMap;
  180.       GLint rowstride;
  181.  
  182.       /* map src texture buffer */
  183.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  184.                                   0, 0, width, height, GL_MAP_READ_BIT,
  185.                                   &srcMap, &rowstride);
  186.  
  187.       if (srcMap) {
  188.          for (row = 0; row < height; row++) {
  189.             const GLubyte *src = srcMap + row * rowstride;
  190.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  191.                                              width, height, format, type,
  192.                                              img, row, 0);
  193.             memcpy(dest, src, width * sizeof(GLushort));
  194.  
  195.             /* check for byte swapping */
  196.             if ((texImage->TexFormat == MESA_FORMAT_YCBCR
  197.                  && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
  198.                 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
  199.                  && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
  200.                if (!ctx->Pack.SwapBytes)
  201.                   _mesa_swap2((GLushort *) dest, width);
  202.             }
  203.             else if (ctx->Pack.SwapBytes) {
  204.                _mesa_swap2((GLushort *) dest, width);
  205.             }
  206.          }
  207.  
  208.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  209.       }
  210.       else {
  211.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  212.          break;
  213.       }
  214.    }
  215. }
  216.  
  217.  
  218. /**
  219.  * Get a color texture image with decompression.
  220.  */
  221. static void
  222. get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
  223.                         GLenum format, GLenum type, GLvoid *pixels,
  224.                         struct gl_texture_image *texImage,
  225.                         GLbitfield transferOps)
  226. {
  227.    /* don't want to apply sRGB -> RGB conversion here so override the format */
  228.    const gl_format texFormat =
  229.       _mesa_get_srgb_format_linear(texImage->TexFormat);
  230.    const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
  231.    const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
  232.    GLenum rebaseFormat = GL_NONE;
  233.    const GLuint width = texImage->Width;
  234.    const GLuint height = texImage->Height;
  235.    const GLuint depth = texImage->Depth;
  236.    GLfloat *tempImage, *tempSlice, *srcRow;
  237.    GLuint row, slice;
  238.  
  239.    /* Decompress into temp float buffer, then pack into user buffer */
  240.    tempImage = malloc(width * height * depth
  241.                                   * 4 * sizeof(GLfloat));
  242.    if (!tempImage) {
  243.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
  244.       return;
  245.    }
  246.  
  247.    /* Decompress the texture image slices - results in 'tempImage' */
  248.    for (slice = 0; slice < depth; slice++) {
  249.       GLubyte *srcMap;
  250.       GLint srcRowStride;
  251.  
  252.       tempSlice = tempImage + slice * 4 * width * height;
  253.  
  254.       ctx->Driver.MapTextureImage(ctx, texImage, slice,
  255.                                   0, 0, width, height,
  256.                                   GL_MAP_READ_BIT,
  257.                                   &srcMap, &srcRowStride);
  258.       if (srcMap) {
  259.          _mesa_decompress_image(texFormat, width, height,
  260.                                 srcMap, srcRowStride, tempSlice);
  261.  
  262.          ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
  263.       }
  264.       else {
  265.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  266.          free(tempImage);
  267.          return;
  268.       }
  269.    }
  270.  
  271.    if (baseFormat == GL_LUMINANCE ||
  272.        baseFormat == GL_INTENSITY ||
  273.        baseFormat == GL_LUMINANCE_ALPHA) {
  274.       /* If a luminance (or intensity) texture is read back as RGB(A), the
  275.        * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
  276.        * here to get G=B=0.
  277.        */
  278.       rebaseFormat = texImage->_BaseFormat;
  279.    }
  280.    else if ((baseFormat == GL_RGBA ||
  281.              baseFormat == GL_RGB  ||
  282.              baseFormat == GL_RG) &&
  283.             (destBaseFormat == GL_LUMINANCE ||
  284.              destBaseFormat == GL_LUMINANCE_ALPHA ||
  285.              destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
  286.              destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
  287.       /* If we're reading back an RGB(A) texture as luminance then we need
  288.        * to return L=tex(R).  Note, that's different from glReadPixels which
  289.        * returns L=R+G+B.
  290.        */
  291.       rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
  292.    }
  293.  
  294.    if (rebaseFormat) {
  295.       _mesa_rebase_rgba_float(width * height, (GLfloat (*)[4]) tempImage,
  296.                               rebaseFormat);
  297.    }
  298.  
  299.    tempSlice = tempImage;
  300.    for (slice = 0; slice < depth; slice++) {
  301.       srcRow = tempSlice;
  302.       for (row = 0; row < height; row++) {
  303.          void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  304.                                           width, height, format, type,
  305.                                           slice, row, 0);
  306.  
  307.          _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow,
  308.                                     format, type, dest, &ctx->Pack, transferOps);
  309.          srcRow += 4 * width;
  310.       }
  311.       tempSlice += 4 * width * height;
  312.    }
  313.  
  314.    free(tempImage);
  315. }
  316.  
  317.  
  318. /**
  319.  * Return a base GL format given the user-requested format
  320.  * for glGetTexImage().
  321.  */
  322. static GLenum
  323. _mesa_base_pack_format(GLenum format)
  324. {
  325.    switch (format) {
  326.    case GL_ABGR_EXT:
  327.    case GL_BGRA:
  328.    case GL_BGRA_INTEGER:
  329.    case GL_RGBA_INTEGER:
  330.       return GL_RGBA;
  331.    case GL_BGR:
  332.    case GL_BGR_INTEGER:
  333.    case GL_RGB_INTEGER:
  334.       return GL_RGB;
  335.    case GL_RED_INTEGER:
  336.       return GL_RED;
  337.    case GL_GREEN_INTEGER:
  338.       return GL_GREEN;
  339.    case GL_BLUE_INTEGER:
  340.       return GL_BLUE;
  341.    case GL_ALPHA_INTEGER:
  342.       return GL_ALPHA;
  343.    case GL_LUMINANCE_INTEGER_EXT:
  344.       return GL_LUMINANCE;
  345.    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
  346.       return GL_LUMINANCE_ALPHA;
  347.    default:
  348.       return format;
  349.    }
  350. }
  351.  
  352.  
  353. /**
  354.  * Get an uncompressed color texture image.
  355.  */
  356. static void
  357. get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
  358.                           GLenum format, GLenum type, GLvoid *pixels,
  359.                           struct gl_texture_image *texImage,
  360.                           GLbitfield transferOps)
  361. {
  362.    /* don't want to apply sRGB -> RGB conversion here so override the format */
  363.    const gl_format texFormat =
  364.       _mesa_get_srgb_format_linear(texImage->TexFormat);
  365.    const GLuint width = texImage->Width;
  366.    GLenum destBaseFormat = _mesa_base_pack_format(format);
  367.    GLenum rebaseFormat = GL_NONE;
  368.    GLuint height = texImage->Height;
  369.    GLuint depth = texImage->Depth;
  370.    GLuint img, row;
  371.    GLfloat (*rgba)[4];
  372.    GLuint (*rgba_uint)[4];
  373.    GLboolean tex_is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
  374.    GLboolean tex_is_uint = _mesa_is_format_unsigned(texImage->TexFormat);
  375.    GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  376.  
  377.    /* Allocate buffer for one row of texels */
  378.    rgba = malloc(4 * width * sizeof(GLfloat));
  379.    rgba_uint = (GLuint (*)[4]) rgba;
  380.    if (!rgba) {
  381.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
  382.       return;
  383.    }
  384.  
  385.    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
  386.       depth = height;
  387.       height = 1;
  388.    }
  389.  
  390.    if (texImage->_BaseFormat == GL_LUMINANCE ||
  391.        texImage->_BaseFormat == GL_INTENSITY ||
  392.        texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
  393.       /* If a luminance (or intensity) texture is read back as RGB(A), the
  394.        * returned value should be (L,0,0,1), not (L,L,L,1).  Set rebaseFormat
  395.        * here to get G=B=0.
  396.        */
  397.       rebaseFormat = texImage->_BaseFormat;
  398.    }
  399.    else if ((texImage->_BaseFormat == GL_RGBA ||
  400.              texImage->_BaseFormat == GL_RGB ||
  401.              texImage->_BaseFormat == GL_RG) &&
  402.             (destBaseFormat == GL_LUMINANCE ||
  403.              destBaseFormat == GL_LUMINANCE_ALPHA ||
  404.              destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
  405.              destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
  406.       /* If we're reading back an RGB(A) texture as luminance then we need
  407.        * to return L=tex(R).  Note, that's different from glReadPixels which
  408.        * returns L=R+G+B.
  409.        */
  410.       rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
  411.    }
  412.    else if (texImage->_BaseFormat != texBaseFormat) {
  413.       /* The internal format and the real format differ, so we can't rely
  414.        * on the unpack functions setting the correct constant values.
  415.        * (e.g. reading back GL_RGB8 which is actually RGBA won't set alpha=1)
  416.        */
  417.       switch (texImage->_BaseFormat) {
  418.       case GL_RED:
  419.          if ((texBaseFormat == GL_RGBA ||
  420.               texBaseFormat == GL_RGB ||
  421.               texBaseFormat == GL_RG) &&
  422.              (destBaseFormat == GL_RGBA ||
  423.               destBaseFormat == GL_RGB ||
  424.               destBaseFormat == GL_RG ||
  425.               destBaseFormat == GL_GREEN)) {
  426.             rebaseFormat = texImage->_BaseFormat;
  427.             break;
  428.          }
  429.          /* fall through */
  430.       case GL_RG:
  431.          if ((texBaseFormat == GL_RGBA ||
  432.               texBaseFormat == GL_RGB) &&
  433.              (destBaseFormat == GL_RGBA ||
  434.               destBaseFormat == GL_RGB ||
  435.               destBaseFormat == GL_BLUE)) {
  436.             rebaseFormat = texImage->_BaseFormat;
  437.             break;
  438.          }
  439.          /* fall through */
  440.       case GL_RGB:
  441.          if (texBaseFormat == GL_RGBA &&
  442.              (destBaseFormat == GL_RGBA ||
  443.               destBaseFormat == GL_ALPHA ||
  444.               destBaseFormat == GL_LUMINANCE_ALPHA)) {
  445.             rebaseFormat = texImage->_BaseFormat;
  446.          }
  447.          break;
  448.  
  449.       case GL_ALPHA:
  450.          if (destBaseFormat != GL_ALPHA) {
  451.             rebaseFormat = texImage->_BaseFormat;
  452.          }
  453.          break;
  454.       }
  455.    }
  456.  
  457.    for (img = 0; img < depth; img++) {
  458.       GLubyte *srcMap;
  459.       GLint rowstride;
  460.  
  461.       /* map src texture buffer */
  462.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  463.                                   0, 0, width, height, GL_MAP_READ_BIT,
  464.                                   &srcMap, &rowstride);
  465.       if (srcMap) {
  466.          for (row = 0; row < height; row++) {
  467.             const GLubyte *src = srcMap + row * rowstride;
  468.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  469.                                              width, height, format, type,
  470.                                              img, row, 0);
  471.  
  472.             if (tex_is_integer) {
  473.                _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
  474.                if (rebaseFormat)
  475.                   _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat);
  476.                if (tex_is_uint) {
  477.                   _mesa_pack_rgba_span_from_uints(ctx, width,
  478.                                                   (GLuint (*)[4]) rgba_uint,
  479.                                                   format, type, dest);
  480.                } else {
  481.                   _mesa_pack_rgba_span_from_ints(ctx, width,
  482.                                                  (GLint (*)[4]) rgba_uint,
  483.                                                  format, type, dest);
  484.                }
  485.             } else {
  486.                _mesa_unpack_rgba_row(texFormat, width, src, rgba);
  487.                if (rebaseFormat)
  488.                   _mesa_rebase_rgba_float(width, rgba, rebaseFormat);
  489.                _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
  490.                                           format, type, dest,
  491.                                           &ctx->Pack, transferOps);
  492.             }
  493.          }
  494.  
  495.          /* Unmap the src texture buffer */
  496.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  497.       }
  498.       else {
  499.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  500.          break;
  501.       }
  502.    }
  503.  
  504.    free(rgba);
  505. }
  506.  
  507.  
  508. /**
  509.  * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
  510.  * Compressed textures are handled here as well.
  511.  */
  512. static void
  513. get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
  514.              GLenum format, GLenum type, GLvoid *pixels,
  515.              struct gl_texture_image *texImage)
  516. {
  517.    const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
  518.    GLbitfield transferOps = 0x0;
  519.  
  520.    /* In general, clamping does not apply to glGetTexImage, except when
  521.     * the returned type of the image can't hold negative values.
  522.     */
  523.    if (type_needs_clamping(type)) {
  524.       /* the returned image type can't have negative values */
  525.       if (dataType == GL_FLOAT ||
  526.           dataType == GL_HALF_FLOAT ||
  527.           dataType == GL_SIGNED_NORMALIZED ||
  528.           format == GL_LUMINANCE ||
  529.           format == GL_LUMINANCE_ALPHA) {
  530.          transferOps |= IMAGE_CLAMP_BIT;
  531.       }
  532.    }
  533.  
  534.    if (_mesa_is_format_compressed(texImage->TexFormat)) {
  535.       get_tex_rgba_compressed(ctx, dimensions, format, type,
  536.                               pixels, texImage, transferOps);
  537.    }
  538.    else {
  539.       get_tex_rgba_uncompressed(ctx, dimensions, format, type,
  540.                                 pixels, texImage, transferOps);
  541.    }
  542. }
  543.  
  544.  
  545. /**
  546.  * Try to do glGetTexImage() with simple memcpy().
  547.  * \return GL_TRUE if done, GL_FALSE otherwise
  548.  */
  549. static GLboolean
  550. get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
  551.                GLvoid *pixels,
  552.                struct gl_texture_image *texImage)
  553. {
  554.    const GLenum target = texImage->TexObject->Target;
  555.    GLboolean memCopy = GL_FALSE;
  556.    GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  557.  
  558.    /*
  559.     * Check if we can use memcpy to copy from the hardware texture
  560.     * format to the user's format/type.
  561.     * Note that GL's pixel transfer ops don't apply to glGetTexImage()
  562.     */
  563.    if ((target == GL_TEXTURE_1D ||
  564.         target == GL_TEXTURE_2D ||
  565.         target == GL_TEXTURE_RECTANGLE ||
  566.         _mesa_is_cube_face(target)) &&
  567.        texBaseFormat == texImage->_BaseFormat) {
  568.       memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat,
  569.                                                      format, type,
  570.                                                      ctx->Pack.SwapBytes);
  571.    }
  572.  
  573.    if (memCopy) {
  574.       const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
  575.       const GLuint bytesPerRow = texImage->Width * bpp;
  576.       GLubyte *dst =
  577.          _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
  578.                                texImage->Height, format, type, 0, 0);
  579.       const GLint dstRowStride =
  580.          _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
  581.       GLubyte *src;
  582.       GLint srcRowStride;
  583.  
  584.       /* map src texture buffer */
  585.       ctx->Driver.MapTextureImage(ctx, texImage, 0,
  586.                                   0, 0, texImage->Width, texImage->Height,
  587.                                   GL_MAP_READ_BIT, &src, &srcRowStride);
  588.  
  589.       if (src) {
  590.          if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
  591.             memcpy(dst, src, bytesPerRow * texImage->Height);
  592.          }
  593.          else {
  594.             GLuint row;
  595.             for (row = 0; row < texImage->Height; row++) {
  596.                memcpy(dst, src, bytesPerRow);
  597.                dst += dstRowStride;
  598.                src += srcRowStride;
  599.             }
  600.          }
  601.  
  602.          /* unmap src texture buffer */
  603.          ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
  604.       }
  605.       else {
  606.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  607.       }
  608.    }
  609.  
  610.    return memCopy;
  611. }
  612.  
  613.  
  614. /**
  615.  * This is the software fallback for Driver.GetTexImage().
  616.  * All error checking will have been done before this routine is called.
  617.  * We'll call ctx->Driver.MapTextureImage() to access the data, then
  618.  * unmap with ctx->Driver.UnmapTextureImage().
  619.  */
  620. void
  621. _mesa_get_teximage(struct gl_context *ctx,
  622.                    GLenum format, GLenum type, GLvoid *pixels,
  623.                    struct gl_texture_image *texImage)
  624. {
  625.    const GLuint dimensions =
  626.       _mesa_get_texture_dimensions(texImage->TexObject->Target);
  627.  
  628.    /* map dest buffer, if PBO */
  629.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  630.       /* Packing texture image into a PBO.
  631.        * Map the (potentially) VRAM-based buffer into our process space so
  632.        * we can write into it with the code below.
  633.        * A hardware driver might use a sophisticated blit to move the
  634.        * texture data to the PBO if the PBO is in VRAM along with the texture.
  635.        */
  636.       GLubyte *buf = (GLubyte *)
  637.          ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
  638.                                     GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
  639.       if (!buf) {
  640.          /* out of memory or other unexpected error */
  641.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
  642.          return;
  643.       }
  644.       /* <pixels> was an offset into the PBO.
  645.        * Now make it a real, client-side pointer inside the mapped region.
  646.        */
  647.       pixels = ADD_POINTERS(buf, pixels);
  648.    }
  649.  
  650.    if (get_tex_memcpy(ctx, format, type, pixels, texImage)) {
  651.       /* all done */
  652.    }
  653.    else if (format == GL_DEPTH_COMPONENT) {
  654.       get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
  655.    }
  656.    else if (format == GL_DEPTH_STENCIL_EXT) {
  657.       get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
  658.    }
  659.    else if (format == GL_YCBCR_MESA) {
  660.       get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
  661.    }
  662.    else {
  663.       get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
  664.    }
  665.  
  666.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  667.       ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
  668.    }
  669. }
  670.  
  671.  
  672.  
  673. /**
  674.  * This is the software fallback for Driver.GetCompressedTexImage().
  675.  * All error checking will have been done before this routine is called.
  676.  */
  677. void
  678. _mesa_get_compressed_teximage(struct gl_context *ctx,
  679.                               struct gl_texture_image *texImage,
  680.                               GLvoid *img)
  681. {
  682.    const GLuint row_stride =
  683.       _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
  684.    GLuint i;
  685.    GLubyte *src;
  686.    GLint srcRowStride;
  687.  
  688.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  689.       /* pack texture image into a PBO */
  690.       GLubyte *buf = (GLubyte *)
  691.          ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
  692.                                     GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
  693.       if (!buf) {
  694.          /* out of memory or other unexpected error */
  695.          _mesa_error(ctx, GL_OUT_OF_MEMORY,
  696.                      "glGetCompresssedTexImage(map PBO failed)");
  697.          return;
  698.       }
  699.       img = ADD_POINTERS(buf, img);
  700.    }
  701.  
  702.    /* map src texture buffer */
  703.    ctx->Driver.MapTextureImage(ctx, texImage, 0,
  704.                                0, 0, texImage->Width, texImage->Height,
  705.                                GL_MAP_READ_BIT, &src, &srcRowStride);
  706.  
  707.    if (src) {
  708.       /* no pixelstore or pixel transfer, but respect stride */
  709.  
  710.       if (row_stride == srcRowStride) {
  711.          const GLuint size = _mesa_format_image_size(texImage->TexFormat,
  712.                                                      texImage->Width,
  713.                                                      texImage->Height,
  714.                                                      texImage->Depth);
  715.          memcpy(img, src, size);
  716.       }
  717.       else {
  718.          GLuint bw, bh;
  719.          _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
  720.          for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) {
  721.             memcpy((GLubyte *)img + i * row_stride,
  722.                    (GLubyte *)src + i * srcRowStride,
  723.                    row_stride);
  724.          }
  725.       }
  726.  
  727.       ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
  728.    }
  729.    else {
  730.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage");
  731.    }
  732.  
  733.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  734.       ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
  735.    }
  736. }
  737.  
  738.  
  739. /**
  740.  * Validate the texture target enum supplied to glTexImage or
  741.  * glCompressedTexImage.
  742.  */
  743. static GLboolean
  744. legal_getteximage_target(struct gl_context *ctx, GLenum target)
  745. {
  746.    switch (target) {
  747.    case GL_TEXTURE_1D:
  748.    case GL_TEXTURE_2D:
  749.    case GL_TEXTURE_3D:
  750.       return GL_TRUE;
  751.    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
  752.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
  753.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
  754.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
  755.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
  756.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
  757.       return ctx->Extensions.ARB_texture_cube_map;
  758.    case GL_TEXTURE_RECTANGLE_NV:
  759.       return ctx->Extensions.NV_texture_rectangle;
  760.    case GL_TEXTURE_1D_ARRAY_EXT:
  761.    case GL_TEXTURE_2D_ARRAY_EXT:
  762.       return (ctx->Extensions.MESA_texture_array ||
  763.               ctx->Extensions.EXT_texture_array);
  764.    case GL_TEXTURE_CUBE_MAP_ARRAY:
  765.       return ctx->Extensions.ARB_texture_cube_map_array;
  766.    default:
  767.       return GL_FALSE;
  768.    }
  769. }
  770.  
  771.  
  772. /**
  773.  * Do error checking for a glGetTexImage() call.
  774.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  775.  */
  776. static GLboolean
  777. getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
  778.                         GLenum format, GLenum type, GLsizei clientMemSize,
  779.                         GLvoid *pixels )
  780. {
  781.    struct gl_texture_object *texObj;
  782.    struct gl_texture_image *texImage;
  783.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  784.    const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
  785.    GLenum baseFormat, err;
  786.  
  787.    if (!legal_getteximage_target(ctx, target)) {
  788.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
  789.       return GL_TRUE;
  790.    }
  791.  
  792.    assert(maxLevels != 0);
  793.    if (level < 0 || level >= maxLevels) {
  794.       _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
  795.       return GL_TRUE;
  796.    }
  797.  
  798.    err = _mesa_error_check_format_and_type(ctx, format, type);
  799.    if (err != GL_NO_ERROR) {
  800.       _mesa_error(ctx, err, "glGetTexImage(format/type)");
  801.       return GL_TRUE;
  802.    }
  803.  
  804.    texObj = _mesa_get_current_tex_object(ctx, target);
  805.  
  806.    if (!texObj) {
  807.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
  808.       return GL_TRUE;
  809.    }
  810.  
  811.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  812.    if (!texImage) {
  813.       /* non-existant texture image */
  814.       return GL_TRUE;
  815.    }
  816.  
  817.    baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  818.      
  819.    /* Make sure the requested image format is compatible with the
  820.     * texture's format.
  821.     */
  822.    if (_mesa_is_color_format(format)
  823.        && !_mesa_is_color_format(baseFormat)) {
  824.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  825.       return GL_TRUE;
  826.    }
  827.    else if (_mesa_is_depth_format(format)
  828.             && !_mesa_is_depth_format(baseFormat)
  829.             && !_mesa_is_depthstencil_format(baseFormat)) {
  830.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  831.       return GL_TRUE;
  832.    }
  833.    else if (_mesa_is_ycbcr_format(format)
  834.             && !_mesa_is_ycbcr_format(baseFormat)) {
  835.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  836.       return GL_TRUE;
  837.    }
  838.    else if (_mesa_is_depthstencil_format(format)
  839.             && !_mesa_is_depthstencil_format(baseFormat)) {
  840.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  841.       return GL_TRUE;
  842.    }
  843.    else if (_mesa_is_dudv_format(format)
  844.             && !_mesa_is_dudv_format(baseFormat)) {
  845.       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
  846.       return GL_TRUE;
  847.    }
  848.  
  849.    if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
  850.                                   texImage->Height, texImage->Depth,
  851.                                   format, type, clientMemSize, pixels)) {
  852.       if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  853.          _mesa_error(ctx, GL_INVALID_OPERATION,
  854.                      "glGetTexImage(out of bounds PBO access)");
  855.       } else {
  856.          _mesa_error(ctx, GL_INVALID_OPERATION,
  857.                      "glGetnTexImageARB(out of bounds access:"
  858.                      " bufSize (%d) is too small)", clientMemSize);
  859.       }
  860.       return GL_TRUE;
  861.    }
  862.  
  863.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  864.       /* PBO should not be mapped */
  865.       if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
  866.          _mesa_error(ctx, GL_INVALID_OPERATION,
  867.                      "glGetTexImage(PBO is mapped)");
  868.          return GL_TRUE;
  869.       }
  870.    }
  871.  
  872.    return GL_FALSE;
  873. }
  874.  
  875.  
  876.  
  877. /**
  878.  * Get texture image.  Called by glGetTexImage.
  879.  *
  880.  * \param target texture target.
  881.  * \param level image level.
  882.  * \param format pixel data format for returned image.
  883.  * \param type pixel data type for returned image.
  884.  * \param bufSize size of the pixels data buffer.
  885.  * \param pixels returned pixel data.
  886.  */
  887. void GLAPIENTRY
  888. _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format,
  889.                        GLenum type, GLsizei bufSize, GLvoid *pixels )
  890. {
  891.    struct gl_texture_object *texObj;
  892.    struct gl_texture_image *texImage;
  893.    GET_CURRENT_CONTEXT(ctx);
  894.  
  895.    FLUSH_VERTICES(ctx, 0);
  896.  
  897.    if (getteximage_error_check(ctx, target, level, format, type,
  898.                                bufSize, pixels)) {
  899.       return;
  900.    }
  901.  
  902.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
  903.       /* not an error, do nothing */
  904.       return;
  905.    }
  906.  
  907.    texObj = _mesa_get_current_tex_object(ctx, target);
  908.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  909.  
  910.    if (_mesa_is_zero_size_texture(texImage))
  911.       return;
  912.  
  913.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  914.       _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
  915.                   " dstFmt=0x%x, dstType=0x%x\n",
  916.                   texObj->Name,
  917.                   _mesa_get_format_name(texImage->TexFormat),
  918.                   texImage->Width, texImage->Height,
  919.                   format, type);
  920.    }
  921.  
  922.    _mesa_lock_texture(ctx, texObj);
  923.    {
  924.       ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage);
  925.    }
  926.    _mesa_unlock_texture(ctx, texObj);
  927. }
  928.  
  929.  
  930. void GLAPIENTRY
  931. _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
  932.                    GLenum type, GLvoid *pixels )
  933. {
  934.    _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels);
  935. }
  936.  
  937.  
  938. /**
  939.  * Do error checking for a glGetCompressedTexImage() call.
  940.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  941.  */
  942. static GLboolean
  943. getcompressedteximage_error_check(struct gl_context *ctx, GLenum target,
  944.                                   GLint level, GLsizei clientMemSize, GLvoid *img)
  945. {
  946.    struct gl_texture_object *texObj;
  947.    struct gl_texture_image *texImage;
  948.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  949.    GLuint compressedSize;
  950.  
  951.    if (!legal_getteximage_target(ctx, target)) {
  952.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
  953.                   target);
  954.       return GL_TRUE;
  955.    }
  956.  
  957.    assert(maxLevels != 0);
  958.    if (level < 0 || level >= maxLevels) {
  959.       _mesa_error(ctx, GL_INVALID_VALUE,
  960.                   "glGetCompressedTexImageARB(bad level = %d)", level);
  961.       return GL_TRUE;
  962.    }
  963.  
  964.    texObj = _mesa_get_current_tex_object(ctx, target);
  965.    if (!texObj) {
  966.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
  967.       return GL_TRUE;
  968.    }
  969.  
  970.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  971.  
  972.    if (!texImage) {
  973.       /* probably invalid mipmap level */
  974.       _mesa_error(ctx, GL_INVALID_VALUE,
  975.                   "glGetCompressedTexImageARB(level)");
  976.       return GL_TRUE;
  977.    }
  978.  
  979.    if (!_mesa_is_format_compressed(texImage->TexFormat)) {
  980.       _mesa_error(ctx, GL_INVALID_OPERATION,
  981.                   "glGetCompressedTexImageARB(texture is not compressed)");
  982.       return GL_TRUE;
  983.    }
  984.  
  985.    compressedSize = _mesa_format_image_size(texImage->TexFormat,
  986.                                             texImage->Width,
  987.                                             texImage->Height,
  988.                                             texImage->Depth);
  989.  
  990.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  991.       /* do bounds checking on writing to client memory */
  992.       if (clientMemSize < (GLsizei) compressedSize) {
  993.          _mesa_error(ctx, GL_INVALID_OPERATION,
  994.                      "glGetnCompressedTexImageARB(out of bounds access:"
  995.                      " bufSize (%d) is too small)", clientMemSize);
  996.          return GL_TRUE;
  997.       }
  998.    } else {
  999.       /* do bounds checking on PBO write */
  1000.       if ((const GLubyte *) img + compressedSize >
  1001.           (const GLubyte *) ctx->Pack.BufferObj->Size) {
  1002.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1003.                      "glGetCompressedTexImage(out of bounds PBO access)");
  1004.          return GL_TRUE;
  1005.       }
  1006.  
  1007.       /* make sure PBO is not mapped */
  1008.       if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
  1009.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1010.                      "glGetCompressedTexImage(PBO is mapped)");
  1011.          return GL_TRUE;
  1012.       }
  1013.    }
  1014.  
  1015.    return GL_FALSE;
  1016. }
  1017.  
  1018.  
  1019. void GLAPIENTRY
  1020. _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,
  1021.                                 GLvoid *img)
  1022. {
  1023.    struct gl_texture_object *texObj;
  1024.    struct gl_texture_image *texImage;
  1025.    GET_CURRENT_CONTEXT(ctx);
  1026.  
  1027.    FLUSH_VERTICES(ctx, 0);
  1028.  
  1029.    if (getcompressedteximage_error_check(ctx, target, level, bufSize, img)) {
  1030.       return;
  1031.    }
  1032.  
  1033.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
  1034.       /* not an error, do nothing */
  1035.       return;
  1036.    }
  1037.  
  1038.    texObj = _mesa_get_current_tex_object(ctx, target);
  1039.    texImage = _mesa_select_tex_image(ctx, texObj, target, level);
  1040.  
  1041.    if (_mesa_is_zero_size_texture(texImage))
  1042.       return;
  1043.  
  1044.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  1045.       _mesa_debug(ctx,
  1046.                   "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
  1047.                   texObj->Name,
  1048.                   _mesa_get_format_name(texImage->TexFormat),
  1049.                   texImage->Width, texImage->Height);
  1050.    }
  1051.  
  1052.    _mesa_lock_texture(ctx, texObj);
  1053.    {
  1054.       ctx->Driver.GetCompressedTexImage(ctx, texImage, img);
  1055.    }
  1056.    _mesa_unlock_texture(ctx, texObj);
  1057. }
  1058.  
  1059. void GLAPIENTRY
  1060. _mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img)
  1061. {
  1062.    _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);
  1063. }
  1064.