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