convolution for glTexImage[123]D now works
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.43 2000/08/31 15:24:39 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.4
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "convolve.h"
34 #include "image.h"
35 #include "mem.h"
36 #include "mmath.h"
37 #include "span.h"
38 #include "state.h"
39 #include "teximage.h"
40 #include "texstate.h"
41 #include "types.h"
42 #endif
43
44
45 /*
46 * NOTES:
47 *
48 * Mesa's native texture datatype is GLubyte. Native formats are
49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
50 * and GL_COLOR_INDEX.
51 * Device drivers are free to implement any internal format they want.
52 */
53
54
55 #ifdef DEBUG
56 static void PrintTexture(const struct gl_texture_image *img)
57 {
58 int i, j, c;
59 GLubyte *data = img->Data;
60
61 if (!data) {
62 printf("No texture data\n");
63 return;
64 }
65
66 switch (img->Format) {
67 case GL_ALPHA:
68 case GL_LUMINANCE:
69 case GL_INTENSITY:
70 case GL_COLOR_INDEX:
71 c = 1;
72 break;
73 case GL_LUMINANCE_ALPHA:
74 c = 2;
75 break;
76 case GL_RGB:
77 c = 3;
78 break;
79 case GL_RGBA:
80 c = 4;
81 break;
82 default:
83 gl_problem(NULL, "error in PrintTexture\n");
84 return;
85 }
86
87
88 for (i = 0; i < img->Height; i++) {
89 for (j = 0; j < img->Width; j++) {
90 if (c==1)
91 printf("%02x ", data[0]);
92 else if (c==2)
93 printf("%02x%02x ", data[0], data[1]);
94 else if (c==3)
95 printf("%02x%02x%02x ", data[0], data[1], data[2]);
96 else if (c==4)
97 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
98 data += c;
99 }
100 printf("\n");
101 }
102 }
103 #endif
104
105
106
107 /*
108 * Compute log base 2 of n.
109 * If n isn't an exact power of two return -1.
110 * If n<0 return -1.
111 */
112 static int
113 logbase2( int n )
114 {
115 GLint i = 1;
116 GLint log2 = 0;
117
118 if (n<0) {
119 return -1;
120 }
121
122 while ( n > i ) {
123 i *= 2;
124 log2++;
125 }
126 if (i != n) {
127 return -1;
128 }
129 else {
130 return log2;
131 }
132 }
133
134
135
136 /*
137 * Given an internal texture format enum or 1, 2, 3, 4 return the
138 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
140 * Return -1 if invalid enum.
141 */
142 GLint
143 _mesa_base_tex_format( GLcontext *ctx, GLint format )
144 {
145 /*
146 * Ask the driver for the base format, if it doesn't
147 * know, it will return -1;
148 */
149 if (ctx->Driver.BaseCompressedTexFormat) {
150 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
151 if (ifmt >= 0) {
152 return ifmt;
153 }
154 }
155 switch (format) {
156 case GL_ALPHA:
157 case GL_ALPHA4:
158 case GL_ALPHA8:
159 case GL_ALPHA12:
160 case GL_ALPHA16:
161 return GL_ALPHA;
162 case 1:
163 case GL_LUMINANCE:
164 case GL_LUMINANCE4:
165 case GL_LUMINANCE8:
166 case GL_LUMINANCE12:
167 case GL_LUMINANCE16:
168 return GL_LUMINANCE;
169 case 2:
170 case GL_LUMINANCE_ALPHA:
171 case GL_LUMINANCE4_ALPHA4:
172 case GL_LUMINANCE6_ALPHA2:
173 case GL_LUMINANCE8_ALPHA8:
174 case GL_LUMINANCE12_ALPHA4:
175 case GL_LUMINANCE12_ALPHA12:
176 case GL_LUMINANCE16_ALPHA16:
177 return GL_LUMINANCE_ALPHA;
178 case GL_INTENSITY:
179 case GL_INTENSITY4:
180 case GL_INTENSITY8:
181 case GL_INTENSITY12:
182 case GL_INTENSITY16:
183 return GL_INTENSITY;
184 case 3:
185 case GL_RGB:
186 case GL_R3_G3_B2:
187 case GL_RGB4:
188 case GL_RGB5:
189 case GL_RGB8:
190 case GL_RGB10:
191 case GL_RGB12:
192 case GL_RGB16:
193 return GL_RGB;
194 case 4:
195 case GL_RGBA:
196 case GL_RGBA2:
197 case GL_RGBA4:
198 case GL_RGB5_A1:
199 case GL_RGBA8:
200 case GL_RGB10_A2:
201 case GL_RGBA12:
202 case GL_RGBA16:
203 return GL_RGBA;
204 case GL_COLOR_INDEX:
205 case GL_COLOR_INDEX1_EXT:
206 case GL_COLOR_INDEX2_EXT:
207 case GL_COLOR_INDEX4_EXT:
208 case GL_COLOR_INDEX8_EXT:
209 case GL_COLOR_INDEX12_EXT:
210 case GL_COLOR_INDEX16_EXT:
211 return GL_COLOR_INDEX;
212 default:
213 return -1; /* error */
214 }
215 }
216
217
218
219 /*
220 * Given an internal texture format enum or 1, 2, 3, 4 return the
221 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
223 * number of components for the format. Return -1 if invalid enum.
224 */
225 static GLint
226 components_in_intformat( GLint format )
227 {
228 switch (format) {
229 case GL_ALPHA:
230 case GL_ALPHA4:
231 case GL_ALPHA8:
232 case GL_ALPHA12:
233 case GL_ALPHA16:
234 return 1;
235 case 1:
236 case GL_LUMINANCE:
237 case GL_LUMINANCE4:
238 case GL_LUMINANCE8:
239 case GL_LUMINANCE12:
240 case GL_LUMINANCE16:
241 return 1;
242 case 2:
243 case GL_LUMINANCE_ALPHA:
244 case GL_LUMINANCE4_ALPHA4:
245 case GL_LUMINANCE6_ALPHA2:
246 case GL_LUMINANCE8_ALPHA8:
247 case GL_LUMINANCE12_ALPHA4:
248 case GL_LUMINANCE12_ALPHA12:
249 case GL_LUMINANCE16_ALPHA16:
250 return 2;
251 case GL_INTENSITY:
252 case GL_INTENSITY4:
253 case GL_INTENSITY8:
254 case GL_INTENSITY12:
255 case GL_INTENSITY16:
256 return 1;
257 case 3:
258 case GL_RGB:
259 case GL_R3_G3_B2:
260 case GL_RGB4:
261 case GL_RGB5:
262 case GL_RGB8:
263 case GL_RGB10:
264 case GL_RGB12:
265 case GL_RGB16:
266 return 3;
267 case 4:
268 case GL_RGBA:
269 case GL_RGBA2:
270 case GL_RGBA4:
271 case GL_RGB5_A1:
272 case GL_RGBA8:
273 case GL_RGB10_A2:
274 case GL_RGBA12:
275 case GL_RGBA16:
276 return 4;
277 case GL_COLOR_INDEX:
278 case GL_COLOR_INDEX1_EXT:
279 case GL_COLOR_INDEX2_EXT:
280 case GL_COLOR_INDEX4_EXT:
281 case GL_COLOR_INDEX8_EXT:
282 case GL_COLOR_INDEX12_EXT:
283 case GL_COLOR_INDEX16_EXT:
284 return 1;
285 default:
286 return -1; /* error */
287 }
288 }
289
290
291 /*
292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
293 * otherwise.
294 */
295 static GLboolean
296 is_compressed_format(GLcontext *ctx, GLenum internalFormat)
297 {
298 if (ctx->Driver.IsCompressedFormat) {
299 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
300 }
301 return GL_FALSE;
302 }
303
304
305
306 /*
307 * Examine the texImage->Format field and set the Red, Green, Blue, etc
308 * texel component sizes to default values.
309 * These fields are set only here by core Mesa but device drivers may
310 * overwritting these fields to indicate true texel resolution.
311 */
312 static void
313 set_teximage_component_sizes( struct gl_texture_image *texImage )
314 {
315 switch (texImage->Format) {
316 case GL_ALPHA:
317 texImage->RedBits = 0;
318 texImage->GreenBits = 0;
319 texImage->BlueBits = 0;
320 texImage->AlphaBits = 8;
321 texImage->IntensityBits = 0;
322 texImage->LuminanceBits = 0;
323 texImage->IndexBits = 0;
324 break;
325 case GL_LUMINANCE:
326 texImage->RedBits = 0;
327 texImage->GreenBits = 0;
328 texImage->BlueBits = 0;
329 texImage->AlphaBits = 0;
330 texImage->IntensityBits = 0;
331 texImage->LuminanceBits = 8;
332 texImage->IndexBits = 0;
333 break;
334 case GL_LUMINANCE_ALPHA:
335 texImage->RedBits = 0;
336 texImage->GreenBits = 0;
337 texImage->BlueBits = 0;
338 texImage->AlphaBits = 8;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 8;
341 texImage->IndexBits = 0;
342 break;
343 case GL_INTENSITY:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 0;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 8;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 0;
351 break;
352 case GL_RED:
353 texImage->RedBits = 8;
354 texImage->GreenBits = 0;
355 texImage->BlueBits = 0;
356 texImage->AlphaBits = 0;
357 texImage->IntensityBits = 0;
358 texImage->LuminanceBits = 0;
359 texImage->IndexBits = 0;
360 break;
361 case GL_GREEN:
362 texImage->RedBits = 0;
363 texImage->GreenBits = 8;
364 texImage->BlueBits = 0;
365 texImage->AlphaBits = 0;
366 texImage->IntensityBits = 0;
367 texImage->LuminanceBits = 0;
368 texImage->IndexBits = 0;
369 break;
370 case GL_BLUE:
371 texImage->RedBits = 0;
372 texImage->GreenBits = 0;
373 texImage->BlueBits = 8;
374 texImage->AlphaBits = 0;
375 texImage->IntensityBits = 0;
376 texImage->LuminanceBits = 0;
377 texImage->IndexBits = 0;
378 break;
379 case GL_RGB:
380 case GL_BGR:
381 texImage->RedBits = 8;
382 texImage->GreenBits = 8;
383 texImage->BlueBits = 8;
384 texImage->AlphaBits = 0;
385 texImage->IntensityBits = 0;
386 texImage->LuminanceBits = 0;
387 texImage->IndexBits = 0;
388 break;
389 case GL_RGBA:
390 case GL_BGRA:
391 case GL_ABGR_EXT:
392 texImage->RedBits = 8;
393 texImage->GreenBits = 8;
394 texImage->BlueBits = 8;
395 texImage->AlphaBits = 8;
396 texImage->IntensityBits = 0;
397 texImage->LuminanceBits = 0;
398 texImage->IndexBits = 0;
399 break;
400 case GL_COLOR_INDEX:
401 texImage->RedBits = 0;
402 texImage->GreenBits = 0;
403 texImage->BlueBits = 0;
404 texImage->AlphaBits = 0;
405 texImage->IntensityBits = 0;
406 texImage->LuminanceBits = 0;
407 texImage->IndexBits = 8;
408 break;
409 default:
410 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
411 }
412 }
413
414
415 static void
416 set_tex_image(struct gl_texture_object *tObj,
417 GLenum target, GLint level,
418 struct gl_texture_image *texImage)
419 {
420 ASSERT(tObj);
421 ASSERT(texImage);
422 switch (target) {
423 case GL_TEXTURE_2D:
424 tObj->Image[level] = texImage;
425 return;
426 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
427 tObj->Image[level] = texImage;
428 return;
429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
430 tObj->NegX[level] = texImage;
431 return;
432 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
433 tObj->PosY[level] = texImage;
434 return;
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
436 tObj->NegY[level] = texImage;
437 return;
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
439 tObj->PosZ[level] = texImage;
440 return;
441 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
442 tObj->NegZ[level] = texImage;
443 return;
444 default:
445 gl_problem(NULL, "bad target in set_tex_image()");
446 return;
447 }
448 }
449
450
451 /*
452 * Return new gl_texture_image struct with all fields initialized to zero.
453 */
454 struct gl_texture_image *
455 _mesa_alloc_texture_image( void )
456 {
457 return CALLOC_STRUCT(gl_texture_image);
458 }
459
460
461
462 /*
463 * Initialize most fields of a gl_texture_image struct.
464 */
465 static void
466 init_texture_image( GLcontext *ctx,
467 struct gl_texture_image *img,
468 GLsizei width, GLsizei height, GLsizei depth,
469 GLint border, GLenum internalFormat )
470 {
471 ASSERT(img);
472 ASSERT(!img->Data);
473 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
474 set_teximage_component_sizes( img );
475 img->IntFormat = (GLenum) internalFormat;
476 img->Border = border;
477 img->Width = width;
478 img->Height = height;
479 img->Depth = depth;
480 img->WidthLog2 = logbase2(width - 2 * border);
481 if (height == 1) /* 1-D texture */
482 img->HeightLog2 = 0;
483 else
484 img->HeightLog2 = logbase2(height - 2 * border);
485 if (depth == 1) /* 2-D texture */
486 img->DepthLog2 = 0;
487 else
488 img->DepthLog2 = logbase2(depth - 2 * border);
489 img->Width2 = 1 << img->WidthLog2;
490 img->Height2 = 1 << img->HeightLog2;
491 img->Depth2 = 1 << img->DepthLog2;
492 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
493 img->IsCompressed = is_compressed_format(ctx, internalFormat);
494 }
495
496
497
498 void
499 _mesa_free_texture_image( struct gl_texture_image *teximage )
500 {
501 if (teximage->Data) {
502 FREE( teximage->Data );
503 teximage->Data = NULL;
504 }
505 FREE( teximage );
506 }
507
508
509
510 /*
511 * Return number of bytes of storage needed to store a compressed texture
512 * image. Only the driver knows for sure. If the driver can't help us,
513 * we must return 0.
514 */
515 GLuint
516 _mesa_compressed_image_size(GLcontext *ctx,
517 GLenum internalFormat,
518 GLint numDimensions,
519 GLint width,
520 GLint height,
521 GLint depth)
522 {
523 if (ctx->Driver.CompressedImageSize) {
524 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
525 numDimensions,
526 width, height, depth);
527 }
528 else {
529 /* Shouldn't this be an internal error of some sort? */
530 return 0;
531 }
532 }
533
534
535
536 /*
537 * Given a texture unit and a texture target, return the corresponding
538 * texture object.
539 */
540 struct gl_texture_object *
541 _mesa_select_tex_object(GLcontext *ctx, struct gl_texture_unit *texUnit,
542 GLenum target)
543 {
544 switch (target) {
545 case GL_TEXTURE_1D:
546 return texUnit->CurrentD[1];
547 case GL_PROXY_TEXTURE_1D:
548 return ctx->Texture.Proxy1D;
549 case GL_TEXTURE_2D:
550 return texUnit->CurrentD[2];
551 case GL_PROXY_TEXTURE_2D:
552 return ctx->Texture.Proxy2D;
553 case GL_TEXTURE_3D:
554 return texUnit->CurrentD[3];
555 case GL_PROXY_TEXTURE_3D:
556 return ctx->Texture.Proxy3D;
557 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
561 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
563 return ctx->Extensions.HaveTextureCubeMap
564 ? texUnit->CurrentCubeMap : NULL;
565 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
566 return ctx->Extensions.HaveTextureCubeMap
567 ? ctx->Texture.ProxyCubeMap : NULL;
568 default:
569 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
570 return NULL;
571 }
572 }
573
574
575 /*
576 * Return the texture image struct which corresponds to target and level
577 * for the given texture unit.
578 */
579 struct gl_texture_image *
580 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
581 GLenum target, GLint level)
582 {
583 ASSERT(texUnit);
584 switch (target) {
585 case GL_TEXTURE_1D:
586 return texUnit->CurrentD[1]->Image[level];
587 case GL_PROXY_TEXTURE_1D:
588 return ctx->Texture.Proxy1D->Image[level];
589 case GL_TEXTURE_2D:
590 return texUnit->CurrentD[2]->Image[level];
591 case GL_PROXY_TEXTURE_2D:
592 return ctx->Texture.Proxy2D->Image[level];
593 case GL_TEXTURE_3D:
594 return texUnit->CurrentD[3]->Image[level];
595 case GL_PROXY_TEXTURE_3D:
596 return ctx->Texture.Proxy3D->Image[level];
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
598 if (ctx->Extensions.HaveTextureCubeMap)
599 return texUnit->CurrentCubeMap->Image[level];
600 else
601 return NULL;
602 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
603 if (ctx->Extensions.HaveTextureCubeMap)
604 return texUnit->CurrentCubeMap->NegX[level];
605 else
606 return NULL;
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
608 if (ctx->Extensions.HaveTextureCubeMap)
609 return texUnit->CurrentCubeMap->PosY[level];
610 else
611 return NULL;
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
613 if (ctx->Extensions.HaveTextureCubeMap)
614 return texUnit->CurrentCubeMap->NegY[level];
615 else
616 return NULL;
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
618 if (ctx->Extensions.HaveTextureCubeMap)
619 return texUnit->CurrentCubeMap->PosZ[level];
620 else
621 return NULL;
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
623 if (ctx->Extensions.HaveTextureCubeMap)
624 return texUnit->CurrentCubeMap->NegZ[level];
625 else
626 return NULL;
627 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
628 if (ctx->Extensions.HaveTextureCubeMap)
629 return ctx->Texture.ProxyCubeMap->Image[level];
630 else
631 return NULL;
632 default:
633 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
634 return NULL;
635 }
636 }
637
638
639
640 /*
641 * Calling glTexImage and related functions when convolution is enabled
642 * with GL_REDUCE border mode causes some complications.
643 * The incoming image must be extra large so that the post-convolution
644 * image size is reduced to a power of two size (plus 2 * border).
645 * This function adjusts a texture width and height accordingly if
646 * convolution with GL_REDUCE is enabled.
647 */
648 static void
649 adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
650 GLsizei *width, GLsizei *height)
651 {
652 if (ctx->Pixel.Convolution1DEnabled
653 && dimensions == 1
654 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
655 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
656 }
657 else if (ctx->Pixel.Convolution2DEnabled
658 && dimensions > 1
659 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
660 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
661 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
662 }
663 else if (ctx->Pixel.Separable2DEnabled
664 && dimensions > 1
665 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
666 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
667 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
668 }
669 }
670
671
672
673 /* Need this to prevent an out-of-bounds memory access when using
674 * X86 optimized code.
675 */
676 #ifdef USE_X86_ASM
677 # define EXTRA_BYTE 1
678 #else
679 # define EXTRA_BYTE 0
680 #endif
681
682
683
684 /*
685 * Called by glTexImage[123]D. Fill in a texture image with data given
686 * by the client. All pixel transfer and unpack modes are handled here.
687 * Input: dimensions (1, 2, or 3)
688 * texImage - destination texture image (we'll malloc the memory)
689 * width, height, depth - size of source image
690 * srcFormat, srcType - source image format and type
691 * pixels - source image data
692 * srcPacking - source image packing parameters
693 *
694 * NOTE: All texture image parameters should have already been error checked.
695 *
696 * NOTE: the texImage dimensions and source image dimensions must be correct
697 * with respect to convolution with border mode = reduce.
698 */
699 static void
700 make_texture_image( GLcontext *ctx, GLuint dimensions,
701 struct gl_texture_image *texImage,
702 GLint width, GLint height, GLint depth,
703 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
704 const struct gl_pixelstore_attrib *srcPacking)
705 {
706 GLint components, numPixels;
707 GLint internalFormat, border;
708
709 ASSERT(ctx);
710 ASSERT(texImage);
711 ASSERT(!texImage->Data);
712 ASSERT(pixels);
713 ASSERT(srcPacking);
714
715 internalFormat = texImage->IntFormat;
716 border = texImage->Border;
717 components = components_in_intformat(internalFormat);
718
719 ASSERT(width > 0);
720 ASSERT(height > 0);
721 ASSERT(depth > 0);
722 ASSERT(border == 0 || border == 1);
723 ASSERT(components);
724
725 numPixels = width * height * depth;
726
727 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
728 if (!texImage->Data)
729 return; /* out of memory */
730
731 /*
732 * OK, the texture image struct has been initialized and the texture
733 * image memory has been allocated.
734 * Now fill in the texture image from the source data.
735 * This includes applying the pixel transfer operations.
736 */
737
738 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
739 _mesa_update_image_transfer_state(ctx);
740
741 /* try common 2D texture cases first */
742 if (!ctx->ImageTransferState && srcType == GL_UNSIGNED_BYTE && depth == 1) {
743
744 if (srcFormat == internalFormat ||
745 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
746 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
747 (srcFormat == GL_RGB && internalFormat == 3) ||
748 (srcFormat == GL_RGBA && internalFormat == 4)) {
749 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
750 * GL_LUMINANCE_ALPHA, etc. texture formats.
751 */
752 const GLubyte *src = (const GLubyte *) _mesa_image_address(
753 srcPacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
754 const GLint srcStride = _mesa_image_row_stride(srcPacking, width,
755 srcFormat, srcType);
756 GLubyte *dst = texImage->Data;
757 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
758 if (srcStride == dstBytesPerRow) {
759 MEMCPY(dst, src, height * dstBytesPerRow);
760 }
761 else {
762 GLint i;
763 for (i = 0; i < height; i++) {
764 MEMCPY(dst, src, dstBytesPerRow);
765 src += srcStride;
766 dst += dstBytesPerRow;
767 }
768 }
769 return; /* all done */
770 }
771 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
772 /* commonly used by Quake */
773 const GLubyte *src = (const GLubyte *) _mesa_image_address(
774 srcPacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
775 const GLint srcStride = _mesa_image_row_stride(srcPacking, width,
776 srcFormat, srcType);
777 GLubyte *dst = texImage->Data;
778 GLint i, j;
779 for (i = 0; i < height; i++) {
780 const GLubyte *s = src;
781 for (j = 0; j < width; j++) {
782 *dst++ = *s++; /*red*/
783 *dst++ = *s++; /*green*/
784 *dst++ = *s++; /*blue*/
785 s++; /*alpha*/
786 }
787 src += srcStride;
788 }
789 return; /* all done */
790 }
791 }
792
793
794 /*
795 * General case solutions
796 */
797 if (texImage->Format == GL_COLOR_INDEX) {
798 /* color index texture */
799 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
800 const GLenum dstType = GL_UNSIGNED_BYTE;
801 GLubyte *destTex = texImage->Data;
802 GLint img, row;
803 for (img = 0; img < depth; img++) {
804 for (row = 0; row < height; row++) {
805 const GLvoid *srcAddr = _mesa_image_address(srcPacking,
806 pixels, width, height, srcFormat, srcType, img, row, 0);
807 _mesa_unpack_index_span(ctx, width, dstType, destTex,
808 srcType, srcAddr, srcPacking,
809 ctx->ImageTransferState);
810 destTex += destBytesPerRow;
811 }
812 }
813 }
814 else {
815 /* regular, color texture */
816 GLint destBytesPerRow;
817 const GLenum dstFormat = texImage->Format;
818 GLubyte *destTex = texImage->Data;
819 GLint img, row;
820 GLint convWidth = width, convHeight = height;
821
822 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
823 (dimensions >= 2 &&
824 (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled)
825 )) {
826 GLfloat *tmpImage, *convImage;
827 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
828 if (!tmpImage) {
829 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
830 return;
831 }
832 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
833 if (!convImage) {
834 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
835 FREE(tmpImage);
836 return;
837 }
838
839 for (img = 0; img < depth; img++) {
840 const GLfloat *srcf;
841 GLfloat *dstf = tmpImage;
842 /* unpack and do transfer ops up to convolution */
843 for (row = 0; row < height; row++) {
844 const GLvoid *srcAddr = _mesa_image_address(srcPacking,
845 pixels, width, height, srcFormat, srcType, img, row, 0);
846 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dstf,
847 srcFormat, srcType, srcAddr, srcPacking,
848 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
849 GL_TRUE);
850 dstf += width * 4;
851 }
852
853 /* convolve */
854 if (dimensions == 1) {
855 ASSERT(ctx->Pixel.Convolution1DEnabled);
856 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
857 }
858 else {
859 if (ctx->Pixel.Convolution2DEnabled) {
860 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
861 tmpImage, convImage);
862 }
863 else {
864 ASSERT(ctx->Pixel.Separable2DEnabled);
865 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
866 tmpImage, convImage);
867 }
868 }
869
870 /* packing and transfer ops after convolution */
871 srcf = convImage;
872 destBytesPerRow = convWidth * components * sizeof(GLubyte);
873 for (row = 0; row < convHeight; row++) {
874 _mesa_pack_float_rgba_span(ctx, convWidth,
875 (const GLfloat (*)[4]) srcf,
876 dstFormat, GL_UNSIGNED_BYTE,
877 destTex, &_mesa_native_packing,
878 ctx->ImageTransferState
879 & IMAGE_POST_CONVOLUTION_BITS);
880 srcf += convWidth * 4;
881 destTex += destBytesPerRow;
882 }
883 }
884
885 FREE(convImage);
886 FREE(tmpImage);
887 }
888 else {
889 /* no convolution */
890 for (img = 0; img < depth; img++) {
891 for (row = 0; row < height; row++) {
892 const GLvoid *srcAddr = _mesa_image_address(srcPacking,
893 pixels, width, height, srcFormat, srcType, img, row, 0);
894 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destTex,
895 srcFormat, srcType, srcAddr, srcPacking,
896 ctx->ImageTransferState);
897 destTex += destBytesPerRow;
898 }
899 }
900 }
901 }
902 }
903
904
905
906 /*
907 * glTexImage[123]D can accept a NULL image pointer. In this case we
908 * create a texture image with unspecified image contents per the OpenGL
909 * spec. This function creates an empty image for the given texture image.
910 */
911 static void
912 make_null_texture( struct gl_texture_image *texImage )
913 {
914 GLint components;
915 GLint numPixels;
916
917 ASSERT(texImage);
918 ASSERT(!texImage->Data);
919
920 components = components_in_intformat(texImage->IntFormat);
921 numPixels = texImage->Width * texImage->Height * texImage->Depth;
922
923 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
924
925 /*
926 * Let's see if anyone finds this. If glTexImage2D() is called with
927 * a NULL image pointer then load the texture image with something
928 * interesting instead of leaving it indeterminate.
929 */
930 if (texImage->Data) {
931 static const char message[8][32] = {
932 " X X XXXXX XXX X ",
933 " XX XX X X X X X ",
934 " X X X X X X X ",
935 " X X XXXX XXX XXXXX ",
936 " X X X X X X ",
937 " X X X X X X X ",
938 " X X XXXXX XXX X X ",
939 " "
940 };
941
942 GLubyte *imgPtr = texImage->Data;
943 GLint i, j, k;
944 for (i = 0; i < texImage->Height; i++) {
945 GLint srcRow = 7 - i % 8;
946 for (j = 0; j < texImage->Width; j++) {
947 GLint srcCol = j % 32;
948 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
949 for (k=0;k<components;k++) {
950 *imgPtr++ = (GLubyte) texel;
951 }
952 }
953 }
954 }
955 }
956
957
958
959 /*
960 * Test glTexImage[123]D() parameters for errors.
961 * Input:
962 * dimensions - must be 1 or 2 or 3
963 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
964 */
965 static GLboolean
966 texture_error_check( GLcontext *ctx, GLenum target,
967 GLint level, GLint internalFormat,
968 GLenum format, GLenum type,
969 GLuint dimensions,
970 GLint width, GLint height,
971 GLint depth, GLint border )
972 {
973 GLboolean isProxy;
974 GLint iformat;
975
976 if (dimensions == 1) {
977 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
978 if (target != GL_TEXTURE_1D && !isProxy) {
979 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
980 return GL_TRUE;
981 }
982 }
983 else if (dimensions == 2) {
984 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
985 if (target != GL_TEXTURE_2D && !isProxy &&
986 !(ctx->Extensions.HaveTextureCubeMap &&
987 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
988 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
989 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
990 return GL_TRUE;
991 }
992 }
993 else if (dimensions == 3) {
994 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
995 if (target != GL_TEXTURE_3D && !isProxy) {
996 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
997 return GL_TRUE;
998 }
999 }
1000 else {
1001 gl_problem( ctx, "bad dims in texture_error_check" );
1002 return GL_TRUE;
1003 }
1004
1005 /* Border */
1006 if (border != 0 && border != 1) {
1007 if (!isProxy) {
1008 char message[100];
1009 sprintf(message, "glTexImage%dD(border)", dimensions);
1010 gl_error(ctx, GL_INVALID_VALUE, message);
1011 }
1012 return GL_TRUE;
1013 }
1014
1015 /* Width */
1016 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1017 || logbase2( width - 2 * border ) < 0) {
1018 if (!isProxy) {
1019 char message[100];
1020 sprintf(message, "glTexImage%dD(width)", dimensions);
1021 gl_error(ctx, GL_INVALID_VALUE, message);
1022 }
1023 return GL_TRUE;
1024 }
1025
1026 /* Height */
1027 if (dimensions >= 2) {
1028 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1029 || logbase2( height - 2 * border ) < 0) {
1030 if (!isProxy) {
1031 char message[100];
1032 sprintf(message, "glTexImage%dD(height)", dimensions);
1033 gl_error(ctx, GL_INVALID_VALUE, message);
1034 }
1035 return GL_TRUE;
1036 }
1037 }
1038
1039 /* For cube map, width must equal height */
1040 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1041 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1042 if (width != height) {
1043 if (!isProxy) {
1044 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1045 }
1046 return GL_TRUE;
1047 }
1048 }
1049
1050 /* Depth */
1051 if (dimensions >= 3) {
1052 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1053 || logbase2( depth - 2 * border ) < 0) {
1054 if (!isProxy) {
1055 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1056 }
1057 return GL_TRUE;
1058 }
1059 }
1060
1061 /* Level */
1062 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1063 if (!isProxy) {
1064 char message[100];
1065 sprintf(message, "glTexImage%dD(level)", dimensions);
1066 gl_error(ctx, GL_INVALID_VALUE, message);
1067 }
1068 return GL_TRUE;
1069 }
1070
1071 iformat = _mesa_base_tex_format( ctx, internalFormat );
1072 if (iformat < 0) {
1073 if (!isProxy) {
1074 char message[100];
1075 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1076 gl_error(ctx, GL_INVALID_VALUE, message);
1077 }
1078 return GL_TRUE;
1079 }
1080
1081 if (!is_compressed_format(ctx, internalFormat)) {
1082 if (!_mesa_is_legal_format_and_type( format, type )) {
1083 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1084 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1085 */
1086 if (!isProxy) {
1087 char message[100];
1088 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1089 gl_error(ctx, GL_INVALID_OPERATION, message);
1090 }
1091 return GL_TRUE;
1092 }
1093 }
1094
1095 /* if we get here, the parameters are OK */
1096 return GL_FALSE;
1097 }
1098
1099
1100
1101 /*
1102 * Test glTexSubImage[123]D() parameters for errors.
1103 * Input:
1104 * dimensions - must be 1 or 2 or 3
1105 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1106 */
1107 static GLboolean
1108 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1109 GLenum target, GLint level,
1110 GLint xoffset, GLint yoffset, GLint zoffset,
1111 GLint width, GLint height, GLint depth,
1112 GLenum format, GLenum type )
1113 {
1114 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1115 struct gl_texture_image *destTex;
1116
1117 if (dimensions == 1) {
1118 if (target != GL_TEXTURE_1D) {
1119 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1120 return GL_TRUE;
1121 }
1122 }
1123 else if (dimensions == 2) {
1124 if (ctx->Extensions.HaveTextureCubeMap) {
1125 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1126 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1127 target != GL_TEXTURE_2D) {
1128 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1129 return GL_TRUE;
1130 }
1131 }
1132 else if (target != GL_TEXTURE_2D) {
1133 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1134 return GL_TRUE;
1135 }
1136 }
1137 else if (dimensions == 3) {
1138 if (target != GL_TEXTURE_3D) {
1139 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1140 return GL_TRUE;
1141 }
1142 }
1143 else {
1144 gl_problem( ctx, "bad dims in texture_error_check" );
1145 return GL_TRUE;
1146 }
1147
1148 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1149 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1150 return GL_TRUE;
1151 }
1152
1153 if (width < 0) {
1154 char message[100];
1155 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1156 gl_error(ctx, GL_INVALID_VALUE, message);
1157 return GL_TRUE;
1158 }
1159 if (height < 0 && dimensions > 1) {
1160 char message[100];
1161 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1162 gl_error(ctx, GL_INVALID_VALUE, message);
1163 return GL_TRUE;
1164 }
1165 if (depth < 0 && dimensions > 2) {
1166 char message[100];
1167 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1168 gl_error(ctx, GL_INVALID_VALUE, message);
1169 return GL_TRUE;
1170 }
1171
1172 destTex = texUnit->CurrentD[2]->Image[level];
1173 if (!destTex) {
1174 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1175 return GL_TRUE;
1176 }
1177
1178 if (xoffset < -((GLint)destTex->Border)) {
1179 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1180 return GL_TRUE;
1181 }
1182 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1183 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1184 return GL_TRUE;
1185 }
1186 if (dimensions > 1) {
1187 if (yoffset < -((GLint)destTex->Border)) {
1188 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1189 return GL_TRUE;
1190 }
1191 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1192 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1193 return GL_TRUE;
1194 }
1195 }
1196 if (dimensions > 2) {
1197 if (zoffset < -((GLint)destTex->Border)) {
1198 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1199 return GL_TRUE;
1200 }
1201 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1202 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1203 return GL_TRUE;
1204 }
1205 }
1206
1207 if (!is_compressed_format(ctx, destTex->IntFormat)) {
1208 if (!_mesa_is_legal_format_and_type(format, type)) {
1209 char message[100];
1210 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1211 gl_error(ctx, GL_INVALID_ENUM, message);
1212 return GL_TRUE;
1213 }
1214 }
1215
1216 return GL_FALSE;
1217 }
1218
1219
1220 /*
1221 * Test glCopyTexImage[12]D() parameters for errors.
1222 * Input: dimensions - must be 1 or 2 or 3
1223 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1224 */
1225 static GLboolean
1226 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1227 GLenum target, GLint level, GLint internalFormat,
1228 GLint width, GLint height, GLint border )
1229 {
1230 GLint iformat;
1231
1232 if (dimensions == 1) {
1233 if (target != GL_TEXTURE_1D) {
1234 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1235 return GL_TRUE;
1236 }
1237 }
1238 else if (dimensions == 2) {
1239 if (ctx->Extensions.HaveTextureCubeMap) {
1240 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1241 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1242 target != GL_TEXTURE_2D) {
1243 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1244 return GL_TRUE;
1245 }
1246 }
1247 else if (target != GL_TEXTURE_2D) {
1248 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1249 return GL_TRUE;
1250 }
1251 }
1252
1253 /* Border */
1254 if (border!=0 && border!=1) {
1255 char message[100];
1256 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1257 gl_error(ctx, GL_INVALID_VALUE, message);
1258 return GL_TRUE;
1259 }
1260
1261 /* Width */
1262 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1263 || logbase2( width - 2 * border ) < 0) {
1264 char message[100];
1265 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1266 gl_error(ctx, GL_INVALID_VALUE, message);
1267 return GL_TRUE;
1268 }
1269
1270 /* Height */
1271 if (dimensions >= 2) {
1272 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1273 || logbase2( height - 2 * border ) < 0) {
1274 char message[100];
1275 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1276 gl_error(ctx, GL_INVALID_VALUE, message);
1277 return GL_TRUE;
1278 }
1279 }
1280
1281 /* For cube map, width must equal height */
1282 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1283 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1284 if (width != height) {
1285 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1286 return GL_TRUE;
1287 }
1288 }
1289
1290 /* Level */
1291 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1292 char message[100];
1293 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1294 gl_error(ctx, GL_INVALID_VALUE, message);
1295 return GL_TRUE;
1296 }
1297
1298 iformat = _mesa_base_tex_format( ctx, internalFormat );
1299 if (iformat < 0) {
1300 char message[100];
1301 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1302 gl_error(ctx, GL_INVALID_VALUE, message);
1303 return GL_TRUE;
1304 }
1305
1306 /* if we get here, the parameters are OK */
1307 return GL_FALSE;
1308 }
1309
1310
1311 static GLboolean
1312 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1313 GLenum target, GLint level,
1314 GLint xoffset, GLint yoffset, GLint zoffset,
1315 GLsizei width, GLsizei height )
1316 {
1317 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1318 struct gl_texture_image *teximage;
1319
1320 if (dimensions == 1) {
1321 if (target != GL_TEXTURE_1D) {
1322 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1323 return GL_TRUE;
1324 }
1325 }
1326 else if (dimensions == 2) {
1327 if (ctx->Extensions.HaveTextureCubeMap) {
1328 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1329 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1330 target != GL_TEXTURE_2D) {
1331 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1332 return GL_TRUE;
1333 }
1334 }
1335 else if (target != GL_TEXTURE_2D) {
1336 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1337 return GL_TRUE;
1338 }
1339 }
1340 else if (dimensions == 3) {
1341 if (target != GL_TEXTURE_3D) {
1342 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1343 return GL_TRUE;
1344 }
1345 }
1346
1347 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1348 char message[100];
1349 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1350 gl_error(ctx, GL_INVALID_VALUE, message);
1351 return GL_TRUE;
1352 }
1353
1354 if (width < 0) {
1355 char message[100];
1356 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1357 gl_error(ctx, GL_INVALID_VALUE, message);
1358 return GL_TRUE;
1359 }
1360 if (dimensions > 1 && height < 0) {
1361 char message[100];
1362 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1363 gl_error(ctx, GL_INVALID_VALUE, message);
1364 return GL_TRUE;
1365 }
1366
1367 teximage = texUnit->CurrentD[dimensions]->Image[level];
1368 if (!teximage) {
1369 char message[100];
1370 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1371 gl_error(ctx, GL_INVALID_OPERATION, message);
1372 return GL_TRUE;
1373 }
1374
1375 if (xoffset < -((GLint)teximage->Border)) {
1376 char message[100];
1377 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1378 gl_error(ctx, GL_INVALID_VALUE, message);
1379 return GL_TRUE;
1380 }
1381 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1382 char message[100];
1383 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1384 gl_error(ctx, GL_INVALID_VALUE, message);
1385 return GL_TRUE;
1386 }
1387 if (dimensions > 1) {
1388 if (yoffset < -((GLint)teximage->Border)) {
1389 char message[100];
1390 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1391 gl_error(ctx, GL_INVALID_VALUE, message);
1392 return GL_TRUE;
1393 }
1394 /* NOTE: we're adding the border here, not subtracting! */
1395 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1396 char message[100];
1397 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1398 gl_error(ctx, GL_INVALID_VALUE, message);
1399 return GL_TRUE;
1400 }
1401 }
1402
1403 if (dimensions > 2) {
1404 if (zoffset < -((GLint)teximage->Border)) {
1405 char message[100];
1406 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1407 gl_error(ctx, GL_INVALID_VALUE, message);
1408 return GL_TRUE;
1409 }
1410 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1411 char message[100];
1412 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1413 gl_error(ctx, GL_INVALID_VALUE, message);
1414 return GL_TRUE;
1415 }
1416 }
1417
1418 /* if we get here, the parameters are OK */
1419 return GL_FALSE;
1420 }
1421
1422
1423
1424
1425 /*
1426 * Turn generic compressed formats into specific compressed format.
1427 * Some of the compressed formats we don't support, so we
1428 * fall back to the uncompressed format. (See issue 15 of
1429 * the GL_ARB_texture_compression specification.)
1430 */
1431 static GLint
1432 get_specific_compressed_tex_format(GLcontext *ctx,
1433 GLint ifmt, GLint numDimensions)
1434 {
1435 char message[100];
1436 GLint internalFormat = ifmt;
1437
1438 if (ctx->Extensions.HaveTextureCompression
1439 && ctx->Driver.SpecificCompressedTexFormat) {
1440 /*
1441 * First, ask the driver for the specific format.
1442 */
1443 switch (internalFormat) {
1444 case GL_COMPRESSED_ALPHA_ARB:
1445 case GL_COMPRESSED_LUMINANCE_ARB:
1446 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1447 case GL_COMPRESSED_INTENSITY_ARB:
1448 case GL_COMPRESSED_RGB_ARB:
1449 case GL_COMPRESSED_RGBA_ARB:
1450 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1451 (ctx, internalFormat, numDimensions);
1452 /* XXX shouldn't we return now? */
1453 break;
1454 default:
1455 /* silence compiler warnings */
1456 ;
1457 }
1458 }
1459
1460 /*
1461 * Now, convert any generic format left to an uncompressed
1462 * specific format. If the driver does not support compression
1463 * of the format, we must drop back to the uncompressed format.
1464 * See issue 15 of the GL_ARB_texture_compression specification.
1465 */
1466 switch (internalFormat) {
1467 case GL_COMPRESSED_ALPHA_ARB:
1468 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1469 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1470 gl_error(ctx, GL_INVALID_VALUE, message);
1471 return -1;
1472 }
1473 internalFormat = GL_ALPHA;
1474 break;
1475 case GL_COMPRESSED_LUMINANCE_ARB:
1476 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1477 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1478 gl_error(ctx, GL_INVALID_VALUE, message);
1479 return -1;
1480 }
1481 internalFormat = GL_LUMINANCE;
1482 break;
1483 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1484 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1485 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1486 gl_error(ctx, GL_INVALID_VALUE, message);
1487 return -1;
1488 }
1489 internalFormat = GL_LUMINANCE_ALPHA;
1490 break;
1491 case GL_COMPRESSED_INTENSITY_ARB:
1492 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1493 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1494 gl_error(ctx, GL_INVALID_VALUE, message);
1495 return -1;
1496 }
1497 internalFormat = GL_INTENSITY;
1498 break;
1499 case GL_COMPRESSED_RGB_ARB:
1500 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1501 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1502 gl_error(ctx, GL_INVALID_VALUE, message);
1503 return -1;
1504 }
1505 internalFormat = GL_RGB;
1506 break;
1507 case GL_COMPRESSED_RGBA_ARB:
1508 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1509 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1510 gl_error(ctx, GL_INVALID_VALUE, message);
1511 return -1;
1512 }
1513 internalFormat = GL_RGBA;
1514 break;
1515 default:
1516 /* silence compiler warning */
1517 ;
1518 }
1519 return internalFormat;
1520 }
1521
1522
1523
1524 /*
1525 * Called from the API. Note that width includes the border.
1526 */
1527 void
1528 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1529 GLsizei width, GLint border, GLenum format,
1530 GLenum type, const GLvoid *pixels )
1531 {
1532 GLsizei postConvWidth;
1533 GET_CURRENT_CONTEXT(ctx);
1534 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1535
1536 postConvWidth = width;
1537 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1538
1539 if (target==GL_TEXTURE_1D) {
1540 struct gl_texture_unit *texUnit;
1541 struct gl_texture_object *texObj;
1542 struct gl_texture_image *texImage;
1543 GLint ifmt;
1544
1545 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1);
1546 if (ifmt < 0) {
1547 /*
1548 * The error here is that we were sent a generic compressed
1549 * format, but the extension is not supported.
1550 */
1551 return;
1552 }
1553 else {
1554 internalFormat = ifmt;
1555 }
1556
1557 if (texture_error_check(ctx, target, level, internalFormat,
1558 format, type, 1, postConvWidth, 1, 1, border)) {
1559 return; /* error in texture image was detected */
1560 }
1561
1562 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1563 texObj = texUnit->CurrentD[1];
1564 texImage = texObj->Image[level];
1565
1566 if (!texImage) {
1567 texImage = _mesa_alloc_texture_image();
1568 texObj->Image[level] = texImage;
1569 if (!texImage) {
1570 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1571 return;
1572 }
1573 }
1574 else if (texImage->Data) {
1575 FREE(texImage->Data);
1576 texImage->Data = NULL;
1577 }
1578
1579 /* setup the teximage struct's fields */
1580 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1581
1582 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1583 _mesa_update_image_transfer_state(ctx);
1584
1585 /* process the texture image */
1586 if (pixels) {
1587 GLboolean retain = GL_TRUE;
1588 GLboolean success = GL_FALSE;
1589 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
1590 /* let device driver try to use raw image */
1591 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1592 type, pixels, &ctx->Unpack,
1593 texObj, texImage, &retain);
1594 }
1595 if (retain || !success) {
1596 /* make internal copy of the texture image */
1597 make_texture_image(ctx, 1, texImage, width, 1, 1,
1598 format, type, pixels, &ctx->Unpack);
1599 if (!success && ctx->Driver.TexImage1D) {
1600 /* let device driver try to use unpacked image */
1601 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1602 GL_UNSIGNED_BYTE, texImage->Data,
1603 &_mesa_native_packing,
1604 texObj, texImage, &retain);
1605 }
1606 }
1607 if (!retain && texImage->Data) {
1608 FREE(texImage->Data);
1609 texImage->Data = NULL;
1610 }
1611 }
1612 else {
1613 make_null_texture(texImage);
1614 if (ctx->Driver.TexImage1D) {
1615 GLboolean retain;
1616 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1617 GL_UNSIGNED_BYTE, texImage->Data,
1618 &_mesa_native_packing,
1619 texObj, texImage, &retain);
1620 }
1621 }
1622
1623 /* state update */
1624 gl_put_texobj_on_dirty_list( ctx, texObj );
1625 ctx->NewState |= NEW_TEXTURING;
1626 }
1627 else if (target==GL_PROXY_TEXTURE_1D) {
1628 /* Proxy texture: check for errors and update proxy state */
1629 if (texture_error_check(ctx, target, level, internalFormat,
1630 format, type, 1, postConvWidth, 1, 1, border)) {
1631 /* if error, clear all proxy texture image parameters */
1632 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1633 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1634 sizeof(struct gl_texture_image) );
1635 }
1636 }
1637 else {
1638 /* if no error, update proxy texture image parameters */
1639 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1640 width, 1, 1, border, internalFormat);
1641 }
1642 }
1643 else {
1644 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1645 return;
1646 }
1647 }
1648
1649
1650 void
1651 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1652 GLsizei width, GLsizei height, GLint border,
1653 GLenum format, GLenum type,
1654 const GLvoid *pixels )
1655 {
1656 GLsizei postConvWidth, postConvHeight;
1657 GET_CURRENT_CONTEXT(ctx);
1658 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1659
1660 postConvWidth = width;
1661 postConvHeight = height;
1662 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1663
1664 if (target==GL_TEXTURE_2D ||
1665 (ctx->Extensions.HaveTextureCubeMap &&
1666 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1667 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1668 struct gl_texture_unit *texUnit;
1669 struct gl_texture_object *texObj;
1670 struct gl_texture_image *texImage;
1671 GLint ifmt;
1672
1673 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2);
1674 if (ifmt < 0) {
1675 /*
1676 * The error here is that we were sent a generic compressed
1677 * format, but the extension is not supported.
1678 */
1679 return;
1680 }
1681 else {
1682 internalFormat = ifmt;
1683 }
1684
1685 if (texture_error_check(ctx, target, level, internalFormat,
1686 format, type, 2, postConvWidth, postConvHeight,
1687 1, border)) {
1688 return; /* error in texture image was detected */
1689 }
1690
1691 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1692 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1693 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1694
1695 if (!texImage) {
1696 texImage = _mesa_alloc_texture_image();
1697 set_tex_image(texObj, target, level, texImage);
1698 /*texObj->Image[level] = texImage;*/
1699 if (!texImage) {
1700 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1701 return;
1702 }
1703 }
1704 else if (texImage->Data) {
1705 FREE(texImage->Data);
1706 texImage->Data = NULL;
1707 }
1708
1709 /* setup the teximage struct's fields */
1710 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1711 1, border, internalFormat);
1712
1713 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1714 _mesa_update_image_transfer_state(ctx);
1715
1716 /* process the texture image */
1717 if (pixels) {
1718 GLboolean retain = GL_TRUE;
1719 GLboolean success = GL_FALSE;
1720 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
1721 /* let device driver try to use raw image */
1722 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1723 type, pixels, &ctx->Unpack,
1724 texObj, texImage, &retain);
1725 }
1726 if (retain || !success) {
1727 /* make internal copy of the texture image */
1728 make_texture_image(ctx, 2, texImage, width, height, 1,
1729 format, type, pixels, &ctx->Unpack);
1730 if (!success && ctx->Driver.TexImage2D) {
1731 /* let device driver try to use unpacked image */
1732 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1733 GL_UNSIGNED_BYTE, texImage->Data,
1734 &_mesa_native_packing,
1735 texObj, texImage, &retain);
1736 }
1737 }
1738 if (!retain && texImage->Data) {
1739 FREE(texImage->Data);
1740 texImage->Data = NULL;
1741 }
1742 }
1743 else {
1744 make_null_texture(texImage);
1745 if (ctx->Driver.TexImage2D) {
1746 GLboolean retain;
1747 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1748 GL_UNSIGNED_BYTE, texImage->Data,
1749 &_mesa_native_packing,
1750 texObj, texImage, &retain);
1751 }
1752 }
1753
1754 #define OLD_DD_TEXTURE
1755 #ifdef OLD_DD_TEXTURE
1756 /* XXX this will be removed in the future */
1757 if (ctx->Driver.TexImage) {
1758 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1759 texImage );
1760 }
1761 #endif
1762
1763 /* state update */
1764 gl_put_texobj_on_dirty_list( ctx, texObj );
1765 ctx->NewState |= NEW_TEXTURING;
1766 }
1767 else if (target==GL_PROXY_TEXTURE_2D) {
1768 /* Proxy texture: check for errors and update proxy state */
1769 if (texture_error_check(ctx, target, level, internalFormat,
1770 format, type, 2, postConvWidth, height, 1, border)) {
1771 /* if error, clear all proxy texture image parameters */
1772 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1773 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1774 sizeof(struct gl_texture_image) );
1775 }
1776 }
1777 else {
1778 /* if no error, update proxy texture image parameters */
1779 init_texture_image(ctx,
1780 ctx->Texture.Proxy2D->Image[level],
1781 width, height, 1, border, internalFormat);
1782 }
1783 }
1784 else {
1785 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1786 return;
1787 }
1788 }
1789
1790
1791
1792 /*
1793 * Called by the API or display list executor.
1794 * Note that width and height include the border.
1795 */
1796 void
1797 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1798 GLsizei width, GLsizei height, GLsizei depth,
1799 GLint border, GLenum format, GLenum type,
1800 const GLvoid *pixels )
1801 {
1802 GET_CURRENT_CONTEXT(ctx);
1803 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1804
1805 if (target==GL_TEXTURE_3D_EXT) {
1806 struct gl_texture_unit *texUnit;
1807 struct gl_texture_object *texObj;
1808 struct gl_texture_image *texImage;
1809 GLint ifmt;
1810
1811 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3);
1812 if (ifmt < 0) {
1813 /*
1814 * The error here is that we were sent a generic compressed
1815 * format, but the extension is not supported.
1816 */
1817 return;
1818 }
1819 else {
1820 internalFormat = ifmt;
1821 }
1822
1823 if (texture_error_check(ctx, target, level, internalFormat,
1824 format, type, 3, width, height, depth, border)) {
1825 return; /* error in texture image was detected */
1826 }
1827
1828 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1829 texObj = texUnit->CurrentD[3];
1830 texImage = texObj->Image[level];
1831
1832 if (!texImage) {
1833 texImage = _mesa_alloc_texture_image();
1834 texObj->Image[level] = texImage;
1835 if (!texImage) {
1836 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1837 return;
1838 }
1839 }
1840 else if (texImage->Data) {
1841 FREE(texImage->Data);
1842 texImage->Data = NULL;
1843 }
1844
1845 /* setup the teximage struct's fields */
1846 init_texture_image(ctx, texImage, width, height, depth,
1847 border, internalFormat);
1848
1849 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1850 _mesa_update_image_transfer_state(ctx);
1851
1852 /* process the texture image */
1853 if (pixels) {
1854 GLboolean retain = GL_TRUE;
1855 GLboolean success = GL_FALSE;
1856 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
1857 /* let device driver try to use raw image */
1858 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1859 type, pixels, &ctx->Unpack,
1860 texObj, texImage, &retain);
1861 }
1862 if (retain || !success) {
1863 /* make internal copy of the texture image */
1864 make_texture_image(ctx, 3, texImage, width, height, depth,
1865 format, type, pixels, &ctx->Unpack);
1866 if (!success && ctx->Driver.TexImage3D) {
1867 /* let device driver try to use unpacked image */
1868 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1869 GL_UNSIGNED_BYTE, texImage->Data,
1870 &_mesa_native_packing,
1871 texObj, texImage, &retain);
1872 }
1873 }
1874 if (!retain && texImage->Data) {
1875 FREE(texImage->Data);
1876 texImage->Data = NULL;
1877 }
1878 }
1879 else {
1880 make_null_texture(texImage);
1881 if (ctx->Driver.TexImage3D) {
1882 GLboolean retain;
1883 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1884 GL_UNSIGNED_BYTE, texImage->Data,
1885 &_mesa_native_packing,
1886 texObj, texImage, &retain);
1887 }
1888 }
1889
1890 /* state update */
1891 gl_put_texobj_on_dirty_list( ctx, texObj );
1892 ctx->NewState |= NEW_TEXTURING;
1893 }
1894 else if (target==GL_PROXY_TEXTURE_3D) {
1895 /* Proxy texture: check for errors and update proxy state */
1896 if (texture_error_check(ctx, target, level, internalFormat,
1897 format, type, 3, width, height, depth, border)) {
1898 /* if error, clear all proxy texture image parameters */
1899 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1900 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1901 sizeof(struct gl_texture_image) );
1902 }
1903 }
1904 else {
1905 /* if no error, update proxy texture image parameters */
1906 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
1907 width, height, depth, border, internalFormat);
1908 }
1909 }
1910 else {
1911 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1912 return;
1913 }
1914 }
1915
1916
1917 void
1918 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1919 GLsizei width, GLsizei height, GLsizei depth,
1920 GLint border, GLenum format, GLenum type,
1921 const GLvoid *pixels )
1922 {
1923 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1924 depth, border, format, type, pixels);
1925 }
1926
1927
1928 /*
1929 * Fetch a texture image from the device driver.
1930 * Store the results in the given texture object at the given mipmap level.
1931 */
1932 void
1933 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1934 const struct gl_texture_object *texObj )
1935 {
1936 GLvoid *image;
1937 GLenum imgFormat, imgType;
1938 GLboolean freeImage;
1939 struct gl_texture_image *texImage;
1940 GLint destComponents, numPixels, srcBytesPerTexel;
1941
1942 if (!ctx->Driver.GetTexImage)
1943 return;
1944
1945 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
1946 &imgFormat, &imgType, &freeImage);
1947 if (!image)
1948 return;
1949
1950 texImage = texObj->Image[level];
1951 ASSERT(texImage);
1952 if (!texImage)
1953 return;
1954
1955 destComponents = components_in_intformat(texImage->Format);
1956 assert(destComponents > 0);
1957 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1958 assert(numPixels > 0);
1959 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1960 assert(srcBytesPerTexel > 0);
1961
1962 if (!texImage->Data) {
1963 /* Allocate memory for the texture image data */
1964 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1965 }
1966
1967 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1968 /* We got lucky! The driver's format and type match Mesa's format. */
1969 if (texImage->Data) {
1970 MEMCPY(texImage->Data, image, numPixels * destComponents);
1971 }
1972 }
1973 else {
1974 /* Convert the texture image from the driver's format to Mesa's
1975 * internal format.
1976 */
1977 const GLint width = texImage->Width;
1978 const GLint height = texImage->Height;
1979 const GLint depth = texImage->Depth;
1980 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1981 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1982 const GLenum dstType = GL_UNSIGNED_BYTE;
1983 const GLenum dstFormat = texImage->Format;
1984 const GLubyte *srcPtr = (const GLubyte *) image;
1985 GLubyte *destPtr = texImage->Data;
1986
1987 if (texImage->Format == GL_COLOR_INDEX) {
1988 /* color index texture */
1989 GLint img, row;
1990 assert(imgFormat == GL_COLOR_INDEX);
1991 for (img = 0; img < depth; img++) {
1992 for (row = 0; row < height; row++) {
1993 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1994 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1995 destPtr += destBytesPerRow;
1996 srcPtr += srcBytesPerRow;
1997 }
1998 }
1999 }
2000 else {
2001 /* color texture */
2002 GLint img, row;
2003 for (img = 0; img < depth; img++) {
2004 for (row = 0; row < height; row++) {
2005 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
2006 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2007 destPtr += destBytesPerRow;
2008 srcPtr += srcBytesPerRow;
2009 }
2010 }
2011 }
2012 }
2013
2014 if (freeImage)
2015 FREE(image);
2016 }
2017
2018
2019 void
2020 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2021 GLenum type, GLvoid *pixels )
2022 {
2023 GET_CURRENT_CONTEXT(ctx);
2024 const struct gl_texture_object *texObj;
2025 struct gl_texture_image *texImage;
2026 GLboolean discardImage;
2027
2028 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2029
2030 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2031 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2032 return;
2033 }
2034
2035 if (_mesa_sizeof_type(type) <= 0) {
2036 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2037 return;
2038 }
2039
2040 if (_mesa_components_in_format(format) <= 0) {
2041 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2042 return;
2043 }
2044
2045 if (!pixels)
2046 return;
2047
2048 switch (target) {
2049 case GL_TEXTURE_1D:
2050 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
2051 texImage = texObj->Image[level];
2052 break;
2053 case GL_TEXTURE_2D:
2054 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
2055 texImage = texObj->Image[level];
2056 break;
2057 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2058 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2059 texImage = texObj->Image[level];
2060 break;
2061 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2062 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2063 texImage = texObj->NegX[level];
2064 break;
2065 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2066 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2067 texImage = texObj->PosY[level];
2068 break;
2069 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2070 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2071 texImage = texObj->NegY[level];
2072 break;
2073 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2074 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2075 texImage = texObj->PosZ[level];
2076 break;
2077 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2078 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
2079 texImage = texObj->NegZ[level];
2080 break;
2081 case GL_TEXTURE_3D:
2082 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
2083 texImage = texObj->Image[level];
2084 break;
2085 default:
2086 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
2087 return;
2088 }
2089
2090 if (!texImage) {
2091 /* invalid mipmap level */
2092 return;
2093 }
2094
2095 if (!texImage->Data) {
2096 /* try to get the texture image from the device driver */
2097 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2098 discardImage = GL_TRUE;
2099 }
2100 else {
2101 discardImage = GL_FALSE;
2102 }
2103
2104 if (texImage->Data) {
2105 GLint width = texImage->Width;
2106 GLint height = texImage->Height;
2107 GLint row;
2108
2109 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2110 _mesa_update_image_transfer_state(ctx);
2111
2112 for (row = 0; row < height; row++) {
2113 /* compute destination address in client memory */
2114 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2115 width, height,
2116 format, type, 0, row, 0);
2117
2118 assert(dest);
2119 if (texImage->Format == GL_RGBA) {
2120 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
2121 /* XXX convolution */
2122 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2123 format, type, dest, &ctx->Pack,
2124 ctx->ImageTransferState );
2125 }
2126 else {
2127 /* fetch RGBA row from texture image then pack it in client mem */
2128 GLubyte rgba[MAX_WIDTH][4];
2129 GLint i;
2130 const GLubyte *src;
2131 switch (texImage->Format) {
2132 case GL_ALPHA:
2133 src = texImage->Data + row * width * sizeof(GLubyte);
2134 for (i = 0; i < width; i++) {
2135 rgba[i][RCOMP] = 255;
2136 rgba[i][GCOMP] = 255;
2137 rgba[i][BCOMP] = 255;
2138 rgba[i][ACOMP] = src[i];
2139 }
2140 break;
2141 case GL_LUMINANCE:
2142 src = texImage->Data + row * width * sizeof(GLubyte);
2143 for (i = 0; i < width; i++) {
2144 rgba[i][RCOMP] = src[i];
2145 rgba[i][GCOMP] = src[i];
2146 rgba[i][BCOMP] = src[i];
2147 rgba[i][ACOMP] = 255;
2148 }
2149 break;
2150 case GL_LUMINANCE_ALPHA:
2151 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2152 for (i = 0; i < width; i++) {
2153 rgba[i][RCOMP] = src[i*2+0];
2154 rgba[i][GCOMP] = src[i*2+0];
2155 rgba[i][BCOMP] = src[i*2+0];
2156 rgba[i][ACOMP] = src[i*2+1];
2157 }
2158 break;
2159 case GL_INTENSITY:
2160 src = texImage->Data + row * width * sizeof(GLubyte);
2161 for (i = 0; i < width; i++) {
2162 rgba[i][RCOMP] = src[i];
2163 rgba[i][GCOMP] = src[i];
2164 rgba[i][BCOMP] = src[i];
2165 rgba[i][ACOMP] = 255;
2166 }
2167 break;
2168 case GL_RGB:
2169 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2170 for (i = 0; i < width; i++) {
2171 rgba[i][RCOMP] = src[i*3+0];
2172 rgba[i][GCOMP] = src[i*3+1];
2173 rgba[i][BCOMP] = src[i*3+2];
2174 rgba[i][ACOMP] = 255;
2175 }
2176 break;
2177 case GL_RGBA:
2178 /* this special case should have been handled above! */
2179 gl_problem( ctx, "error 1 in gl_GetTexImage" );
2180 break;
2181 case GL_COLOR_INDEX:
2182 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2183 break;
2184 default:
2185 gl_problem( ctx, "bad format in gl_GetTexImage" );
2186 }
2187 /* XXX convolution */
2188 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2189 format, type, dest, &ctx->Pack,
2190 ctx->ImageTransferState );
2191 }
2192 }
2193
2194 /* if we got the teximage from the device driver we'll discard it now */
2195 if (discardImage) {
2196 FREE(texImage->Data);
2197 texImage->Data = NULL;
2198 }
2199 }
2200 }
2201
2202
2203
2204 void
2205 _mesa_TexSubImage1D( GLenum target, GLint level,
2206 GLint xoffset, GLsizei width,
2207 GLenum format, GLenum type,
2208 const GLvoid *pixels )
2209 {
2210 GET_CURRENT_CONTEXT(ctx);
2211 struct gl_texture_unit *texUnit;
2212 struct gl_texture_object *texObj;
2213 struct gl_texture_image *texImage;
2214 GLboolean success = GL_FALSE;
2215
2216 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2217 width, 1, 1, format, type)) {
2218 return; /* error was detected */
2219 }
2220
2221 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2222 texObj = texUnit->CurrentD[1];
2223 texImage = texObj->Image[level];
2224 assert(texImage);
2225
2226 if (width == 0 || !pixels)
2227 return; /* no-op, not an error */
2228
2229 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2230 _mesa_update_image_transfer_state(ctx);
2231
2232 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2233 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2234 width, format, type, pixels,
2235 &ctx->Unpack, texObj, texImage );
2236 }
2237 if (!success) {
2238 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2239
2240 const GLint texComponents = components_in_intformat(texImage->Format);
2241 const GLenum texFormat = texImage->Format;
2242 const GLint xoffsetb = xoffset + texImage->Border;
2243 GLboolean retain = GL_TRUE;
2244 if (!texImage->Data) {
2245 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2246 if (!texImage->Data) {
2247 make_null_texture(texImage);
2248 }
2249 if (!texImage->Data)
2250 return; /* we're really out of luck! */
2251 }
2252
2253 if (texFormat == GL_COLOR_INDEX) {
2254 /* color index texture */
2255 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
2256 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
2257 1, format, type, 0, 0, 0);
2258 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
2259 type, src, &ctx->Unpack,
2260 ctx->ImageTransferState);
2261 }
2262 else {
2263 /* color texture */
2264 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
2265 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
2266 1, format, type, 0, 0, 0);
2267 /* XXX change for convolution */
2268 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
2269 type, src, &ctx->Unpack,
2270 ctx->ImageTransferState);
2271 }
2272
2273 if (ctx->Driver.TexImage1D) {
2274 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2275 GL_UNSIGNED_BYTE, texImage->Data,
2276 &_mesa_native_packing, texObj, texImage,
2277 &retain );
2278 }
2279
2280 if (!retain && texImage->Data) {
2281 FREE(texImage->Data);
2282 texImage->Data = NULL;
2283 }
2284 }
2285
2286 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
2287 }
2288
2289
2290 void
2291 _mesa_TexSubImage2D( GLenum target, GLint level,
2292 GLint xoffset, GLint yoffset,
2293 GLsizei width, GLsizei height,
2294 GLenum format, GLenum type,
2295 const GLvoid *pixels )
2296 {
2297 GET_CURRENT_CONTEXT(ctx);
2298 struct gl_texture_unit *texUnit;
2299 struct gl_texture_object *texObj;
2300 struct gl_texture_image *texImage;
2301 GLboolean success = GL_FALSE;
2302
2303 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2304 width, height, 1, format, type)) {
2305 return; /* error was detected */
2306 }
2307
2308 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2309 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2310 texImage = texObj->Image[level];
2311 assert(texImage);
2312
2313 if (width == 0 || height == 0 || !pixels)
2314 return; /* no-op, not an error */
2315
2316 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2317 _mesa_update_image_transfer_state(ctx);
2318
2319 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2320 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2321 yoffset, width, height, format, type,
2322 pixels, &ctx->Unpack, texObj, texImage );
2323 }
2324 if (!success) {
2325 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2326
2327 const GLint texComponents = components_in_intformat(texImage->Format);
2328 const GLenum texFormat = texImage->Format;
2329 const GLint xoffsetb = xoffset + texImage->Border;
2330 const GLint yoffsetb = yoffset + texImage->Border;
2331 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
2332 format, type);
2333 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
2334 GLboolean retain = GL_TRUE;
2335
2336 if (!texImage->Data) {
2337 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2338 if (!texImage->Data) {
2339 make_null_texture(texImage);
2340 }
2341 if (!texImage->Data)
2342 return; /* we're really out of luck! */
2343 }
2344
2345 if (texFormat == GL_COLOR_INDEX) {
2346 /* color index texture */
2347 GLubyte *dst = texImage->Data
2348 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2349 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2350 width, height, format, type, 0, 0, 0);
2351 GLint row;
2352 for (row = 0; row < height; row++) {
2353 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
2354 (const GLvoid *) src, &ctx->Unpack,
2355 ctx->ImageTransferState);
2356 src += srcStride;
2357 dst += dstStride;
2358 }
2359 }
2360 else {
2361 /* color texture */
2362 GLubyte *dst = texImage->Data
2363 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2364 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2365 width, height, format, type, 0, 0, 0);
2366 GLint row;
2367 /* XXX change for convolution */
2368 for (row = 0; row < height; row++) {
2369 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
2370 type, (const GLvoid *) src,
2371 &ctx->Unpack,
2372 ctx->ImageTransferState);
2373 src += srcStride;
2374 dst += dstStride;
2375 }
2376 }
2377
2378 if (ctx->Driver.TexImage2D) {
2379 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2380 GL_UNSIGNED_BYTE, texImage->Data,
2381 &_mesa_native_packing, texObj, texImage,
2382 &retain);
2383 }
2384
2385 if (!retain && texImage->Data) {
2386 FREE(texImage->Data);
2387 texImage->Data = NULL;
2388 }
2389
2390 #ifdef OLD_DD_TEXTURE
2391 /* XXX this will be removed in the future */
2392 if (ctx->Driver.TexSubImage) {
2393 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2394 xoffset, yoffset, width, height,
2395 texImage->IntFormat, texImage);
2396 }
2397 else if (ctx->Driver.TexImage) {
2398 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2399 level, texImage->IntFormat, texImage );
2400 }
2401 #endif
2402 }
2403 }
2404
2405
2406
2407 void
2408 _mesa_TexSubImage3D( GLenum target, GLint level,
2409 GLint xoffset, GLint yoffset, GLint zoffset,
2410 GLsizei width, GLsizei height, GLsizei depth,
2411 GLenum format, GLenum type,
2412 const GLvoid *pixels )
2413 {
2414 GET_CURRENT_CONTEXT(ctx);
2415 struct gl_texture_unit *texUnit;
2416 struct gl_texture_object *texObj;
2417 struct gl_texture_image *texImage;
2418 GLboolean success = GL_FALSE;
2419
2420 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2421 width, height, depth, format, type)) {
2422 return; /* error was detected */
2423 }
2424
2425 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2426 texObj = texUnit->CurrentD[3];
2427 texImage = texObj->Image[level];
2428 assert(texImage);
2429
2430 if (width == 0 || height == 0 || height == 0 || !pixels)
2431 return; /* no-op, not an error */
2432
2433 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2434 _mesa_update_image_transfer_state(ctx);
2435
2436 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2437 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2438 yoffset, zoffset, width, height, depth, format,
2439 type, pixels, &ctx->Unpack, texObj, texImage );
2440 }
2441 if (!success) {
2442 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2443
2444 const GLint texComponents = components_in_intformat(texImage->Format);
2445 const GLenum texFormat = texImage->Format;
2446 const GLint xoffsetb = xoffset + texImage->Border;
2447 const GLint yoffsetb = yoffset + texImage->Border;
2448 const GLint zoffsetb = zoffset + texImage->Border;
2449 const GLint texWidth = texImage->Width;
2450 const GLint dstRectArea = texWidth * texImage->Height;
2451 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
2452 width, format, type);
2453 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
2454 GLboolean retain = GL_TRUE;
2455
2456 if (texFormat == GL_COLOR_INDEX) {
2457 /* color index texture */
2458 GLint img, row;
2459 for (img = 0; img < depth; img++) {
2460 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2461 width, height, format, type, img, 0, 0);
2462 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2463 + yoffsetb * texWidth + xoffsetb) * texComponents;
2464 for (row = 0; row < height; row++) {
2465 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
2466 type, (const GLvoid *) src,
2467 &ctx->Unpack, ctx->ImageTransferState);
2468 src += srcStride;
2469 dst += dstStride;
2470 }
2471 }
2472 }
2473 else {
2474 /* color texture */
2475 GLint img, row;
2476 /* XXX convolution */
2477 for (img = 0; img < depth; img++) {
2478 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2479 width, height, format, type, img, 0, 0);
2480 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2481 + yoffsetb * texWidth + xoffsetb) * texComponents;
2482 for (row = 0; row < height; row++) {
2483 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
2484 format, type,
2485 (const GLvoid *) src,
2486 &ctx->Unpack,
2487 ctx->ImageTransferState);
2488 src += srcStride;
2489 dst += dstStride;
2490 }
2491 }
2492 }
2493
2494 if (ctx->Driver.TexImage3D) {
2495 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2496 GL_UNSIGNED_BYTE, texImage->Data,
2497 &_mesa_native_packing, texObj, texImage,
2498 &retain);
2499 }
2500
2501 if (!retain && texImage->Data) {
2502 FREE(texImage->Data);
2503 texImage->Data = NULL;
2504 }
2505 }
2506 }
2507
2508
2509
2510 /*
2511 * Read an RGBA image from the frame buffer.
2512 * This is used by glCopyTexSubImage[12]D().
2513 * Input: ctx - the context
2514 * x, y - lower left corner
2515 * width, height - size of region to read
2516 * Return: pointer to block of GL_RGBA, GLubyte data.
2517 */
2518 static GLubyte *
2519 read_color_image( GLcontext *ctx, GLint x, GLint y,
2520 GLsizei width, GLsizei height )
2521 {
2522 GLint stride, i;
2523 GLubyte *image, *dst;
2524
2525 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2526 if (!image)
2527 return NULL;
2528
2529 /* Select buffer to read from */
2530 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2531 ctx->Pixel.DriverReadBuffer );
2532
2533 /* XXX TODO we have to apply pixel transfer ops here! */
2534
2535 dst = image;
2536 stride = width * 4 * sizeof(GLubyte);
2537 for (i = 0; i < height; i++) {
2538 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2539 (GLubyte (*)[4]) dst );
2540 dst += stride;
2541 }
2542
2543 /* Read from draw buffer (the default) */
2544 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2545 ctx->Color.DriverDrawBuffer );
2546
2547 return image;
2548 }
2549
2550
2551
2552 void
2553 _mesa_CopyTexImage1D( GLenum target, GLint level,
2554 GLenum internalFormat,
2555 GLint x, GLint y,
2556 GLsizei width, GLint border )
2557 {
2558 GET_CURRENT_CONTEXT(ctx);
2559 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2560
2561 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2562 width, 1, border))
2563 return;
2564
2565 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2566 _mesa_update_image_transfer_state(ctx);
2567
2568 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2569 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2570 internalFormat, x, y, width, border))
2571 {
2572 struct gl_pixelstore_attrib unpackSave;
2573
2574 /* get image from framebuffer */
2575 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2576 if (!image) {
2577 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2578 return;
2579 }
2580
2581 /* call glTexImage1D to redefine the texture */
2582 unpackSave = ctx->Unpack;
2583 ctx->Unpack = _mesa_native_packing;
2584 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2585 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2586 ctx->Unpack = unpackSave;
2587
2588 FREE(image);
2589 }
2590 }
2591
2592
2593
2594 void
2595 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2596 GLint x, GLint y, GLsizei width, GLsizei height,
2597 GLint border )
2598 {
2599 GET_CURRENT_CONTEXT(ctx);
2600 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2601
2602 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2603 width, height, border))
2604 return;
2605
2606 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2607 _mesa_update_image_transfer_state(ctx);
2608
2609 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2610 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2611 internalFormat, x, y, width, height, border))
2612 {
2613 struct gl_pixelstore_attrib unpackSave;
2614
2615 /* get image from framebuffer */
2616 GLubyte *image = read_color_image( ctx, x, y, width, height );
2617 if (!image) {
2618 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2619 return;
2620 }
2621
2622 /* call glTexImage2D to redefine the texture */
2623 unpackSave = ctx->Unpack;
2624 ctx->Unpack = _mesa_native_packing;
2625 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2626 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2627 ctx->Unpack = unpackSave;
2628
2629 FREE(image);
2630 }
2631 }
2632
2633
2634
2635 void
2636 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2637 GLint xoffset, GLint x, GLint y, GLsizei width )
2638 {
2639 GET_CURRENT_CONTEXT(ctx);
2640 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2641
2642 if (copytexsubimage_error_check(ctx, 1, target, level,
2643 xoffset, 0, 0, width, 1))
2644 return;
2645
2646 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2647 _mesa_update_image_transfer_state(ctx);
2648
2649 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2650 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2651 xoffset, x, y, width)) {
2652 struct gl_texture_unit *texUnit;
2653 struct gl_texture_image *teximage;
2654 struct gl_pixelstore_attrib unpackSave;
2655 GLubyte *image;
2656
2657 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2658 teximage = texUnit->CurrentD[1]->Image[level];
2659 assert(teximage);
2660
2661 /* get image from frame buffer */
2662 image = read_color_image(ctx, x, y, width, 1);
2663 if (!image) {
2664 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2665 return;
2666 }
2667
2668 /* now call glTexSubImage1D to do the real work */
2669 unpackSave = ctx->Unpack;
2670 ctx->Unpack = _mesa_native_packing;
2671 _mesa_TexSubImage1D(target, level, xoffset, width,
2672 GL_RGBA, GL_UNSIGNED_BYTE, image);
2673 ctx->Unpack = unpackSave;
2674
2675 FREE(image);
2676 }
2677 }
2678
2679
2680
2681 void
2682 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2683 GLint xoffset, GLint yoffset,
2684 GLint x, GLint y, GLsizei width, GLsizei height )
2685 {
2686 GET_CURRENT_CONTEXT(ctx);
2687 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2688
2689 if (copytexsubimage_error_check(ctx, 2, target, level,
2690 xoffset, yoffset, 0, width, height))
2691 return;
2692
2693 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2694 _mesa_update_image_transfer_state(ctx);
2695
2696 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2697 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2698 xoffset, yoffset, x, y, width, height )) {
2699 struct gl_texture_unit *texUnit;
2700 struct gl_texture_image *teximage;
2701 struct gl_pixelstore_attrib unpackSave;
2702 GLubyte *image;
2703
2704 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2705 teximage = texUnit->CurrentD[2]->Image[level];
2706 assert(teximage);
2707
2708 /* get image from frame buffer */
2709 image = read_color_image(ctx, x, y, width, height);
2710 if (!image) {
2711 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2712 return;
2713 }
2714
2715 /* now call glTexSubImage2D to do the real work */
2716 unpackSave = ctx->Unpack;
2717 ctx->Unpack = _mesa_native_packing;
2718 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2719 GL_RGBA, GL_UNSIGNED_BYTE, image);
2720 ctx->Unpack = unpackSave;
2721
2722 FREE(image);
2723 }
2724 }
2725
2726
2727
2728 void
2729 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2730 GLint xoffset, GLint yoffset, GLint zoffset,
2731 GLint x, GLint y, GLsizei width, GLsizei height )
2732 {
2733 GET_CURRENT_CONTEXT(ctx);
2734 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2735
2736 if (copytexsubimage_error_check(ctx, 3, target, level,
2737 xoffset, yoffset, zoffset, width, height))
2738 return;
2739
2740 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2741 _mesa_update_image_transfer_state(ctx);
2742
2743 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2744 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2745 xoffset, yoffset, zoffset, x, y, width, height )) {
2746 struct gl_texture_unit *texUnit;
2747 struct gl_texture_image *teximage;
2748 struct gl_pixelstore_attrib unpackSave;
2749 GLubyte *image;
2750
2751 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2752 teximage = texUnit->CurrentD[3]->Image[level];
2753 assert(teximage);
2754
2755 /* get image from frame buffer */
2756 image = read_color_image(ctx, x, y, width, height);
2757 if (!image) {
2758 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2759 return;
2760 }
2761
2762 /* now call glTexSubImage2D to do the real work */
2763 unpackSave = ctx->Unpack;
2764 ctx->Unpack = _mesa_native_packing;
2765 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2766 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2767 ctx->Unpack = unpackSave;
2768
2769 FREE(image);
2770 }
2771 }
2772
2773
2774
2775 void
2776 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2777 GLenum internalFormat, GLsizei width,
2778 GLint border, GLsizei imageSize,
2779 const GLvoid *data)
2780 {
2781 GET_CURRENT_CONTEXT(ctx);
2782 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2783
2784 switch (internalFormat) {
2785 case GL_COMPRESSED_ALPHA_ARB:
2786 case GL_COMPRESSED_LUMINANCE_ARB:
2787 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2788 case GL_COMPRESSED_INTENSITY_ARB:
2789 case GL_COMPRESSED_RGB_ARB:
2790 case GL_COMPRESSED_RGBA_ARB:
2791 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2792 return;
2793 default:
2794 /* silence compiler warning */
2795 ;
2796 }
2797
2798 if (target == GL_TEXTURE_1D) {
2799 struct gl_texture_unit *texUnit;
2800 struct gl_texture_object *texObj;
2801 struct gl_texture_image *texImage;
2802 GLsizei computedImageSize;
2803
2804 if (texture_error_check(ctx, target, level, internalFormat,
2805 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2806 return; /* error in texture image was detected */
2807 }
2808
2809 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2810 texObj = texUnit->CurrentD[1];
2811 texImage = texObj->Image[level];
2812
2813 if (!texImage) {
2814 texImage = _mesa_alloc_texture_image();
2815 texObj->Image[level] = texImage;
2816 if (!texImage) {
2817 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2818 return;
2819 }
2820 }
2821 else if (texImage->Data) {
2822 FREE(texImage->Data);
2823 texImage->Data = NULL;
2824 }
2825
2826 /* setup the teximage struct's fields */
2827 init_texture_image(ctx, texImage, width, 1, 1,
2828 border, internalFormat);
2829
2830 /* process the texture image */
2831 if (data) {
2832 GLboolean retain = GL_TRUE;
2833 GLboolean success = GL_FALSE;
2834 if (ctx->Driver.CompressedTexImage1D) {
2835 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2836 imageSize, data, texObj, texImage, &retain);
2837 }
2838 if (retain || !success) {
2839 /* make internal copy of the texture image */
2840 computedImageSize = _mesa_compressed_image_size(ctx,
2841 internalFormat,
2842 1, /* num dims */
2843 width,
2844 1, /* height */
2845 1); /* depth */
2846 if (computedImageSize != imageSize) {
2847 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2848 return;
2849 }
2850 texImage->Data = MALLOC(computedImageSize);
2851 if (texImage->Data) {
2852 MEMCPY(texImage->Data, data, computedImageSize);
2853 }
2854 }
2855 if (!retain && texImage->Data) {
2856 FREE(texImage->Data);
2857 texImage->Data = NULL;
2858 }
2859 }
2860 else {
2861 make_null_texture(texImage);
2862 if (ctx->Driver.CompressedTexImage1D) {
2863 GLboolean retain;
2864 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2865 texImage->Data, texObj,
2866 texImage, &retain);
2867 }
2868 }
2869
2870 /* state update */
2871 gl_put_texobj_on_dirty_list( ctx, texObj );
2872 ctx->NewState |= NEW_TEXTURING;
2873 }
2874 else if (target == GL_PROXY_TEXTURE_1D) {
2875 /* Proxy texture: check for errors and update proxy state */
2876 if (texture_error_check(ctx, target, level, internalFormat,
2877 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2878 /* if error, clear all proxy texture image parameters */
2879 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2880 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
2881 sizeof(struct gl_texture_image) );
2882 }
2883 }
2884 else {
2885 /* if no error, update proxy texture image parameters */
2886 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2887 width, 1, 1, border, internalFormat);
2888 }
2889 }
2890 else {
2891 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2892 return;
2893 }
2894 }
2895
2896
2897 void
2898 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2899 GLenum internalFormat, GLsizei width,
2900 GLsizei height, GLint border, GLsizei imageSize,
2901 const GLvoid *data)
2902 {
2903 GET_CURRENT_CONTEXT(ctx);
2904 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2905
2906 switch (internalFormat) {
2907 case GL_COMPRESSED_ALPHA_ARB:
2908 case GL_COMPRESSED_LUMINANCE_ARB:
2909 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2910 case GL_COMPRESSED_INTENSITY_ARB:
2911 case GL_COMPRESSED_RGB_ARB:
2912 case GL_COMPRESSED_RGBA_ARB:
2913 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2914 return;
2915 default:
2916 /* silence compiler warning */
2917 ;
2918 }
2919
2920 if (target==GL_TEXTURE_2D ||
2921 (ctx->Extensions.HaveTextureCubeMap &&
2922 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2923 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
2924 struct gl_texture_unit *texUnit;
2925 struct gl_texture_object *texObj;
2926 struct gl_texture_image *texImage;
2927 GLsizei computedImageSize;
2928
2929 if (texture_error_check(ctx, target, level, internalFormat,
2930 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2931 return; /* error in texture image was detected */
2932 }
2933
2934 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2935 texObj = texUnit->CurrentD[2];
2936 texImage = texObj->Image[level];
2937
2938 if (!texImage) {
2939 texImage = _mesa_alloc_texture_image();
2940 texObj->Image[level] = texImage;
2941 if (!texImage) {
2942 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2943 return;
2944 }
2945 }
2946 else if (texImage->Data) {
2947 FREE(texImage->Data);
2948 texImage->Data = NULL;
2949 }
2950
2951 /* setup the teximage struct's fields */
2952 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
2953
2954 /* process the texture image */
2955 if (data) {
2956 GLboolean retain = GL_TRUE;
2957 GLboolean success = GL_FALSE;
2958 if (ctx->Driver.CompressedTexImage2D) {
2959 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
2960 target,
2961 level,
2962 imageSize,
2963 data,
2964 texObj,
2965 texImage,
2966 &retain);
2967 }
2968 if (retain || !success) {
2969 /* make internal copy of the texture image */
2970 computedImageSize = _mesa_compressed_image_size(ctx,
2971 internalFormat,
2972 2, /* num dims */
2973 width,
2974 height,
2975 1); /* depth */
2976 if (computedImageSize != imageSize) {
2977 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
2978 return;
2979 }
2980 texImage->Data = MALLOC(computedImageSize);
2981 if (texImage->Data) {
2982 MEMCPY(texImage->Data, data, computedImageSize);
2983 }
2984 }
2985 if (!retain && texImage->Data) {
2986 FREE(texImage->Data);
2987 texImage->Data = NULL;
2988 }
2989 }
2990 else {
2991 make_null_texture(texImage);
2992 if (ctx->Driver.CompressedTexImage2D) {
2993 GLboolean retain;
2994 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
2995 texImage->Data, texObj,
2996 texImage, &retain);
2997 }
2998 }
2999
3000 /* state update */
3001 gl_put_texobj_on_dirty_list( ctx, texObj );
3002 ctx->NewState |= NEW_TEXTURING;
3003 }
3004 else if (target == GL_PROXY_TEXTURE_2D) {
3005 /* Proxy texture: check for errors and update proxy state */
3006 if (texture_error_check(ctx, target, level, internalFormat,
3007 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
3008 /* if error, clear all proxy texture image parameters */
3009 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3010 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
3011 sizeof(struct gl_texture_image) );
3012 }
3013 }
3014 else {
3015 /* if no error, update proxy texture image parameters */
3016 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3017 width, 1, 1, border, internalFormat);
3018 }
3019 }
3020 else {
3021 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3022 return;
3023 }
3024 }
3025
3026
3027 void
3028 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3029 GLenum internalFormat, GLsizei width,
3030 GLsizei height, GLsizei depth, GLint border,
3031 GLsizei imageSize, const GLvoid *data)
3032 {
3033 GET_CURRENT_CONTEXT(ctx);
3034 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3035
3036 switch (internalFormat) {
3037 case GL_COMPRESSED_ALPHA_ARB:
3038 case GL_COMPRESSED_LUMINANCE_ARB:
3039 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3040 case GL_COMPRESSED_INTENSITY_ARB:
3041 case GL_COMPRESSED_RGB_ARB:
3042 case GL_COMPRESSED_RGBA_ARB:
3043 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3044 return;
3045 default:
3046 /* silence compiler warning */
3047 ;
3048 }
3049
3050 if (target == GL_TEXTURE_3D) {
3051 struct gl_texture_unit *texUnit;
3052 struct gl_texture_object *texObj;
3053 struct gl_texture_image *texImage;
3054 GLsizei computedImageSize;
3055
3056 if (texture_error_check(ctx, target, level, internalFormat,
3057 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3058 return; /* error in texture image was detected */
3059 }
3060
3061 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3062 texObj = texUnit->CurrentD[3];
3063 texImage = texObj->Image[level];
3064
3065 if (!texImage) {
3066 texImage = _mesa_alloc_texture_image();
3067 texObj->Image[level] = texImage;
3068 if (!texImage) {
3069 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3070 return;
3071 }
3072 }
3073 else if (texImage->Data) {
3074 FREE(texImage->Data);
3075 texImage->Data = NULL;
3076 }
3077
3078 /* setup the teximage struct's fields */
3079 init_texture_image(ctx, texImage, width, height, depth,
3080 border, internalFormat);
3081
3082 /* process the texture image */
3083 if (data) {
3084 GLboolean retain = GL_TRUE;
3085 GLboolean success = GL_FALSE;
3086 if (ctx->Driver.CompressedTexImage3D) {
3087 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3088 imageSize, data,
3089 texObj, texImage,
3090 &retain);
3091 }
3092 if (retain || !success) {
3093 /* make internal copy of the texture image */
3094 computedImageSize = _mesa_compressed_image_size(ctx,
3095 internalFormat,
3096 3, /* num dims */
3097 width,
3098 height,
3099 depth);
3100 if (computedImageSize != imageSize) {
3101 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3102 return;
3103 }
3104 texImage->Data = MALLOC(computedImageSize);
3105 if (texImage->Data) {
3106 MEMCPY(texImage->Data, data, computedImageSize);
3107 }
3108 }
3109 if (!retain && texImage->Data) {
3110 FREE(texImage->Data);
3111 texImage->Data = NULL;
3112 }
3113 }
3114 else {
3115 make_null_texture(texImage);
3116 if (ctx->Driver.CompressedTexImage3D) {
3117 GLboolean retain;
3118 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3119 texImage->Data, texObj,
3120 texImage, &retain);
3121 }
3122 }
3123
3124 /* state update */
3125 gl_put_texobj_on_dirty_list( ctx, texObj );
3126 ctx->NewState |= NEW_TEXTURING;
3127 }
3128 else if (target == GL_PROXY_TEXTURE_3D) {
3129 /* Proxy texture: check for errors and update proxy state */
3130 if (texture_error_check(ctx, target, level, internalFormat,
3131 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3132 /* if error, clear all proxy texture image parameters */
3133 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3134 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
3135 sizeof(struct gl_texture_image) );
3136 }
3137 }
3138 else {
3139 /* if no error, update proxy texture image parameters */
3140 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3141 width, 1, 1, border, internalFormat);
3142 }
3143 }
3144 else {
3145 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3146 return;
3147 }
3148 }
3149
3150
3151 void
3152 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3153 GLsizei width, GLenum format,
3154 GLsizei imageSize, const GLvoid *data)
3155 {
3156 GET_CURRENT_CONTEXT(ctx);
3157 struct gl_texture_unit *texUnit;
3158 struct gl_texture_object *texObj;
3159 struct gl_texture_image *texImage;
3160 GLboolean success = GL_FALSE;
3161
3162 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3163 width, 1, 1, format, GL_NONE)) {
3164 return; /* error was detected */
3165 }
3166
3167 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3168 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3169 texImage = texObj->Image[level];
3170 assert(texImage);
3171
3172 if (width == 0 || !data)
3173 return; /* no-op, not an error */
3174
3175 if (ctx->Driver.CompressedTexSubImage1D) {
3176 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3177 xoffset, width, format, imageSize, data, texObj, texImage);
3178 }
3179 if (!success) {
3180 /* XXX what else can we do? */
3181 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3182 return;
3183 }
3184 }
3185
3186
3187 void
3188 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3189 GLint yoffset, GLsizei width, GLsizei height,
3190 GLenum format, GLsizei imageSize,
3191 const GLvoid *data)
3192 {
3193 GET_CURRENT_CONTEXT(ctx);
3194 struct gl_texture_unit *texUnit;
3195 struct gl_texture_object *texObj;
3196 struct gl_texture_image *texImage;
3197 GLboolean success = GL_FALSE;
3198
3199 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3200 width, height, 1, format, GL_NONE)) {
3201 return; /* error was detected */
3202 }
3203
3204 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3205 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3206 texImage = texObj->Image[level];
3207 assert(texImage);
3208
3209 if (width == 0 || height == 0 || !data)
3210 return; /* no-op, not an error */
3211
3212 if (ctx->Driver.CompressedTexSubImage2D) {
3213 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3214 xoffset, yoffset, width, height, format,
3215 imageSize, data, texObj, texImage);
3216 }
3217 if (!success) {
3218 /* XXX what else can we do? */
3219 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3220 return;
3221 }
3222 }
3223
3224
3225 void
3226 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3227 GLint yoffset, GLint zoffset, GLsizei width,
3228 GLsizei height, GLsizei depth, GLenum format,
3229 GLsizei imageSize, const GLvoid *data)
3230 {
3231 GET_CURRENT_CONTEXT(ctx);
3232 struct gl_texture_unit *texUnit;
3233 struct gl_texture_object *texObj;
3234 struct gl_texture_image *texImage;
3235 GLboolean success = GL_FALSE;
3236
3237 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3238 width, height, depth, format, GL_NONE)) {
3239 return; /* error was detected */
3240 }
3241
3242 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3243 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3244 texImage = texObj->Image[level];
3245 assert(texImage);
3246
3247 if (width == 0 || height == 0 || depth == 0 || !data)
3248 return; /* no-op, not an error */
3249
3250 if (ctx->Driver.CompressedTexSubImage3D) {
3251 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3252 xoffset, yoffset, zoffset, width, height, depth,
3253 format, imageSize, data, texObj, texImage);
3254 }
3255 if (!success) {
3256 /* XXX what else can we do? */
3257 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3258 return;
3259 }
3260 }
3261
3262
3263 void
3264 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3265 {
3266 GET_CURRENT_CONTEXT(ctx);
3267 const struct gl_texture_object *texObj;
3268 struct gl_texture_image *texImage;
3269
3270 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3271
3272 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3273 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3274 return;
3275 }
3276
3277 switch (target) {
3278 case GL_TEXTURE_1D:
3279 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3280 texImage = texObj->Image[level];
3281 break;
3282 case GL_TEXTURE_2D:
3283 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3284 texImage = texObj->Image[level];
3285 break;
3286 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3287 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3288 texImage = texObj->Image[level];
3289 break;
3290 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3291 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3292 texImage = texObj->NegX[level];
3293 break;
3294 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3295 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3296 texImage = texObj->PosY[level];
3297 break;
3298 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3299 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3300 texImage = texObj->NegY[level];
3301 break;
3302 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3303 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3304 texImage = texObj->PosZ[level];
3305 break;
3306 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3307 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3308 texImage = texObj->NegZ[level];
3309 break;
3310 case GL_TEXTURE_3D:
3311 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3312 texImage = texObj->Image[level];
3313 break;
3314 default:
3315 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3316 return;
3317 }
3318
3319 if (!texImage) {
3320 /* invalid mipmap level */
3321 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3322 return;
3323 }
3324
3325 if (!texImage->IsCompressed) {
3326 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3327 return;
3328 }
3329
3330 if (!img)
3331 return;
3332
3333 if (ctx->Driver.GetCompressedTexImage) {
3334 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3335 texImage);
3336 }
3337 else {
3338 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3339 }
3340 }