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