Subversion Repositories Kolibri OS

Rev

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 "pixelstore.h"
  44. #include "texcompress.h"
  45. #include "texgetimage.h"
  46. #include "teximage.h"
  47. #include "texobj.h"
  48. #include "texstore.h"
  49. #include "format_utils.h"
  50. #include "pixeltransfer.h"
  51.  
  52. /**
  53.  * Can the given type represent negative values?
  54.  */
  55. static inline GLboolean
  56. type_needs_clamping(GLenum type)
  57. {
  58.    switch (type) {
  59.    case GL_BYTE:
  60.    case GL_SHORT:
  61.    case GL_INT:
  62.    case GL_FLOAT:
  63.    case GL_HALF_FLOAT_ARB:
  64.    case GL_UNSIGNED_INT_10F_11F_11F_REV:
  65.    case GL_UNSIGNED_INT_5_9_9_9_REV:
  66.       return GL_FALSE;
  67.    default:
  68.       return GL_TRUE;
  69.    }
  70. }
  71.  
  72.  
  73. /**
  74.  * glGetTexImage for depth/Z pixels.
  75.  */
  76. static void
  77. get_tex_depth(struct gl_context *ctx, GLuint dimensions,
  78.               GLenum format, GLenum type, GLvoid *pixels,
  79.               struct gl_texture_image *texImage)
  80. {
  81.    const GLint width = texImage->Width;
  82.    GLint height = texImage->Height;
  83.    GLint depth = texImage->Depth;
  84.    GLint img, row;
  85.    GLfloat *depthRow = malloc(width * sizeof(GLfloat));
  86.  
  87.    if (!depthRow) {
  88.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  89.       return;
  90.    }
  91.  
  92.    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
  93.       depth = height;
  94.       height = 1;
  95.    }
  96.  
  97.    for (img = 0; img < depth; img++) {
  98.       GLubyte *srcMap;
  99.       GLint srcRowStride;
  100.  
  101.       /* map src texture buffer */
  102.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  103.                                   0, 0, width, height, GL_MAP_READ_BIT,
  104.                                   &srcMap, &srcRowStride);
  105.  
  106.       if (srcMap) {
  107.          for (row = 0; row < height; row++) {
  108.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  109.                                              width, height, format, type,
  110.                                              img, row, 0);
  111.             const GLubyte *src = srcMap + row * srcRowStride;
  112.             _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
  113.             _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
  114.          }
  115.  
  116.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  117.       }
  118.       else {
  119.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  120.          break;
  121.       }
  122.    }
  123.  
  124.    free(depthRow);
  125. }
  126.  
  127.  
  128. /**
  129.  * glGetTexImage for depth/stencil pixels.
  130.  */
  131. static void
  132. get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions,
  133.                       GLenum format, GLenum type, GLvoid *pixels,
  134.                       struct gl_texture_image *texImage)
  135. {
  136.    const GLint width = texImage->Width;
  137.    const GLint height = texImage->Height;
  138.    const GLint depth = texImage->Depth;
  139.    GLint img, row;
  140.  
  141.    assert(format == GL_DEPTH_STENCIL);
  142.    assert(type == GL_UNSIGNED_INT_24_8 ||
  143.           type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
  144.  
  145.    for (img = 0; img < depth; img++) {
  146.       GLubyte *srcMap;
  147.       GLint rowstride;
  148.  
  149.       /* map src texture buffer */
  150.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  151.                                   0, 0, width, height, GL_MAP_READ_BIT,
  152.                                   &srcMap, &rowstride);
  153.  
  154.       if (srcMap) {
  155.          for (row = 0; row < height; row++) {
  156.             const GLubyte *src = srcMap + row * rowstride;
  157.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  158.                                              width, height, format, type,
  159.                                              img, row, 0);
  160.             _mesa_unpack_depth_stencil_row(texImage->TexFormat,
  161.                                            width,
  162.                                            (const GLuint *) src,
  163.                                            type, dest);
  164.             if (ctx->Pack.SwapBytes) {
  165.                _mesa_swap4((GLuint *) dest, width);
  166.             }
  167.          }
  168.  
  169.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  170.       }
  171.       else {
  172.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  173.          break;
  174.       }
  175.    }
  176. }
  177.  
  178. /**
  179.  * glGetTexImage for stencil pixels.
  180.  */
  181. static void
  182. get_tex_stencil(struct gl_context *ctx, GLuint dimensions,
  183.                 GLenum format, GLenum type, GLvoid *pixels,
  184.                 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.    GLint img, row;
  190.  
  191.    assert(format == GL_STENCIL_INDEX);
  192.  
  193.    for (img = 0; img < depth; img++) {
  194.       GLubyte *srcMap;
  195.       GLint rowstride;
  196.  
  197.       /* map src texture buffer */
  198.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  199.                                   0, 0, width, height, GL_MAP_READ_BIT,
  200.                                   &srcMap, &rowstride);
  201.  
  202.       if (srcMap) {
  203.          for (row = 0; row < height; row++) {
  204.             const GLubyte *src = srcMap + row * rowstride;
  205.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  206.                                              width, height, format, type,
  207.                                              img, row, 0);
  208.             _mesa_unpack_ubyte_stencil_row(texImage->TexFormat,
  209.                                            width,
  210.                                            (const GLuint *) src,
  211.                                            dest);
  212.          }
  213.  
  214.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  215.       }
  216.       else {
  217.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  218.          break;
  219.       }
  220.    }
  221. }
  222.  
  223.  
  224. /**
  225.  * glGetTexImage for YCbCr pixels.
  226.  */
  227. static void
  228. get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
  229.               GLenum format, GLenum type, GLvoid *pixels,
  230.               struct gl_texture_image *texImage)
  231. {
  232.    const GLint width = texImage->Width;
  233.    const GLint height = texImage->Height;
  234.    const GLint depth = texImage->Depth;
  235.    GLint img, row;
  236.  
  237.    for (img = 0; img < depth; img++) {
  238.       GLubyte *srcMap;
  239.       GLint rowstride;
  240.  
  241.       /* map src texture buffer */
  242.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  243.                                   0, 0, width, height, GL_MAP_READ_BIT,
  244.                                   &srcMap, &rowstride);
  245.  
  246.       if (srcMap) {
  247.          for (row = 0; row < height; row++) {
  248.             const GLubyte *src = srcMap + row * rowstride;
  249.             void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  250.                                              width, height, format, type,
  251.                                              img, row, 0);
  252.             memcpy(dest, src, width * sizeof(GLushort));
  253.  
  254.             /* check for byte swapping */
  255.             if ((texImage->TexFormat == MESA_FORMAT_YCBCR
  256.                  && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
  257.                 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
  258.                  && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
  259.                if (!ctx->Pack.SwapBytes)
  260.                   _mesa_swap2((GLushort *) dest, width);
  261.             }
  262.             else if (ctx->Pack.SwapBytes) {
  263.                _mesa_swap2((GLushort *) dest, width);
  264.             }
  265.          }
  266.  
  267.          ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  268.       }
  269.       else {
  270.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  271.          break;
  272.       }
  273.    }
  274. }
  275.  
  276.  
  277. /**
  278.  * Get a color texture image with decompression.
  279.  */
  280. static void
  281. get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions,
  282.                         GLenum format, GLenum type, GLvoid *pixels,
  283.                         struct gl_texture_image *texImage,
  284.                         GLbitfield transferOps)
  285. {
  286.    /* don't want to apply sRGB -> RGB conversion here so override the format */
  287.    const mesa_format texFormat =
  288.       _mesa_get_srgb_format_linear(texImage->TexFormat);
  289.    const GLenum baseFormat = _mesa_get_format_base_format(texFormat);
  290.    const GLuint width = texImage->Width;
  291.    const GLuint height = texImage->Height;
  292.    const GLuint depth = texImage->Depth;
  293.    GLfloat *tempImage, *tempSlice;
  294.    GLuint slice;
  295.    int srcStride, dstStride;
  296.    uint32_t dstFormat;
  297.    bool needsRebase;
  298.    uint8_t rebaseSwizzle[4];
  299.  
  300.    /* Decompress into temp float buffer, then pack into user buffer */
  301.    tempImage = malloc(width * height * depth
  302.                                   * 4 * sizeof(GLfloat));
  303.    if (!tempImage) {
  304.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
  305.       return;
  306.    }
  307.  
  308.    /* Decompress the texture image slices - results in 'tempImage' */
  309.    for (slice = 0; slice < depth; slice++) {
  310.       GLubyte *srcMap;
  311.       GLint srcRowStride;
  312.  
  313.       tempSlice = tempImage + slice * 4 * width * height;
  314.  
  315.       ctx->Driver.MapTextureImage(ctx, texImage, slice,
  316.                                   0, 0, width, height,
  317.                                   GL_MAP_READ_BIT,
  318.                                   &srcMap, &srcRowStride);
  319.       if (srcMap) {
  320.          _mesa_decompress_image(texFormat, width, height,
  321.                                 srcMap, srcRowStride, tempSlice);
  322.  
  323.          ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
  324.       }
  325.       else {
  326.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  327.          free(tempImage);
  328.          return;
  329.       }
  330.    }
  331.  
  332.    /* Depending on the base format involved we may need to apply a rebase
  333.     * transform (for example: if we download to a Luminance format we want
  334.     * G=0 and B=0).
  335.     */
  336.    if (baseFormat == GL_LUMINANCE ||
  337.        baseFormat == GL_INTENSITY) {
  338.       needsRebase = true;
  339.       rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
  340.       rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
  341.       rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
  342.       rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
  343.    } else if (baseFormat == GL_LUMINANCE_ALPHA) {
  344.       needsRebase = true;
  345.       rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
  346.       rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
  347.       rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
  348.       rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
  349.    } else {
  350.       needsRebase = false;
  351.    }
  352.  
  353.    srcStride = 4 * width * sizeof(GLfloat);
  354.    dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type);
  355.    dstFormat = _mesa_format_from_format_and_type(format, type);
  356.    tempSlice = tempImage;
  357.    for (slice = 0; slice < depth; slice++) {
  358.       void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  359.                                        width, height, format, type,
  360.                                        slice, 0, 0);
  361.       _mesa_format_convert(dest, dstFormat, dstStride,
  362.                            tempSlice, RGBA32_FLOAT, srcStride,
  363.                            width, height,
  364.                            needsRebase ? rebaseSwizzle : NULL);
  365.       tempSlice += 4 * width * height;
  366.    }
  367.  
  368.    free(tempImage);
  369. }
  370.  
  371.  
  372. /**
  373.  * Return a base GL format given the user-requested format
  374.  * for glGetTexImage().
  375.  */
  376. GLenum
  377. _mesa_base_pack_format(GLenum format)
  378. {
  379.    switch (format) {
  380.    case GL_ABGR_EXT:
  381.    case GL_BGRA:
  382.    case GL_BGRA_INTEGER:
  383.    case GL_RGBA_INTEGER:
  384.       return GL_RGBA;
  385.    case GL_BGR:
  386.    case GL_BGR_INTEGER:
  387.    case GL_RGB_INTEGER:
  388.       return GL_RGB;
  389.    case GL_RED_INTEGER:
  390.       return GL_RED;
  391.    case GL_GREEN_INTEGER:
  392.       return GL_GREEN;
  393.    case GL_BLUE_INTEGER:
  394.       return GL_BLUE;
  395.    case GL_ALPHA_INTEGER:
  396.       return GL_ALPHA;
  397.    case GL_LUMINANCE_INTEGER_EXT:
  398.       return GL_LUMINANCE;
  399.    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
  400.       return GL_LUMINANCE_ALPHA;
  401.    default:
  402.       return format;
  403.    }
  404. }
  405.  
  406.  
  407. /**
  408.  * Get an uncompressed color texture image.
  409.  */
  410. static void
  411. get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
  412.                           GLenum format, GLenum type, GLvoid *pixels,
  413.                           struct gl_texture_image *texImage,
  414.                           GLbitfield transferOps)
  415. {
  416.    /* don't want to apply sRGB -> RGB conversion here so override the format */
  417.    const mesa_format texFormat =
  418.       _mesa_get_srgb_format_linear(texImage->TexFormat);
  419.    const GLuint width = texImage->Width;
  420.    GLuint height = texImage->Height;
  421.    GLuint depth = texImage->Depth;
  422.    GLuint img;
  423.    GLboolean dst_is_integer;
  424.    uint32_t dst_format;
  425.    int dst_stride;
  426.    uint8_t rebaseSwizzle[4];
  427.    bool needsRebase;
  428.    void *rgba = NULL;
  429.  
  430.    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
  431.       depth = height;
  432.       height = 1;
  433.    }
  434.  
  435.    /* Depending on the base format involved we may need to apply a rebase
  436.     * transform (for example: if we download to a Luminance format we want
  437.     * G=0 and B=0).
  438.     */
  439.    if (texImage->_BaseFormat == GL_LUMINANCE ||
  440.        texImage->_BaseFormat == GL_INTENSITY) {
  441.       needsRebase = true;
  442.       rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
  443.       rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
  444.       rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
  445.       rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
  446.    } else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
  447.       needsRebase = true;
  448.       rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X;
  449.       rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
  450.       rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
  451.       rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W;
  452.     } else if (texImage->_BaseFormat != _mesa_get_format_base_format(texFormat)) {
  453.       needsRebase =
  454.          _mesa_compute_rgba2base2rgba_component_mapping(texImage->_BaseFormat,
  455.                                                         rebaseSwizzle);
  456.     } else {
  457.       needsRebase = false;
  458.     }
  459.  
  460.    /* Describe the dst format */
  461.    dst_is_integer = _mesa_is_enum_format_integer(format);
  462.    dst_format = _mesa_format_from_format_and_type(format, type);
  463.    dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type);
  464.  
  465.    /* Since _mesa_format_convert does not handle transferOps we need to handle
  466.     * them before we call the function. This requires to convert to RGBA float
  467.     * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
  468.     * integer then transferOps do not apply.
  469.     */
  470.    assert(!transferOps || (transferOps && !dst_is_integer));
  471.    (void) dst_is_integer; /* silence unused var warning */
  472.  
  473.    for (img = 0; img < depth; img++) {
  474.       GLubyte *srcMap;
  475.       GLint rowstride;
  476.       GLubyte *img_src;
  477.       void *dest;
  478.       void *src;
  479.       int src_stride;
  480.       uint32_t src_format;
  481.  
  482.       /* map src texture buffer */
  483.       ctx->Driver.MapTextureImage(ctx, texImage, img,
  484.                                   0, 0, width, height, GL_MAP_READ_BIT,
  485.                                   &srcMap, &rowstride);
  486.       if (!srcMap) {
  487.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  488.          goto done;
  489.       }
  490.  
  491.       img_src = srcMap;
  492.       dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
  493.                                  width, height, format, type,
  494.                                  img, 0, 0);
  495.  
  496.       if (transferOps) {
  497.          uint32_t rgba_format;
  498.          int rgba_stride;
  499.          bool need_convert = false;
  500.  
  501.          /* We will convert to RGBA float */
  502.          rgba_format = RGBA32_FLOAT;
  503.          rgba_stride = width * 4 * sizeof(GLfloat);
  504.  
  505.          /* If we are lucky and the dst format matches the RGBA format we need
  506.           * to convert to, then we can convert directly into the dst buffer
  507.           * and avoid the final conversion/copy from the rgba buffer to the dst
  508.           * buffer.
  509.           */
  510.          if (format == rgba_format) {
  511.             rgba = dest;
  512.          } else if (rgba == NULL) { /* Allocate the RGBA buffer only once */
  513.             need_convert = true;
  514.             rgba = malloc(height * rgba_stride);
  515.             if (!rgba) {
  516.                _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
  517.                ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  518.                return;
  519.             }
  520.          }
  521.  
  522.          _mesa_format_convert(rgba, rgba_format, rgba_stride,
  523.                               img_src, texFormat, rowstride,
  524.                               width, height,
  525.                               needsRebase ? rebaseSwizzle : NULL);
  526.  
  527.          /* Handle transfer ops now */
  528.          _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
  529.  
  530.          /* If we had to rebase, we have already handled that */
  531.          needsRebase = false;
  532.  
  533.          /* If we were lucky and our RGBA conversion matches the dst format, then
  534.           * we are done.
  535.           */
  536.          if (!need_convert)
  537.             goto do_swap;
  538.  
  539.          /* Otherwise, we need to convert from RGBA to dst next */
  540.          src = rgba;
  541.          src_format = rgba_format;
  542.          src_stride = rgba_stride;
  543.       } else {
  544.          /* No RGBA conversion needed, convert directly to dst */
  545.          src = img_src;
  546.          src_format = texFormat;
  547.          src_stride = rowstride;
  548.       }
  549.  
  550.       /* Do the conversion to destination format */
  551.       _mesa_format_convert(dest, dst_format, dst_stride,
  552.                            src, src_format, src_stride,
  553.                            width, height,
  554.                            needsRebase ? rebaseSwizzle : NULL);
  555.  
  556.    do_swap:
  557.       /* Handle byte swapping if required */
  558.       if (ctx->Pack.SwapBytes) {
  559.          GLint swapSize = _mesa_sizeof_packed_type(type);
  560.          if (swapSize == 2 || swapSize == 4) {
  561.             int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
  562.             assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
  563.             if (swapSize == 2)
  564.                _mesa_swap2((GLushort *) dest, width * height * swapsPerPixel);
  565.             else if (swapSize == 4)
  566.                _mesa_swap4((GLuint *) dest, width * height * swapsPerPixel);
  567.          }
  568.       }
  569.  
  570.       /* Unmap the src texture buffer */
  571.       ctx->Driver.UnmapTextureImage(ctx, texImage, img);
  572.    }
  573.  
  574. done:
  575.    if (rgba)
  576.       free(rgba);
  577. }
  578.  
  579.  
  580. /**
  581.  * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
  582.  * Compressed textures are handled here as well.
  583.  */
  584. static void
  585. get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
  586.              GLenum format, GLenum type, GLvoid *pixels,
  587.              struct gl_texture_image *texImage)
  588. {
  589.    const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
  590.    GLbitfield transferOps = 0x0;
  591.  
  592.    /* In general, clamping does not apply to glGetTexImage, except when
  593.     * the returned type of the image can't hold negative values.
  594.     */
  595.    if (type_needs_clamping(type)) {
  596.       /* the returned image type can't have negative values */
  597.       if (dataType == GL_FLOAT ||
  598.           dataType == GL_HALF_FLOAT ||
  599.           dataType == GL_SIGNED_NORMALIZED ||
  600.           format == GL_LUMINANCE ||
  601.           format == GL_LUMINANCE_ALPHA) {
  602.          transferOps |= IMAGE_CLAMP_BIT;
  603.       }
  604.    }
  605.  
  606.    if (_mesa_is_format_compressed(texImage->TexFormat)) {
  607.       get_tex_rgba_compressed(ctx, dimensions, format, type,
  608.                               pixels, texImage, transferOps);
  609.    }
  610.    else {
  611.       get_tex_rgba_uncompressed(ctx, dimensions, format, type,
  612.                                 pixels, texImage, transferOps);
  613.    }
  614. }
  615.  
  616.  
  617. /**
  618.  * Try to do glGetTexImage() with simple memcpy().
  619.  * \return GL_TRUE if done, GL_FALSE otherwise
  620.  */
  621. static GLboolean
  622. get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
  623.                GLvoid *pixels,
  624.                struct gl_texture_image *texImage)
  625. {
  626.    const GLenum target = texImage->TexObject->Target;
  627.    GLboolean memCopy = GL_FALSE;
  628.    GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  629.  
  630.    /*
  631.     * Check if we can use memcpy to copy from the hardware texture
  632.     * format to the user's format/type.
  633.     * Note that GL's pixel transfer ops don't apply to glGetTexImage()
  634.     */
  635.    if ((target == GL_TEXTURE_1D ||
  636.         target == GL_TEXTURE_2D ||
  637.         target == GL_TEXTURE_RECTANGLE ||
  638.         _mesa_is_cube_face(target)) &&
  639.        texBaseFormat == texImage->_BaseFormat) {
  640.       memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat,
  641.                                                      format, type,
  642.                                                      ctx->Pack.SwapBytes);
  643.    }
  644.  
  645.    if (memCopy) {
  646.       const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
  647.       const GLint bytesPerRow = texImage->Width * bpp;
  648.       GLubyte *dst =
  649.          _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
  650.                                texImage->Height, format, type, 0, 0);
  651.       const GLint dstRowStride =
  652.          _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
  653.       GLubyte *src;
  654.       GLint srcRowStride;
  655.  
  656.       /* map src texture buffer */
  657.       ctx->Driver.MapTextureImage(ctx, texImage, 0,
  658.                                   0, 0, texImage->Width, texImage->Height,
  659.                                   GL_MAP_READ_BIT, &src, &srcRowStride);
  660.  
  661.       if (src) {
  662.          if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
  663.             memcpy(dst, src, bytesPerRow * texImage->Height);
  664.          }
  665.          else {
  666.             GLuint row;
  667.             for (row = 0; row < texImage->Height; row++) {
  668.                memcpy(dst, src, bytesPerRow);
  669.                dst += dstRowStride;
  670.                src += srcRowStride;
  671.             }
  672.          }
  673.  
  674.          /* unmap src texture buffer */
  675.          ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
  676.       }
  677.       else {
  678.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
  679.       }
  680.    }
  681.  
  682.    return memCopy;
  683. }
  684.  
  685.  
  686. /**
  687.  * This is the software fallback for Driver.GetTexImage().
  688.  * All error checking will have been done before this routine is called.
  689.  * We'll call ctx->Driver.MapTextureImage() to access the data, then
  690.  * unmap with ctx->Driver.UnmapTextureImage().
  691.  */
  692. void
  693. _mesa_GetTexImage_sw(struct gl_context *ctx,
  694.                      GLenum format, GLenum type, GLvoid *pixels,
  695.                      struct gl_texture_image *texImage)
  696. {
  697.    const GLuint dimensions =
  698.       _mesa_get_texture_dimensions(texImage->TexObject->Target);
  699.  
  700.    /* map dest buffer, if PBO */
  701.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  702.       /* Packing texture image into a PBO.
  703.        * Map the (potentially) VRAM-based buffer into our process space so
  704.        * we can write into it with the code below.
  705.        * A hardware driver might use a sophisticated blit to move the
  706.        * texture data to the PBO if the PBO is in VRAM along with the texture.
  707.        */
  708.       GLubyte *buf = (GLubyte *)
  709.          ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
  710.                                     GL_MAP_WRITE_BIT, ctx->Pack.BufferObj,
  711.                                     MAP_INTERNAL);
  712.       if (!buf) {
  713.          /* out of memory or other unexpected error */
  714.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
  715.          return;
  716.       }
  717.       /* <pixels> was an offset into the PBO.
  718.        * Now make it a real, client-side pointer inside the mapped region.
  719.        */
  720.       pixels = ADD_POINTERS(buf, pixels);
  721.    }
  722.  
  723.    if (get_tex_memcpy(ctx, format, type, pixels, texImage)) {
  724.       /* all done */
  725.    }
  726.    else if (format == GL_DEPTH_COMPONENT) {
  727.       get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
  728.    }
  729.    else if (format == GL_DEPTH_STENCIL_EXT) {
  730.       get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage);
  731.    }
  732.    else if (format == GL_STENCIL_INDEX) {
  733.       get_tex_stencil(ctx, dimensions, format, type, pixels, texImage);
  734.    }
  735.    else if (format == GL_YCBCR_MESA) {
  736.       get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
  737.    }
  738.    else {
  739.       get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
  740.    }
  741.  
  742.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  743.       ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL);
  744.    }
  745. }
  746.  
  747.  
  748.  
  749. /**
  750.  * This is the software fallback for Driver.GetCompressedTexImage().
  751.  * All error checking will have been done before this routine is called.
  752.  */
  753. void
  754. _mesa_GetCompressedTexImage_sw(struct gl_context *ctx,
  755.                                struct gl_texture_image *texImage,
  756.                                GLvoid *img)
  757. {
  758.    const GLuint dimensions =
  759.       _mesa_get_texture_dimensions(texImage->TexObject->Target);
  760.    struct compressed_pixelstore store;
  761.    GLint slice;
  762.    GLubyte *dest;
  763.  
  764.    _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat,
  765.                                        texImage->Width, texImage->Height,
  766.                                        texImage->Depth,
  767.                                        &ctx->Pack,
  768.                                        &store);
  769.  
  770.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  771.       /* pack texture image into a PBO */
  772.       dest = (GLubyte *)
  773.          ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
  774.                                     GL_MAP_WRITE_BIT, ctx->Pack.BufferObj,
  775.                                     MAP_INTERNAL);
  776.       if (!dest) {
  777.          /* out of memory or other unexpected error */
  778.          _mesa_error(ctx, GL_OUT_OF_MEMORY,
  779.                      "glGetCompresssedTexImage(map PBO failed)");
  780.          return;
  781.       }
  782.       dest = ADD_POINTERS(dest, img);
  783.    } else {
  784.       dest = img;
  785.    }
  786.  
  787.    dest += store.SkipBytes;
  788.  
  789.    for (slice = 0; slice < store.CopySlices; slice++) {
  790.       GLint srcRowStride;
  791.       GLubyte *src;
  792.  
  793.       /* map src texture buffer */
  794.       ctx->Driver.MapTextureImage(ctx, texImage, slice,
  795.                                   0, 0, texImage->Width, texImage->Height,
  796.                                   GL_MAP_READ_BIT, &src, &srcRowStride);
  797.  
  798.       if (src) {
  799.          GLint i;
  800.          for (i = 0; i < store.CopyRowsPerSlice; i++) {
  801.             memcpy(dest, src, store.CopyBytesPerRow);
  802.             dest += store.TotalBytesPerRow;
  803.             src += srcRowStride;
  804.          }
  805.  
  806.          ctx->Driver.UnmapTextureImage(ctx, texImage, slice);
  807.  
  808.          /* Advance to next slice */
  809.          dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice);
  810.  
  811.       } else {
  812.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage");
  813.       }
  814.    }
  815.  
  816.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  817.       ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL);
  818.    }
  819. }
  820.  
  821.  
  822. /**
  823.  * Validate the texture target enum supplied to glGetTex(ture)Image or
  824.  * glGetCompressedTex(ture)Image.
  825.  */
  826. static GLboolean
  827. legal_getteximage_target(struct gl_context *ctx, GLenum target, bool dsa)
  828. {
  829.    switch (target) {
  830.    case GL_TEXTURE_1D:
  831.    case GL_TEXTURE_2D:
  832.    case GL_TEXTURE_3D:
  833.       return GL_TRUE;
  834.    case GL_TEXTURE_RECTANGLE_NV:
  835.       return ctx->Extensions.NV_texture_rectangle;
  836.    case GL_TEXTURE_1D_ARRAY_EXT:
  837.    case GL_TEXTURE_2D_ARRAY_EXT:
  838.       return ctx->Extensions.EXT_texture_array;
  839.    case GL_TEXTURE_CUBE_MAP_ARRAY:
  840.       return ctx->Extensions.ARB_texture_cube_map_array;
  841.  
  842.    /* Section 8.11 (Texture Queries) of the OpenGL 4.5 core profile spec
  843.     * (30.10.2014) says:
  844.     *    "An INVALID_ENUM error is generated if the effective target is not
  845.     *    one of TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_1D_ARRAY,
  846.     *    TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, TEXTURE_RECTANGLE, one of
  847.     *    the targets from table 8.19 (for GetTexImage and GetnTexImage *only*),
  848.     *    or TEXTURE_CUBE_MAP (for GetTextureImage *only*)." (Emphasis added.)
  849.     */
  850.    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
  851.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
  852.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
  853.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
  854.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
  855.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
  856.       return dsa ? GL_FALSE : ctx->Extensions.ARB_texture_cube_map;
  857.    case GL_TEXTURE_CUBE_MAP:
  858.       return dsa ? GL_TRUE : GL_FALSE;
  859.    default:
  860.       return GL_FALSE;
  861.    }
  862. }
  863.  
  864.  
  865. /**
  866.  * Do error checking for a glGetTex(ture)Image() call.
  867.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  868.  */
  869. static GLboolean
  870. getteximage_error_check(struct gl_context *ctx,
  871.                         struct gl_texture_image *texImage,
  872.                         GLenum target, GLint level,
  873.                         GLenum format, GLenum type, GLsizei clientMemSize,
  874.                         GLvoid *pixels, bool dsa)
  875. {
  876.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  877.    const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
  878.    GLenum baseFormat;
  879.    const char *suffix = dsa ? "ture" : "";
  880.  
  881.    assert(texImage);
  882.    assert(maxLevels != 0);
  883.    if (level < 0 || level >= maxLevels) {
  884.       _mesa_error(ctx, GL_INVALID_VALUE,
  885.                   "glGetTex%sImage(level out of range)", suffix);
  886.       return GL_TRUE;
  887.    }
  888.  
  889.    /*
  890.     * Format and type checking has been moved up to GetnTexImage and
  891.     * GetTextureImage so that it happens before getting the texImage object.
  892.     */
  893.  
  894.    baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
  895.  
  896.    /* Make sure the requested image format is compatible with the
  897.     * texture's format.
  898.     */
  899.    if (_mesa_is_color_format(format)
  900.        && !_mesa_is_color_format(baseFormat)) {
  901.       _mesa_error(ctx, GL_INVALID_OPERATION,
  902.                   "glGetTex%sImage(format mismatch)", suffix);
  903.       return GL_TRUE;
  904.    }
  905.    else if (_mesa_is_depth_format(format)
  906.             && !_mesa_is_depth_format(baseFormat)
  907.             && !_mesa_is_depthstencil_format(baseFormat)) {
  908.       _mesa_error(ctx, GL_INVALID_OPERATION,
  909.                   "glGetTex%sImage(format mismatch)", suffix);
  910.       return GL_TRUE;
  911.    }
  912.    else if (_mesa_is_stencil_format(format)
  913.             && !ctx->Extensions.ARB_texture_stencil8) {
  914.       _mesa_error(ctx, GL_INVALID_ENUM,
  915.                   "glGetTex%sImage(format=GL_STENCIL_INDEX)", suffix);
  916.       return GL_TRUE;
  917.    }
  918.    else if (_mesa_is_ycbcr_format(format)
  919.             && !_mesa_is_ycbcr_format(baseFormat)) {
  920.       _mesa_error(ctx, GL_INVALID_OPERATION,
  921.                   "glGetTex%sImage(format mismatch)", suffix);
  922.       return GL_TRUE;
  923.    }
  924.    else if (_mesa_is_depthstencil_format(format)
  925.             && !_mesa_is_depthstencil_format(baseFormat)) {
  926.       _mesa_error(ctx, GL_INVALID_OPERATION,
  927.                   "glGetTex%sImage(format mismatch)", suffix);
  928.       return GL_TRUE;
  929.    }
  930.    else if (!_mesa_is_stencil_format(format) && _mesa_is_enum_format_integer(format) !=
  931.             _mesa_is_format_integer(texImage->TexFormat)) {
  932.       _mesa_error(ctx, GL_INVALID_OPERATION,
  933.                   "glGetTex%sImage(format mismatch)", suffix);
  934.       return GL_TRUE;
  935.    }
  936.  
  937.    if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
  938.                                   texImage->Height, texImage->Depth,
  939.                                   format, type, clientMemSize, pixels)) {
  940.       if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  941.          _mesa_error(ctx, GL_INVALID_OPERATION,
  942.                      "glGetTex%sImage(out of bounds PBO access)", suffix);
  943.       } else {
  944.          _mesa_error(ctx, GL_INVALID_OPERATION,
  945.                      "%s(out of bounds access:"
  946.                      " bufSize (%d) is too small)",
  947.                      dsa ? "glGetTextureImage" : "glGetnTexImageARB",
  948.                      clientMemSize);
  949.       }
  950.       return GL_TRUE;
  951.    }
  952.  
  953.    if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  954.       /* PBO should not be mapped */
  955.       if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
  956.          _mesa_error(ctx, GL_INVALID_OPERATION,
  957.                      "glGetTex%sImage(PBO is mapped)", suffix);
  958.          return GL_TRUE;
  959.       }
  960.    }
  961.  
  962.    return GL_FALSE;
  963. }
  964.  
  965.  
  966. /**
  967.  * This is the implementation for glGetnTexImageARB, glGetTextureImage,
  968.  * and glGetTexImage.
  969.  *
  970.  * Requires caller to pass in texImage object because _mesa_GetTextureImage
  971.  * must handle the GL_TEXTURE_CUBE_MAP target.
  972.  *
  973.  * \param target texture target.
  974.  * \param level image level.
  975.  * \param format pixel data format for returned image.
  976.  * \param type pixel data type for returned image.
  977.  * \param bufSize size of the pixels data buffer.
  978.  * \param pixels returned pixel data.
  979.  * \param dsa True when the caller is an ARB_direct_state_access function,
  980.  *            false otherwise
  981.  */
  982. void
  983. _mesa_get_texture_image(struct gl_context *ctx,
  984.                         struct gl_texture_object *texObj,
  985.                         struct gl_texture_image *texImage, GLenum target,
  986.                         GLint level, GLenum format, GLenum type,
  987.                         GLsizei bufSize, GLvoid *pixels, bool dsa)
  988. {
  989.    assert(texObj);
  990.    assert(texImage);
  991.  
  992.    FLUSH_VERTICES(ctx, 0);
  993.  
  994.    /*
  995.     * Legal target checking has been moved up to GetnTexImage and
  996.     * GetTextureImage so that it can be caught before receiving a NULL
  997.     * texImage object and exiting.
  998.     */
  999.  
  1000.    if (getteximage_error_check(ctx, texImage, target, level, format,
  1001.                                type, bufSize, pixels, dsa)) {
  1002.       return;
  1003.    }
  1004.  
  1005.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
  1006.       /* not an error, do nothing */
  1007.       return;
  1008.    }
  1009.  
  1010.    if (_mesa_is_zero_size_texture(texImage))
  1011.       return;
  1012.  
  1013.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  1014.       _mesa_debug(ctx, "glGetTex%sImage(tex %u) format = %s, w=%d, h=%d,"
  1015.                   " dstFmt=0x%x, dstType=0x%x\n",
  1016.                   dsa ? "ture": "",
  1017.                   texObj->Name,
  1018.                   _mesa_get_format_name(texImage->TexFormat),
  1019.                   texImage->Width, texImage->Height,
  1020.                   format, type);
  1021.    }
  1022.  
  1023.    _mesa_lock_texture(ctx, texObj);
  1024.    {
  1025.       ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage);
  1026.    }
  1027.    _mesa_unlock_texture(ctx, texObj);
  1028. }
  1029.  
  1030. /**
  1031.  * Get texture image.  Called by glGetTexImage.
  1032.  *
  1033.  * \param target texture target.
  1034.  * \param level image level.
  1035.  * \param format pixel data format for returned image.
  1036.  * \param type pixel data type for returned image.
  1037.  * \param bufSize size of the pixels data buffer.
  1038.  * \param pixels returned pixel data.
  1039.  */
  1040. void GLAPIENTRY
  1041. _mesa_GetnTexImageARB(GLenum target, GLint level, GLenum format,
  1042.                       GLenum type, GLsizei bufSize, GLvoid *pixels)
  1043. {
  1044.    struct gl_texture_object *texObj;
  1045.    struct gl_texture_image *texImage;
  1046.    GLenum err;
  1047.    GET_CURRENT_CONTEXT(ctx);
  1048.  
  1049.    /*
  1050.     * This has been moved here because a format/type mismatch can cause a NULL
  1051.     * texImage object, which in turn causes the mismatch error to be
  1052.     * ignored.
  1053.     */
  1054.    err = _mesa_error_check_format_and_type(ctx, format, type);
  1055.    if (err != GL_NO_ERROR) {
  1056.       _mesa_error(ctx, err, "glGetnTexImage(format/type)");
  1057.       return;
  1058.    }
  1059.  
  1060.    /*
  1061.     * Legal target checking has been moved here to prevent exiting with a NULL
  1062.     * texImage object.
  1063.     */
  1064.    if (!legal_getteximage_target(ctx, target, false)) {
  1065.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetnTexImage(target=0x%x)",
  1066.                   target);
  1067.       return;
  1068.    }
  1069.  
  1070.    texObj = _mesa_get_current_tex_object(ctx, target);
  1071.    if (!texObj)
  1072.       return;
  1073.  
  1074.    texImage = _mesa_select_tex_image(texObj, target, level);
  1075.    if (!texImage)
  1076.       return;
  1077.  
  1078.    _mesa_get_texture_image(ctx, texObj, texImage, target, level, format, type,
  1079.                            bufSize, pixels, false);
  1080. }
  1081.  
  1082.  
  1083. void GLAPIENTRY
  1084. _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
  1085.                    GLenum type, GLvoid *pixels )
  1086. {
  1087.    _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels);
  1088. }
  1089.  
  1090. /**
  1091.  * Get texture image.
  1092.  *
  1093.  * \param texture texture name.
  1094.  * \param level image level.
  1095.  * \param format pixel data format for returned image.
  1096.  * \param type pixel data type for returned image.
  1097.  * \param bufSize size of the pixels data buffer.
  1098.  * \param pixels returned pixel data.
  1099.  */
  1100. void GLAPIENTRY
  1101. _mesa_GetTextureImage(GLuint texture, GLint level, GLenum format,
  1102.                       GLenum type, GLsizei bufSize, GLvoid *pixels)
  1103. {
  1104.    struct gl_texture_object *texObj;
  1105.    struct gl_texture_image *texImage;
  1106.    int i;
  1107.    GLint image_stride;
  1108.    GLenum err;
  1109.    GET_CURRENT_CONTEXT(ctx);
  1110.  
  1111.    if (!ctx->Extensions.ARB_direct_state_access) {
  1112.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1113.                   "glGetTextureImage(GL_ARB_direct_state_access "
  1114.                   "is not supported)");
  1115.       return;
  1116.    }
  1117.  
  1118.    /*
  1119.     * This has been moved here because a format/type mismatch can cause a NULL
  1120.     * texImage object, which in turn causes the mismatch error to be
  1121.     * ignored.
  1122.     */
  1123.    err = _mesa_error_check_format_and_type(ctx, format, type);
  1124.    if (err != GL_NO_ERROR) {
  1125.       _mesa_error(ctx, err, "glGetTextureImage(format/type)");
  1126.       return;
  1127.    }
  1128.  
  1129.    texObj = _mesa_lookup_texture_err(ctx, texture, "glGetTextureImage");
  1130.    if (!texObj)
  1131.       return;
  1132.  
  1133.    /*
  1134.     * Legal target checking has been moved here to prevent exiting with a NULL
  1135.     * texImage object.
  1136.     */
  1137.    if (!legal_getteximage_target(ctx, texObj->Target, true)) {
  1138.       _mesa_error(ctx, GL_INVALID_ENUM, "glGetTextureImage(target=%s)",
  1139.                   _mesa_lookup_enum_by_nr(texObj->Target));
  1140.       return;
  1141.    }
  1142.  
  1143.    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
  1144.    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
  1145.  
  1146.       /* Make sure the texture object is a proper cube.
  1147.        * (See texturesubimage in teximage.c for details on why this check is
  1148.        * performed.)
  1149.        */
  1150.       if (!_mesa_cube_level_complete(texObj, level)) {
  1151.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1152.                      "glGetTextureImage(cube map incomplete)");
  1153.          return;
  1154.       }
  1155.  
  1156.       /* Copy each face. */
  1157.       for (i = 0; i < 6; ++i) {
  1158.          texImage = texObj->Image[i][level];
  1159.          assert(texImage);
  1160.  
  1161.          _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level,
  1162.                                  format, type, bufSize, pixels, true);
  1163.  
  1164.          image_stride = _mesa_image_image_stride(&ctx->Pack, texImage->Width,
  1165.                                                  texImage->Height, format,
  1166.                                                  type);
  1167.          pixels = (GLubyte *) pixels + image_stride;
  1168.          bufSize -= image_stride;
  1169.       }
  1170.    }
  1171.    else {
  1172.       texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
  1173.       if (!texImage)
  1174.          return;
  1175.  
  1176.       _mesa_get_texture_image(ctx, texObj, texImage, texObj->Target, level,
  1177.                               format, type, bufSize, pixels, true);
  1178.    }
  1179. }
  1180.  
  1181. /**
  1182.  * Do error checking for a glGetCompressedTexImage() call.
  1183.  * \return GL_TRUE if any error, GL_FALSE if no errors.
  1184.  */
  1185. static GLboolean
  1186. getcompressedteximage_error_check(struct gl_context *ctx,
  1187.                                   struct gl_texture_image *texImage,
  1188.                                   GLenum target,
  1189.                                   GLint level, GLsizei clientMemSize,
  1190.                                   GLvoid *img, bool dsa)
  1191. {
  1192.    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
  1193.    GLuint compressedSize, dimensions;
  1194.    const char *suffix = dsa ? "ture" : "";
  1195.  
  1196.    assert(texImage);
  1197.  
  1198.    if (!legal_getteximage_target(ctx, target, dsa)) {
  1199.       _mesa_error(ctx, GL_INVALID_ENUM,
  1200.                   "glGetCompressedTex%sImage(target=%s)", suffix,
  1201.                   _mesa_lookup_enum_by_nr(target));
  1202.       return GL_TRUE;
  1203.    }
  1204.  
  1205.    assert(maxLevels != 0);
  1206.    if (level < 0 || level >= maxLevels) {
  1207.       _mesa_error(ctx, GL_INVALID_VALUE,
  1208.                   "glGetCompressedTex%sImage(bad level = %d)", suffix, level);
  1209.       return GL_TRUE;
  1210.    }
  1211.  
  1212.    if (!_mesa_is_format_compressed(texImage->TexFormat)) {
  1213.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1214.                   "glGetCompressedTex%sImage(texture is not compressed)",
  1215.                   suffix);
  1216.       return GL_TRUE;
  1217.    }
  1218.  
  1219.    compressedSize = _mesa_format_image_size(texImage->TexFormat,
  1220.                                             texImage->Width,
  1221.                                             texImage->Height,
  1222.                                             texImage->Depth);
  1223.  
  1224.    /* Check for invalid pixel storage modes */
  1225.    dimensions = _mesa_get_texture_dimensions(texImage->TexObject->Target);
  1226.    if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
  1227.                                               &ctx->Pack, dsa ?
  1228.                                               "glGetCompressedTextureImage":
  1229.                                               "glGetCompressedTexImage")) {
  1230.       return GL_TRUE;
  1231.    }
  1232.  
  1233.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
  1234.       /* do bounds checking on writing to client memory */
  1235.       if (clientMemSize < (GLsizei) compressedSize) {
  1236.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1237.                      "%s(out of bounds access: bufSize (%d) is too small)",
  1238.                      dsa ? "glGetCompressedTextureImage" :
  1239.                      "glGetnCompressedTexImageARB", clientMemSize);
  1240.          return GL_TRUE;
  1241.       }
  1242.    } else {
  1243.       /* do bounds checking on PBO write */
  1244.       if ((const GLubyte *) img + compressedSize >
  1245.           (const GLubyte *) ctx->Pack.BufferObj->Size) {
  1246.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1247.                      "glGetCompressedTex%sImage(out of bounds PBO access)",
  1248.                      suffix);
  1249.          return GL_TRUE;
  1250.       }
  1251.  
  1252.       /* make sure PBO is not mapped */
  1253.       if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
  1254.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1255.                      "glGetCompressedTex%sImage(PBO is mapped)", suffix);
  1256.          return GL_TRUE;
  1257.       }
  1258.    }
  1259.  
  1260.    return GL_FALSE;
  1261. }
  1262.  
  1263. /** Implements glGetnCompressedTexImageARB, glGetCompressedTexImage, and
  1264.  * glGetCompressedTextureImage.
  1265.  *
  1266.  * texImage must be passed in because glGetCompressedTexImage must handle the
  1267.  * target GL_TEXTURE_CUBE_MAP.
  1268.  */
  1269. void
  1270. _mesa_get_compressed_texture_image(struct gl_context *ctx,
  1271.                                    struct gl_texture_object *texObj,
  1272.                                    struct gl_texture_image *texImage,
  1273.                                    GLenum target, GLint level,
  1274.                                    GLsizei bufSize, GLvoid *pixels,
  1275.                                    bool dsa)
  1276. {
  1277.    assert(texObj);
  1278.    assert(texImage);
  1279.  
  1280.    FLUSH_VERTICES(ctx, 0);
  1281.  
  1282.    if (getcompressedteximage_error_check(ctx, texImage, target, level,
  1283.                                          bufSize, pixels, dsa)) {
  1284.       return;
  1285.    }
  1286.  
  1287.    if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
  1288.       /* not an error, do nothing */
  1289.       return;
  1290.    }
  1291.  
  1292.    if (_mesa_is_zero_size_texture(texImage))
  1293.       return;
  1294.  
  1295.    if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
  1296.       _mesa_debug(ctx,
  1297.                   "glGetCompressedTex%sImage(tex %u) format = %s, w=%d, h=%d\n",
  1298.                   dsa ? "ture" : "", texObj->Name,
  1299.                   _mesa_get_format_name(texImage->TexFormat),
  1300.                   texImage->Width, texImage->Height);
  1301.    }
  1302.  
  1303.    _mesa_lock_texture(ctx, texObj);
  1304.    {
  1305.       ctx->Driver.GetCompressedTexImage(ctx, texImage, pixels);
  1306.    }
  1307.    _mesa_unlock_texture(ctx, texObj);
  1308. }
  1309.  
  1310. void GLAPIENTRY
  1311. _mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize,
  1312.                                 GLvoid *img)
  1313. {
  1314.    struct gl_texture_object *texObj;
  1315.    struct gl_texture_image *texImage;
  1316.    GET_CURRENT_CONTEXT(ctx);
  1317.  
  1318.    texObj = _mesa_get_current_tex_object(ctx, target);
  1319.    if (!texObj)
  1320.       return;
  1321.  
  1322.    texImage = _mesa_select_tex_image(texObj, target, level);
  1323.    if (!texImage)
  1324.       return;
  1325.  
  1326.    _mesa_get_compressed_texture_image(ctx, texObj, texImage, target, level,
  1327.                                       bufSize, img, false);
  1328. }
  1329.  
  1330. void GLAPIENTRY
  1331. _mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *img)
  1332. {
  1333.    _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img);
  1334. }
  1335.  
  1336. /**
  1337.  * Get compressed texture image.
  1338.  *
  1339.  * \param texture texture name.
  1340.  * \param level image level.
  1341.  * \param bufSize size of the pixels data buffer.
  1342.  * \param pixels returned pixel data.
  1343.  */
  1344. void GLAPIENTRY
  1345. _mesa_GetCompressedTextureImage(GLuint texture, GLint level,
  1346.                                 GLsizei bufSize, GLvoid *pixels)
  1347. {
  1348.    struct gl_texture_object *texObj;
  1349.    struct gl_texture_image *texImage;
  1350.    int i;
  1351.    GLint image_stride;
  1352.    GET_CURRENT_CONTEXT(ctx);
  1353.  
  1354.    if (!ctx->Extensions.ARB_direct_state_access) {
  1355.       _mesa_error(ctx, GL_INVALID_OPERATION,
  1356.                   "glGetCompressedTextureImage(GL_ARB_direct_state_access "
  1357.                   "is not supported)");
  1358.       return;
  1359.    }
  1360.  
  1361.    texObj = _mesa_lookup_texture_err(ctx, texture,
  1362.                                      "glGetCompressedTextureImage");
  1363.    if (!texObj)
  1364.       return;
  1365.  
  1366.    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
  1367.    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
  1368.  
  1369.       /* Make sure the texture object is a proper cube.
  1370.        * (See texturesubimage in teximage.c for details on why this check is
  1371.        * performed.)
  1372.        */
  1373.       if (!_mesa_cube_level_complete(texObj, level)) {
  1374.          _mesa_error(ctx, GL_INVALID_OPERATION,
  1375.                      "glGetCompressedTextureImage(cube map incomplete)");
  1376.          return;
  1377.       }
  1378.  
  1379.       /* Copy each face. */
  1380.       for (i = 0; i < 6; ++i) {
  1381.          texImage = texObj->Image[i][level];
  1382.          assert(texImage);
  1383.  
  1384.          _mesa_get_compressed_texture_image(ctx, texObj, texImage,
  1385.                                             texObj->Target, level,
  1386.                                             bufSize, pixels, true);
  1387.  
  1388.          /* Compressed images don't have a client format */
  1389.          image_stride = _mesa_format_image_size(texImage->TexFormat,
  1390.                                                 texImage->Width,
  1391.                                                 texImage->Height, 1);
  1392.  
  1393.          pixels = (GLubyte *) pixels + image_stride;
  1394.          bufSize -= image_stride;
  1395.       }
  1396.    }
  1397.    else {
  1398.       texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
  1399.       if (!texImage)
  1400.          return;
  1401.  
  1402.       _mesa_get_compressed_texture_image(ctx, texObj, texImage,
  1403.                                          texObj->Target, level, bufSize,
  1404.                                          pixels, true);
  1405.    }
  1406. }
  1407.