[MSHTML_WINETEST]
[reactos.git] / reactos / dll / opengl / mesa / main / texgetimage.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.7
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (c) 2009 VMware, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * Code for glGetTexImage() and glGetCompressedTexImage().
29 */
30
31
32 #include "glheader.h"
33 #include "bufferobj.h"
34 #include "enums.h"
35 #include "context.h"
36 #include "formats.h"
37 #include "format_unpack.h"
38 #include "image.h"
39 #include "mfeatures.h"
40 #include "mtypes.h"
41 #include "pack.h"
42 #include "pbo.h"
43 #include "texgetimage.h"
44 #include "teximage.h"
45
46
47
48 /**
49 * Can the given type represent negative values?
50 */
51 static inline GLboolean
52 type_needs_clamping(GLenum type)
53 {
54 switch (type) {
55 case GL_BYTE:
56 case GL_SHORT:
57 case GL_INT:
58 case GL_FLOAT:
59 case GL_HALF_FLOAT_ARB:
60 case GL_UNSIGNED_INT_10F_11F_11F_REV:
61 case GL_UNSIGNED_INT_5_9_9_9_REV:
62 return GL_FALSE;
63 default:
64 return GL_TRUE;
65 }
66 }
67
68
69 /**
70 * glGetTexImage for depth/Z pixels.
71 */
72 static void
73 get_tex_depth(struct gl_context *ctx, GLuint dimensions,
74 GLenum format, GLenum type, GLvoid *pixels,
75 struct gl_texture_image *texImage)
76 {
77 const GLint width = texImage->Width;
78 const GLint height = texImage->Height;
79 const GLint depth = texImage->Depth;
80 GLint img, row;
81 GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat));
82
83 if (!depthRow) {
84 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
85 return;
86 }
87
88 for (img = 0; img < depth; img++) {
89 GLubyte *srcMap;
90 GLint srcRowStride;
91
92 /* map src texture buffer */
93 ctx->Driver.MapTextureImage(ctx, texImage, img,
94 0, 0, width, height, GL_MAP_READ_BIT,
95 &srcMap, &srcRowStride);
96
97 if (srcMap) {
98 for (row = 0; row < height; row++) {
99 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
100 width, height, format, type,
101 img, row, 0);
102 const GLubyte *src = srcMap + row * srcRowStride;
103 _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow);
104 _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack);
105 }
106
107 ctx->Driver.UnmapTextureImage(ctx, texImage, img);
108 }
109 else {
110 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
111 break;
112 }
113 }
114
115 free(depthRow);
116 }
117
118 /**
119 * glGetTexImage for YCbCr pixels.
120 */
121 static void
122 get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions,
123 GLenum format, GLenum type, GLvoid *pixels,
124 struct gl_texture_image *texImage)
125 {
126 const GLint width = texImage->Width;
127 const GLint height = texImage->Height;
128 const GLint depth = texImage->Depth;
129 GLint img, row;
130
131 for (img = 0; img < depth; img++) {
132 GLubyte *srcMap;
133 GLint rowstride;
134
135 /* map src texture buffer */
136 ctx->Driver.MapTextureImage(ctx, texImage, img,
137 0, 0, width, height, GL_MAP_READ_BIT,
138 &srcMap, &rowstride);
139
140 if (srcMap) {
141 for (row = 0; row < height; row++) {
142 const GLubyte *src = srcMap + row * rowstride;
143 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
144 width, height, format, type,
145 img, row, 0);
146 memcpy(dest, src, width * sizeof(GLushort));
147
148 /* check for byte swapping */
149 if ((texImage->TexFormat == MESA_FORMAT_YCBCR
150 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
151 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
152 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
153 if (!ctx->Pack.SwapBytes)
154 _mesa_swap2((GLushort *) dest, width);
155 }
156 else if (ctx->Pack.SwapBytes) {
157 _mesa_swap2((GLushort *) dest, width);
158 }
159 }
160
161 ctx->Driver.UnmapTextureImage(ctx, texImage, img);
162 }
163 else {
164 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
165 break;
166 }
167 }
168 }
169
170 /**
171 * Get an uncompressed color texture image.
172 */
173 static void
174 get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions,
175 GLenum format, GLenum type, GLvoid *pixels,
176 struct gl_texture_image *texImage,
177 GLbitfield transferOps)
178 {
179 const gl_format texFormat = texImage->TexFormat;
180 const GLuint width = texImage->Width;
181 const GLenum destBaseFormat = _mesa_base_tex_format(ctx, format);
182 GLenum rebaseFormat = GL_NONE;
183 GLuint height = texImage->Height;
184 GLuint depth = texImage->Depth;
185 GLuint img, row;
186 GLfloat (*rgba)[4];
187 GLuint (*rgba_uint)[4];
188 GLboolean is_integer = _mesa_is_format_integer_color(texImage->TexFormat);
189
190 /* Allocate buffer for one row of texels */
191 rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
192 rgba_uint = (GLuint (*)[4]) rgba;
193 if (!rgba) {
194 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()");
195 return;
196 }
197
198 if (texImage->_BaseFormat == GL_LUMINANCE ||
199 texImage->_BaseFormat == GL_INTENSITY ||
200 texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
201 /* If a luminance (or intensity) texture is read back as RGB(A), the
202 * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat
203 * here to get G=B=0.
204 */
205 rebaseFormat = texImage->_BaseFormat;
206 }
207 else if ((texImage->_BaseFormat == GL_RGBA ||
208 texImage->_BaseFormat == GL_RGB) &&
209 (destBaseFormat == GL_LUMINANCE ||
210 destBaseFormat == GL_LUMINANCE_ALPHA ||
211 destBaseFormat == GL_LUMINANCE_INTEGER_EXT ||
212 destBaseFormat == GL_LUMINANCE_ALPHA_INTEGER_EXT)) {
213 /* If we're reading back an RGB(A) texture as luminance then we need
214 * to return L=tex(R). Note, that's different from glReadPixels which
215 * returns L=R+G+B.
216 */
217 rebaseFormat = GL_LUMINANCE_ALPHA; /* this covers GL_LUMINANCE too */
218 }
219
220 for (img = 0; img < depth; img++) {
221 GLubyte *srcMap;
222 GLint rowstride;
223
224 /* map src texture buffer */
225 ctx->Driver.MapTextureImage(ctx, texImage, img,
226 0, 0, width, height, GL_MAP_READ_BIT,
227 &srcMap, &rowstride);
228 if (srcMap) {
229 for (row = 0; row < height; row++) {
230 const GLubyte *src = srcMap + row * rowstride;
231 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels,
232 width, height, format, type,
233 img, row, 0);
234
235 if (is_integer) {
236 _mesa_unpack_uint_rgba_row(texFormat, width, src, rgba_uint);
237 if (rebaseFormat)
238 _mesa_rebase_rgba_uint(width, rgba_uint, rebaseFormat);
239 _mesa_pack_rgba_span_int(ctx, width, rgba_uint,
240 format, type, dest);
241 } else {
242 _mesa_unpack_rgba_row(texFormat, width, src, rgba);
243 if (rebaseFormat)
244 _mesa_rebase_rgba_float(width, rgba, rebaseFormat);
245 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
246 format, type, dest,
247 &ctx->Pack, transferOps);
248 }
249 }
250
251 /* Unmap the src texture buffer */
252 ctx->Driver.UnmapTextureImage(ctx, texImage, img);
253 }
254 else {
255 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
256 break;
257 }
258 }
259
260 free(rgba);
261 }
262
263
264 /**
265 * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
266 * Compressed textures are handled here as well.
267 */
268 static void
269 get_tex_rgba(struct gl_context *ctx, GLuint dimensions,
270 GLenum format, GLenum type, GLvoid *pixels,
271 struct gl_texture_image *texImage)
272 {
273 const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat);
274 GLbitfield transferOps = 0x0;
275
276 /* In general, clamping does not apply to glGetTexImage, except when
277 * the returned type of the image can't hold negative values.
278 */
279 if (type_needs_clamping(type)) {
280 /* the returned image type can't have negative values */
281 if (dataType == GL_FLOAT ||
282 dataType == GL_SIGNED_NORMALIZED ||
283 format == GL_LUMINANCE ||
284 format == GL_LUMINANCE_ALPHA) {
285 transferOps |= IMAGE_CLAMP_BIT;
286 }
287 }
288 /* This applies to RGB, RGBA textures. if the format is either LUMINANCE
289 * or LUMINANCE ALPHA, luminance (L) is computed as L=R+G+B .we need to
290 * clamp the sum to [0,1].
291 */
292 else if ((format == GL_LUMINANCE ||
293 format == GL_LUMINANCE_ALPHA) &&
294 dataType == GL_UNSIGNED_NORMALIZED) {
295 transferOps |= IMAGE_CLAMP_BIT;
296 }
297 get_tex_rgba_uncompressed(ctx, dimensions, format, type,
298 pixels, texImage, transferOps);
299 }
300
301
302 /**
303 * Try to do glGetTexImage() with simple memcpy().
304 * \return GL_TRUE if done, GL_FALSE otherwise
305 */
306 static GLboolean
307 get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type,
308 GLvoid *pixels,
309 struct gl_texture_image *texImage)
310 {
311 const GLenum target = texImage->TexObject->Target;
312 GLboolean memCopy = GL_FALSE;
313
314 /*
315 * Check if the src/dst formats are compatible.
316 * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
317 * so we don't have to worry about those.
318 * XXX more format combinations could be supported here.
319 */
320 if (target == GL_TEXTURE_1D ||
321 target == GL_TEXTURE_2D ||
322 _mesa_is_cube_face(target)) {
323 if ((texImage->TexFormat == MESA_FORMAT_ARGB8888) &&
324 format == GL_BGRA &&
325 (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) &&
326 !ctx->Pack.SwapBytes &&
327 _mesa_little_endian()) {
328 memCopy = GL_TRUE;
329 }
330 else if ((texImage->TexFormat == MESA_FORMAT_AL88) &&
331 format == GL_LUMINANCE_ALPHA &&
332 type == GL_UNSIGNED_BYTE &&
333 !ctx->Pack.SwapBytes &&
334 _mesa_little_endian()) {
335 memCopy = GL_TRUE;
336 }
337 else if ((texImage->TexFormat == MESA_FORMAT_L8) &&
338 format == GL_LUMINANCE &&
339 type == GL_UNSIGNED_BYTE) {
340 memCopy = GL_TRUE;
341 }
342 else if (texImage->TexFormat == MESA_FORMAT_L16 &&
343 format == GL_LUMINANCE &&
344 type == GL_UNSIGNED_SHORT) {
345 memCopy = GL_TRUE;
346 }
347 else if (texImage->TexFormat == MESA_FORMAT_A8 &&
348 format == GL_ALPHA &&
349 type == GL_UNSIGNED_BYTE) {
350 memCopy = GL_TRUE;
351 }
352 else if (texImage->TexFormat == MESA_FORMAT_A16 &&
353 format == GL_ALPHA &&
354 type == GL_UNSIGNED_SHORT) {
355 memCopy = GL_TRUE;
356 }
357 }
358
359 if (memCopy) {
360 const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
361 const GLuint bytesPerRow = texImage->Width * bpp;
362 GLubyte *dst =
363 _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
364 texImage->Height, format, type, 0, 0);
365 const GLint dstRowStride =
366 _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
367 GLubyte *src;
368 GLint srcRowStride;
369
370 /* map src texture buffer */
371 ctx->Driver.MapTextureImage(ctx, texImage, 0,
372 0, 0, texImage->Width, texImage->Height,
373 GL_MAP_READ_BIT, &src, &srcRowStride);
374
375 if (src) {
376 if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) {
377 memcpy(dst, src, bytesPerRow * texImage->Height);
378 }
379 else {
380 GLuint row;
381 for (row = 0; row < texImage->Height; row++) {
382 memcpy(dst, src, bytesPerRow);
383 dst += dstRowStride;
384 src += srcRowStride;
385 }
386 }
387
388 /* unmap src texture buffer */
389 ctx->Driver.UnmapTextureImage(ctx, texImage, 0);
390 }
391 else {
392 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
393 }
394 }
395
396 return memCopy;
397 }
398
399
400 /**
401 * This is the software fallback for Driver.GetTexImage().
402 * All error checking will have been done before this routine is called.
403 * We'll call ctx->Driver.MapTextureImage() to access the data, then
404 * unmap with ctx->Driver.UnmapTextureImage().
405 */
406 void
407 _mesa_get_teximage(struct gl_context *ctx,
408 GLenum format, GLenum type, GLvoid *pixels,
409 struct gl_texture_image *texImage)
410 {
411 GLuint dimensions;
412
413 switch (texImage->TexObject->Target) {
414 case GL_TEXTURE_1D:
415 dimensions = 1;
416 break;
417 case GL_TEXTURE_3D:
418 dimensions = 3;
419 break;
420 default:
421 dimensions = 2;
422 }
423
424 /* map dest buffer, if PBO */
425 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
426 /* Packing texture image into a PBO.
427 * Map the (potentially) VRAM-based buffer into our process space so
428 * we can write into it with the code below.
429 * A hardware driver might use a sophisticated blit to move the
430 * texture data to the PBO if the PBO is in VRAM along with the texture.
431 */
432 GLubyte *buf = (GLubyte *)
433 ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size,
434 GL_MAP_WRITE_BIT, ctx->Pack.BufferObj);
435 if (!buf) {
436 /* out of memory or other unexpected error */
437 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
438 return;
439 }
440 /* <pixels> was an offset into the PBO.
441 * Now make it a real, client-side pointer inside the mapped region.
442 */
443 pixels = ADD_POINTERS(buf, pixels);
444 }
445
446 if (get_tex_memcpy(ctx, format, type, pixels, texImage)) {
447 /* all done */
448 }
449 else if (format == GL_DEPTH_COMPONENT) {
450 get_tex_depth(ctx, dimensions, format, type, pixels, texImage);
451 }
452 else if (format == GL_YCBCR_MESA) {
453 get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage);
454 }
455 else {
456 get_tex_rgba(ctx, dimensions, format, type, pixels, texImage);
457 }
458
459 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
460 ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj);
461 }
462 }
463
464 /**
465 * Do error checking for a glGetTexImage() call.
466 * \return GL_TRUE if any error, GL_FALSE if no errors.
467 */
468 static GLboolean
469 getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level,
470 GLenum format, GLenum type, GLsizei clientMemSize,
471 GLvoid *pixels )
472 {
473 struct gl_texture_object *texObj;
474 struct gl_texture_image *texImage;
475 const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
476 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
477 GLenum baseFormat, err;
478
479 if (maxLevels == 0) {
480 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
481 return GL_TRUE;
482 }
483
484 if (level < 0 || level >= maxLevels) {
485 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
486 return GL_TRUE;
487 }
488
489 if (_mesa_sizeof_packed_type(type) <= 0) {
490 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
491 return GL_TRUE;
492 }
493
494 if (_mesa_components_in_format(format) <= 0 ||
495 format == GL_STENCIL_INDEX ||
496 format == GL_COLOR_INDEX) {
497 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
498 return GL_TRUE;
499 }
500
501 if (_mesa_is_depth_format(format)) {
502 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
503 return GL_TRUE;
504 }
505
506 if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
507 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
508 return GL_TRUE;
509 }
510
511 err = _mesa_error_check_format_and_type(ctx, format, type);
512 if (err != GL_NO_ERROR) {
513 _mesa_error(ctx, err, "glGetTexImage(format/type)");
514 return GL_TRUE;
515 }
516
517 texObj = _mesa_select_tex_object(ctx, target);
518
519 if (!texObj || _mesa_is_proxy_texture(target)) {
520 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
521 return GL_TRUE;
522 }
523
524 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
525 if (!texImage) {
526 /* non-existant texture image */
527 return GL_TRUE;
528 }
529
530 baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
531
532 /* Make sure the requested image format is compatible with the
533 * texture's format.
534 */
535 if (_mesa_is_color_format(format)
536 && !_mesa_is_color_format(baseFormat)) {
537 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
538 return GL_TRUE;
539 }
540 else if (_mesa_is_depth_format(format)
541 && !_mesa_is_depth_format(baseFormat)) {
542 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
543 return GL_TRUE;
544 }
545 else if (_mesa_is_ycbcr_format(format)
546 && !_mesa_is_ycbcr_format(baseFormat)) {
547 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
548 return GL_TRUE;
549 }
550
551 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
552 texImage->Height, texImage->Depth,
553 format, type, clientMemSize, pixels)) {
554 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
555 _mesa_error(ctx, GL_INVALID_OPERATION,
556 "glGetTexImage(out of bounds PBO access)");
557 } else {
558 _mesa_error(ctx, GL_INVALID_OPERATION,
559 "glGetnTexImageARB(out of bounds access:"
560 " bufSize (%d) is too small)", clientMemSize);
561 }
562 return GL_TRUE;
563 }
564
565 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
566 /* PBO should not be mapped */
567 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
568 _mesa_error(ctx, GL_INVALID_OPERATION,
569 "glGetTexImage(PBO is mapped)");
570 return GL_TRUE;
571 }
572 }
573
574 return GL_FALSE;
575 }
576
577
578
579 /**
580 * Get texture image. Called by glGetTexImage.
581 *
582 * \param target texture target.
583 * \param level image level.
584 * \param format pixel data format for returned image.
585 * \param type pixel data type for returned image.
586 * \param bufSize size of the pixels data buffer.
587 * \param pixels returned pixel data.
588 */
589 void GLAPIENTRY
590 _mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format,
591 GLenum type, GLsizei bufSize, GLvoid *pixels )
592 {
593 struct gl_texture_object *texObj;
594 struct gl_texture_image *texImage;
595 GET_CURRENT_CONTEXT(ctx);
596 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
597
598 if (getteximage_error_check(ctx, target, level, format, type,
599 bufSize, pixels)) {
600 return;
601 }
602
603 if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
604 /* not an error, do nothing */
605 return;
606 }
607
608 texObj = _mesa_select_tex_object(ctx, target);
609 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
610
611 if (_mesa_is_zero_size_texture(texImage))
612 return;
613
614 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
615 _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
616 " dstFmt=0x%x, dstType=0x%x\n",
617 texObj->Name,
618 _mesa_get_format_name(texImage->TexFormat),
619 texImage->Width, texImage->Height,
620 format, type);
621 }
622
623 _mesa_lock_texture(ctx, texObj);
624 {
625 ctx->Driver.GetTexImage(ctx, format, type, pixels, texImage);
626 }
627 _mesa_unlock_texture(ctx, texObj);
628 }
629
630
631 void GLAPIENTRY
632 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
633 GLenum type, GLvoid *pixels )
634 {
635 _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels);
636 }