6e20fe87760784f624259d624730003d29c263c6
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.53 2000/10/28 18:34:48 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
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, const 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 /*
674 * This function is used to move user image data into a texture image.
675 * We handle full texture images and subtexture images. We also take
676 * care of all image transfer operations here, including convolution.
677 * Input:
678 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
679 * dstRowStride, dstImageStride - strides in bytes
680 */
681 static void
682 fill_texture_image( GLcontext *ctx, GLuint dimensions,
683 GLenum texFormat, GLubyte *texAddr,
684 GLint srcWidth, GLint srcHeight, GLint srcDepth,
685 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
686 GLint dstRowStride, GLint dstImageStride,
687 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
688 const struct gl_pixelstore_attrib *srcPacking)
689 {
690 GLint texComponents;
691
692 ASSERT(ctx);
693 ASSERT(dimensions >= 1 && dimensions <= 3);
694 ASSERT(texAddr);
695 ASSERT(srcWidth >= 1);
696 ASSERT(srcHeight >= 1);
697 ASSERT(srcDepth >= 1);
698 ASSERT(dstXoffset >= 0);
699 ASSERT(dstYoffset >= 0);
700 ASSERT(dstZoffset >= 0);
701 ASSERT(dstRowStride >= 0);
702 ASSERT(dstImageStride >= 0);
703 ASSERT(srcAddr);
704 ASSERT(srcPacking);
705
706 texComponents = components_in_intformat(texFormat);
707
708 /* try common 2D texture cases first */
709 if (!ctx->ImageTransferState && dimensions == 2
710 && srcType == GL_UNSIGNED_BYTE) {
711
712 if (srcFormat == texFormat) {
713 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
714 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
715 */
716 const GLubyte *src = (const GLubyte *) _mesa_image_address(
717 srcPacking, srcAddr, srcWidth, srcHeight,
718 srcFormat, srcType, 0, 0, 0);
719 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
720 srcWidth, srcFormat, srcType);
721 const GLint widthInBytes = srcWidth * texComponents;
722 GLubyte *dst = texAddr + dstYoffset * dstRowStride
723 + dstXoffset * texComponents * sizeof(GLubyte);
724 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
725 MEMCPY(dst, src, srcHeight * widthInBytes);
726 }
727 else {
728 GLint i;
729 for (i = 0; i < srcHeight; i++) {
730 MEMCPY(dst, src, widthInBytes);
731 src += srcRowStride;
732 dst += dstRowStride;
733 }
734 }
735 return; /* all done */
736 }
737 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
738 /* commonly used by Quake */
739 const GLubyte *src = (const GLubyte *) _mesa_image_address(
740 srcPacking, srcAddr, srcWidth, srcHeight,
741 srcFormat, srcType, 0, 0, 0);
742 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
743 srcWidth, srcFormat, srcType);
744 GLubyte *dst = texAddr + dstYoffset * dstRowStride
745 + dstXoffset * texComponents * sizeof(GLubyte);
746 GLint i, j;
747 for (i = 0; i < srcHeight; i++) {
748 const GLubyte *s = src;
749 GLubyte *d = dst;
750 for (j = 0; j < srcWidth; j++) {
751 *d++ = *s++; /*red*/
752 *d++ = *s++; /*green*/
753 *d++ = *s++; /*blue*/
754 s++; /*alpha*/
755 }
756 src += srcRowStride;
757 dst += dstRowStride;
758 }
759 return; /* all done */
760 }
761 }
762
763 /*
764 * General case solutions
765 */
766 if (texFormat == GL_COLOR_INDEX) {
767 /* color index texture */
768 const GLenum texType = GL_UNSIGNED_BYTE;
769 GLint img, row;
770 GLubyte *dest = texAddr + dstZoffset * dstImageStride
771 + dstYoffset * dstRowStride
772 + dstXoffset * texComponents * sizeof(GLubyte);
773 for (img = 0; img < srcDepth; img++) {
774 GLubyte *destRow = dest;
775 for (row = 0; row < srcHeight; row++) {
776 const GLvoid *src = _mesa_image_address(srcPacking,
777 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
778 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
779 srcType, src, srcPacking,
780 ctx->ImageTransferState);
781 destRow += dstRowStride;
782 }
783 dest += dstImageStride;
784 }
785 }
786 else {
787 /* regular, color texture */
788 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
789 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
790 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
791 /*
792 * Fill texture image with convolution
793 */
794 GLint img, row;
795 GLint convWidth = srcWidth, convHeight = srcHeight;
796 GLfloat *tmpImage, *convImage;
797 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
798 if (!tmpImage) {
799 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
800 return;
801 }
802 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
803 if (!convImage) {
804 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
805 FREE(tmpImage);
806 return;
807 }
808
809 for (img = 0; img < srcDepth; img++) {
810 const GLfloat *srcf;
811 GLfloat *dstf = tmpImage;
812 GLubyte *dest;
813
814 /* unpack and do transfer ops up to convolution */
815 for (row = 0; row < srcHeight; row++) {
816 const GLvoid *src = _mesa_image_address(srcPacking,
817 srcAddr, srcWidth, srcHeight,
818 srcFormat, srcType, img, row, 0);
819 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
820 srcFormat, srcType, src, srcPacking,
821 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
822 GL_TRUE);
823 dstf += srcWidth * 4;
824 }
825
826 /* convolve */
827 if (dimensions == 1) {
828 ASSERT(ctx->Pixel.Convolution1DEnabled);
829 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
830 }
831 else {
832 if (ctx->Pixel.Convolution2DEnabled) {
833 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
834 tmpImage, convImage);
835 }
836 else {
837 ASSERT(ctx->Pixel.Separable2DEnabled);
838 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
839 tmpImage, convImage);
840 }
841 }
842
843 /* packing and transfer ops after convolution */
844 srcf = convImage;
845 dest = texAddr + (dstZoffset + img) * dstImageStride
846 + dstYoffset * dstRowStride;
847 for (row = 0; row < convHeight; row++) {
848 _mesa_pack_float_rgba_span(ctx, convWidth,
849 (const GLfloat (*)[4]) srcf,
850 texFormat, GL_UNSIGNED_BYTE,
851 dest, &_mesa_native_packing,
852 ctx->ImageTransferState
853 & IMAGE_POST_CONVOLUTION_BITS);
854 srcf += convWidth * 4;
855 dest += dstRowStride;
856 }
857 }
858
859 FREE(convImage);
860 FREE(tmpImage);
861 }
862 else {
863 /*
864 * no convolution
865 */
866 GLint img, row;
867 GLubyte *dest = texAddr + dstZoffset * dstImageStride
868 + dstYoffset * dstRowStride
869 + dstXoffset * texComponents * sizeof(GLubyte);
870 for (img = 0; img < srcDepth; img++) {
871 GLubyte *destRow = dest;
872 for (row = 0; row < srcHeight; row++) {
873 const GLvoid *srcRow = _mesa_image_address(srcPacking,
874 srcAddr, srcWidth, srcHeight,
875 srcFormat, srcType, img, row, 0);
876 _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow,
877 srcFormat, srcType, srcRow, srcPacking,
878 ctx->ImageTransferState);
879 destRow += dstRowStride;
880 }
881 dest += dstImageStride;
882 }
883 }
884 }
885 }
886
887
888
889 /* Need this to prevent an out-of-bounds memory access when using
890 * X86 optimized code.
891 */
892 #ifdef USE_X86_ASM
893 # define EXTRA_BYTE 1
894 #else
895 # define EXTRA_BYTE 0
896 #endif
897
898
899
900 /*
901 * Called by glTexImage[123]D. Fill in a texture image with data given
902 * by the client. All pixel transfer and unpack modes are handled here.
903 * Input: dimensions (1, 2, or 3)
904 * texImage - destination texture image (we'll malloc the memory)
905 * width, height, depth - size of source image
906 * srcFormat, srcType - source image format and type
907 * pixels - source image data
908 * srcPacking - source image packing parameters
909 *
910 * NOTE: All texture image parameters should have already been error checked.
911 *
912 * NOTE: the texImage dimensions and source image dimensions must be correct
913 * with respect to convolution with border mode = reduce.
914 */
915 static void
916 make_texture_image( GLcontext *ctx, GLuint dimensions,
917 struct gl_texture_image *texImage,
918 GLint width, GLint height, GLint depth,
919 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
920 const struct gl_pixelstore_attrib *srcPacking)
921 {
922 const GLint internalFormat = texImage->IntFormat;
923 const GLint components = components_in_intformat(internalFormat);
924 GLint convWidth = width, convHeight = height;
925
926 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) {
927 _mesa_update_image_transfer_state(ctx);
928 }
929
930 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
931 adjust_texture_size_for_convolution(ctx, dimensions,
932 &convWidth, &convHeight);
933 }
934
935 texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth
936 * components + EXTRA_BYTE);
937 if (!texImage->Data)
938 return; /* out of memory */
939
940 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
941 width, height, depth, 0, 0, 0,
942 convWidth * components * sizeof(GLubyte),
943 convWidth * convHeight * components * sizeof(GLubyte),
944 srcFormat, srcType, pixels, srcPacking);
945 }
946
947
948
949 /*
950 * glTexImage[123]D can accept a NULL image pointer. In this case we
951 * create a texture image with unspecified image contents per the OpenGL
952 * spec. This function creates an empty image for the given texture image.
953 */
954 static void
955 make_null_texture( struct gl_texture_image *texImage )
956 {
957 GLint components;
958 GLint numPixels;
959
960 ASSERT(texImage);
961 ASSERT(!texImage->Data);
962
963 components = components_in_intformat(texImage->IntFormat);
964 numPixels = texImage->Width * texImage->Height * texImage->Depth;
965
966 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
967
968 /*
969 * Let's see if anyone finds this. If glTexImage2D() is called with
970 * a NULL image pointer then load the texture image with something
971 * interesting instead of leaving it indeterminate.
972 */
973 if (texImage->Data) {
974 static const char message[8][32] = {
975 " X X XXXXX XXX X ",
976 " XX XX X X X X X ",
977 " X X X X X X X ",
978 " X X XXXX XXX XXXXX ",
979 " X X X X X X ",
980 " X X X X X X X ",
981 " X X XXXXX XXX X X ",
982 " "
983 };
984
985 GLubyte *imgPtr = texImage->Data;
986 GLint i, j, k;
987 for (i = 0; i < texImage->Height; i++) {
988 GLint srcRow = 7 - i % 8;
989 for (j = 0; j < texImage->Width; j++) {
990 GLint srcCol = j % 32;
991 GLint texel = (message[srcRow][srcCol]=='X') ? CHAN_MAX : 70;
992 for (k=0;k<components;k++) {
993 *imgPtr++ = (GLubyte) texel;
994 }
995 }
996 }
997 }
998 }
999
1000
1001
1002 /*
1003 * This is called when a proxy texture test fails, we set all the
1004 * image members (except DriverData) to zero.
1005 */
1006 static void
1007 clear_proxy_teximage(struct gl_texture_image *img)
1008 {
1009 ASSERT(img);
1010 img->Format = 0;
1011 img->IntFormat = 0;
1012 img->RedBits = 0;
1013 img->GreenBits = 0;
1014 img->BlueBits = 0;
1015 img->AlphaBits = 0;
1016 img->IntensityBits = 0;
1017 img->LuminanceBits = 0;
1018 img->IndexBits = 0;
1019 img->Border = 0;
1020 img->Width = 0;
1021 img->Height = 0;
1022 img->Depth = 0;
1023 img->Width2 = 0;
1024 img->Height2 = 0;
1025 img->Depth2 = 0;
1026 img->WidthLog2 = 0;
1027 img->HeightLog2 = 0;
1028 img->DepthLog2 = 0;
1029 img->Data = NULL;
1030 img->IsCompressed = 0;
1031 img->CompressedSize = 0;
1032 }
1033
1034
1035
1036 /*
1037 * Test glTexImage[123]D() parameters for errors.
1038 * Input:
1039 * dimensions - must be 1 or 2 or 3
1040 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1041 */
1042 static GLboolean
1043 texture_error_check( GLcontext *ctx, GLenum target,
1044 GLint level, GLint internalFormat,
1045 GLenum format, GLenum type,
1046 GLuint dimensions,
1047 GLint width, GLint height,
1048 GLint depth, GLint border )
1049 {
1050 GLboolean isProxy;
1051 GLint iformat;
1052
1053 if (dimensions == 1) {
1054 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
1055 if (target != GL_TEXTURE_1D && !isProxy) {
1056 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1057 return GL_TRUE;
1058 }
1059 }
1060 else if (dimensions == 2) {
1061 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
1062 if (target != GL_TEXTURE_2D && !isProxy &&
1063 !(ctx->Extensions.HaveTextureCubeMap &&
1064 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1065 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1066 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1067 return GL_TRUE;
1068 }
1069 }
1070 else if (dimensions == 3) {
1071 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
1072 if (target != GL_TEXTURE_3D && !isProxy) {
1073 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1074 return GL_TRUE;
1075 }
1076 }
1077 else {
1078 gl_problem( ctx, "bad dims in texture_error_check" );
1079 return GL_TRUE;
1080 }
1081
1082 /* Border */
1083 if (border != 0 && border != 1) {
1084 if (!isProxy) {
1085 char message[100];
1086 sprintf(message, "glTexImage%dD(border)", dimensions);
1087 gl_error(ctx, GL_INVALID_VALUE, message);
1088 }
1089 return GL_TRUE;
1090 }
1091
1092 /* Width */
1093 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1094 || logbase2( width - 2 * border ) < 0) {
1095 if (!isProxy) {
1096 char message[100];
1097 sprintf(message, "glTexImage%dD(width)", dimensions);
1098 gl_error(ctx, GL_INVALID_VALUE, message);
1099 }
1100 return GL_TRUE;
1101 }
1102
1103 /* Height */
1104 if (dimensions >= 2) {
1105 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1106 || logbase2( height - 2 * border ) < 0) {
1107 if (!isProxy) {
1108 char message[100];
1109 sprintf(message, "glTexImage%dD(height)", dimensions);
1110 gl_error(ctx, GL_INVALID_VALUE, message);
1111 }
1112 return GL_TRUE;
1113 }
1114 }
1115
1116 /* For cube map, width must equal height */
1117 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1118 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1119 if (width != height) {
1120 if (!isProxy) {
1121 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1122 }
1123 return GL_TRUE;
1124 }
1125 }
1126
1127 /* Depth */
1128 if (dimensions >= 3) {
1129 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1130 || logbase2( depth - 2 * border ) < 0) {
1131 if (!isProxy) {
1132 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1133 }
1134 return GL_TRUE;
1135 }
1136 }
1137
1138 /* Level */
1139 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1140 if (!isProxy) {
1141 char message[100];
1142 sprintf(message, "glTexImage%dD(level)", dimensions);
1143 gl_error(ctx, GL_INVALID_VALUE, message);
1144 }
1145 return GL_TRUE;
1146 }
1147
1148 iformat = _mesa_base_tex_format( ctx, internalFormat );
1149 if (iformat < 0) {
1150 if (!isProxy) {
1151 char message[100];
1152 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1153 gl_error(ctx, GL_INVALID_VALUE, message);
1154 }
1155 return GL_TRUE;
1156 }
1157
1158 if (!is_compressed_format(ctx, internalFormat)) {
1159 if (!_mesa_is_legal_format_and_type( format, type )) {
1160 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1161 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1162 */
1163 if (!isProxy) {
1164 char message[100];
1165 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1166 gl_error(ctx, GL_INVALID_OPERATION, message);
1167 }
1168 return GL_TRUE;
1169 }
1170 }
1171
1172 /* if we get here, the parameters are OK */
1173 return GL_FALSE;
1174 }
1175
1176
1177
1178 /*
1179 * Test glTexSubImage[123]D() parameters for errors.
1180 * Input:
1181 * dimensions - must be 1 or 2 or 3
1182 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1183 */
1184 static GLboolean
1185 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1186 GLenum target, GLint level,
1187 GLint xoffset, GLint yoffset, GLint zoffset,
1188 GLint width, GLint height, GLint depth,
1189 GLenum format, GLenum type )
1190 {
1191 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1192 struct gl_texture_image *destTex;
1193
1194 if (dimensions == 1) {
1195 if (target != GL_TEXTURE_1D) {
1196 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1197 return GL_TRUE;
1198 }
1199 }
1200 else if (dimensions == 2) {
1201 if (ctx->Extensions.HaveTextureCubeMap) {
1202 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1203 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1204 target != GL_TEXTURE_2D) {
1205 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1206 return GL_TRUE;
1207 }
1208 }
1209 else if (target != GL_TEXTURE_2D) {
1210 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1211 return GL_TRUE;
1212 }
1213 }
1214 else if (dimensions == 3) {
1215 if (target != GL_TEXTURE_3D) {
1216 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1217 return GL_TRUE;
1218 }
1219 }
1220 else {
1221 gl_problem( ctx, "bad dims in texture_error_check" );
1222 return GL_TRUE;
1223 }
1224
1225 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1226 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1227 return GL_TRUE;
1228 }
1229
1230 if (width < 0) {
1231 char message[100];
1232 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1233 gl_error(ctx, GL_INVALID_VALUE, message);
1234 return GL_TRUE;
1235 }
1236 if (height < 0 && dimensions > 1) {
1237 char message[100];
1238 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1239 gl_error(ctx, GL_INVALID_VALUE, message);
1240 return GL_TRUE;
1241 }
1242 if (depth < 0 && dimensions > 2) {
1243 char message[100];
1244 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1245 gl_error(ctx, GL_INVALID_VALUE, message);
1246 return GL_TRUE;
1247 }
1248
1249 destTex = texUnit->CurrentD[2]->Image[level];
1250 if (!destTex) {
1251 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1252 return GL_TRUE;
1253 }
1254
1255 if (xoffset < -((GLint)destTex->Border)) {
1256 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1257 return GL_TRUE;
1258 }
1259 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1260 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1261 return GL_TRUE;
1262 }
1263 if (dimensions > 1) {
1264 if (yoffset < -((GLint)destTex->Border)) {
1265 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1266 return GL_TRUE;
1267 }
1268 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1269 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1270 return GL_TRUE;
1271 }
1272 }
1273 if (dimensions > 2) {
1274 if (zoffset < -((GLint)destTex->Border)) {
1275 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1276 return GL_TRUE;
1277 }
1278 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1279 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1280 return GL_TRUE;
1281 }
1282 }
1283
1284 if (!is_compressed_format(ctx, destTex->IntFormat)) {
1285 if (!_mesa_is_legal_format_and_type(format, type)) {
1286 char message[100];
1287 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1288 gl_error(ctx, GL_INVALID_ENUM, message);
1289 return GL_TRUE;
1290 }
1291 }
1292
1293 return GL_FALSE;
1294 }
1295
1296
1297 /*
1298 * Test glCopyTexImage[12]D() parameters for errors.
1299 * Input: dimensions - must be 1 or 2 or 3
1300 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1301 */
1302 static GLboolean
1303 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1304 GLenum target, GLint level, GLint internalFormat,
1305 GLint width, GLint height, GLint border )
1306 {
1307 GLint iformat;
1308
1309 if (dimensions == 1) {
1310 if (target != GL_TEXTURE_1D) {
1311 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1312 return GL_TRUE;
1313 }
1314 }
1315 else if (dimensions == 2) {
1316 if (ctx->Extensions.HaveTextureCubeMap) {
1317 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1318 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1319 target != GL_TEXTURE_2D) {
1320 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1321 return GL_TRUE;
1322 }
1323 }
1324 else if (target != GL_TEXTURE_2D) {
1325 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1326 return GL_TRUE;
1327 }
1328 }
1329
1330 /* Border */
1331 if (border!=0 && border!=1) {
1332 char message[100];
1333 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1334 gl_error(ctx, GL_INVALID_VALUE, message);
1335 return GL_TRUE;
1336 }
1337
1338 /* Width */
1339 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1340 || logbase2( width - 2 * border ) < 0) {
1341 char message[100];
1342 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1343 gl_error(ctx, GL_INVALID_VALUE, message);
1344 return GL_TRUE;
1345 }
1346
1347 /* Height */
1348 if (dimensions >= 2) {
1349 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1350 || logbase2( height - 2 * border ) < 0) {
1351 char message[100];
1352 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1353 gl_error(ctx, GL_INVALID_VALUE, message);
1354 return GL_TRUE;
1355 }
1356 }
1357
1358 /* For cube map, width must equal height */
1359 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1360 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1361 if (width != height) {
1362 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1363 return GL_TRUE;
1364 }
1365 }
1366
1367 /* Level */
1368 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1369 char message[100];
1370 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1371 gl_error(ctx, GL_INVALID_VALUE, message);
1372 return GL_TRUE;
1373 }
1374
1375 iformat = _mesa_base_tex_format( ctx, internalFormat );
1376 if (iformat < 0) {
1377 char message[100];
1378 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1379 gl_error(ctx, GL_INVALID_VALUE, message);
1380 return GL_TRUE;
1381 }
1382
1383 /* if we get here, the parameters are OK */
1384 return GL_FALSE;
1385 }
1386
1387
1388 static GLboolean
1389 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1390 GLenum target, GLint level,
1391 GLint xoffset, GLint yoffset, GLint zoffset,
1392 GLsizei width, GLsizei height )
1393 {
1394 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1395 struct gl_texture_image *teximage;
1396
1397 if (dimensions == 1) {
1398 if (target != GL_TEXTURE_1D) {
1399 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1400 return GL_TRUE;
1401 }
1402 }
1403 else if (dimensions == 2) {
1404 if (ctx->Extensions.HaveTextureCubeMap) {
1405 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1406 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1407 target != GL_TEXTURE_2D) {
1408 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1409 return GL_TRUE;
1410 }
1411 }
1412 else if (target != GL_TEXTURE_2D) {
1413 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1414 return GL_TRUE;
1415 }
1416 }
1417 else if (dimensions == 3) {
1418 if (target != GL_TEXTURE_3D) {
1419 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1420 return GL_TRUE;
1421 }
1422 }
1423
1424 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1425 char message[100];
1426 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1427 gl_error(ctx, GL_INVALID_VALUE, message);
1428 return GL_TRUE;
1429 }
1430
1431 if (width < 0) {
1432 char message[100];
1433 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1434 gl_error(ctx, GL_INVALID_VALUE, message);
1435 return GL_TRUE;
1436 }
1437 if (dimensions > 1 && height < 0) {
1438 char message[100];
1439 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1440 gl_error(ctx, GL_INVALID_VALUE, message);
1441 return GL_TRUE;
1442 }
1443
1444 teximage = texUnit->CurrentD[dimensions]->Image[level];
1445 if (!teximage) {
1446 char message[100];
1447 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1448 gl_error(ctx, GL_INVALID_OPERATION, message);
1449 return GL_TRUE;
1450 }
1451
1452 if (xoffset < -((GLint)teximage->Border)) {
1453 char message[100];
1454 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1455 gl_error(ctx, GL_INVALID_VALUE, message);
1456 return GL_TRUE;
1457 }
1458 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1459 char message[100];
1460 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1461 gl_error(ctx, GL_INVALID_VALUE, message);
1462 return GL_TRUE;
1463 }
1464 if (dimensions > 1) {
1465 if (yoffset < -((GLint)teximage->Border)) {
1466 char message[100];
1467 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1468 gl_error(ctx, GL_INVALID_VALUE, message);
1469 return GL_TRUE;
1470 }
1471 /* NOTE: we're adding the border here, not subtracting! */
1472 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1473 char message[100];
1474 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1475 gl_error(ctx, GL_INVALID_VALUE, message);
1476 return GL_TRUE;
1477 }
1478 }
1479
1480 if (dimensions > 2) {
1481 if (zoffset < -((GLint)teximage->Border)) {
1482 char message[100];
1483 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1484 gl_error(ctx, GL_INVALID_VALUE, message);
1485 return GL_TRUE;
1486 }
1487 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1488 char message[100];
1489 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1490 gl_error(ctx, GL_INVALID_VALUE, message);
1491 return GL_TRUE;
1492 }
1493 }
1494
1495 /* if we get here, the parameters are OK */
1496 return GL_FALSE;
1497 }
1498
1499
1500
1501
1502 /*
1503 * Turn generic compressed formats into specific compressed format.
1504 * Some of the compressed formats we don't support, so we
1505 * fall back to the uncompressed format. (See issue 15 of
1506 * the GL_ARB_texture_compression specification.)
1507 */
1508 static GLint
1509 get_specific_compressed_tex_format(GLcontext *ctx,
1510 GLint ifmt, GLint numDimensions,
1511 GLint *levelp,
1512 GLsizei *widthp,
1513 GLsizei *heightp,
1514 GLsizei *depthp,
1515 GLint *borderp,
1516 GLenum *formatp,
1517 GLenum *typep)
1518 {
1519 char message[100];
1520 GLint internalFormat = ifmt;
1521
1522 if (ctx->Extensions.HaveTextureCompression
1523 && ctx->Driver.SpecificCompressedTexFormat) {
1524 /*
1525 * First, ask the driver for the specific format.
1526 * We do this for all formats, since we may want to
1527 * fake one compressed format for another.
1528 */
1529 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1530 (ctx, internalFormat, numDimensions,
1531 levelp,
1532 widthp, heightp, depthp,
1533 borderp, formatp, typep);
1534 }
1535
1536 /*
1537 * Now, convert any generic format left to an uncompressed
1538 * specific format. If the driver does not support compression
1539 * of the format, we must drop back to the uncompressed format.
1540 * See issue 15 of the GL_ARB_texture_compression specification.
1541 */
1542 switch (internalFormat) {
1543 case GL_COMPRESSED_ALPHA_ARB:
1544 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1545 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1546 gl_error(ctx, GL_INVALID_VALUE, message);
1547 return -1;
1548 }
1549 internalFormat = GL_ALPHA;
1550 break;
1551 case GL_COMPRESSED_LUMINANCE_ARB:
1552 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1553 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1554 gl_error(ctx, GL_INVALID_VALUE, message);
1555 return -1;
1556 }
1557 internalFormat = GL_LUMINANCE;
1558 break;
1559 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1560 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1561 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1562 gl_error(ctx, GL_INVALID_VALUE, message);
1563 return -1;
1564 }
1565 internalFormat = GL_LUMINANCE_ALPHA;
1566 break;
1567 case GL_COMPRESSED_INTENSITY_ARB:
1568 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1569 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1570 gl_error(ctx, GL_INVALID_VALUE, message);
1571 return -1;
1572 }
1573 internalFormat = GL_INTENSITY;
1574 break;
1575 case GL_COMPRESSED_RGB_ARB:
1576 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1577 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1578 gl_error(ctx, GL_INVALID_VALUE, message);
1579 return -1;
1580 }
1581 internalFormat = GL_RGB;
1582 break;
1583 case GL_COMPRESSED_RGBA_ARB:
1584 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1585 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1586 gl_error(ctx, GL_INVALID_VALUE, message);
1587 return -1;
1588 }
1589 internalFormat = GL_RGBA;
1590 break;
1591 default:
1592 /* silence compiler warning */
1593 ;
1594 }
1595 return internalFormat;
1596 }
1597
1598
1599 /*
1600 * Called from the API. Note that width includes the border.
1601 */
1602 void
1603 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1604 GLsizei width, GLint border, GLenum format,
1605 GLenum type, const GLvoid *pixels )
1606 {
1607 GLsizei postConvWidth;
1608 GET_CURRENT_CONTEXT(ctx);
1609 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1610
1611 postConvWidth = width;
1612 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1613
1614 if (target==GL_TEXTURE_1D) {
1615 struct gl_texture_unit *texUnit;
1616 struct gl_texture_object *texObj;
1617 struct gl_texture_image *texImage;
1618 GLint ifmt;
1619
1620 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1621 &level,
1622 &width, 0, 0,
1623 &border, &format, &type);
1624 if (ifmt < 0) {
1625 /*
1626 * The error here is that we were sent a generic compressed
1627 * format, but the extension is not supported.
1628 */
1629 return;
1630 }
1631 else {
1632 internalFormat = ifmt;
1633 }
1634
1635 if (texture_error_check(ctx, target, level, internalFormat,
1636 format, type, 1, postConvWidth, 1, 1, border)) {
1637 return; /* error in texture image was detected */
1638 }
1639
1640 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1641 texObj = texUnit->CurrentD[1];
1642 texImage = texObj->Image[level];
1643
1644 if (!texImage) {
1645 texImage = _mesa_alloc_texture_image();
1646 texObj->Image[level] = texImage;
1647 if (!texImage) {
1648 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1649 return;
1650 }
1651 }
1652 else if (texImage->Data) {
1653 FREE(texImage->Data);
1654 texImage->Data = NULL;
1655 }
1656
1657 /* setup the teximage struct's fields */
1658 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1659
1660 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1661 _mesa_update_image_transfer_state(ctx);
1662
1663 /* process the texture image */
1664 if (pixels) {
1665 GLboolean retain = GL_TRUE;
1666 GLboolean success = GL_FALSE;
1667 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
1668 /* let device driver try to use raw image */
1669 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1670 type, pixels, &ctx->Unpack,
1671 texObj, texImage, &retain);
1672 }
1673 if (retain || !success) {
1674 /* make internal copy of the texture image */
1675 make_texture_image(ctx, 1, texImage, width, 1, 1,
1676 format, type, pixels, &ctx->Unpack);
1677 if (!success && ctx->Driver.TexImage1D) {
1678 /* let device driver try to use unpacked image */
1679 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1680 GL_UNSIGNED_BYTE, texImage->Data,
1681 &_mesa_native_packing,
1682 texObj, texImage, &retain);
1683 }
1684 }
1685 if (!retain && texImage->Data) {
1686 FREE(texImage->Data);
1687 texImage->Data = NULL;
1688 }
1689 }
1690 else {
1691 make_null_texture(texImage);
1692 if (ctx->Driver.TexImage1D) {
1693 GLboolean retain;
1694 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1695 GL_UNSIGNED_BYTE, texImage->Data,
1696 &_mesa_native_packing,
1697 texObj, texImage, &retain);
1698 }
1699 }
1700
1701 /* state update */
1702 gl_put_texobj_on_dirty_list( ctx, texObj );
1703 ctx->NewState |= NEW_TEXTURING;
1704 }
1705 else if (target == GL_PROXY_TEXTURE_1D) {
1706 /* Proxy texture: check for errors and update proxy state */
1707 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1708 format, type, 1, width, 1, 1, border);
1709 if (!error && ctx->Driver.TestProxyTexImage) {
1710 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1711 internalFormat, format, type,
1712 width, 1, 1, border);
1713 }
1714 if (error) {
1715 /* if error, clear all proxy texture image parameters */
1716 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1717 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
1718 }
1719 }
1720 else {
1721 /* if no error, update proxy texture image parameters */
1722 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1723 width, 1, 1, border, internalFormat);
1724 }
1725 }
1726 else {
1727 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1728 return;
1729 }
1730 }
1731
1732
1733 void
1734 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1735 GLsizei width, GLsizei height, GLint border,
1736 GLenum format, GLenum type,
1737 const GLvoid *pixels )
1738 {
1739 GLsizei postConvWidth, postConvHeight;
1740 GET_CURRENT_CONTEXT(ctx);
1741 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1742
1743 postConvWidth = width;
1744 postConvHeight = height;
1745 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1746
1747 if (target==GL_TEXTURE_2D ||
1748 (ctx->Extensions.HaveTextureCubeMap &&
1749 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1750 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1751 struct gl_texture_unit *texUnit;
1752 struct gl_texture_object *texObj;
1753 struct gl_texture_image *texImage;
1754 GLint ifmt;
1755
1756 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1757 &level,
1758 &width, &height, 0,
1759 &border, &format, &type);
1760 if (ifmt < 0) {
1761 /*
1762 * The error here is that we were sent a generic compressed
1763 * format, but the extension is not supported.
1764 */
1765 return;
1766 }
1767 else {
1768 internalFormat = ifmt;
1769 }
1770
1771 if (texture_error_check(ctx, target, level, internalFormat,
1772 format, type, 2, postConvWidth, postConvHeight,
1773 1, border)) {
1774 return; /* error in texture image was detected */
1775 }
1776
1777 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1778 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1779 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1780
1781 if (!texImage) {
1782 texImage = _mesa_alloc_texture_image();
1783 set_tex_image(texObj, target, level, texImage);
1784 /*texObj->Image[level] = texImage;*/
1785 if (!texImage) {
1786 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1787 return;
1788 }
1789 }
1790 else if (texImage->Data) {
1791 FREE(texImage->Data);
1792 texImage->Data = NULL;
1793 }
1794
1795 /* setup the teximage struct's fields */
1796 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1797 1, border, internalFormat);
1798
1799 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1800 _mesa_update_image_transfer_state(ctx);
1801
1802 /* process the texture image */
1803 if (pixels) {
1804 GLboolean retain = GL_TRUE;
1805 GLboolean success = GL_FALSE;
1806 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
1807 /* let device driver try to use raw image */
1808 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1809 type, pixels, &ctx->Unpack,
1810 texObj, texImage, &retain);
1811 }
1812 if (retain || !success) {
1813 /* make internal copy of the texture image */
1814 make_texture_image(ctx, 2, texImage, width, height, 1,
1815 format, type, pixels, &ctx->Unpack);
1816 if (!success && ctx->Driver.TexImage2D) {
1817 /* let device driver try to use unpacked image */
1818 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1819 GL_UNSIGNED_BYTE, texImage->Data,
1820 &_mesa_native_packing,
1821 texObj, texImage, &retain);
1822 }
1823 }
1824 if (!retain && texImage->Data) {
1825 FREE(texImage->Data);
1826 texImage->Data = NULL;
1827 }
1828 }
1829 else {
1830 make_null_texture(texImage);
1831 if (ctx->Driver.TexImage2D) {
1832 GLboolean retain;
1833 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1834 GL_UNSIGNED_BYTE, texImage->Data,
1835 &_mesa_native_packing,
1836 texObj, texImage, &retain);
1837 }
1838 }
1839
1840 #define OLD_DD_TEXTURE
1841 #ifdef OLD_DD_TEXTURE
1842 /* XXX this will be removed in the future */
1843 if (ctx->Driver.TexImage) {
1844 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1845 texImage );
1846 }
1847 #endif
1848
1849 /* state update */
1850 gl_put_texobj_on_dirty_list( ctx, texObj );
1851 ctx->NewState |= NEW_TEXTURING;
1852 }
1853 else if (target == GL_PROXY_TEXTURE_2D) {
1854 /* Proxy texture: check for errors and update proxy state */
1855 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1856 format, type, 2, width, height, 1, border);
1857 if (!error && ctx->Driver.TestProxyTexImage) {
1858 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1859 internalFormat, format, type,
1860 width, height, 1, border);
1861 }
1862 if (error) {
1863 /* if error, clear all proxy texture image parameters */
1864 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1865 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
1866 }
1867 }
1868 else {
1869 /* if no error, update proxy texture image parameters */
1870 init_texture_image(ctx,
1871 ctx->Texture.Proxy2D->Image[level],
1872 width, height, 1, border, internalFormat);
1873 }
1874 }
1875 else {
1876 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1877 return;
1878 }
1879 }
1880
1881
1882 /*
1883 * Called by the API or display list executor.
1884 * Note that width and height include the border.
1885 */
1886 void
1887 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1888 GLsizei width, GLsizei height, GLsizei depth,
1889 GLint border, GLenum format, GLenum type,
1890 const GLvoid *pixels )
1891 {
1892 GET_CURRENT_CONTEXT(ctx);
1893 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1894
1895 if (target==GL_TEXTURE_3D_EXT) {
1896 struct gl_texture_unit *texUnit;
1897 struct gl_texture_object *texObj;
1898 struct gl_texture_image *texImage;
1899 GLint ifmt;
1900
1901 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1902 &level,
1903 &width, &height, &depth,
1904 &border, &format, &type);
1905 if (ifmt < 0) {
1906 /*
1907 * The error here is that we were sent a generic compressed
1908 * format, but the extension is not supported.
1909 */
1910 return;
1911 }
1912 else {
1913 internalFormat = ifmt;
1914 }
1915
1916 if (texture_error_check(ctx, target, level, internalFormat,
1917 format, type, 3, width, height, depth, border)) {
1918 return; /* error in texture image was detected */
1919 }
1920
1921 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1922 texObj = texUnit->CurrentD[3];
1923 texImage = texObj->Image[level];
1924
1925 if (!texImage) {
1926 texImage = _mesa_alloc_texture_image();
1927 texObj->Image[level] = texImage;
1928 if (!texImage) {
1929 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1930 return;
1931 }
1932 }
1933 else if (texImage->Data) {
1934 FREE(texImage->Data);
1935 texImage->Data = NULL;
1936 }
1937
1938 /* setup the teximage struct's fields */
1939 init_texture_image(ctx, texImage, width, height, depth,
1940 border, internalFormat);
1941
1942 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1943 _mesa_update_image_transfer_state(ctx);
1944
1945 /* process the texture image */
1946 if (pixels) {
1947 GLboolean retain = GL_TRUE;
1948 GLboolean success = GL_FALSE;
1949 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
1950 /* let device driver try to use raw image */
1951 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1952 type, pixels, &ctx->Unpack,
1953 texObj, texImage, &retain);
1954 }
1955 if (retain || !success) {
1956 /* make internal copy of the texture image */
1957 make_texture_image(ctx, 3, texImage, width, height, depth,
1958 format, type, pixels, &ctx->Unpack);
1959 if (!success && ctx->Driver.TexImage3D) {
1960 /* let device driver try to use unpacked image */
1961 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1962 GL_UNSIGNED_BYTE, texImage->Data,
1963 &_mesa_native_packing,
1964 texObj, texImage, &retain);
1965 }
1966 }
1967 if (!retain && texImage->Data) {
1968 FREE(texImage->Data);
1969 texImage->Data = NULL;
1970 }
1971 }
1972 else {
1973 make_null_texture(texImage);
1974 if (ctx->Driver.TexImage3D) {
1975 GLboolean retain;
1976 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1977 GL_UNSIGNED_BYTE, texImage->Data,
1978 &_mesa_native_packing,
1979 texObj, texImage, &retain);
1980 }
1981 }
1982
1983 /* state update */
1984 gl_put_texobj_on_dirty_list( ctx, texObj );
1985 ctx->NewState |= NEW_TEXTURING;
1986 }
1987 else if (target == GL_PROXY_TEXTURE_3D) {
1988 /* Proxy texture: check for errors and update proxy state */
1989 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1990 format, type, 3, width, height, depth, border);
1991 if (!error && ctx->Driver.TestProxyTexImage) {
1992 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1993 internalFormat, format, type,
1994 width, height, depth, border);
1995 }
1996 if (error) {
1997 /* if error, clear all proxy texture image parameters */
1998 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1999 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
2000 }
2001 }
2002 else {
2003 /* if no error, update proxy texture image parameters */
2004 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
2005 width, height, depth, border, internalFormat);
2006 }
2007 }
2008 else {
2009 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2010 return;
2011 }
2012 }
2013
2014
2015 void
2016 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2017 GLsizei width, GLsizei height, GLsizei depth,
2018 GLint border, GLenum format, GLenum type,
2019 const GLvoid *pixels )
2020 {
2021 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2022 depth, border, format, type, pixels);
2023 }
2024
2025
2026 /*
2027 * Fetch a texture image from the device driver.
2028 * Store the results in the given texture object at the given mipmap level.
2029 */
2030 void
2031 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2032 const struct gl_texture_object *texObj )
2033 {
2034 GLvoid *image;
2035 GLenum imgFormat, imgType;
2036 GLboolean freeImage;
2037 struct gl_texture_image *texImage;
2038 GLint destComponents, numPixels, srcBytesPerTexel;
2039
2040 if (!ctx->Driver.GetTexImage)
2041 return;
2042
2043 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
2044 &imgFormat, &imgType, &freeImage);
2045 if (!image)
2046 return;
2047
2048 texImage = texObj->Image[level];
2049 ASSERT(texImage);
2050 if (!texImage)
2051 return;
2052
2053 destComponents = components_in_intformat(texImage->Format);
2054 assert(destComponents > 0);
2055 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2056 assert(numPixels > 0);
2057 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
2058 assert(srcBytesPerTexel > 0);
2059
2060 if (!texImage->Data) {
2061 /* Allocate memory for the texture image data */
2062 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
2063 }
2064
2065 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2066 /* We got lucky! The driver's format and type match Mesa's format. */
2067 if (texImage->Data) {
2068 MEMCPY(texImage->Data, image, numPixels * destComponents);
2069 }
2070 }
2071 else {
2072 /* Convert the texture image from the driver's format to Mesa's
2073 * internal format.
2074 */
2075 const GLint width = texImage->Width;
2076 const GLint height = texImage->Height;
2077 const GLint depth = texImage->Depth;
2078 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2079 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2080 const GLenum dstType = GL_UNSIGNED_BYTE;
2081 const GLenum dstFormat = texImage->Format;
2082 const GLubyte *srcPtr = (const GLubyte *) image;
2083 GLubyte *destPtr = texImage->Data;
2084
2085 if (texImage->Format == GL_COLOR_INDEX) {
2086 /* color index texture */
2087 GLint img, row;
2088 assert(imgFormat == GL_COLOR_INDEX);
2089 for (img = 0; img < depth; img++) {
2090 for (row = 0; row < height; row++) {
2091 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
2092 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2093 destPtr += destBytesPerRow;
2094 srcPtr += srcBytesPerRow;
2095 }
2096 }
2097 }
2098 else {
2099 /* color texture */
2100 GLint img, row;
2101 for (img = 0; img < depth; img++) {
2102 for (row = 0; row < height; row++) {
2103 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
2104 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2105 destPtr += destBytesPerRow;
2106 srcPtr += srcBytesPerRow;
2107 }
2108 }
2109 }
2110 }
2111
2112 if (freeImage)
2113 FREE(image);
2114 }
2115
2116
2117 /*
2118 * Get all the mipmap images for a texture object from the device driver.
2119 * Actually, only get mipmap images if we're using a mipmap filter.
2120 */
2121 GLboolean
2122 _mesa_get_teximages_from_driver(GLcontext *ctx,
2123 struct gl_texture_object *texObj)
2124 {
2125 if (ctx->Driver.GetTexImage) {
2126 static const GLenum targets[] = {
2127 GL_TEXTURE_1D,
2128 GL_TEXTURE_2D,
2129 GL_TEXTURE_3D,
2130 GL_TEXTURE_CUBE_MAP_ARB,
2131 GL_TEXTURE_CUBE_MAP_ARB,
2132 GL_TEXTURE_CUBE_MAP_ARB
2133 };
2134 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2135 GLenum target = targets[texObj->Dimensions - 1];
2136 if (needLambda) {
2137 GLint level;
2138 /* Get images for all mipmap levels. We might not need them
2139 * all but this is easier. We're on a (slow) software path
2140 * anyway.
2141 */
2142 for (level = 0; level <= texObj->P; level++) {
2143 struct gl_texture_image *texImg = texObj->Image[level];
2144 if (texImg && !texImg->Data) {
2145 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2146 if (!texImg->Data)
2147 return GL_FALSE; /* out of memory */
2148 }
2149 }
2150 }
2151 else {
2152 GLint level = texObj->BaseLevel;
2153 struct gl_texture_image *texImg = texObj->Image[level];
2154 if (texImg && !texImg->Data) {
2155 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2156 if (!texImg->Data)
2157 return GL_FALSE; /* out of memory */
2158 }
2159 }
2160 return GL_TRUE;
2161 }
2162 return GL_FALSE;
2163 }
2164
2165
2166
2167 void
2168 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2169 GLenum type, GLvoid *pixels )
2170 {
2171 GET_CURRENT_CONTEXT(ctx);
2172 const struct gl_texture_unit *texUnit;
2173 const struct gl_texture_object *texObj;
2174 struct gl_texture_image *texImage;
2175 GLboolean discardImage;
2176
2177 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2178
2179 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2180 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2181 return;
2182 }
2183
2184 if (_mesa_sizeof_type(type) <= 0) {
2185 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2186 return;
2187 }
2188
2189 if (_mesa_components_in_format(format) <= 0) {
2190 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2191 return;
2192 }
2193
2194 if (!pixels)
2195 return;
2196
2197 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2198 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2199 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2200 if (!texObj || !texImage ||
2201 target == GL_PROXY_TEXTURE_1D ||
2202 target == GL_PROXY_TEXTURE_2D ||
2203 target == GL_PROXY_TEXTURE_3D) {
2204 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2205 return;
2206 }
2207
2208 if (!texImage) {
2209 /* invalid mipmap level */
2210 return;
2211 }
2212
2213 if (!texImage->Data) {
2214 /* try to get the texture image from the device driver */
2215 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2216 discardImage = GL_TRUE;
2217 }
2218 else {
2219 discardImage = GL_FALSE;
2220 }
2221
2222 if (texImage->Data) {
2223 GLint width = texImage->Width;
2224 GLint height = texImage->Height;
2225 GLint depth = texImage->Depth;
2226 GLint img, row;
2227
2228 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2229 _mesa_update_image_transfer_state(ctx);
2230
2231 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2232 /* convert texture image to GL_RGBA, GL_FLOAT */
2233 GLfloat *tmpImage, *convImage;
2234 const GLint comps = components_in_intformat(texImage->Format);
2235
2236 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2237 if (!tmpImage) {
2238 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2239 return;
2240 }
2241 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2242 if (!convImage) {
2243 FREE(tmpImage);
2244 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2245 return;
2246 }
2247
2248 for (img = 0; img < depth; img++) {
2249 GLint convWidth, convHeight;
2250
2251 /* convert to GL_RGBA */
2252 for (row = 0; row < height; row++) {
2253 const GLubyte *src = texImage->Data
2254 + (img * height + row ) * width * comps;
2255 GLfloat *dst = tmpImage + row * width * 4;
2256 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2257 texImage->Format, GL_UNSIGNED_BYTE,
2258 src, &_mesa_native_packing,
2259 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2260 GL_FALSE);
2261 }
2262
2263 convWidth = width;
2264 convHeight = height;
2265
2266 /* convolve */
2267 if (target == GL_TEXTURE_1D) {
2268 if (ctx->Pixel.Convolution1DEnabled) {
2269 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2270 }
2271 }
2272 else {
2273 if (ctx->Pixel.Convolution2DEnabled) {
2274 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2275 tmpImage, convImage);
2276 }
2277 else if (ctx->Pixel.Separable2DEnabled) {
2278 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2279 tmpImage, convImage);
2280 }
2281 }
2282
2283 /* pack convolved image */
2284 for (row = 0; row < convHeight; row++) {
2285 const GLfloat *src = convImage + row * convWidth * 4;
2286 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2287 convWidth, convHeight,
2288 format, type, img, row, 0);
2289 _mesa_pack_float_rgba_span(ctx, convWidth,
2290 (const GLfloat(*)[4]) src,
2291 format, type, dest, &ctx->Pack,
2292 ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2293 }
2294 }
2295
2296 FREE(tmpImage);
2297 FREE(convImage);
2298 }
2299 else {
2300 /* no convolution */
2301 for (img = 0; img < depth; img++) {
2302 for (row = 0; row < height; row++) {
2303 /* compute destination address in client memory */
2304 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2305 width, height, format, type, img, row, 0);
2306 assert(dest);
2307 if (texImage->Format == GL_RGBA) {
2308 /* simple case */
2309 const GLubyte *src = texImage->Data
2310 + (img * height + row ) * width * 4;
2311 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2312 format, type, dest, &ctx->Pack,
2313 ctx->ImageTransferState );
2314 }
2315 else {
2316 /* general case: convert row to RGBA format */
2317 GLubyte rgba[MAX_WIDTH][4];
2318 GLint i;
2319 const GLubyte *src;
2320 switch (texImage->Format) {
2321 case GL_ALPHA:
2322 src = texImage->Data + row * width * sizeof(GLubyte);
2323 for (i = 0; i < width; i++) {
2324 rgba[i][RCOMP] = CHAN_MAX;
2325 rgba[i][GCOMP] = CHAN_MAX;
2326 rgba[i][BCOMP] = CHAN_MAX;
2327 rgba[i][ACOMP] = src[i];
2328 }
2329 break;
2330 case GL_LUMINANCE:
2331 src = texImage->Data + row * width * sizeof(GLubyte);
2332 for (i = 0; i < width; i++) {
2333 rgba[i][RCOMP] = src[i];
2334 rgba[i][GCOMP] = src[i];
2335 rgba[i][BCOMP] = src[i];
2336 rgba[i][ACOMP] = CHAN_MAX;
2337 }
2338 break;
2339 case GL_LUMINANCE_ALPHA:
2340 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2341 for (i = 0; i < width; i++) {
2342 rgba[i][RCOMP] = src[i*2+0];
2343 rgba[i][GCOMP] = src[i*2+0];
2344 rgba[i][BCOMP] = src[i*2+0];
2345 rgba[i][ACOMP] = src[i*2+1];
2346 }
2347 break;
2348 case GL_INTENSITY:
2349 src = texImage->Data + row * width * sizeof(GLubyte);
2350 for (i = 0; i < width; i++) {
2351 rgba[i][RCOMP] = src[i];
2352 rgba[i][GCOMP] = src[i];
2353 rgba[i][BCOMP] = src[i];
2354 rgba[i][ACOMP] = CHAN_MAX;
2355 }
2356 break;
2357 case GL_RGB:
2358 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2359 for (i = 0; i < width; i++) {
2360 rgba[i][RCOMP] = src[i*3+0];
2361 rgba[i][GCOMP] = src[i*3+1];
2362 rgba[i][BCOMP] = src[i*3+2];
2363 rgba[i][ACOMP] = CHAN_MAX;
2364 }
2365 break;
2366 case GL_COLOR_INDEX:
2367 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2368 break;
2369 case GL_RGBA:
2370 default:
2371 gl_problem( ctx, "bad format in gl_GetTexImage" );
2372 }
2373 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2374 format, type, dest, &ctx->Pack,
2375 ctx->ImageTransferState );
2376 } /* format */
2377 } /* row */
2378 } /* img */
2379 } /* convolution */
2380
2381 /* if we got the teximage from the device driver we'll discard it now */
2382 if (discardImage) {
2383 FREE(texImage->Data);
2384 texImage->Data = NULL;
2385 }
2386 }
2387 }
2388
2389
2390
2391 void
2392 _mesa_TexSubImage1D( GLenum target, GLint level,
2393 GLint xoffset, GLsizei width,
2394 GLenum format, GLenum type,
2395 const GLvoid *pixels )
2396 {
2397 GET_CURRENT_CONTEXT(ctx);
2398 struct gl_texture_unit *texUnit;
2399 struct gl_texture_object *texObj;
2400 struct gl_texture_image *texImage;
2401 GLboolean success = GL_FALSE;
2402 GLsizei postConvWidth;
2403
2404 postConvWidth = width;
2405 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2406
2407 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2408 postConvWidth, 1, 1, format, type)) {
2409 return; /* error was detected */
2410 }
2411
2412 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2413 texObj = texUnit->CurrentD[1];
2414 texImage = texObj->Image[level];
2415 assert(texImage);
2416
2417 if (width == 0 || !pixels)
2418 return; /* no-op, not an error */
2419
2420 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2421 _mesa_update_image_transfer_state(ctx);
2422
2423 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2424 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2425 width, format, type, pixels,
2426 &ctx->Unpack, texObj, texImage );
2427 }
2428 if (!success) {
2429 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2430 GLboolean retain = GL_TRUE;
2431 if (!texImage->Data) {
2432 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2433 if (!texImage->Data) {
2434 make_null_texture(texImage);
2435 }
2436 if (!texImage->Data)
2437 return; /* we're really out of luck! */
2438 }
2439
2440 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2441 width, 1, 1, xoffset, 0, 0, /* size and offsets */
2442 0, 0, /* strides */
2443 format, type, pixels, &ctx->Unpack);
2444
2445 if (ctx->Driver.TexImage1D) {
2446 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2447 GL_UNSIGNED_BYTE, texImage->Data,
2448 &_mesa_native_packing, texObj, texImage,
2449 &retain );
2450 }
2451
2452 if (!retain && texImage->Data) {
2453 FREE(texImage->Data);
2454 texImage->Data = NULL;
2455 }
2456 }
2457 }
2458
2459
2460 void
2461 _mesa_TexSubImage2D( GLenum target, GLint level,
2462 GLint xoffset, GLint yoffset,
2463 GLsizei width, GLsizei height,
2464 GLenum format, GLenum type,
2465 const GLvoid *pixels )
2466 {
2467 GET_CURRENT_CONTEXT(ctx);
2468 struct gl_texture_unit *texUnit;
2469 struct gl_texture_object *texObj;
2470 struct gl_texture_image *texImage;
2471 GLboolean success = GL_FALSE;
2472 GLsizei postConvWidth, postConvHeight;
2473
2474 postConvWidth = width;
2475 postConvHeight = height;
2476 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2477
2478 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2479 postConvWidth, postConvHeight, 1, format, type)) {
2480 return; /* error was detected */
2481 }
2482
2483 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2484 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2485 texImage = texObj->Image[level];
2486 assert(texImage);
2487
2488 if (width == 0 || height == 0 || !pixels)
2489 return; /* no-op, not an error */
2490
2491 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2492 _mesa_update_image_transfer_state(ctx);
2493
2494 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2495 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2496 yoffset, width, height, format, type,
2497 pixels, &ctx->Unpack, texObj, texImage );
2498 }
2499 if (!success) {
2500 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2501 const GLint texComps = components_in_intformat(texImage->Format);
2502 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2503 GLboolean retain = GL_TRUE;
2504
2505 if (!texImage->Data) {
2506 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2507 if (!texImage->Data) {
2508 make_null_texture(texImage);
2509 }
2510 if (!texImage->Data)
2511 return; /* we're really out of luck! */
2512 }
2513
2514 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2515 width, height, 1, xoffset, yoffset, 0,
2516 texRowStride, 0,
2517 format, type, pixels, &ctx->Unpack);
2518
2519 if (ctx->Driver.TexImage2D) {
2520 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2521 GL_UNSIGNED_BYTE, texImage->Data,
2522 &_mesa_native_packing, texObj, texImage,
2523 &retain);
2524 }
2525
2526 if (!retain && texImage->Data) {
2527 FREE(texImage->Data);
2528 texImage->Data = NULL;
2529 }
2530
2531 #ifdef OLD_DD_TEXTURE
2532 /* XXX this will be removed in the future */
2533 if (ctx->Driver.TexSubImage) {
2534 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2535 xoffset, yoffset, width, height,
2536 texImage->IntFormat, texImage);
2537 }
2538 else if (ctx->Driver.TexImage) {
2539 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2540 level, texImage->IntFormat, texImage );
2541 }
2542 #endif
2543 }
2544 }
2545
2546
2547
2548 void
2549 _mesa_TexSubImage3D( GLenum target, GLint level,
2550 GLint xoffset, GLint yoffset, GLint zoffset,
2551 GLsizei width, GLsizei height, GLsizei depth,
2552 GLenum format, GLenum type,
2553 const GLvoid *pixels )
2554 {
2555 GET_CURRENT_CONTEXT(ctx);
2556 struct gl_texture_unit *texUnit;
2557 struct gl_texture_object *texObj;
2558 struct gl_texture_image *texImage;
2559 GLboolean success = GL_FALSE;
2560
2561 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2562 width, height, depth, format, type)) {
2563 return; /* error was detected */
2564 }
2565
2566 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2567 texObj = texUnit->CurrentD[3];
2568 texImage = texObj->Image[level];
2569 assert(texImage);
2570
2571 if (width == 0 || height == 0 || height == 0 || !pixels)
2572 return; /* no-op, not an error */
2573
2574 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2575 _mesa_update_image_transfer_state(ctx);
2576
2577 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2578 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2579 yoffset, zoffset, width, height, depth, format,
2580 type, pixels, &ctx->Unpack, texObj, texImage );
2581 }
2582 if (!success) {
2583 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2584 const GLint texComps = components_in_intformat(texImage->Format);
2585 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2586 const GLint texImgStride = texRowStride * texImage->Height;
2587 GLboolean retain = GL_TRUE;
2588
2589 if (!texImage->Data) {
2590 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2591 if (!texImage->Data) {
2592 make_null_texture(texImage);
2593 }
2594 if (!texImage->Data)
2595 return; /* we're really out of luck! */
2596 }
2597
2598 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2599 width, height, depth, xoffset, yoffset, zoffset,
2600 texRowStride, texImgStride,
2601 format, type, pixels, &ctx->Unpack);
2602
2603 if (ctx->Driver.TexImage3D) {
2604 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2605 GL_UNSIGNED_BYTE, texImage->Data,
2606 &_mesa_native_packing, texObj, texImage,
2607 &retain);
2608 }
2609
2610 if (!retain && texImage->Data) {
2611 FREE(texImage->Data);
2612 texImage->Data = NULL;
2613 }
2614 }
2615 }
2616
2617
2618
2619 /*
2620 * Read an RGBA image from the frame buffer.
2621 * This is used by glCopyTex[Sub]Image[12]D().
2622 * Input: ctx - the context
2623 * x, y - lower left corner
2624 * width, height - size of region to read
2625 * Return: pointer to block of GL_RGBA, GLubyte data.
2626 */
2627 static GLubyte *
2628 read_color_image( GLcontext *ctx, GLint x, GLint y,
2629 GLsizei width, GLsizei height )
2630 {
2631 GLint stride, i;
2632 GLubyte *image, *dst;
2633
2634 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2635 if (!image)
2636 return NULL;
2637
2638 /* Select buffer to read from */
2639 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2640 ctx->Pixel.DriverReadBuffer );
2641
2642 dst = image;
2643 stride = width * 4 * sizeof(GLubyte);
2644 for (i = 0; i < height; i++) {
2645 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2646 (GLubyte (*)[4]) dst );
2647 dst += stride;
2648 }
2649
2650 /* Read from draw buffer (the default) */
2651 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2652 ctx->Color.DriverDrawBuffer );
2653
2654 return image;
2655 }
2656
2657
2658
2659 void
2660 _mesa_CopyTexImage1D( GLenum target, GLint level,
2661 GLenum internalFormat,
2662 GLint x, GLint y,
2663 GLsizei width, GLint border )
2664 {
2665 GET_CURRENT_CONTEXT(ctx);
2666 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2667
2668 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2669 width, 1, border))
2670 return;
2671
2672 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2673 _mesa_update_image_transfer_state(ctx);
2674
2675 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2676 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2677 internalFormat, x, y, width, border)) {
2678 struct gl_pixelstore_attrib unpackSave;
2679
2680 /* get image from framebuffer */
2681 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2682 if (!image) {
2683 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2684 return;
2685 }
2686
2687 /* call glTexImage1D to redefine the texture */
2688 unpackSave = ctx->Unpack;
2689 ctx->Unpack = _mesa_native_packing;
2690 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2691 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2692 ctx->Unpack = unpackSave;
2693
2694 FREE(image);
2695 }
2696 }
2697
2698
2699
2700 void
2701 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2702 GLint x, GLint y, GLsizei width, GLsizei height,
2703 GLint border )
2704 {
2705 GET_CURRENT_CONTEXT(ctx);
2706 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2707
2708 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2709 width, height, border))
2710 return;
2711
2712 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2713 _mesa_update_image_transfer_state(ctx);
2714
2715 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2716 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2717 internalFormat, x, y, width, height, border)) {
2718 struct gl_pixelstore_attrib unpackSave;
2719
2720 /* get image from framebuffer */
2721 GLubyte *image = read_color_image( ctx, x, y, width, height );
2722 if (!image) {
2723 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2724 return;
2725 }
2726
2727 /* call glTexImage2D to redefine the texture */
2728 unpackSave = ctx->Unpack;
2729 ctx->Unpack = _mesa_native_packing;
2730 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2731 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2732 ctx->Unpack = unpackSave;
2733
2734 FREE(image);
2735 }
2736 }
2737
2738
2739
2740 void
2741 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2742 GLint xoffset, GLint x, GLint y, GLsizei width )
2743 {
2744 GET_CURRENT_CONTEXT(ctx);
2745 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2746
2747 if (copytexsubimage_error_check(ctx, 1, target, level,
2748 xoffset, 0, 0, width, 1))
2749 return;
2750
2751 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2752 _mesa_update_image_transfer_state(ctx);
2753
2754 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2755 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2756 xoffset, x, y, width)) {
2757 struct gl_texture_unit *texUnit;
2758 struct gl_texture_image *teximage;
2759 struct gl_pixelstore_attrib unpackSave;
2760 GLubyte *image;
2761
2762 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2763 teximage = texUnit->CurrentD[1]->Image[level];
2764 assert(teximage);
2765
2766 /* get image from frame buffer */
2767 image = read_color_image(ctx, x, y, width, 1);
2768 if (!image) {
2769 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2770 return;
2771 }
2772
2773 /* now call glTexSubImage1D to do the real work */
2774 unpackSave = ctx->Unpack;
2775 ctx->Unpack = _mesa_native_packing;
2776 _mesa_TexSubImage1D(target, level, xoffset, width,
2777 GL_RGBA, GL_UNSIGNED_BYTE, image);
2778 ctx->Unpack = unpackSave;
2779
2780 FREE(image);
2781 }
2782 }
2783
2784
2785
2786 void
2787 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2788 GLint xoffset, GLint yoffset,
2789 GLint x, GLint y, GLsizei width, GLsizei height )
2790 {
2791 GET_CURRENT_CONTEXT(ctx);
2792 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2793
2794 if (copytexsubimage_error_check(ctx, 2, target, level,
2795 xoffset, yoffset, 0, width, height))
2796 return;
2797
2798 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2799 _mesa_update_image_transfer_state(ctx);
2800
2801 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2802 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2803 xoffset, yoffset, x, y, width, height )) {
2804 struct gl_texture_unit *texUnit;
2805 struct gl_texture_image *teximage;
2806 struct gl_pixelstore_attrib unpackSave;
2807 GLubyte *image;
2808
2809 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2810 teximage = texUnit->CurrentD[2]->Image[level];
2811 assert(teximage);
2812
2813 /* get image from frame buffer */
2814 image = read_color_image(ctx, x, y, width, height);
2815 if (!image) {
2816 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2817 return;
2818 }
2819
2820 /* now call glTexSubImage2D to do the real work */
2821 unpackSave = ctx->Unpack;
2822 ctx->Unpack = _mesa_native_packing;
2823 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2824 GL_RGBA, GL_UNSIGNED_BYTE, image);
2825 ctx->Unpack = unpackSave;
2826
2827 FREE(image);
2828 }
2829 }
2830
2831
2832
2833 void
2834 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2835 GLint xoffset, GLint yoffset, GLint zoffset,
2836 GLint x, GLint y, GLsizei width, GLsizei height )
2837 {
2838 GET_CURRENT_CONTEXT(ctx);
2839 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2840
2841 if (copytexsubimage_error_check(ctx, 3, target, level,
2842 xoffset, yoffset, zoffset, width, height))
2843 return;
2844
2845 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2846 _mesa_update_image_transfer_state(ctx);
2847
2848 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2849 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2850 xoffset, yoffset, zoffset, x, y, width, height )) {
2851 struct gl_texture_unit *texUnit;
2852 struct gl_texture_image *teximage;
2853 struct gl_pixelstore_attrib unpackSave;
2854 GLubyte *image;
2855
2856 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2857 teximage = texUnit->CurrentD[3]->Image[level];
2858 assert(teximage);
2859
2860 /* get image from frame buffer */
2861 image = read_color_image(ctx, x, y, width, height);
2862 if (!image) {
2863 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2864 return;
2865 }
2866
2867 /* now call glTexSubImage2D to do the real work */
2868 unpackSave = ctx->Unpack;
2869 ctx->Unpack = _mesa_native_packing;
2870 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2871 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2872 ctx->Unpack = unpackSave;
2873
2874 FREE(image);
2875 }
2876 }
2877
2878
2879
2880 void
2881 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2882 GLenum internalFormat, GLsizei width,
2883 GLint border, GLsizei imageSize,
2884 const GLvoid *data)
2885 {
2886 GET_CURRENT_CONTEXT(ctx);
2887 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2888
2889 switch (internalFormat) {
2890 case GL_COMPRESSED_ALPHA_ARB:
2891 case GL_COMPRESSED_LUMINANCE_ARB:
2892 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2893 case GL_COMPRESSED_INTENSITY_ARB:
2894 case GL_COMPRESSED_RGB_ARB:
2895 case GL_COMPRESSED_RGBA_ARB:
2896 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2897 return;
2898 default:
2899 /* silence compiler warning */
2900 ;
2901 }
2902
2903 if (target == GL_TEXTURE_1D) {
2904 struct gl_texture_unit *texUnit;
2905 struct gl_texture_object *texObj;
2906 struct gl_texture_image *texImage;
2907 GLsizei computedImageSize;
2908
2909 if (texture_error_check(ctx, target, level, internalFormat,
2910 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2911 return; /* error in texture image was detected */
2912 }
2913
2914 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2915 texObj = texUnit->CurrentD[1];
2916 texImage = texObj->Image[level];
2917
2918 if (!texImage) {
2919 texImage = _mesa_alloc_texture_image();
2920 texObj->Image[level] = texImage;
2921 if (!texImage) {
2922 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2923 return;
2924 }
2925 }
2926 else if (texImage->Data) {
2927 FREE(texImage->Data);
2928 texImage->Data = NULL;
2929 }
2930
2931 /* setup the teximage struct's fields */
2932 init_texture_image(ctx, texImage, width, 1, 1,
2933 border, internalFormat);
2934
2935 /* process the texture image */
2936 if (data) {
2937 GLboolean retain = GL_TRUE;
2938 GLboolean success = GL_FALSE;
2939 if (ctx->Driver.CompressedTexImage1D) {
2940 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2941 imageSize, data, texObj, texImage, &retain);
2942 }
2943 if (retain || !success) {
2944 /* make internal copy of the texture image */
2945 computedImageSize = _mesa_compressed_image_size(ctx,
2946 internalFormat,
2947 1, /* num dims */
2948 width,
2949 1, /* height */
2950 1); /* depth */
2951 if (computedImageSize != imageSize) {
2952 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2953 return;
2954 }
2955 texImage->Data = MALLOC(computedImageSize);
2956 if (texImage->Data) {
2957 MEMCPY(texImage->Data, data, computedImageSize);
2958 }
2959 }
2960 if (!retain && texImage->Data) {
2961 FREE(texImage->Data);
2962 texImage->Data = NULL;
2963 }
2964 }
2965 else {
2966 make_null_texture(texImage);
2967 if (ctx->Driver.CompressedTexImage1D) {
2968 GLboolean retain;
2969 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2970 texImage->Data, texObj,
2971 texImage, &retain);
2972 }
2973 }
2974
2975 /* state update */
2976 gl_put_texobj_on_dirty_list( ctx, texObj );
2977 ctx->NewState |= NEW_TEXTURING;
2978 }
2979 else if (target == GL_PROXY_TEXTURE_1D) {
2980 /* Proxy texture: check for errors and update proxy state */
2981 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2982 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2983 if (!error && ctx->Driver.TestProxyTexImage) {
2984 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2985 internalFormat, GL_NONE, GL_NONE,
2986 width, 1, 1, border);
2987 }
2988 if (error) {
2989 /* if error, clear all proxy texture image parameters */
2990 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2991 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2992 }
2993 }
2994 else {
2995 /* if no error, update proxy texture image parameters */
2996 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2997 width, 1, 1, border, internalFormat);
2998 }
2999 }
3000 else {
3001 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
3002 return;
3003 }
3004 }
3005
3006
3007 void
3008 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3009 GLenum internalFormat, GLsizei width,
3010 GLsizei height, GLint border, GLsizei imageSize,
3011 const GLvoid *data)
3012 {
3013 GET_CURRENT_CONTEXT(ctx);
3014 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
3015
3016 switch (internalFormat) {
3017 case GL_COMPRESSED_ALPHA_ARB:
3018 case GL_COMPRESSED_LUMINANCE_ARB:
3019 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3020 case GL_COMPRESSED_INTENSITY_ARB:
3021 case GL_COMPRESSED_RGB_ARB:
3022 case GL_COMPRESSED_RGBA_ARB:
3023 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3024 return;
3025 default:
3026 /* silence compiler warning */
3027 ;
3028 }
3029
3030 if (target==GL_TEXTURE_2D ||
3031 (ctx->Extensions.HaveTextureCubeMap &&
3032 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3033 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3034 struct gl_texture_unit *texUnit;
3035 struct gl_texture_object *texObj;
3036 struct gl_texture_image *texImage;
3037 GLsizei computedImageSize;
3038
3039 if (texture_error_check(ctx, target, level, internalFormat,
3040 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3041 return; /* error in texture image was detected */
3042 }
3043
3044 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3045 texObj = texUnit->CurrentD[2];
3046 texImage = texObj->Image[level];
3047
3048 if (!texImage) {
3049 texImage = _mesa_alloc_texture_image();
3050 texObj->Image[level] = texImage;
3051 if (!texImage) {
3052 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3053 return;
3054 }
3055 }
3056 else if (texImage->Data) {
3057 FREE(texImage->Data);
3058 texImage->Data = NULL;
3059 }
3060
3061 /* setup the teximage struct's fields */
3062 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
3063
3064 /* process the texture image */
3065 if (data) {
3066 GLboolean retain = GL_TRUE;
3067 GLboolean success = GL_FALSE;
3068 if (ctx->Driver.CompressedTexImage2D) {
3069 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3070 target,
3071 level,
3072 imageSize,
3073 data,
3074 texObj,
3075 texImage,
3076 &retain);
3077 }
3078 if (retain || !success) {
3079 /* make internal copy of the texture image */
3080 computedImageSize = _mesa_compressed_image_size(ctx,
3081 internalFormat,
3082 2, /* num dims */
3083 width,
3084 height,
3085 1); /* depth */
3086 if (computedImageSize != imageSize) {
3087 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3088 return;
3089 }
3090 texImage->Data = MALLOC(computedImageSize);
3091 if (texImage->Data) {
3092 MEMCPY(texImage->Data, data, computedImageSize);
3093 }
3094 }
3095 if (!retain && texImage->Data) {
3096 FREE(texImage->Data);
3097 texImage->Data = NULL;
3098 }
3099 }
3100 else {
3101 make_null_texture(texImage);
3102 if (ctx->Driver.CompressedTexImage2D) {
3103 GLboolean retain;
3104 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3105 texImage->Data, texObj,
3106 texImage, &retain);
3107 }
3108 }
3109
3110 /* state update */
3111 gl_put_texobj_on_dirty_list( ctx, texObj );
3112 ctx->NewState |= NEW_TEXTURING;
3113 }
3114 else if (target == GL_PROXY_TEXTURE_2D) {
3115 /* Proxy texture: check for errors and update proxy state */
3116 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3117 GL_NONE, GL_NONE, 2, width, height, 1, border);
3118 if (!error && ctx->Driver.TestProxyTexImage) {
3119 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3120 internalFormat, GL_NONE, GL_NONE,
3121 width, height, 1, border);
3122 }
3123 if (error) {
3124 /* if error, clear all proxy texture image parameters */
3125 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3126 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
3127 }
3128 }
3129 else {
3130 /* if no error, update proxy texture image parameters */
3131 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3132 width, 1, 1, border, internalFormat);
3133 }
3134 }
3135 else {
3136 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3137 return;
3138 }
3139 }
3140
3141
3142 void
3143 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3144 GLenum internalFormat, GLsizei width,
3145 GLsizei height, GLsizei depth, GLint border,
3146 GLsizei imageSize, const GLvoid *data)
3147 {
3148 GET_CURRENT_CONTEXT(ctx);
3149 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3150
3151 switch (internalFormat) {
3152 case GL_COMPRESSED_ALPHA_ARB:
3153 case GL_COMPRESSED_LUMINANCE_ARB:
3154 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3155 case GL_COMPRESSED_INTENSITY_ARB:
3156 case GL_COMPRESSED_RGB_ARB:
3157 case GL_COMPRESSED_RGBA_ARB:
3158 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3159 return;
3160 default:
3161 /* silence compiler warning */
3162 ;
3163 }
3164
3165 if (target == GL_TEXTURE_3D) {
3166 struct gl_texture_unit *texUnit;
3167 struct gl_texture_object *texObj;
3168 struct gl_texture_image *texImage;
3169 GLsizei computedImageSize;
3170
3171 if (texture_error_check(ctx, target, level, internalFormat,
3172 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3173 return; /* error in texture image was detected */
3174 }
3175
3176 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3177 texObj = texUnit->CurrentD[3];
3178 texImage = texObj->Image[level];
3179
3180 if (!texImage) {
3181 texImage = _mesa_alloc_texture_image();
3182 texObj->Image[level] = texImage;
3183 if (!texImage) {
3184 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3185 return;
3186 }
3187 }
3188 else if (texImage->Data) {
3189 FREE(texImage->Data);
3190 texImage->Data = NULL;
3191 }
3192
3193 /* setup the teximage struct's fields */
3194 init_texture_image(ctx, texImage, width, height, depth,
3195 border, internalFormat);
3196
3197 /* process the texture image */
3198 if (data) {
3199 GLboolean retain = GL_TRUE;
3200 GLboolean success = GL_FALSE;
3201 if (ctx->Driver.CompressedTexImage3D) {
3202 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3203 imageSize, data,
3204 texObj, texImage,
3205 &retain);
3206 }
3207 if (retain || !success) {
3208 /* make internal copy of the texture image */
3209 computedImageSize = _mesa_compressed_image_size(ctx,
3210 internalFormat,
3211 3, /* num dims */
3212 width,
3213 height,
3214 depth);
3215 if (computedImageSize != imageSize) {
3216 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3217 return;
3218 }
3219 texImage->Data = MALLOC(computedImageSize);
3220 if (texImage->Data) {
3221 MEMCPY(texImage->Data, data, computedImageSize);
3222 }
3223 }
3224 if (!retain && texImage->Data) {
3225 FREE(texImage->Data);
3226 texImage->Data = NULL;
3227 }
3228 }
3229 else {
3230 make_null_texture(texImage);
3231 if (ctx->Driver.CompressedTexImage3D) {
3232 GLboolean retain;
3233 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3234 texImage->Data, texObj,
3235 texImage, &retain);
3236 }
3237 }
3238
3239 /* state update */
3240 gl_put_texobj_on_dirty_list( ctx, texObj );
3241 ctx->NewState |= NEW_TEXTURING;
3242 }
3243 else if (target == GL_PROXY_TEXTURE_3D) {
3244 /* Proxy texture: check for errors and update proxy state */
3245 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3246 GL_NONE, GL_NONE, 1, width, height, depth, border);
3247 if (!error && ctx->Driver.TestProxyTexImage) {
3248 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3249 internalFormat, GL_NONE, GL_NONE,
3250 width, height, depth, border);
3251 }
3252 if (error) {
3253 /* if error, clear all proxy texture image parameters */
3254 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3255 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3256 }
3257 }
3258 else {
3259 /* if no error, update proxy texture image parameters */
3260 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3261 width, 1, 1, border, internalFormat);
3262 }
3263 }
3264 else {
3265 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3266 return;
3267 }
3268 }
3269
3270
3271 void
3272 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3273 GLsizei width, GLenum format,
3274 GLsizei imageSize, const GLvoid *data)
3275 {
3276 GET_CURRENT_CONTEXT(ctx);
3277 struct gl_texture_unit *texUnit;
3278 struct gl_texture_object *texObj;
3279 struct gl_texture_image *texImage;
3280 GLboolean success = GL_FALSE;
3281
3282 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3283 width, 1, 1, format, GL_NONE)) {
3284 return; /* error was detected */
3285 }
3286
3287 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3288 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3289 texImage = texObj->Image[level];
3290 assert(texImage);
3291
3292 if (width == 0 || !data)
3293 return; /* no-op, not an error */
3294
3295 if (ctx->Driver.CompressedTexSubImage1D) {
3296 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3297 xoffset, width, format, imageSize, data, texObj, texImage);
3298 }
3299 if (!success) {
3300 /* XXX what else can we do? */
3301 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3302 return;
3303 }
3304 }
3305
3306
3307 void
3308 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3309 GLint yoffset, GLsizei width, GLsizei height,
3310 GLenum format, GLsizei imageSize,
3311 const GLvoid *data)
3312 {
3313 GET_CURRENT_CONTEXT(ctx);
3314 struct gl_texture_unit *texUnit;
3315 struct gl_texture_object *texObj;
3316 struct gl_texture_image *texImage;
3317 GLboolean success = GL_FALSE;
3318
3319 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3320 width, height, 1, format, GL_NONE)) {
3321 return; /* error was detected */
3322 }
3323
3324 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3325 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3326 texImage = texObj->Image[level];
3327 assert(texImage);
3328
3329 if (width == 0 || height == 0 || !data)
3330 return; /* no-op, not an error */
3331
3332 if (ctx->Driver.CompressedTexSubImage2D) {
3333 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3334 xoffset, yoffset, width, height, format,
3335 imageSize, data, texObj, texImage);
3336 }
3337 if (!success) {
3338 /* XXX what else can we do? */
3339 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3340 return;
3341 }
3342 }
3343
3344
3345 void
3346 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3347 GLint yoffset, GLint zoffset, GLsizei width,
3348 GLsizei height, GLsizei depth, GLenum format,
3349 GLsizei imageSize, const GLvoid *data)
3350 {
3351 GET_CURRENT_CONTEXT(ctx);
3352 struct gl_texture_unit *texUnit;
3353 struct gl_texture_object *texObj;
3354 struct gl_texture_image *texImage;
3355 GLboolean success = GL_FALSE;
3356
3357 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3358 width, height, depth, format, GL_NONE)) {
3359 return; /* error was detected */
3360 }
3361
3362 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3363 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3364 texImage = texObj->Image[level];
3365 assert(texImage);
3366
3367 if (width == 0 || height == 0 || depth == 0 || !data)
3368 return; /* no-op, not an error */
3369
3370 if (ctx->Driver.CompressedTexSubImage3D) {
3371 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3372 xoffset, yoffset, zoffset, width, height, depth,
3373 format, imageSize, data, texObj, texImage);
3374 }
3375 if (!success) {
3376 /* XXX what else can we do? */
3377 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3378 return;
3379 }
3380 }
3381
3382
3383 void
3384 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3385 {
3386 GET_CURRENT_CONTEXT(ctx);
3387 const struct gl_texture_object *texObj;
3388 struct gl_texture_image *texImage;
3389
3390 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3391
3392 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3393 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3394 return;
3395 }
3396
3397 switch (target) {
3398 case GL_TEXTURE_1D:
3399 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3400 texImage = texObj->Image[level];
3401 break;
3402 case GL_TEXTURE_2D:
3403 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3404 texImage = texObj->Image[level];
3405 break;
3406 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3407 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3408 texImage = texObj->Image[level];
3409 break;
3410 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3411 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3412 texImage = texObj->NegX[level];
3413 break;
3414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3415 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3416 texImage = texObj->PosY[level];
3417 break;
3418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3419 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3420 texImage = texObj->NegY[level];
3421 break;
3422 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3423 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3424 texImage = texObj->PosZ[level];
3425 break;
3426 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3427 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3428 texImage = texObj->NegZ[level];
3429 break;
3430 case GL_TEXTURE_3D:
3431 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3432 texImage = texObj->Image[level];
3433 break;
3434 default:
3435 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3436 return;
3437 }
3438
3439 if (!texImage) {
3440 /* invalid mipmap level */
3441 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3442 return;
3443 }
3444
3445 if (!texImage->IsCompressed) {
3446 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3447 return;
3448 }
3449
3450 if (!img)
3451 return;
3452
3453 if (ctx->Driver.GetCompressedTexImage) {
3454 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3455 texImage);
3456 }
3457 else {
3458 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3459 }
3460 }