initial code for GL_ARB_texture_cube_map
[mesa.git] / src / mesa / main / teximage.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 3.3
5 *
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 #ifdef PC_HEADER
28 #include "all.h"
29 #else
30 #include "glheader.h"
31 #include "context.h"
32 #include "image.h"
33 #include "mem.h"
34 #include "mmath.h"
35 #include "span.h"
36 #include "teximage.h"
37 #include "texstate.h"
38 #include "types.h"
39 #endif
40
41
42 /*
43 * NOTES:
44 *
45 * Mesa's native texture datatype is GLubyte. Native formats are
46 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
47 * and GL_COLOR_INDEX.
48 * Device drivers are free to implement any internal format they want.
49 */
50
51
52 #ifdef DEBUG
53 static void PrintTexture(const struct gl_texture_image *img)
54 {
55 int i, j, c;
56 GLubyte *data = img->Data;
57
58 if (!data) {
59 printf("No texture data\n");
60 return;
61 }
62
63 switch (img->Format) {
64 case GL_ALPHA:
65 case GL_LUMINANCE:
66 case GL_INTENSITY:
67 case GL_COLOR_INDEX:
68 c = 1;
69 break;
70 case GL_LUMINANCE_ALPHA:
71 c = 2;
72 break;
73 case GL_RGB:
74 c = 3;
75 break;
76 case GL_RGBA:
77 c = 4;
78 break;
79 default:
80 gl_problem(NULL, "error in PrintTexture\n");
81 return;
82 }
83
84
85 for (i = 0; i < img->Height; i++) {
86 for (j = 0; j < img->Width; j++) {
87 if (c==1)
88 printf("%02x ", data[0]);
89 else if (c==2)
90 printf("%02x%02x ", data[0], data[1]);
91 else if (c==3)
92 printf("%02x%02x%02x ", data[0], data[1], data[2]);
93 else if (c==4)
94 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
95 data += c;
96 }
97 printf("\n");
98 }
99 }
100 #endif
101
102
103
104 /*
105 * Compute log base 2 of n.
106 * If n isn't an exact power of two return -1.
107 * If n<0 return -1.
108 */
109 static int
110 logbase2( int n )
111 {
112 GLint i = 1;
113 GLint log2 = 0;
114
115 if (n<0) {
116 return -1;
117 }
118
119 while ( n > i ) {
120 i *= 2;
121 log2++;
122 }
123 if (i != n) {
124 return -1;
125 }
126 else {
127 return log2;
128 }
129 }
130
131
132
133 /*
134 * Given an internal texture format enum or 1, 2, 3, 4 return the
135 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
136 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
137 * Return -1 if invalid enum.
138 */
139 GLint
140 _mesa_base_tex_format( GLint format )
141 {
142 switch (format) {
143 case GL_ALPHA:
144 case GL_ALPHA4:
145 case GL_ALPHA8:
146 case GL_ALPHA12:
147 case GL_ALPHA16:
148 return GL_ALPHA;
149 case 1:
150 case GL_LUMINANCE:
151 case GL_LUMINANCE4:
152 case GL_LUMINANCE8:
153 case GL_LUMINANCE12:
154 case GL_LUMINANCE16:
155 return GL_LUMINANCE;
156 case 2:
157 case GL_LUMINANCE_ALPHA:
158 case GL_LUMINANCE4_ALPHA4:
159 case GL_LUMINANCE6_ALPHA2:
160 case GL_LUMINANCE8_ALPHA8:
161 case GL_LUMINANCE12_ALPHA4:
162 case GL_LUMINANCE12_ALPHA12:
163 case GL_LUMINANCE16_ALPHA16:
164 return GL_LUMINANCE_ALPHA;
165 case GL_INTENSITY:
166 case GL_INTENSITY4:
167 case GL_INTENSITY8:
168 case GL_INTENSITY12:
169 case GL_INTENSITY16:
170 return GL_INTENSITY;
171 case 3:
172 case GL_RGB:
173 case GL_R3_G3_B2:
174 case GL_RGB4:
175 case GL_RGB5:
176 case GL_RGB8:
177 case GL_RGB10:
178 case GL_RGB12:
179 case GL_RGB16:
180 return GL_RGB;
181 case 4:
182 case GL_RGBA:
183 case GL_RGBA2:
184 case GL_RGBA4:
185 case GL_RGB5_A1:
186 case GL_RGBA8:
187 case GL_RGB10_A2:
188 case GL_RGBA12:
189 case GL_RGBA16:
190 return GL_RGBA;
191 case GL_COLOR_INDEX:
192 case GL_COLOR_INDEX1_EXT:
193 case GL_COLOR_INDEX2_EXT:
194 case GL_COLOR_INDEX4_EXT:
195 case GL_COLOR_INDEX8_EXT:
196 case GL_COLOR_INDEX12_EXT:
197 case GL_COLOR_INDEX16_EXT:
198 return GL_COLOR_INDEX;
199 default:
200 return -1; /* error */
201 }
202 }
203
204
205
206 /*
207 * Given an internal texture format enum or 1, 2, 3, 4 return the
208 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
209 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
210 * number of components for the format. Return -1 if invalid enum.
211 */
212 static GLint
213 components_in_intformat( GLint format )
214 {
215 switch (format) {
216 case GL_ALPHA:
217 case GL_ALPHA4:
218 case GL_ALPHA8:
219 case GL_ALPHA12:
220 case GL_ALPHA16:
221 return 1;
222 case 1:
223 case GL_LUMINANCE:
224 case GL_LUMINANCE4:
225 case GL_LUMINANCE8:
226 case GL_LUMINANCE12:
227 case GL_LUMINANCE16:
228 return 1;
229 case 2:
230 case GL_LUMINANCE_ALPHA:
231 case GL_LUMINANCE4_ALPHA4:
232 case GL_LUMINANCE6_ALPHA2:
233 case GL_LUMINANCE8_ALPHA8:
234 case GL_LUMINANCE12_ALPHA4:
235 case GL_LUMINANCE12_ALPHA12:
236 case GL_LUMINANCE16_ALPHA16:
237 return 2;
238 case GL_INTENSITY:
239 case GL_INTENSITY4:
240 case GL_INTENSITY8:
241 case GL_INTENSITY12:
242 case GL_INTENSITY16:
243 return 1;
244 case 3:
245 case GL_RGB:
246 case GL_R3_G3_B2:
247 case GL_RGB4:
248 case GL_RGB5:
249 case GL_RGB8:
250 case GL_RGB10:
251 case GL_RGB12:
252 case GL_RGB16:
253 return 3;
254 case 4:
255 case GL_RGBA:
256 case GL_RGBA2:
257 case GL_RGBA4:
258 case GL_RGB5_A1:
259 case GL_RGBA8:
260 case GL_RGB10_A2:
261 case GL_RGBA12:
262 case GL_RGBA16:
263 return 4;
264 case GL_COLOR_INDEX:
265 case GL_COLOR_INDEX1_EXT:
266 case GL_COLOR_INDEX2_EXT:
267 case GL_COLOR_INDEX4_EXT:
268 case GL_COLOR_INDEX8_EXT:
269 case GL_COLOR_INDEX12_EXT:
270 case GL_COLOR_INDEX16_EXT:
271 return 1;
272 default:
273 return -1; /* error */
274 }
275 }
276
277
278
279 /*
280 * Examine the texImage->Format field and set the Red, Green, Blue, etc
281 * texel component sizes to default values.
282 * These fields are set only here by core Mesa but device drivers may
283 * overwritting these fields to indicate true texel resolution.
284 */
285 static void
286 set_teximage_component_sizes( struct gl_texture_image *texImage )
287 {
288 switch (texImage->Format) {
289 case GL_ALPHA:
290 texImage->RedBits = 0;
291 texImage->GreenBits = 0;
292 texImage->BlueBits = 0;
293 texImage->AlphaBits = 8;
294 texImage->IntensityBits = 0;
295 texImage->LuminanceBits = 0;
296 texImage->IndexBits = 0;
297 break;
298 case GL_LUMINANCE:
299 texImage->RedBits = 0;
300 texImage->GreenBits = 0;
301 texImage->BlueBits = 0;
302 texImage->AlphaBits = 0;
303 texImage->IntensityBits = 0;
304 texImage->LuminanceBits = 8;
305 texImage->IndexBits = 0;
306 break;
307 case GL_LUMINANCE_ALPHA:
308 texImage->RedBits = 0;
309 texImage->GreenBits = 0;
310 texImage->BlueBits = 0;
311 texImage->AlphaBits = 8;
312 texImage->IntensityBits = 0;
313 texImage->LuminanceBits = 8;
314 texImage->IndexBits = 0;
315 break;
316 case GL_INTENSITY:
317 texImage->RedBits = 0;
318 texImage->GreenBits = 0;
319 texImage->BlueBits = 0;
320 texImage->AlphaBits = 0;
321 texImage->IntensityBits = 8;
322 texImage->LuminanceBits = 0;
323 texImage->IndexBits = 0;
324 break;
325 case GL_RED:
326 texImage->RedBits = 8;
327 texImage->GreenBits = 0;
328 texImage->BlueBits = 0;
329 texImage->AlphaBits = 0;
330 texImage->IntensityBits = 0;
331 texImage->LuminanceBits = 0;
332 texImage->IndexBits = 0;
333 break;
334 case GL_GREEN:
335 texImage->RedBits = 0;
336 texImage->GreenBits = 8;
337 texImage->BlueBits = 0;
338 texImage->AlphaBits = 0;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 0;
341 texImage->IndexBits = 0;
342 break;
343 case GL_BLUE:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 8;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 0;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 0;
351 break;
352 case GL_RGB:
353 case GL_BGR:
354 texImage->RedBits = 8;
355 texImage->GreenBits = 8;
356 texImage->BlueBits = 8;
357 texImage->AlphaBits = 0;
358 texImage->IntensityBits = 0;
359 texImage->LuminanceBits = 0;
360 texImage->IndexBits = 0;
361 break;
362 case GL_RGBA:
363 case GL_BGRA:
364 case GL_ABGR_EXT:
365 texImage->RedBits = 8;
366 texImage->GreenBits = 8;
367 texImage->BlueBits = 8;
368 texImage->AlphaBits = 8;
369 texImage->IntensityBits = 0;
370 texImage->LuminanceBits = 0;
371 texImage->IndexBits = 0;
372 break;
373 case GL_COLOR_INDEX:
374 texImage->RedBits = 0;
375 texImage->GreenBits = 0;
376 texImage->BlueBits = 0;
377 texImage->AlphaBits = 0;
378 texImage->IntensityBits = 0;
379 texImage->LuminanceBits = 0;
380 texImage->IndexBits = 8;
381 break;
382 default:
383 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
384 }
385 }
386
387
388 /*
389 * Given a texture unit and a texture target, return the corresponding
390 * texture object.
391 */
392 static struct gl_texture_object *
393 select_tex_object(struct gl_texture_unit *unit, GLenum target)
394 {
395 switch (target) {
396 case GL_TEXTURE_1D:
397 return unit->CurrentD[1];
398 case GL_TEXTURE_2D:
399 return unit->CurrentD[2];
400 case GL_TEXTURE_3D:
401 return unit->CurrentD[3];
402 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
403 return unit->CurrentPosX;
404 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
405 return unit->CurrentNegX;
406 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
407 return unit->CurrentPosY;
408 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
409 return unit->CurrentNegY;
410 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
411 return unit->CurrentPosZ;
412 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
413 return unit->CurrentNegZ;
414 default:
415 gl_problem(NULL, "bad target in select_tex_object()");
416 return NULL;
417 }
418 }
419
420
421 /*
422 * Return new gl_texture_image struct with all fields initialized to zero.
423 */
424 struct gl_texture_image *
425 _mesa_alloc_texture_image( void )
426 {
427 return CALLOC_STRUCT(gl_texture_image);
428 }
429
430
431
432 /*
433 * Initialize most fields of a gl_texture_image struct.
434 */
435 static void
436 init_texture_image( struct gl_texture_image *img,
437 GLsizei width, GLsizei height, GLsizei depth,
438 GLint border, GLenum internalFormat )
439 {
440 ASSERT(img);
441 ASSERT(!img->Data);
442 img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
443 set_teximage_component_sizes( img );
444 img->IntFormat = (GLenum) internalFormat;
445 img->Border = border;
446 img->Width = width;
447 img->Height = height;
448 img->Depth = depth;
449 img->WidthLog2 = logbase2(width - 2 * border);
450 if (height == 1) /* 1-D texture */
451 img->HeightLog2 = 0;
452 else
453 img->HeightLog2 = logbase2(height - 2 * border);
454 if (depth == 1) /* 2-D texture */
455 img->DepthLog2 = 0;
456 else
457 img->DepthLog2 = logbase2(depth - 2 * border);
458 img->Width2 = 1 << img->WidthLog2;
459 img->Height2 = 1 << img->HeightLog2;
460 img->Depth2 = 1 << img->DepthLog2;
461 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
462 }
463
464
465
466 void
467 _mesa_free_texture_image( struct gl_texture_image *teximage )
468 {
469 if (teximage->Data) {
470 FREE( teximage->Data );
471 teximage->Data = NULL;
472 }
473 FREE( teximage );
474 }
475
476
477
478 /* Need this to prevent an out-of-bounds memory access when using
479 * X86 optimized code.
480 */
481 #ifdef USE_X86_ASM
482 # define EXTRA_BYTE 1
483 #else
484 # define EXTRA_BYTE 0
485 #endif
486
487
488
489 /*
490 * Called by glTexImage[123]D. Fill in a texture image with data given
491 * by the client. All pixel transfer and unpack modes are handled here.
492 * NOTE: All texture image parameters should have already been error checked.
493 */
494 static void
495 make_texture_image( GLcontext *ctx,
496 struct gl_texture_image *texImage,
497 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
498 const struct gl_pixelstore_attrib *unpacking)
499 {
500 GLint components, numPixels;
501 GLint internalFormat, width, height, depth, border;
502
503 ASSERT(ctx);
504 ASSERT(texImage);
505 ASSERT(!texImage->Data);
506 ASSERT(pixels);
507 ASSERT(unpacking);
508
509 internalFormat = texImage->IntFormat;
510 width = texImage->Width;
511 height = texImage->Height;
512 depth = texImage->Depth;
513 border = texImage->Border;
514 components = components_in_intformat(internalFormat);
515
516 ASSERT(width > 0);
517 ASSERT(height > 0);
518 ASSERT(depth > 0);
519 ASSERT(border == 0 || border == 1);
520 ASSERT(pixels);
521 ASSERT(unpacking);
522 ASSERT(components);
523
524 numPixels = width * height * depth;
525
526 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
527 if (!texImage->Data)
528 return; /* out of memory */
529
530 /*
531 * OK, the texture image struct has been initialized and the texture
532 * image memory has been allocated.
533 * Now fill in the texture image from the source data.
534 * This includes applying the pixel transfer operations.
535 */
536
537 /* try common 2D texture cases first */
538 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
539 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
540 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
541
542 if (srcFormat == internalFormat ||
543 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
544 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
545 (srcFormat == GL_RGB && internalFormat == 3) ||
546 (srcFormat == GL_RGBA && internalFormat == 4)) {
547 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
548 * GL_LUMINANCE_ALPHA, etc. texture formats.
549 */
550 const GLubyte *src = (const GLubyte *) _mesa_image_address(
551 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
552 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
553 srcFormat, srcType);
554 GLubyte *dst = texImage->Data;
555 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
556 if (srcStride == dstBytesPerRow) {
557 MEMCPY(dst, src, height * dstBytesPerRow);
558 }
559 else {
560 GLint i;
561 for (i = 0; i < height; i++) {
562 MEMCPY(dst, src, dstBytesPerRow);
563 src += srcStride;
564 dst += dstBytesPerRow;
565 }
566 }
567 return; /* all done */
568 }
569 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
570 /* commonly used by Quake */
571 const GLubyte *src = (const GLubyte *) _mesa_image_address(
572 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
573 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
574 srcFormat, srcType);
575 GLubyte *dst = texImage->Data;
576 GLint i, j;
577 for (i = 0; i < height; i++) {
578 const GLubyte *s = src;
579 for (j = 0; j < width; j++) {
580 *dst++ = *s++; /*red*/
581 *dst++ = *s++; /*green*/
582 *dst++ = *s++; /*blue*/
583 s++; /*alpha*/
584 }
585 src += srcStride;
586 }
587 return; /* all done */
588 }
589 }
590
591
592 /*
593 * General case solutions
594 */
595 if (texImage->Format == GL_COLOR_INDEX) {
596 /* color index texture */
597 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
598 const GLenum dstType = GL_UNSIGNED_BYTE;
599 GLubyte *dest = texImage->Data;
600 GLint img, row;
601 for (img = 0; img < depth; img++) {
602 for (row = 0; row < height; row++) {
603 const GLvoid *source = _mesa_image_address(unpacking,
604 pixels, width, height, srcFormat, srcType, img, row, 0);
605 _mesa_unpack_index_span(ctx, width, dstType, dest,
606 srcType, source, unpacking, GL_TRUE);
607 dest += destBytesPerRow;
608 }
609 }
610 }
611 else {
612 /* regular, color texture */
613 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
614 const GLenum dstFormat = texImage->Format;
615 GLubyte *dest = texImage->Data;
616 GLint img, row;
617 for (img = 0; img < depth; img++) {
618 for (row = 0; row < height; row++) {
619 const GLvoid *source = _mesa_image_address(unpacking,
620 pixels, width, height, srcFormat, srcType, img, row, 0);
621 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
622 srcFormat, srcType, source, unpacking, GL_TRUE);
623 dest += destBytesPerRow;
624 }
625 }
626 }
627 }
628
629
630
631 /*
632 * glTexImage[123]D can accept a NULL image pointer. In this case we
633 * create a texture image with unspecified image contents per the OpenGL
634 * spec. This function creates an empty image for the given texture image.
635 */
636 static void
637 make_null_texture( struct gl_texture_image *texImage )
638 {
639 GLint components;
640 GLint numPixels;
641
642 ASSERT(texImage);
643 ASSERT(!texImage->Data);
644
645 components = components_in_intformat(texImage->IntFormat);
646 numPixels = texImage->Width * texImage->Height * texImage->Depth;
647
648 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
649
650 /*
651 * Let's see if anyone finds this. If glTexImage2D() is called with
652 * a NULL image pointer then load the texture image with something
653 * interesting instead of leaving it indeterminate.
654 */
655 if (texImage->Data) {
656 static const char message[8][32] = {
657 " X X XXXXX XXX X ",
658 " XX XX X X X X X ",
659 " X X X X X X X ",
660 " X X XXXX XXX XXXXX ",
661 " X X X X X X ",
662 " X X X X X X X ",
663 " X X XXXXX XXX X X ",
664 " "
665 };
666
667 GLubyte *imgPtr = texImage->Data;
668 GLint i, j, k;
669 for (i = 0; i < texImage->Height; i++) {
670 GLint srcRow = 7 - i % 8;
671 for (j = 0; j < texImage->Width; j++) {
672 GLint srcCol = j % 32;
673 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
674 for (k=0;k<components;k++) {
675 *imgPtr++ = (GLubyte) texel;
676 }
677 }
678 }
679 }
680 }
681
682
683
684 /*
685 * Test glTexImage[123]D() parameters for errors.
686 * Input:
687 * dimensions - must be 1 or 2 or 3
688 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
689 */
690 static GLboolean
691 texture_error_check( GLcontext *ctx, GLenum target,
692 GLint level, GLint internalFormat,
693 GLenum format, GLenum type,
694 GLuint dimensions,
695 GLint width, GLint height,
696 GLint depth, GLint border )
697 {
698 GLboolean isProxy;
699 GLint iformat;
700
701 if (dimensions == 1) {
702 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
703 if (target != GL_TEXTURE_1D && !isProxy) {
704 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
705 return GL_TRUE;
706 }
707 }
708 else if (dimensions == 2) {
709 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
710 if (target != GL_TEXTURE_2D && !isProxy) {
711 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
712 return GL_TRUE;
713 }
714 }
715 else if (dimensions == 3) {
716 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
717 if (target != GL_TEXTURE_3D && !isProxy) {
718 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
719 return GL_TRUE;
720 }
721 }
722 else {
723 gl_problem( ctx, "bad dims in texture_error_check" );
724 return GL_TRUE;
725 }
726
727 /* Border */
728 if (border != 0 && border != 1) {
729 if (!isProxy) {
730 char message[100];
731 sprintf(message, "glTexImage%dD(border)", dimensions);
732 gl_error(ctx, GL_INVALID_VALUE, message);
733 }
734 return GL_TRUE;
735 }
736
737 /* Width */
738 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
739 || logbase2( width - 2 * border ) < 0) {
740 if (!isProxy) {
741 char message[100];
742 sprintf(message, "glTexImage%dD(width)", dimensions);
743 gl_error(ctx, GL_INVALID_VALUE, message);
744 }
745 return GL_TRUE;
746 }
747
748 /* Height */
749 if (dimensions >= 2) {
750 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
751 || logbase2( height - 2 * border ) < 0) {
752 if (!isProxy) {
753 char message[100];
754 sprintf(message, "glTexImage%dD(height)", dimensions);
755 gl_error(ctx, GL_INVALID_VALUE, message);
756 }
757 return GL_TRUE;
758 }
759 }
760
761 /* Depth */
762 if (dimensions >= 3) {
763 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
764 || logbase2( depth - 2 * border ) < 0) {
765 if (!isProxy) {
766 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
767 }
768 return GL_TRUE;
769 }
770 }
771
772 /* Level */
773 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
774 if (!isProxy) {
775 char message[100];
776 sprintf(message, "glTexImage%dD(level)", dimensions);
777 gl_error(ctx, GL_INVALID_VALUE, message);
778 }
779 return GL_TRUE;
780 }
781
782 iformat = _mesa_base_tex_format( internalFormat );
783 if (iformat < 0) {
784 if (!isProxy) {
785 char message[100];
786 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
787 gl_error(ctx, GL_INVALID_VALUE, message);
788 }
789 return GL_TRUE;
790 }
791
792 if (!_mesa_is_legal_format_and_type( format, type )) {
793 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
794 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
795 */
796 if (!isProxy) {
797 char message[100];
798 sprintf(message, "glTexImage%dD(format or type)", dimensions);
799 gl_error(ctx, GL_INVALID_OPERATION, message);
800 }
801 return GL_TRUE;
802 }
803
804 /* if we get here, the parameters are OK */
805 return GL_FALSE;
806 }
807
808
809
810 /*
811 * Test glTexSubImage[123]D() parameters for errors.
812 * Input:
813 * dimensions - must be 1 or 2 or 3
814 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
815 */
816 static GLboolean
817 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
818 GLenum target, GLint level,
819 GLint xoffset, GLint yoffset, GLint zoffset,
820 GLint width, GLint height, GLint depth,
821 GLenum format, GLenum type )
822 {
823 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
824 struct gl_texture_image *destTex;
825
826 if (dimensions == 1) {
827 if (target != GL_TEXTURE_1D) {
828 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
829 return GL_TRUE;
830 }
831 }
832 else if (dimensions == 2) {
833 if (target != GL_TEXTURE_2D) {
834 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
835 return GL_TRUE;
836 }
837 }
838 else if (dimensions == 3) {
839 if (target != GL_TEXTURE_3D) {
840 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
841 return GL_TRUE;
842 }
843 }
844 else {
845 gl_problem( ctx, "bad dims in texture_error_check" );
846 return GL_TRUE;
847 }
848
849 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
850 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
851 return GL_TRUE;
852 }
853
854 if (width < 0) {
855 char message[100];
856 sprintf(message, "glTexSubImage%dD(width)", dimensions);
857 gl_error(ctx, GL_INVALID_VALUE, message);
858 return GL_TRUE;
859 }
860 if (height < 0 && dimensions > 1) {
861 char message[100];
862 sprintf(message, "glTexSubImage%dD(height)", dimensions);
863 gl_error(ctx, GL_INVALID_VALUE, message);
864 return GL_TRUE;
865 }
866 if (depth < 0 && dimensions > 2) {
867 char message[100];
868 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
869 gl_error(ctx, GL_INVALID_VALUE, message);
870 return GL_TRUE;
871 }
872
873 destTex = texUnit->CurrentD[2]->Image[level];
874 if (!destTex) {
875 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
876 return GL_TRUE;
877 }
878
879 if (xoffset < -((GLint)destTex->Border)) {
880 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
881 return GL_TRUE;
882 }
883 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
884 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
885 return GL_TRUE;
886 }
887 if (dimensions > 1) {
888 if (yoffset < -((GLint)destTex->Border)) {
889 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
890 return GL_TRUE;
891 }
892 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
893 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
894 return GL_TRUE;
895 }
896 }
897 if (dimensions > 2) {
898 if (zoffset < -((GLint)destTex->Border)) {
899 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
900 return GL_TRUE;
901 }
902 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
903 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
904 return GL_TRUE;
905 }
906 }
907
908 if (!_mesa_is_legal_format_and_type(format, type)) {
909 char message[100];
910 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
911 gl_error(ctx, GL_INVALID_ENUM, message);
912 return GL_TRUE;
913 }
914
915 return GL_FALSE;
916 }
917
918
919 /*
920 * Test glCopyTexImage[12]D() parameters for errors.
921 * Input: dimensions - must be 1 or 2 or 3
922 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
923 */
924 static GLboolean
925 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
926 GLenum target, GLint level, GLint internalFormat,
927 GLint width, GLint height, GLint border )
928 {
929 GLint iformat;
930
931 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
932 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
933 return GL_TRUE;
934 }
935
936 if (dimensions == 1 && target != GL_TEXTURE_1D) {
937 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
938 return GL_TRUE;
939 }
940 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
941 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
942 return GL_TRUE;
943 }
944
945 /* Border */
946 if (border!=0 && border!=1) {
947 char message[100];
948 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
949 gl_error(ctx, GL_INVALID_VALUE, message);
950 return GL_TRUE;
951 }
952
953 /* Width */
954 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
955 || logbase2( width - 2 * border ) < 0) {
956 char message[100];
957 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
958 gl_error(ctx, GL_INVALID_VALUE, message);
959 return GL_TRUE;
960 }
961
962 /* Height */
963 if (dimensions >= 2) {
964 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
965 || logbase2( height - 2 * border ) < 0) {
966 char message[100];
967 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
968 gl_error(ctx, GL_INVALID_VALUE, message);
969 return GL_TRUE;
970 }
971 }
972
973 /* Level */
974 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
975 char message[100];
976 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
977 gl_error(ctx, GL_INVALID_VALUE, message);
978 return GL_TRUE;
979 }
980
981 iformat = _mesa_base_tex_format( internalFormat );
982 if (iformat < 0) {
983 char message[100];
984 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
985 gl_error(ctx, GL_INVALID_VALUE, message);
986 return GL_TRUE;
987 }
988
989 /* if we get here, the parameters are OK */
990 return GL_FALSE;
991 }
992
993
994 static GLboolean
995 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
996 GLenum target, GLint level,
997 GLint xoffset, GLint yoffset, GLint zoffset,
998 GLsizei width, GLsizei height )
999 {
1000 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1001 struct gl_texture_image *teximage;
1002
1003 if (dimensions == 1 && target != GL_TEXTURE_1D) {
1004 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1005 return GL_TRUE;
1006 }
1007 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
1008 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1009 return GL_TRUE;
1010 }
1011 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
1012 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1013 return GL_TRUE;
1014 }
1015
1016 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1017 char message[100];
1018 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1019 gl_error(ctx, GL_INVALID_VALUE, message);
1020 return GL_TRUE;
1021 }
1022
1023 if (width < 0) {
1024 char message[100];
1025 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1026 gl_error(ctx, GL_INVALID_VALUE, message);
1027 return GL_TRUE;
1028 }
1029 if (dimensions > 1 && height < 0) {
1030 char message[100];
1031 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1032 gl_error(ctx, GL_INVALID_VALUE, message);
1033 return GL_TRUE;
1034 }
1035
1036 teximage = texUnit->CurrentD[dimensions]->Image[level];
1037 if (!teximage) {
1038 char message[100];
1039 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1040 gl_error(ctx, GL_INVALID_OPERATION, message);
1041 return GL_TRUE;
1042 }
1043
1044 if (xoffset < -((GLint)teximage->Border)) {
1045 char message[100];
1046 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1047 gl_error(ctx, GL_INVALID_VALUE, message);
1048 return GL_TRUE;
1049 }
1050 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1051 char message[100];
1052 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1053 gl_error(ctx, GL_INVALID_VALUE, message);
1054 return GL_TRUE;
1055 }
1056 if (dimensions > 1) {
1057 if (yoffset < -((GLint)teximage->Border)) {
1058 char message[100];
1059 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1060 gl_error(ctx, GL_INVALID_VALUE, message);
1061 return GL_TRUE;
1062 }
1063 /* NOTE: we're adding the border here, not subtracting! */
1064 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1065 char message[100];
1066 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1067 gl_error(ctx, GL_INVALID_VALUE, message);
1068 return GL_TRUE;
1069 }
1070 }
1071
1072 if (dimensions > 2) {
1073 if (zoffset < -((GLint)teximage->Border)) {
1074 char message[100];
1075 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1076 gl_error(ctx, GL_INVALID_VALUE, message);
1077 return GL_TRUE;
1078 }
1079 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1080 char message[100];
1081 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1082 gl_error(ctx, GL_INVALID_VALUE, message);
1083 return GL_TRUE;
1084 }
1085 }
1086
1087 /* if we get here, the parameters are OK */
1088 return GL_FALSE;
1089 }
1090
1091
1092
1093
1094 /*
1095 * Called from the API. Note that width includes the border.
1096 */
1097 void
1098 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1099 GLsizei width, GLint border, GLenum format,
1100 GLenum type, const GLvoid *pixels )
1101 {
1102 GET_CURRENT_CONTEXT(ctx);
1103 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1104
1105 if (target==GL_TEXTURE_1D) {
1106 struct gl_texture_unit *texUnit;
1107 struct gl_texture_object *texObj;
1108 struct gl_texture_image *texImage;
1109
1110 if (texture_error_check( ctx, target, level, internalFormat,
1111 format, type, 1, width, 1, 1, border )) {
1112 return; /* error in texture image was detected */
1113 }
1114
1115 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1116 texObj = texUnit->CurrentD[1];
1117 texImage = texObj->Image[level];
1118
1119 if (!texImage) {
1120 texImage = _mesa_alloc_texture_image();
1121 texObj->Image[level] = texImage;
1122 if (!texImage) {
1123 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1124 return;
1125 }
1126 }
1127 else if (texImage->Data) {
1128 FREE(texImage->Data);
1129 texImage->Data = NULL;
1130 }
1131
1132 /* setup the teximage struct's fields */
1133 init_texture_image(texImage, width, 1, 1, border, internalFormat);
1134
1135 /* process the texture image */
1136 if (pixels) {
1137 GLboolean retain = GL_TRUE;
1138 GLboolean success = GL_FALSE;
1139 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1140 && ctx->Driver.TexImage1D) {
1141 /* let device driver try to use raw image */
1142 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1143 type, pixels, &ctx->Unpack,
1144 texObj, texImage, &retain);
1145 }
1146 if (retain || !success) {
1147 /* make internal copy of the texture image */
1148 make_texture_image(ctx, texImage, format, type,
1149 pixels, &ctx->Unpack);
1150 if (!success && ctx->Driver.TexImage1D) {
1151 /* let device driver try to use unpacked image */
1152 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1153 GL_UNSIGNED_BYTE, texImage->Data,
1154 &_mesa_native_packing,
1155 texObj, texImage, &retain);
1156 }
1157 }
1158 if (!retain && texImage->Data) {
1159 FREE(texImage->Data);
1160 texImage->Data = NULL;
1161 }
1162 }
1163 else {
1164 make_null_texture(texImage);
1165 if (ctx->Driver.TexImage1D) {
1166 GLboolean retain;
1167 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1168 GL_UNSIGNED_BYTE, texImage->Data,
1169 &_mesa_native_packing,
1170 texObj, texImage, &retain);
1171 }
1172 }
1173
1174 /* state update */
1175 gl_put_texobj_on_dirty_list( ctx, texObj );
1176 ctx->NewState |= NEW_TEXTURING;
1177 }
1178 else if (target==GL_PROXY_TEXTURE_1D) {
1179 /* Proxy texture: check for errors and update proxy state */
1180 if (texture_error_check( ctx, target, level, internalFormat,
1181 format, type, 1, width, 1, 1, border )) {
1182 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1183 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1184 sizeof(struct gl_texture_image) );
1185 }
1186 }
1187 else {
1188 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1189 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1190 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
1191 ctx->Texture.Proxy1D->Image[level]->Border = border;
1192 ctx->Texture.Proxy1D->Image[level]->Width = width;
1193 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1194 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1195 }
1196 }
1197 else {
1198 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1199 return;
1200 }
1201 }
1202
1203
1204 void
1205 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1206 GLsizei width, GLsizei height, GLint border,
1207 GLenum format, GLenum type,
1208 const GLvoid *pixels )
1209 {
1210 GET_CURRENT_CONTEXT(ctx);
1211 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1212
1213 if (target==GL_TEXTURE_2D) {
1214 struct gl_texture_unit *texUnit;
1215 struct gl_texture_object *texObj;
1216 struct gl_texture_image *texImage;
1217
1218 if (texture_error_check( ctx, target, level, internalFormat,
1219 format, type, 2, width, height, 1, border )) {
1220 return; /* error in texture image was detected */
1221 }
1222
1223 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1224 texObj = select_tex_object(texUnit, target);
1225 texImage = texObj->Image[level];
1226
1227 if (!texImage) {
1228 texImage = _mesa_alloc_texture_image();
1229 texObj->Image[level] = texImage;
1230 if (!texImage) {
1231 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1232 return;
1233 }
1234 }
1235 else if (texImage->Data) {
1236 FREE(texImage->Data);
1237 texImage->Data = NULL;
1238 }
1239
1240 /* setup the teximage struct's fields */
1241 init_texture_image(texImage, width, height, 1, border, internalFormat);
1242
1243 /* process the texture image */
1244 if (pixels) {
1245 GLboolean retain = GL_TRUE;
1246 GLboolean success = GL_FALSE;
1247 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1248 && ctx->Driver.TexImage2D) {
1249 /* let device driver try to use raw image */
1250 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1251 type, pixels, &ctx->Unpack,
1252 texObj, texImage, &retain);
1253 }
1254 if (retain || !success) {
1255 /* make internal copy of the texture image */
1256 make_texture_image(ctx, texImage, format, type,
1257 pixels, &ctx->Unpack);
1258 if (!success && ctx->Driver.TexImage2D) {
1259 /* let device driver try to use unpacked image */
1260 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1261 GL_UNSIGNED_BYTE, texImage->Data,
1262 &_mesa_native_packing,
1263 texObj, texImage, &retain);
1264 }
1265 }
1266 if (!retain && texImage->Data) {
1267 FREE(texImage->Data);
1268 texImage->Data = NULL;
1269 }
1270 }
1271 else {
1272 make_null_texture(texImage);
1273 if (ctx->Driver.TexImage2D) {
1274 GLboolean retain;
1275 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1276 GL_UNSIGNED_BYTE, texImage->Data,
1277 &_mesa_native_packing,
1278 texObj, texImage, &retain);
1279 }
1280 }
1281
1282 #define OLD_DD_TEXTURE
1283 #ifdef OLD_DD_TEXTURE
1284 /* XXX this will be removed in the future */
1285 if (ctx->Driver.TexImage) {
1286 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1287 texImage );
1288 }
1289 #endif
1290
1291 /* state update */
1292 gl_put_texobj_on_dirty_list( ctx, texObj );
1293 ctx->NewState |= NEW_TEXTURING;
1294 }
1295 else if (target==GL_PROXY_TEXTURE_2D) {
1296 /* Proxy texture: check for errors and update proxy state */
1297 if (texture_error_check( ctx, target, level, internalFormat,
1298 format, type, 2, width, height, 1, border )) {
1299 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1300 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1301 sizeof(struct gl_texture_image) );
1302 }
1303 }
1304 else {
1305 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1306 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1307 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
1308 ctx->Texture.Proxy2D->Image[level]->Border = border;
1309 ctx->Texture.Proxy2D->Image[level]->Width = width;
1310 ctx->Texture.Proxy2D->Image[level]->Height = height;
1311 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1312 }
1313 }
1314 else {
1315 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1316 return;
1317 }
1318 }
1319
1320
1321
1322 /*
1323 * Called by the API or display list executor.
1324 * Note that width and height include the border.
1325 */
1326 void
1327 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1328 GLsizei width, GLsizei height, GLsizei depth,
1329 GLint border, GLenum format, GLenum type,
1330 const GLvoid *pixels )
1331 {
1332 GET_CURRENT_CONTEXT(ctx);
1333 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1334
1335 if (target==GL_TEXTURE_3D_EXT) {
1336 struct gl_texture_unit *texUnit;
1337 struct gl_texture_object *texObj;
1338 struct gl_texture_image *texImage;
1339 if (texture_error_check( ctx, target, level, internalFormat,
1340 format, type, 3, width, height, depth,
1341 border )) {
1342 return; /* error in texture image was detected */
1343 }
1344
1345 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1346 texObj = texUnit->CurrentD[3];
1347 texImage = texObj->Image[level];
1348
1349 if (!texImage) {
1350 texImage = _mesa_alloc_texture_image();
1351 texObj->Image[level] = texImage;
1352 if (!texImage) {
1353 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1354 return;
1355 }
1356 }
1357 else if (texImage->Data) {
1358 FREE(texImage->Data);
1359 texImage->Data = NULL;
1360 }
1361
1362 /* setup the teximage struct's fields */
1363 init_texture_image(texImage, width, height, depth,
1364 border, internalFormat);
1365
1366 /* process the texture image */
1367 if (pixels) {
1368 GLboolean retain = GL_TRUE;
1369 GLboolean success = GL_FALSE;
1370 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1371 && ctx->Driver.TexImage3D) {
1372 /* let device driver try to use raw image */
1373 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1374 type, pixels, &ctx->Unpack,
1375 texObj, texImage, &retain);
1376 }
1377 if (retain || !success) {
1378 /* make internal copy of the texture image */
1379 make_texture_image(ctx, texImage, format, type,
1380 pixels, &ctx->Unpack);
1381 if (!success && ctx->Driver.TexImage3D) {
1382 /* let device driver try to use unpacked image */
1383 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1384 GL_UNSIGNED_BYTE, texImage->Data,
1385 &_mesa_native_packing,
1386 texObj, texImage, &retain);
1387 }
1388 }
1389 if (!retain && texImage->Data) {
1390 FREE(texImage->Data);
1391 texImage->Data = NULL;
1392 }
1393 }
1394 else {
1395 make_null_texture(texImage);
1396 if (ctx->Driver.TexImage3D) {
1397 GLboolean retain;
1398 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1399 GL_UNSIGNED_BYTE, texImage->Data,
1400 &_mesa_native_packing,
1401 texObj, texImage, &retain);
1402 }
1403 }
1404
1405 /* state update */
1406 gl_put_texobj_on_dirty_list( ctx, texObj );
1407 ctx->NewState |= NEW_TEXTURING;
1408 }
1409 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1410 /* Proxy texture: check for errors and update proxy state */
1411 if (texture_error_check( ctx, target, level, internalFormat,
1412 format, type, 3, width, height, depth,
1413 border )) {
1414 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1415 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1416 sizeof(struct gl_texture_image) );
1417 }
1418 }
1419 else {
1420 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1421 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1422 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
1423 ctx->Texture.Proxy3D->Image[level]->Border = border;
1424 ctx->Texture.Proxy3D->Image[level]->Width = width;
1425 ctx->Texture.Proxy3D->Image[level]->Height = height;
1426 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1427 }
1428 }
1429 else {
1430 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1431 return;
1432 }
1433 }
1434
1435
1436 void
1437 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1438 GLsizei width, GLsizei height, GLsizei depth,
1439 GLint border, GLenum format, GLenum type,
1440 const GLvoid *pixels )
1441 {
1442 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1443 depth, border, format, type, pixels);
1444 }
1445
1446
1447 /*
1448 * Fetch a texture image from the device driver.
1449 * Store the results in the given texture object at the given mipmap level.
1450 */
1451 void
1452 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1453 const struct gl_texture_object *texObj )
1454 {
1455 GLvoid *image;
1456 GLenum imgFormat, imgType;
1457 GLboolean freeImage;
1458 struct gl_texture_image *texImage;
1459 GLint destComponents, numPixels, srcBytesPerTexel;
1460
1461 if (!ctx->Driver.GetTexImage)
1462 return;
1463
1464 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
1465 &imgFormat, &imgType, &freeImage);
1466 if (!image)
1467 return;
1468
1469 texImage = texObj->Image[level];
1470 ASSERT(texImage);
1471 if (!texImage)
1472 return;
1473
1474 destComponents = components_in_intformat(texImage->Format);
1475 assert(destComponents > 0);
1476 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1477 assert(numPixels > 0);
1478 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1479 assert(srcBytesPerTexel > 0);
1480
1481 if (!texImage->Data) {
1482 /* Allocate memory for the texture image data */
1483 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1484 }
1485
1486 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1487 /* We got lucky! The driver's format and type match Mesa's format. */
1488 if (texImage->Data) {
1489 MEMCPY(texImage->Data, image, numPixels * destComponents);
1490 }
1491 }
1492 else {
1493 /* Convert the texture image from the driver's format to Mesa's
1494 * internal format.
1495 */
1496 const GLint width = texImage->Width;
1497 const GLint height = texImage->Height;
1498 const GLint depth = texImage->Depth;
1499 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1500 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1501 const GLenum dstType = GL_UNSIGNED_BYTE;
1502 const GLenum dstFormat = texImage->Format;
1503 const GLubyte *srcPtr = (const GLubyte *) image;
1504 GLubyte *destPtr = texImage->Data;
1505
1506 if (texImage->Format == GL_COLOR_INDEX) {
1507 /* color index texture */
1508 GLint img, row;
1509 assert(imgFormat == GL_COLOR_INDEX);
1510 for (img = 0; img < depth; img++) {
1511 for (row = 0; row < height; row++) {
1512 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1513 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1514 destPtr += destBytesPerRow;
1515 srcPtr += srcBytesPerRow;
1516 }
1517 }
1518 }
1519 else {
1520 /* color texture */
1521 GLint img, row;
1522 for (img = 0; img < depth; img++) {
1523 for (row = 0; row < height; row++) {
1524 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
1525 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1526 destPtr += destBytesPerRow;
1527 srcPtr += srcBytesPerRow;
1528 }
1529 }
1530 }
1531 }
1532
1533 if (freeImage)
1534 FREE(image);
1535 }
1536
1537
1538 void
1539 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1540 GLenum type, GLvoid *pixels )
1541 {
1542 GET_CURRENT_CONTEXT(ctx);
1543 const struct gl_texture_object *texObj;
1544 struct gl_texture_image *texImage;
1545 GLboolean discardImage;
1546
1547 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1548
1549 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1550 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1551 return;
1552 }
1553
1554 if (_mesa_sizeof_type(type) <= 0) {
1555 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1556 return;
1557 }
1558
1559 if (_mesa_components_in_format(format) <= 0) {
1560 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1561 return;
1562 }
1563
1564 if (!pixels)
1565 return;
1566
1567 switch (target) {
1568 case GL_TEXTURE_1D:
1569 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1570 break;
1571 case GL_TEXTURE_2D:
1572 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1573 break;
1574 case GL_TEXTURE_3D:
1575 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1576 break;
1577 default:
1578 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1579 return;
1580 }
1581
1582 texImage = texObj->Image[level];
1583 if (!texImage) {
1584 /* invalid mipmap level */
1585 return;
1586 }
1587
1588 if (!texImage->Data) {
1589 /* try to get the texture image from the device driver */
1590 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
1591 discardImage = GL_TRUE;
1592 }
1593 else {
1594 discardImage = GL_FALSE;
1595 }
1596
1597 if (texImage->Data) {
1598 GLint width = texImage->Width;
1599 GLint height = texImage->Height;
1600 GLint row;
1601
1602 for (row = 0; row < height; row++) {
1603 /* compute destination address in client memory */
1604 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1605 width, height,
1606 format, type, 0, row, 0);
1607
1608 assert(dest);
1609 if (texImage->Format == GL_RGBA) {
1610 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1611 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1612 format, type, dest, &ctx->Pack, GL_TRUE );
1613 }
1614 else {
1615 /* fetch RGBA row from texture image then pack it in client mem */
1616 GLubyte rgba[MAX_WIDTH][4];
1617 GLint i;
1618 const GLubyte *src;
1619 switch (texImage->Format) {
1620 case GL_ALPHA:
1621 src = texImage->Data + row * width * sizeof(GLubyte);
1622 for (i = 0; i < width; i++) {
1623 rgba[i][RCOMP] = 255;
1624 rgba[i][GCOMP] = 255;
1625 rgba[i][BCOMP] = 255;
1626 rgba[i][ACOMP] = src[i];
1627 }
1628 break;
1629 case GL_LUMINANCE:
1630 src = texImage->Data + row * width * sizeof(GLubyte);
1631 for (i = 0; i < width; i++) {
1632 rgba[i][RCOMP] = src[i];
1633 rgba[i][GCOMP] = src[i];
1634 rgba[i][BCOMP] = src[i];
1635 rgba[i][ACOMP] = 255;
1636 }
1637 break;
1638 case GL_LUMINANCE_ALPHA:
1639 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1640 for (i = 0; i < width; i++) {
1641 rgba[i][RCOMP] = src[i*2+0];
1642 rgba[i][GCOMP] = src[i*2+0];
1643 rgba[i][BCOMP] = src[i*2+0];
1644 rgba[i][ACOMP] = src[i*2+1];
1645 }
1646 break;
1647 case GL_INTENSITY:
1648 src = texImage->Data + row * width * sizeof(GLubyte);
1649 for (i = 0; i < width; i++) {
1650 rgba[i][RCOMP] = src[i];
1651 rgba[i][GCOMP] = src[i];
1652 rgba[i][BCOMP] = src[i];
1653 rgba[i][ACOMP] = 255;
1654 }
1655 break;
1656 case GL_RGB:
1657 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1658 for (i = 0; i < width; i++) {
1659 rgba[i][RCOMP] = src[i*3+0];
1660 rgba[i][GCOMP] = src[i*3+1];
1661 rgba[i][BCOMP] = src[i*3+2];
1662 rgba[i][ACOMP] = 255;
1663 }
1664 break;
1665 case GL_RGBA:
1666 /* this special case should have been handled above! */
1667 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1668 break;
1669 case GL_COLOR_INDEX:
1670 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1671 break;
1672 default:
1673 gl_problem( ctx, "bad format in gl_GetTexImage" );
1674 }
1675 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1676 format, type, dest, &ctx->Pack, GL_TRUE );
1677 }
1678 }
1679
1680 /* if we got the teximage from the device driver we'll discard it now */
1681 if (discardImage) {
1682 FREE(texImage->Data);
1683 texImage->Data = NULL;
1684 }
1685 }
1686 }
1687
1688
1689
1690 void
1691 _mesa_TexSubImage1D( GLenum target, GLint level,
1692 GLint xoffset, GLsizei width,
1693 GLenum format, GLenum type,
1694 const GLvoid *pixels )
1695 {
1696 GET_CURRENT_CONTEXT(ctx);
1697 struct gl_texture_unit *texUnit;
1698 struct gl_texture_object *texObj;
1699 struct gl_texture_image *texImage;
1700 GLboolean success = GL_FALSE;
1701
1702 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1703 width, 1, 1, format, type)) {
1704 return; /* error was detected */
1705 }
1706
1707 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1708 texObj = texUnit->CurrentD[1];
1709 texImage = texObj->Image[level];
1710 assert(texImage);
1711
1712 if (width == 0 || !pixels)
1713 return; /* no-op, not an error */
1714
1715
1716 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1717 && ctx->Driver.TexSubImage1D) {
1718 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1719 width, format, type, pixels,
1720 &ctx->Unpack, texObj, texImage );
1721 }
1722 if (!success) {
1723 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1724
1725 const GLint texComponents = components_in_intformat(texImage->Format);
1726 const GLenum texFormat = texImage->Format;
1727 const GLint xoffsetb = xoffset + texImage->Border;
1728 GLboolean retain = GL_TRUE;
1729 if (!texImage->Data) {
1730 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
1731 if (!texImage->Data) {
1732 make_null_texture(texImage);
1733 }
1734 if (!texImage->Data)
1735 return; /* we're really out of luck! */
1736 }
1737
1738 if (texFormat == GL_COLOR_INDEX) {
1739 /* color index texture */
1740 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1741 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1742 1, format, type, 0, 0, 0);
1743 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1744 type, src, &ctx->Unpack, GL_TRUE);
1745 }
1746 else {
1747 /* color texture */
1748 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1749 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1750 1, format, type, 0, 0, 0);
1751 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1752 type, src, &ctx->Unpack, GL_TRUE);
1753 }
1754
1755 if (ctx->Driver.TexImage1D) {
1756 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1757 GL_UNSIGNED_BYTE, texImage->Data,
1758 &_mesa_native_packing, texObj, texImage,
1759 &retain );
1760 }
1761
1762 if (!retain && texImage->Data) {
1763 FREE(texImage->Data);
1764 texImage->Data = NULL;
1765 }
1766 }
1767
1768 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
1769 }
1770
1771
1772 void
1773 _mesa_TexSubImage2D( GLenum target, GLint level,
1774 GLint xoffset, GLint yoffset,
1775 GLsizei width, GLsizei height,
1776 GLenum format, GLenum type,
1777 const GLvoid *pixels )
1778 {
1779 GET_CURRENT_CONTEXT(ctx);
1780 struct gl_texture_unit *texUnit;
1781 struct gl_texture_object *texObj;
1782 struct gl_texture_image *texImage;
1783 GLboolean success = GL_FALSE;
1784
1785 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1786 width, height, 1, format, type)) {
1787 return; /* error was detected */
1788 }
1789
1790 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1791 texObj = select_tex_object(texUnit, target);
1792 texImage = texObj->Image[level];
1793 assert(texImage);
1794
1795 if (width == 0 || height == 0 || !pixels)
1796 return; /* no-op, not an error */
1797
1798 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1799 && ctx->Driver.TexSubImage2D) {
1800 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1801 yoffset, width, height, format, type,
1802 pixels, &ctx->Unpack, texObj, texImage );
1803 }
1804 if (!success) {
1805 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
1806
1807 const GLint texComponents = components_in_intformat(texImage->Format);
1808 const GLenum texFormat = texImage->Format;
1809 const GLint xoffsetb = xoffset + texImage->Border;
1810 const GLint yoffsetb = yoffset + texImage->Border;
1811 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1812 format, type);
1813 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1814 GLboolean retain = GL_TRUE;
1815
1816 if (!texImage->Data) {
1817 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
1818 if (!texImage->Data) {
1819 make_null_texture(texImage);
1820 }
1821 if (!texImage->Data)
1822 return; /* we're really out of luck! */
1823 }
1824
1825 if (texFormat == GL_COLOR_INDEX) {
1826 /* color index texture */
1827 GLubyte *dst = texImage->Data
1828 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1829 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1830 width, height, format, type, 0, 0, 0);
1831 GLint row;
1832 for (row = 0; row < height; row++) {
1833 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1834 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1835 src += srcStride;
1836 dst += dstStride;
1837 }
1838 }
1839 else {
1840 /* color texture */
1841 GLubyte *dst = texImage->Data
1842 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1843 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1844 width, height, format, type, 0, 0, 0);
1845 GLint row;
1846 for (row = 0; row < height; row++) {
1847 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1848 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1849 src += srcStride;
1850 dst += dstStride;
1851 }
1852 }
1853
1854 if (ctx->Driver.TexImage2D) {
1855 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1856 GL_UNSIGNED_BYTE, texImage->Data,
1857 &_mesa_native_packing, texObj, texImage,
1858 &retain);
1859 }
1860
1861 if (!retain && texImage->Data) {
1862 FREE(texImage->Data);
1863 texImage->Data = NULL;
1864 }
1865
1866 #ifdef OLD_DD_TEXTURE
1867 /* XXX this will be removed in the future */
1868 if (ctx->Driver.TexSubImage) {
1869 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1870 xoffset, yoffset, width, height,
1871 texImage->IntFormat, texImage);
1872 }
1873 else if (ctx->Driver.TexImage) {
1874 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
1875 level, texImage->IntFormat, texImage );
1876 }
1877 #endif
1878 }
1879 }
1880
1881
1882
1883 void
1884 _mesa_TexSubImage3D( GLenum target, GLint level,
1885 GLint xoffset, GLint yoffset, GLint zoffset,
1886 GLsizei width, GLsizei height, GLsizei depth,
1887 GLenum format, GLenum type,
1888 const GLvoid *pixels )
1889 {
1890 GET_CURRENT_CONTEXT(ctx);
1891 struct gl_texture_unit *texUnit;
1892 struct gl_texture_object *texObj;
1893 struct gl_texture_image *texImage;
1894 GLboolean success = GL_FALSE;
1895
1896 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1897 width, height, depth, format, type)) {
1898 return; /* error was detected */
1899 }
1900
1901 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1902 texObj = texUnit->CurrentD[3];
1903 texImage = texObj->Image[level];
1904 assert(texImage);
1905
1906 if (width == 0 || height == 0 || height == 0 || !pixels)
1907 return; /* no-op, not an error */
1908
1909 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1910 && ctx->Driver.TexSubImage3D) {
1911 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1912 yoffset, zoffset, width, height, depth, format,
1913 type, pixels, &ctx->Unpack, texObj, texImage );
1914 }
1915 if (!success) {
1916 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1917
1918 const GLint texComponents = components_in_intformat(texImage->Format);
1919 const GLenum texFormat = texImage->Format;
1920 const GLint xoffsetb = xoffset + texImage->Border;
1921 const GLint yoffsetb = yoffset + texImage->Border;
1922 const GLint zoffsetb = zoffset + texImage->Border;
1923 const GLint texWidth = texImage->Width;
1924 const GLint dstRectArea = texWidth * texImage->Height;
1925 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1926 width, format, type);
1927 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1928 GLboolean retain = GL_TRUE;
1929
1930 if (texFormat == GL_COLOR_INDEX) {
1931 /* color index texture */
1932 GLint img, row;
1933 for (img = 0; img < depth; img++) {
1934 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1935 width, height, format, type, img, 0, 0);
1936 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1937 + yoffsetb * texWidth + xoffsetb) * texComponents;
1938 for (row = 0; row < height; row++) {
1939 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1940 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1941 src += srcStride;
1942 dst += dstStride;
1943 }
1944 }
1945 }
1946 else {
1947 /* color texture */
1948 GLint img, row;
1949 for (img = 0; img < depth; img++) {
1950 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1951 width, height, format, type, img, 0, 0);
1952 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1953 + yoffsetb * texWidth + xoffsetb) * texComponents;
1954 for (row = 0; row < height; row++) {
1955 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1956 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1957 src += srcStride;
1958 dst += dstStride;
1959 }
1960 }
1961 }
1962
1963 if (ctx->Driver.TexImage3D) {
1964 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1965 GL_UNSIGNED_BYTE, texImage->Data,
1966 &_mesa_native_packing, texObj, texImage,
1967 &retain);
1968 }
1969
1970 if (!retain && texImage->Data) {
1971 FREE(texImage->Data);
1972 texImage->Data = NULL;
1973 }
1974 }
1975 }
1976
1977
1978
1979 /*
1980 * Read an RGBA image from the frame buffer.
1981 * This is used by glCopyTexSubImage[12]D().
1982 * Input: ctx - the context
1983 * x, y - lower left corner
1984 * width, height - size of region to read
1985 * Return: pointer to block of GL_RGBA, GLubyte data.
1986 */
1987 static GLubyte *
1988 read_color_image( GLcontext *ctx, GLint x, GLint y,
1989 GLsizei width, GLsizei height )
1990 {
1991 GLint stride, i;
1992 GLubyte *image, *dst;
1993
1994 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
1995 if (!image)
1996 return NULL;
1997
1998 /* Select buffer to read from */
1999 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2000 ctx->Pixel.DriverReadBuffer );
2001
2002 dst = image;
2003 stride = width * 4 * sizeof(GLubyte);
2004 for (i = 0; i < height; i++) {
2005 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2006 (GLubyte (*)[4]) dst );
2007 dst += stride;
2008 }
2009
2010 /* Read from draw buffer (the default) */
2011 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2012 ctx->Color.DriverDrawBuffer );
2013
2014 return image;
2015 }
2016
2017
2018
2019 void
2020 _mesa_CopyTexImage1D( GLenum target, GLint level,
2021 GLenum internalFormat,
2022 GLint x, GLint y,
2023 GLsizei width, GLint border )
2024 {
2025 GET_CURRENT_CONTEXT(ctx);
2026 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2027
2028 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2029 width, 1, border))
2030 return;
2031
2032 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2033 || !ctx->Driver.CopyTexImage1D
2034 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2035 internalFormat, x, y, width, border))
2036 {
2037 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2038 if (!image) {
2039 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2040 return;
2041 }
2042 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2043 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2044 FREE(image);
2045 }
2046 }
2047
2048
2049
2050 void
2051 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2052 GLint x, GLint y, GLsizei width, GLsizei height,
2053 GLint border )
2054 {
2055 GET_CURRENT_CONTEXT(ctx);
2056 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2057
2058 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2059 width, height, border))
2060 return;
2061
2062 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2063 || !ctx->Driver.CopyTexImage2D
2064 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2065 internalFormat, x, y, width, height, border))
2066 {
2067 GLubyte *image = read_color_image( ctx, x, y, width, height );
2068 if (!image) {
2069 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2070 return;
2071 }
2072 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2073 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2074 FREE(image);
2075 }
2076 }
2077
2078
2079
2080 /*
2081 * Do the work of glCopyTexSubImage[123]D.
2082 */
2083 static void
2084 copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2085 GLint width, GLint height,
2086 GLint srcx, GLint srcy,
2087 GLint dstx, GLint dsty, GLint dstz )
2088 {
2089 GLint i;
2090 GLint format, components, rectarea;
2091 GLint texwidth, texheight, zoffset;
2092
2093 /* dst[xyz] may be negative if we have a texture border! */
2094 dstx += dest->Border;
2095 dsty += dest->Border;
2096 dstz += dest->Border;
2097 texwidth = dest->Width;
2098 texheight = dest->Height;
2099 rectarea = texwidth * texheight;
2100 zoffset = dstz * rectarea;
2101 format = dest->Format;
2102 components = components_in_intformat( format );
2103
2104 /* Select buffer to read from */
2105 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2106 ctx->Pixel.DriverReadBuffer );
2107
2108 for (i = 0;i < height; i++) {
2109 GLubyte rgba[MAX_WIDTH][4];
2110 GLubyte *dst;
2111 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
2112 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2113 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2114 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
2115 &_mesa_native_packing, GL_TRUE);
2116 }
2117
2118 /* Read from draw buffer (the default) */
2119 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2120 ctx->Color.DriverDrawBuffer );
2121 }
2122
2123
2124
2125
2126 void
2127 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2128 GLint xoffset, GLint x, GLint y, GLsizei width )
2129 {
2130 GET_CURRENT_CONTEXT(ctx);
2131 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2132
2133 if (copytexsubimage_error_check(ctx, 1, target, level,
2134 xoffset, 0, 0, width, 1))
2135 return;
2136
2137 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2138 || !ctx->Driver.CopyTexSubImage1D
2139 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2140 xoffset, x, y, width)) {
2141 struct gl_texture_unit *texUnit;
2142 struct gl_texture_image *teximage;
2143 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2144 teximage = texUnit->CurrentD[1]->Image[level];
2145 assert(teximage);
2146 if (teximage->Data) {
2147 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
2148 /* tell driver about the change */
2149 /* XXX this is obsolete */
2150 if (ctx->Driver.TexImage) {
2151 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2152 texUnit->CurrentD[1],
2153 level, teximage->IntFormat, teximage );
2154 }
2155 }
2156 }
2157 }
2158
2159
2160
2161 void
2162 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2163 GLint xoffset, GLint yoffset,
2164 GLint x, GLint y, GLsizei width, GLsizei height )
2165 {
2166 GET_CURRENT_CONTEXT(ctx);
2167 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2168
2169 if (copytexsubimage_error_check(ctx, 2, target, level,
2170 xoffset, yoffset, 0, width, height))
2171 return;
2172
2173 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2174 || !ctx->Driver.CopyTexSubImage2D
2175 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2176 xoffset, yoffset, x, y, width, height )) {
2177 struct gl_texture_unit *texUnit;
2178 struct gl_texture_image *teximage;
2179 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2180 teximage = texUnit->CurrentD[2]->Image[level];
2181 assert(teximage);
2182 if (teximage->Data) {
2183 copy_tex_sub_image(ctx, teximage, width, height,
2184 x, y, xoffset, yoffset, 0);
2185 /* tell driver about the change */
2186 /* XXX this is obsolete */
2187 if (ctx->Driver.TexImage) {
2188 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2189 texUnit->CurrentD[2],
2190 level, teximage->IntFormat, teximage );
2191 }
2192 }
2193 }
2194 }
2195
2196
2197
2198 void
2199 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2200 GLint xoffset, GLint yoffset, GLint zoffset,
2201 GLint x, GLint y, GLsizei width, GLsizei height )
2202 {
2203 GET_CURRENT_CONTEXT(ctx);
2204 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2205
2206 if (copytexsubimage_error_check(ctx, 3, target, level,
2207 xoffset, yoffset, zoffset, width, height))
2208 return;
2209
2210 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2211 || !ctx->Driver.CopyTexSubImage3D
2212 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2213 xoffset, yoffset, zoffset, x, y, width, height )) {
2214 struct gl_texture_unit *texUnit;
2215 struct gl_texture_image *teximage;
2216 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2217 teximage = texUnit->CurrentD[3]->Image[level];
2218 assert(teximage);
2219 if (teximage->Data) {
2220 copy_tex_sub_image(ctx, teximage, width, height,
2221 x, y, xoffset, yoffset, zoffset);
2222 /* tell driver about the change */
2223 /* XXX this is obsolete */
2224 if (ctx->Driver.TexImage) {
2225 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2226 texUnit->CurrentD[3],
2227 level, teximage->IntFormat, teximage );
2228 }
2229 }
2230 }
2231 }