fbd61d5ae6d4af1caf10b7f309f1ecc8671d64bf
[mesa.git] / src / 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 "image.h"
38 #include "texcompress.h"
39 #include "texgetimage.h"
40 #include "teximage.h"
41 #include "texstate.h"
42
43
44
45 #if FEATURE_EXT_texture_sRGB
46
47 /**
48 * Convert a float value from linear space to a
49 * non-linear sRGB value in [0, 255].
50 * Not terribly efficient.
51 */
52 static INLINE GLfloat
53 linear_to_nonlinear(GLfloat cl)
54 {
55 /* can't have values outside [0, 1] */
56 GLfloat cs;
57 if (cl < 0.0031308f) {
58 cs = 12.92f * cl;
59 }
60 else {
61 cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055);
62 }
63 return cs;
64 }
65
66 #endif /* FEATURE_EXT_texture_sRGB */
67
68
69 /**
70 * Can the given type represent negative values?
71 */
72 static INLINE GLboolean
73 type_with_negative_values(GLenum type)
74 {
75 switch (type) {
76 case GL_BYTE:
77 case GL_SHORT:
78 case GL_INT:
79 case GL_FLOAT:
80 case GL_HALF_FLOAT_ARB:
81 return GL_TRUE;
82 default:
83 return GL_FALSE;
84 }
85 }
86
87
88 /**
89 * This is the software fallback for Driver.GetTexImage().
90 * All error checking will have been done before this routine is called.
91 */
92 void
93 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
94 GLenum format, GLenum type, GLvoid *pixels,
95 struct gl_texture_object *texObj,
96 struct gl_texture_image *texImage)
97 {
98 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
99
100 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
101 /* Packing texture image into a PBO.
102 * Map the (potentially) VRAM-based buffer into our process space so
103 * we can write into it with the code below.
104 * A hardware driver might use a sophisticated blit to move the
105 * texture data to the PBO if the PBO is in VRAM along with the texture.
106 */
107 GLubyte *buf = (GLubyte *)
108 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
109 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
110 if (!buf) {
111 /* out of memory or other unexpected error */
112 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
113 return;
114 }
115 /* <pixels> was an offset into the PBO.
116 * Now make it a real, client-side pointer inside the mapped region.
117 */
118 pixels = ADD_POINTERS(buf, pixels);
119 }
120
121 {
122 const GLint width = texImage->Width;
123 const GLint height = texImage->Height;
124 const GLint depth = texImage->Depth;
125 GLint img, row;
126 for (img = 0; img < depth; img++) {
127 for (row = 0; row < height; row++) {
128 /* compute destination address in client memory */
129 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
130 width, height, format, type,
131 img, row, 0);
132 assert(dest);
133
134 if (format == GL_COLOR_INDEX) {
135 GLuint indexRow[MAX_WIDTH];
136 GLint col;
137 GLuint indexBits = _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT);
138 /* Can't use FetchTexel here because that returns RGBA */
139 if (indexBits == 8) {
140 const GLubyte *src = (const GLubyte *) texImage->Data;
141 src += width * (img * texImage->Height + row);
142 for (col = 0; col < width; col++) {
143 indexRow[col] = src[col];
144 }
145 }
146 else if (indexBits == 16) {
147 const GLushort *src = (const GLushort *) texImage->Data;
148 src += width * (img * texImage->Height + row);
149 for (col = 0; col < width; col++) {
150 indexRow[col] = src[col];
151 }
152 }
153 else {
154 _mesa_problem(ctx,
155 "Color index problem in _mesa_GetTexImage");
156 }
157 _mesa_pack_index_span(ctx, width, type, dest,
158 indexRow, &ctx->Pack,
159 0 /* no image transfer */);
160 }
161 else if (format == GL_DEPTH_COMPONENT) {
162 GLfloat depthRow[MAX_WIDTH];
163 GLint col;
164 for (col = 0; col < width; col++) {
165 (*texImage->FetchTexelf)(texImage, col, row, img,
166 depthRow + col);
167 }
168 _mesa_pack_depth_span(ctx, width, dest, type,
169 depthRow, &ctx->Pack);
170 }
171 else if (format == GL_DEPTH_STENCIL_EXT) {
172 /* XXX Note: we're bypassing texImage->FetchTexel()! */
173 const GLuint *src = (const GLuint *) texImage->Data;
174 src += width * row + width * height * img;
175 _mesa_memcpy(dest, src, width * sizeof(GLuint));
176 if (ctx->Pack.SwapBytes) {
177 _mesa_swap4((GLuint *) dest, width);
178 }
179 }
180 else if (format == GL_YCBCR_MESA) {
181 /* No pixel transfer */
182 const GLint rowstride = texImage->RowStride;
183 MEMCPY(dest,
184 (const GLushort *) texImage->Data + row * rowstride,
185 width * sizeof(GLushort));
186 /* check for byte swapping */
187 if ((texImage->TexFormat == MESA_FORMAT_YCBCR
188 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
189 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV
190 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
191 if (!ctx->Pack.SwapBytes)
192 _mesa_swap2((GLushort *) dest, width);
193 }
194 else if (ctx->Pack.SwapBytes) {
195 _mesa_swap2((GLushort *) dest, width);
196 }
197 }
198 #if FEATURE_EXT_texture_sRGB
199 else if (_mesa_get_format_color_encoding(texImage->TexFormat)
200 == GL_SRGB) {
201 /* special case this since need to backconvert values */
202 /* convert row to RGBA format */
203 GLfloat rgba[MAX_WIDTH][4];
204 GLint col;
205 GLbitfield transferOps = 0x0;
206
207 for (col = 0; col < width; col++) {
208 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
209 if (texImage->_BaseFormat == GL_LUMINANCE) {
210 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
211 rgba[col][GCOMP] = 0.0;
212 rgba[col][BCOMP] = 0.0;
213 }
214 else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
215 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
216 rgba[col][GCOMP] = 0.0;
217 rgba[col][BCOMP] = 0.0;
218 }
219 else if (texImage->_BaseFormat == GL_RGB ||
220 texImage->_BaseFormat == GL_RGBA) {
221 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]);
222 rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]);
223 rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]);
224 }
225 }
226 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
227 format, type, dest,
228 &ctx->Pack, transferOps);
229 }
230 #endif /* FEATURE_EXT_texture_sRGB */
231 else {
232 /* general case: convert row to RGBA format */
233 GLfloat rgba[MAX_WIDTH][4];
234 GLint col;
235 GLbitfield transferOps = 0x0;
236 GLenum dataType =
237 _mesa_get_format_datatype(texImage->TexFormat);
238
239 /* clamp does not apply to GetTexImage (final conversion)?
240 * Looks like we need clamp though when going from format
241 * containing negative values to unsigned format.
242 */
243 if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA)
244 transferOps |= IMAGE_CLAMP_BIT;
245 else if (!type_with_negative_values(type) &&
246 (dataType == GL_FLOAT ||
247 dataType == GL_SIGNED_NORMALIZED))
248 transferOps |= IMAGE_CLAMP_BIT;
249
250 for (col = 0; col < width; col++) {
251 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
252 if (texImage->_BaseFormat == GL_ALPHA) {
253 rgba[col][RCOMP] = 0.0;
254 rgba[col][GCOMP] = 0.0;
255 rgba[col][BCOMP] = 0.0;
256 }
257 else if (texImage->_BaseFormat == GL_LUMINANCE) {
258 rgba[col][GCOMP] = 0.0;
259 rgba[col][BCOMP] = 0.0;
260 rgba[col][ACOMP] = 1.0;
261 }
262 else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
263 rgba[col][GCOMP] = 0.0;
264 rgba[col][BCOMP] = 0.0;
265 }
266 else if (texImage->_BaseFormat == GL_INTENSITY) {
267 rgba[col][GCOMP] = 0.0;
268 rgba[col][BCOMP] = 0.0;
269 rgba[col][ACOMP] = 1.0;
270 }
271 }
272 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba,
273 format, type, dest,
274 &ctx->Pack, transferOps);
275 } /* format */
276 } /* row */
277 } /* img */
278 }
279
280 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
281 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
282 ctx->Pack.BufferObj);
283 }
284 }
285
286
287
288 /**
289 * This is the software fallback for Driver.GetCompressedTexImage().
290 * All error checking will have been done before this routine is called.
291 */
292 void
293 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
294 GLvoid *img,
295 struct gl_texture_object *texObj,
296 struct gl_texture_image *texImage)
297 {
298 const GLuint size = _mesa_format_image_size(texImage->TexFormat,
299 texImage->Width,
300 texImage->Height,
301 texImage->Depth);
302
303 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
304 /* pack texture image into a PBO */
305 GLubyte *buf = (GLubyte *)
306 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
307 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj);
308 if (!buf) {
309 /* out of memory or other unexpected error */
310 _mesa_error(ctx, GL_OUT_OF_MEMORY,
311 "glGetCompresssedTexImage(map PBO failed)");
312 return;
313 }
314 img = ADD_POINTERS(buf, img);
315 }
316
317 /* just memcpy, no pixelstore or pixel transfer */
318 _mesa_memcpy(img, texImage->Data, size);
319
320 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
321 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
322 ctx->Pack.BufferObj);
323 }
324 }
325
326
327
328 /**
329 * Do error checking for a glGetTexImage() call.
330 * \return GL_TRUE if any error, GL_FALSE if no errors.
331 */
332 static GLboolean
333 getteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
334 GLenum format, GLenum type, GLvoid *pixels )
335 {
336 const struct gl_texture_unit *texUnit;
337 struct gl_texture_object *texObj;
338 struct gl_texture_image *texImage;
339 const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
340 GLenum baseFormat;
341
342 if (maxLevels == 0) {
343 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target);
344 return GL_TRUE;
345 }
346
347 if (level < 0 || level >= maxLevels) {
348 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
349 return GL_TRUE;
350 }
351
352 if (_mesa_sizeof_packed_type(type) <= 0) {
353 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
354 return GL_TRUE;
355 }
356
357 if (_mesa_components_in_format(format) <= 0 ||
358 format == GL_STENCIL_INDEX) {
359 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
360 return GL_TRUE;
361 }
362
363 if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) {
364 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
365 return GL_TRUE;
366 }
367
368 if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) {
369 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
370 return GL_TRUE;
371 }
372
373 if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) {
374 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
375 return GL_TRUE;
376 }
377
378 if (!ctx->Extensions.EXT_packed_depth_stencil
379 && _mesa_is_depthstencil_format(format)) {
380 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
381 return GL_TRUE;
382 }
383
384 if (!ctx->Extensions.ATI_envmap_bumpmap
385 && _mesa_is_dudv_format(format)) {
386 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
387 return GL_TRUE;
388 }
389
390 texUnit = _mesa_get_current_tex_unit(ctx);
391 texObj = _mesa_select_tex_object(ctx, texUnit, target);
392
393 if (!texObj || _mesa_is_proxy_texture(target)) {
394 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
395 return GL_TRUE;
396 }
397
398 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
399 if (!texImage) {
400 /* out of memory */
401 return GL_TRUE;
402 }
403
404 baseFormat = _mesa_get_format_base_format(texImage->TexFormat);
405
406 /* Make sure the requested image format is compatible with the
407 * texture's format. Note that a color index texture can be converted
408 * to RGBA so that combo is allowed.
409 */
410 if (_mesa_is_color_format(format)
411 && !_mesa_is_color_format(baseFormat)
412 && !_mesa_is_index_format(baseFormat)) {
413 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
414 return GL_TRUE;
415 }
416 else if (_mesa_is_index_format(format)
417 && !_mesa_is_index_format(baseFormat)) {
418 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
419 return GL_TRUE;
420 }
421 else if (_mesa_is_depth_format(format)
422 && !_mesa_is_depth_format(baseFormat)
423 && !_mesa_is_depthstencil_format(baseFormat)) {
424 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
425 return GL_TRUE;
426 }
427 else if (_mesa_is_ycbcr_format(format)
428 && !_mesa_is_ycbcr_format(baseFormat)) {
429 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
430 return GL_TRUE;
431 }
432 else if (_mesa_is_depthstencil_format(format)
433 && !_mesa_is_depthstencil_format(baseFormat)) {
434 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
435 return GL_TRUE;
436 }
437 else if (_mesa_is_dudv_format(format)
438 && !_mesa_is_dudv_format(baseFormat)) {
439 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
440 return GL_TRUE;
441 }
442
443 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
444 /* packing texture image into a PBO */
445 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
446 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
447 texImage->Height, texImage->Depth,
448 format, type, pixels)) {
449 _mesa_error(ctx, GL_INVALID_OPERATION,
450 "glGetTexImage(out of bounds PBO write)");
451 return GL_TRUE;
452 }
453
454 /* PBO should not be mapped */
455 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
456 _mesa_error(ctx, GL_INVALID_OPERATION,
457 "glGetTexImage(PBO is mapped)");
458 return GL_TRUE;
459 }
460 }
461
462 return GL_FALSE;
463 }
464
465
466
467 /**
468 * Get texture image. Called by glGetTexImage.
469 *
470 * \param target texture target.
471 * \param level image level.
472 * \param format pixel data format for returned image.
473 * \param type pixel data type for returned image.
474 * \param pixels returned pixel data.
475 */
476 void GLAPIENTRY
477 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
478 GLenum type, GLvoid *pixels )
479 {
480 const struct gl_texture_unit *texUnit;
481 struct gl_texture_object *texObj;
482 struct gl_texture_image *texImage;
483 GET_CURRENT_CONTEXT(ctx);
484 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
485
486 if (getteximage_error_check(ctx, target, level, format, type, pixels)) {
487 return;
488 }
489
490 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) {
491 /* not an error, do nothing */
492 return;
493 }
494
495 texUnit = _mesa_get_current_tex_unit(ctx);
496 texObj = _mesa_select_tex_object(ctx, texUnit, target);
497 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
498
499 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
500 _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
501 " dstFmt=0x%x, dstType=0x%x\n",
502 texObj->Name,
503 _mesa_get_format_name(texImage->TexFormat),
504 texImage->Width, texImage->Height,
505 format, type);
506 }
507
508 _mesa_lock_texture(ctx, texObj);
509 {
510 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels,
511 texObj, texImage);
512 }
513 _mesa_unlock_texture(ctx, texObj);
514 }
515
516
517
518 /**
519 * Do error checking for a glGetCompressedTexImage() call.
520 * \return GL_TRUE if any error, GL_FALSE if no errors.
521 */
522 static GLboolean
523 getcompressedteximage_error_check(GLcontext *ctx, GLenum target, GLint level,
524 GLvoid *img)
525 {
526 const struct gl_texture_unit *texUnit;
527 struct gl_texture_object *texObj;
528 struct gl_texture_image *texImage;
529 const GLuint maxLevels = _mesa_max_texture_levels(ctx, target);
530
531 if (maxLevels == 0) {
532 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)",
533 target);
534 return GL_TRUE;
535 }
536
537 if (level < 0 || level >= maxLevels) {
538 _mesa_error(ctx, GL_INVALID_VALUE,
539 "glGetCompressedTexImageARB(bad level = %d)", level);
540 return GL_TRUE;
541 }
542
543 if (_mesa_is_proxy_texture(target)) {
544 _mesa_error(ctx, GL_INVALID_ENUM,
545 "glGetCompressedTexImageARB(bad target = %s)",
546 _mesa_lookup_enum_by_nr(target));
547 return GL_TRUE;
548 }
549
550 texUnit = _mesa_get_current_tex_unit(ctx);
551 texObj = _mesa_select_tex_object(ctx, texUnit, target);
552
553 if (!texObj) {
554 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
555 return GL_TRUE;
556 }
557
558 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
559
560 if (!texImage) {
561 /* probably invalid mipmap level */
562 _mesa_error(ctx, GL_INVALID_VALUE,
563 "glGetCompressedTexImageARB(level)");
564 return GL_TRUE;
565 }
566
567 if (!_mesa_is_format_compressed(texImage->TexFormat)) {
568 _mesa_error(ctx, GL_INVALID_OPERATION,
569 "glGetCompressedTexImageARB(texture is not compressed)");
570 return GL_TRUE;
571 }
572
573 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
574 GLuint compressedSize;
575
576 /* make sure PBO is not mapped */
577 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
578 _mesa_error(ctx, GL_INVALID_OPERATION,
579 "glGetCompressedTexImage(PBO is mapped)");
580 return GL_TRUE;
581 }
582
583 compressedSize = _mesa_format_image_size(texImage->TexFormat,
584 texImage->Width,
585 texImage->Height,
586 texImage->Depth);
587
588 /* do bounds checking on PBO write */
589 if ((const GLubyte *) img + compressedSize >
590 (const GLubyte *) ctx->Pack.BufferObj->Size) {
591 _mesa_error(ctx, GL_INVALID_OPERATION,
592 "glGetCompressedTexImage(out of bounds PBO write)");
593 return GL_TRUE;
594 }
595 }
596
597 return GL_FALSE;
598 }
599
600
601 void GLAPIENTRY
602 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
603 {
604 const struct gl_texture_unit *texUnit;
605 struct gl_texture_object *texObj;
606 struct gl_texture_image *texImage;
607 GET_CURRENT_CONTEXT(ctx);
608 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
609
610 if (getcompressedteximage_error_check(ctx, target, level, img)) {
611 return;
612 }
613
614 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) {
615 /* not an error, do nothing */
616 return;
617 }
618
619 texUnit = _mesa_get_current_tex_unit(ctx);
620 texObj = _mesa_select_tex_object(ctx, texUnit, target);
621 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
622
623 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) {
624 _mesa_debug(ctx,
625 "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
626 texObj->Name,
627 _mesa_get_format_name(texImage->TexFormat),
628 texImage->Width, texImage->Height);
629 }
630
631 _mesa_lock_texture(ctx, texObj);
632 {
633 ctx->Driver.GetCompressedTexImage(ctx, target, level, img,
634 texObj, texImage);
635 }
636 _mesa_unlock_texture(ctx, texObj);
637 }