use BCOPY macro on FreeBSD
[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 /*
390 * Return new gl_texture_image struct with all fields initialized to zero.
391 */
392 struct gl_texture_image *
393 _mesa_alloc_texture_image( void )
394 {
395 return CALLOC_STRUCT(gl_texture_image);
396 }
397
398
399
400 /*
401 * Initialize most fields of a gl_texture_image struct.
402 */
403 static void
404 init_texture_image( struct gl_texture_image *img,
405 GLsizei width, GLsizei height, GLsizei depth,
406 GLint border, GLenum internalFormat )
407 {
408 ASSERT(img);
409 ASSERT(!img->Data);
410 img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
411 set_teximage_component_sizes( img );
412 img->IntFormat = (GLenum) internalFormat;
413 img->Border = border;
414 img->Width = width;
415 img->Height = height;
416 img->Depth = depth;
417 img->WidthLog2 = logbase2(width - 2 * border);
418 if (height == 1) /* 1-D texture */
419 img->HeightLog2 = 0;
420 else
421 img->HeightLog2 = logbase2(height - 2 * border);
422 if (depth == 1) /* 2-D texture */
423 img->DepthLog2 = 0;
424 else
425 img->DepthLog2 = logbase2(depth - 2 * border);
426 img->Width2 = 1 << img->WidthLog2;
427 img->Height2 = 1 << img->HeightLog2;
428 img->Depth2 = 1 << img->DepthLog2;
429 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
430 }
431
432
433
434 void
435 _mesa_free_texture_image( struct gl_texture_image *teximage )
436 {
437 if (teximage->Data) {
438 FREE( teximage->Data );
439 teximage->Data = NULL;
440 }
441 FREE( teximage );
442 }
443
444
445
446 /* Need this to prevent an out-of-bounds memory access when using
447 * X86 optimized code.
448 */
449 #ifdef USE_X86_ASM
450 # define EXTRA_BYTE 1
451 #else
452 # define EXTRA_BYTE 0
453 #endif
454
455
456
457 /*
458 * Called by glTexImage[123]D. Fill in a texture image with data given
459 * by the client. All pixel transfer and unpack modes are handled here.
460 * NOTE: All texture image parameters should have already been error checked.
461 */
462 static void
463 make_texture_image( GLcontext *ctx,
464 struct gl_texture_image *texImage,
465 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
466 const struct gl_pixelstore_attrib *unpacking)
467 {
468 GLint components, numPixels;
469 GLint internalFormat, width, height, depth, border;
470
471 ASSERT(ctx);
472 ASSERT(texImage);
473 ASSERT(!texImage->Data);
474 ASSERT(pixels);
475 ASSERT(unpacking);
476
477 internalFormat = texImage->IntFormat;
478 width = texImage->Width;
479 height = texImage->Height;
480 depth = texImage->Depth;
481 border = texImage->Border;
482 components = components_in_intformat(internalFormat);
483
484 ASSERT(width > 0);
485 ASSERT(height > 0);
486 ASSERT(depth > 0);
487 ASSERT(border == 0 || border == 1);
488 ASSERT(pixels);
489 ASSERT(unpacking);
490 ASSERT(components);
491
492 numPixels = width * height * depth;
493
494 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
495 if (!texImage->Data)
496 return; /* out of memory */
497
498 /*
499 * OK, the texture image struct has been initialized and the texture
500 * image memory has been allocated.
501 * Now fill in the texture image from the source data.
502 * This includes applying the pixel transfer operations.
503 */
504
505 /* try common 2D texture cases first */
506 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
507 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
508 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
509
510 if (srcFormat == internalFormat ||
511 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
512 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
513 (srcFormat == GL_RGB && internalFormat == 3) ||
514 (srcFormat == GL_RGBA && internalFormat == 4)) {
515 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
516 * GL_LUMINANCE_ALPHA, etc. texture formats.
517 */
518 const GLubyte *src = (const GLubyte *) _mesa_image_address(
519 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
520 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
521 srcFormat, srcType);
522 GLubyte *dst = texImage->Data;
523 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
524 if (srcStride == dstBytesPerRow) {
525 MEMCPY(dst, src, height * dstBytesPerRow);
526 }
527 else {
528 GLint i;
529 for (i = 0; i < height; i++) {
530 MEMCPY(dst, src, dstBytesPerRow);
531 src += srcStride;
532 dst += dstBytesPerRow;
533 }
534 }
535 return; /* all done */
536 }
537 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
538 /* commonly used by Quake */
539 const GLubyte *src = (const GLubyte *) _mesa_image_address(
540 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
541 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
542 srcFormat, srcType);
543 GLubyte *dst = texImage->Data;
544 GLint i, j;
545 for (i = 0; i < height; i++) {
546 const GLubyte *s = src;
547 for (j = 0; j < width; j++) {
548 *dst++ = *s++; /*red*/
549 *dst++ = *s++; /*green*/
550 *dst++ = *s++; /*blue*/
551 s++; /*alpha*/
552 }
553 src += srcStride;
554 }
555 return; /* all done */
556 }
557 }
558
559
560 /*
561 * General case solutions
562 */
563 if (texImage->Format == GL_COLOR_INDEX) {
564 /* color index texture */
565 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
566 const GLenum dstType = GL_UNSIGNED_BYTE;
567 GLubyte *dest = texImage->Data;
568 GLint img, row;
569 for (img = 0; img < depth; img++) {
570 for (row = 0; row < height; row++) {
571 const GLvoid *source = _mesa_image_address(unpacking,
572 pixels, width, height, srcFormat, srcType, img, row, 0);
573 _mesa_unpack_index_span(ctx, width, dstType, dest,
574 srcType, source, unpacking, GL_TRUE);
575 dest += destBytesPerRow;
576 }
577 }
578 }
579 else {
580 /* regular, color texture */
581 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
582 const GLenum dstFormat = texImage->Format;
583 GLubyte *dest = texImage->Data;
584 GLint img, row;
585 for (img = 0; img < depth; img++) {
586 for (row = 0; row < height; row++) {
587 const GLvoid *source = _mesa_image_address(unpacking,
588 pixels, width, height, srcFormat, srcType, img, row, 0);
589 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
590 srcFormat, srcType, source, unpacking, GL_TRUE);
591 dest += destBytesPerRow;
592 }
593 }
594 }
595 }
596
597
598
599 /*
600 * glTexImage[123]D can accept a NULL image pointer. In this case we
601 * create a texture image with unspecified image contents per the OpenGL
602 * spec. This function creates an empty image for the given texture image.
603 */
604 static void
605 make_null_texture( struct gl_texture_image *texImage )
606 {
607 GLint components;
608 GLint numPixels;
609
610 ASSERT(texImage);
611 ASSERT(!texImage->Data);
612
613 components = components_in_intformat(texImage->IntFormat);
614 numPixels = texImage->Width * texImage->Height * texImage->Depth;
615
616 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
617
618 /*
619 * Let's see if anyone finds this. If glTexImage2D() is called with
620 * a NULL image pointer then load the texture image with something
621 * interesting instead of leaving it indeterminate.
622 */
623 if (texImage->Data) {
624 static const char message[8][32] = {
625 " X X XXXXX XXX X ",
626 " XX XX X X X X X ",
627 " X X X X X X X ",
628 " X X XXXX XXX XXXXX ",
629 " X X X X X X ",
630 " X X X X X X X ",
631 " X X XXXXX XXX X X ",
632 " "
633 };
634
635 GLubyte *imgPtr = texImage->Data;
636 GLint i, j, k;
637 for (i = 0; i < texImage->Height; i++) {
638 GLint srcRow = 7 - i % 8;
639 for (j = 0; j < texImage->Width; j++) {
640 GLint srcCol = j % 32;
641 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
642 for (k=0;k<components;k++) {
643 *imgPtr++ = (GLubyte) texel;
644 }
645 }
646 }
647 }
648 }
649
650
651
652 /*
653 * Test glTexImage[123]D() parameters for errors.
654 * Input:
655 * dimensions - must be 1 or 2 or 3
656 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
657 */
658 static GLboolean
659 texture_error_check( GLcontext *ctx, GLenum target,
660 GLint level, GLint internalFormat,
661 GLenum format, GLenum type,
662 GLuint dimensions,
663 GLint width, GLint height,
664 GLint depth, GLint border )
665 {
666 GLboolean isProxy;
667 GLint iformat;
668
669 if (dimensions == 1) {
670 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
671 if (target != GL_TEXTURE_1D && !isProxy) {
672 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
673 return GL_TRUE;
674 }
675 }
676 else if (dimensions == 2) {
677 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
678 if (target != GL_TEXTURE_2D && !isProxy) {
679 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
680 return GL_TRUE;
681 }
682 }
683 else if (dimensions == 3) {
684 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
685 if (target != GL_TEXTURE_3D && !isProxy) {
686 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
687 return GL_TRUE;
688 }
689 }
690 else {
691 gl_problem( ctx, "bad dims in texture_error_check" );
692 return GL_TRUE;
693 }
694
695 /* Border */
696 if (border != 0 && border != 1) {
697 if (!isProxy) {
698 char message[100];
699 sprintf(message, "glTexImage%dD(border)", dimensions);
700 gl_error(ctx, GL_INVALID_VALUE, message);
701 }
702 return GL_TRUE;
703 }
704
705 /* Width */
706 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
707 || logbase2( width - 2 * border ) < 0) {
708 if (!isProxy) {
709 char message[100];
710 sprintf(message, "glTexImage%dD(width)", dimensions);
711 gl_error(ctx, GL_INVALID_VALUE, message);
712 }
713 return GL_TRUE;
714 }
715
716 /* Height */
717 if (dimensions >= 2) {
718 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
719 || logbase2( height - 2 * border ) < 0) {
720 if (!isProxy) {
721 char message[100];
722 sprintf(message, "glTexImage%dD(height)", dimensions);
723 gl_error(ctx, GL_INVALID_VALUE, message);
724 }
725 return GL_TRUE;
726 }
727 }
728
729 /* Depth */
730 if (dimensions >= 3) {
731 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
732 || logbase2( depth - 2 * border ) < 0) {
733 if (!isProxy) {
734 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
735 }
736 return GL_TRUE;
737 }
738 }
739
740 /* Level */
741 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
742 if (!isProxy) {
743 char message[100];
744 sprintf(message, "glTexImage%dD(level)", dimensions);
745 gl_error(ctx, GL_INVALID_VALUE, message);
746 }
747 return GL_TRUE;
748 }
749
750 iformat = _mesa_base_tex_format( internalFormat );
751 if (iformat < 0) {
752 if (!isProxy) {
753 char message[100];
754 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
755 gl_error(ctx, GL_INVALID_VALUE, message);
756 }
757 return GL_TRUE;
758 }
759
760 if (!_mesa_is_legal_format_and_type( format, type )) {
761 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
762 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
763 */
764 if (!isProxy) {
765 char message[100];
766 sprintf(message, "glTexImage%dD(format or type)", dimensions);
767 gl_error(ctx, GL_INVALID_OPERATION, message);
768 }
769 return GL_TRUE;
770 }
771
772 /* if we get here, the parameters are OK */
773 return GL_FALSE;
774 }
775
776
777
778 /*
779 * Test glTexSubImage[123]D() parameters for errors.
780 * Input:
781 * dimensions - must be 1 or 2 or 3
782 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
783 */
784 static GLboolean
785 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
786 GLenum target, GLint level,
787 GLint xoffset, GLint yoffset, GLint zoffset,
788 GLint width, GLint height, GLint depth,
789 GLenum format, GLenum type )
790 {
791 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
792 struct gl_texture_image *destTex;
793
794 if (dimensions == 1) {
795 if (target != GL_TEXTURE_1D) {
796 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
797 return GL_TRUE;
798 }
799 }
800 else if (dimensions == 2) {
801 if (target != GL_TEXTURE_2D) {
802 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
803 return GL_TRUE;
804 }
805 }
806 else if (dimensions == 3) {
807 if (target != GL_TEXTURE_3D) {
808 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
809 return GL_TRUE;
810 }
811 }
812 else {
813 gl_problem( ctx, "bad dims in texture_error_check" );
814 return GL_TRUE;
815 }
816
817 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
818 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
819 return GL_TRUE;
820 }
821
822 if (width < 0) {
823 char message[100];
824 sprintf(message, "glTexSubImage%dD(width)", dimensions);
825 gl_error(ctx, GL_INVALID_VALUE, message);
826 return GL_TRUE;
827 }
828 if (height < 0 && dimensions > 1) {
829 char message[100];
830 sprintf(message, "glTexSubImage%dD(height)", dimensions);
831 gl_error(ctx, GL_INVALID_VALUE, message);
832 return GL_TRUE;
833 }
834 if (depth < 0 && dimensions > 2) {
835 char message[100];
836 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
837 gl_error(ctx, GL_INVALID_VALUE, message);
838 return GL_TRUE;
839 }
840
841 destTex = texUnit->CurrentD[2]->Image[level];
842 if (!destTex) {
843 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
844 return GL_TRUE;
845 }
846
847 if (xoffset < -((GLint)destTex->Border)) {
848 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
849 return GL_TRUE;
850 }
851 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
852 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
853 return GL_TRUE;
854 }
855 if (dimensions > 1) {
856 if (yoffset < -((GLint)destTex->Border)) {
857 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
858 return GL_TRUE;
859 }
860 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
861 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
862 return GL_TRUE;
863 }
864 }
865 if (dimensions > 2) {
866 if (zoffset < -((GLint)destTex->Border)) {
867 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
868 return GL_TRUE;
869 }
870 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
871 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
872 return GL_TRUE;
873 }
874 }
875
876 if (!_mesa_is_legal_format_and_type(format, type)) {
877 char message[100];
878 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
879 gl_error(ctx, GL_INVALID_ENUM, message);
880 return GL_TRUE;
881 }
882
883 return GL_FALSE;
884 }
885
886
887 /*
888 * Test glCopyTexImage[12]D() parameters for errors.
889 * Input: dimensions - must be 1 or 2 or 3
890 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
891 */
892 static GLboolean
893 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
894 GLenum target, GLint level, GLint internalFormat,
895 GLint width, GLint height, GLint border )
896 {
897 GLint iformat;
898
899 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
900 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
901 return GL_TRUE;
902 }
903
904 if (dimensions == 1 && target != GL_TEXTURE_1D) {
905 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
906 return GL_TRUE;
907 }
908 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
909 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
910 return GL_TRUE;
911 }
912
913 /* Border */
914 if (border!=0 && border!=1) {
915 char message[100];
916 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
917 gl_error(ctx, GL_INVALID_VALUE, message);
918 return GL_TRUE;
919 }
920
921 /* Width */
922 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
923 || logbase2( width - 2 * border ) < 0) {
924 char message[100];
925 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
926 gl_error(ctx, GL_INVALID_VALUE, message);
927 return GL_TRUE;
928 }
929
930 /* Height */
931 if (dimensions >= 2) {
932 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
933 || logbase2( height - 2 * border ) < 0) {
934 char message[100];
935 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
936 gl_error(ctx, GL_INVALID_VALUE, message);
937 return GL_TRUE;
938 }
939 }
940
941 /* Level */
942 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
943 char message[100];
944 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
945 gl_error(ctx, GL_INVALID_VALUE, message);
946 return GL_TRUE;
947 }
948
949 iformat = _mesa_base_tex_format( internalFormat );
950 if (iformat < 0) {
951 char message[100];
952 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
953 gl_error(ctx, GL_INVALID_VALUE, message);
954 return GL_TRUE;
955 }
956
957 /* if we get here, the parameters are OK */
958 return GL_FALSE;
959 }
960
961
962 static GLboolean
963 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
964 GLenum target, GLint level,
965 GLint xoffset, GLint yoffset, GLint zoffset,
966 GLsizei width, GLsizei height )
967 {
968 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
969 struct gl_texture_image *teximage;
970
971 if (dimensions == 1 && target != GL_TEXTURE_1D) {
972 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
973 return GL_TRUE;
974 }
975 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
976 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
977 return GL_TRUE;
978 }
979 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
980 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
981 return GL_TRUE;
982 }
983
984 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
985 char message[100];
986 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
987 gl_error(ctx, GL_INVALID_VALUE, message);
988 return GL_TRUE;
989 }
990
991 if (width < 0) {
992 char message[100];
993 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
994 gl_error(ctx, GL_INVALID_VALUE, message);
995 return GL_TRUE;
996 }
997 if (dimensions > 1 && height < 0) {
998 char message[100];
999 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1000 gl_error(ctx, GL_INVALID_VALUE, message);
1001 return GL_TRUE;
1002 }
1003
1004 teximage = texUnit->CurrentD[dimensions]->Image[level];
1005 if (!teximage) {
1006 char message[100];
1007 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1008 gl_error(ctx, GL_INVALID_OPERATION, message);
1009 return GL_TRUE;
1010 }
1011
1012 if (xoffset < -((GLint)teximage->Border)) {
1013 char message[100];
1014 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1015 gl_error(ctx, GL_INVALID_VALUE, message);
1016 return GL_TRUE;
1017 }
1018 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1019 char message[100];
1020 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1021 gl_error(ctx, GL_INVALID_VALUE, message);
1022 return GL_TRUE;
1023 }
1024 if (dimensions > 1) {
1025 if (yoffset < -((GLint)teximage->Border)) {
1026 char message[100];
1027 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1028 gl_error(ctx, GL_INVALID_VALUE, message);
1029 return GL_TRUE;
1030 }
1031 /* NOTE: we're adding the border here, not subtracting! */
1032 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1033 char message[100];
1034 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1035 gl_error(ctx, GL_INVALID_VALUE, message);
1036 return GL_TRUE;
1037 }
1038 }
1039
1040 if (dimensions > 2) {
1041 if (zoffset < -((GLint)teximage->Border)) {
1042 char message[100];
1043 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1044 gl_error(ctx, GL_INVALID_VALUE, message);
1045 return GL_TRUE;
1046 }
1047 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1048 char message[100];
1049 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1050 gl_error(ctx, GL_INVALID_VALUE, message);
1051 return GL_TRUE;
1052 }
1053 }
1054
1055 /* if we get here, the parameters are OK */
1056 return GL_FALSE;
1057 }
1058
1059
1060
1061
1062 /*
1063 * Called from the API. Note that width includes the border.
1064 */
1065 void
1066 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1067 GLsizei width, GLint border, GLenum format,
1068 GLenum type, const GLvoid *pixels )
1069 {
1070 GET_CURRENT_CONTEXT(ctx);
1071 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1072
1073 if (target==GL_TEXTURE_1D) {
1074 struct gl_texture_unit *texUnit;
1075 struct gl_texture_object *texObj;
1076 struct gl_texture_image *texImage;
1077
1078 if (texture_error_check( ctx, target, level, internalFormat,
1079 format, type, 1, width, 1, 1, border )) {
1080 return; /* error in texture image was detected */
1081 }
1082
1083 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1084 texObj = texUnit->CurrentD[1];
1085 texImage = texObj->Image[level];
1086
1087 if (!texImage) {
1088 texImage = _mesa_alloc_texture_image();
1089 texObj->Image[level] = texImage;
1090 if (!texImage) {
1091 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1092 return;
1093 }
1094 }
1095 else if (texImage->Data) {
1096 FREE(texImage->Data);
1097 texImage->Data = NULL;
1098 }
1099
1100 /* setup the teximage struct's fields */
1101 init_texture_image(texImage, width, 1, 1, border, internalFormat);
1102
1103 /* process the texture image */
1104 if (pixels) {
1105 GLboolean retain = GL_TRUE;
1106 GLboolean success = GL_FALSE;
1107 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1108 && ctx->Driver.TexImage1D) {
1109 /* let device driver try to use raw image */
1110 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1111 type, pixels, &ctx->Unpack,
1112 texObj, texImage, &retain);
1113 }
1114 if (retain || !success) {
1115 /* make internal copy of the texture image */
1116 make_texture_image(ctx, texImage, format, type,
1117 pixels, &ctx->Unpack);
1118 if (!success && ctx->Driver.TexImage1D) {
1119 /* let device driver try to use unpacked image */
1120 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1121 GL_UNSIGNED_BYTE, texImage->Data,
1122 &_mesa_native_packing,
1123 texObj, texImage, &retain);
1124 }
1125 }
1126 if (!retain && texImage->Data) {
1127 FREE(texImage->Data);
1128 texImage->Data = NULL;
1129 }
1130 }
1131 else {
1132 make_null_texture(texImage);
1133 if (ctx->Driver.TexImage1D) {
1134 GLboolean retain;
1135 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1136 GL_UNSIGNED_BYTE, texImage->Data,
1137 &_mesa_native_packing,
1138 texObj, texImage, &retain);
1139 }
1140 }
1141
1142 /* state update */
1143 gl_put_texobj_on_dirty_list( ctx, texObj );
1144 ctx->NewState |= NEW_TEXTURING;
1145 }
1146 else if (target==GL_PROXY_TEXTURE_1D) {
1147 /* Proxy texture: check for errors and update proxy state */
1148 if (texture_error_check( ctx, target, level, internalFormat,
1149 format, type, 1, width, 1, 1, border )) {
1150 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1151 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1152 sizeof(struct gl_texture_image) );
1153 }
1154 }
1155 else {
1156 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1157 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1158 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
1159 ctx->Texture.Proxy1D->Image[level]->Border = border;
1160 ctx->Texture.Proxy1D->Image[level]->Width = width;
1161 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1162 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1163 }
1164 }
1165 else {
1166 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1167 return;
1168 }
1169 }
1170
1171
1172 void
1173 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1174 GLsizei width, GLsizei height, GLint border,
1175 GLenum format, GLenum type,
1176 const GLvoid *pixels )
1177 {
1178 GET_CURRENT_CONTEXT(ctx);
1179 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1180
1181 if (target==GL_TEXTURE_2D) {
1182 struct gl_texture_unit *texUnit;
1183 struct gl_texture_object *texObj;
1184 struct gl_texture_image *texImage;
1185
1186 if (texture_error_check( ctx, target, level, internalFormat,
1187 format, type, 2, width, height, 1, border )) {
1188 return; /* error in texture image was detected */
1189 }
1190
1191 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1192 texObj = texUnit->CurrentD[2];
1193 texImage = texObj->Image[level];
1194
1195 if (!texImage) {
1196 texImage = _mesa_alloc_texture_image();
1197 texObj->Image[level] = texImage;
1198 if (!texImage) {
1199 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1200 return;
1201 }
1202 }
1203 else if (texImage->Data) {
1204 FREE(texImage->Data);
1205 texImage->Data = NULL;
1206 }
1207
1208 /* setup the teximage struct's fields */
1209 init_texture_image(texImage, width, height, 1, border, internalFormat);
1210
1211 /* process the texture image */
1212 if (pixels) {
1213 GLboolean retain = GL_TRUE;
1214 GLboolean success = GL_FALSE;
1215 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1216 && ctx->Driver.TexImage2D) {
1217 /* let device driver try to use raw image */
1218 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1219 type, pixels, &ctx->Unpack,
1220 texObj, texImage, &retain);
1221 }
1222 if (retain || !success) {
1223 /* make internal copy of the texture image */
1224 make_texture_image(ctx, texImage, format, type,
1225 pixels, &ctx->Unpack);
1226 if (!success && ctx->Driver.TexImage2D) {
1227 /* let device driver try to use unpacked image */
1228 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1229 GL_UNSIGNED_BYTE, texImage->Data,
1230 &_mesa_native_packing,
1231 texObj, texImage, &retain);
1232 }
1233 }
1234 if (!retain && texImage->Data) {
1235 FREE(texImage->Data);
1236 texImage->Data = NULL;
1237 }
1238 }
1239 else {
1240 make_null_texture(texImage);
1241 if (ctx->Driver.TexImage2D) {
1242 GLboolean retain;
1243 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1244 GL_UNSIGNED_BYTE, texImage->Data,
1245 &_mesa_native_packing,
1246 texObj, texImage, &retain);
1247 }
1248 }
1249
1250 #define OLD_DD_TEXTURE
1251 #ifdef OLD_DD_TEXTURE
1252 /* XXX this will be removed in the future */
1253 if (ctx->Driver.TexImage) {
1254 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1255 texImage );
1256 }
1257 #endif
1258
1259 /* state update */
1260 gl_put_texobj_on_dirty_list( ctx, texObj );
1261 ctx->NewState |= NEW_TEXTURING;
1262 }
1263 else if (target==GL_PROXY_TEXTURE_2D) {
1264 /* Proxy texture: check for errors and update proxy state */
1265 if (texture_error_check( ctx, target, level, internalFormat,
1266 format, type, 2, width, height, 1, border )) {
1267 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1268 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1269 sizeof(struct gl_texture_image) );
1270 }
1271 }
1272 else {
1273 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1274 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1275 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
1276 ctx->Texture.Proxy2D->Image[level]->Border = border;
1277 ctx->Texture.Proxy2D->Image[level]->Width = width;
1278 ctx->Texture.Proxy2D->Image[level]->Height = height;
1279 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1280 }
1281 }
1282 else {
1283 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1284 return;
1285 }
1286 }
1287
1288
1289
1290 /*
1291 * Called by the API or display list executor.
1292 * Note that width and height include the border.
1293 */
1294 void
1295 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1296 GLsizei width, GLsizei height, GLsizei depth,
1297 GLint border, GLenum format, GLenum type,
1298 const GLvoid *pixels )
1299 {
1300 GET_CURRENT_CONTEXT(ctx);
1301 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1302
1303 if (target==GL_TEXTURE_3D_EXT) {
1304 struct gl_texture_unit *texUnit;
1305 struct gl_texture_object *texObj;
1306 struct gl_texture_image *texImage;
1307 if (texture_error_check( ctx, target, level, internalFormat,
1308 format, type, 3, width, height, depth,
1309 border )) {
1310 return; /* error in texture image was detected */
1311 }
1312
1313 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1314 texObj = texUnit->CurrentD[3];
1315 texImage = texObj->Image[level];
1316
1317 if (!texImage) {
1318 texImage = _mesa_alloc_texture_image();
1319 texObj->Image[level] = texImage;
1320 if (!texImage) {
1321 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1322 return;
1323 }
1324 }
1325 else if (texImage->Data) {
1326 FREE(texImage->Data);
1327 texImage->Data = NULL;
1328 }
1329
1330 /* setup the teximage struct's fields */
1331 init_texture_image(texImage, width, height, depth,
1332 border, internalFormat);
1333
1334 /* process the texture image */
1335 if (pixels) {
1336 GLboolean retain = GL_TRUE;
1337 GLboolean success = GL_FALSE;
1338 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1339 && ctx->Driver.TexImage3D) {
1340 /* let device driver try to use raw image */
1341 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1342 type, pixels, &ctx->Unpack,
1343 texObj, texImage, &retain);
1344 }
1345 if (retain || !success) {
1346 /* make internal copy of the texture image */
1347 make_texture_image(ctx, texImage, format, type,
1348 pixels, &ctx->Unpack);
1349 if (!success && ctx->Driver.TexImage3D) {
1350 /* let device driver try to use unpacked image */
1351 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1352 GL_UNSIGNED_BYTE, texImage->Data,
1353 &_mesa_native_packing,
1354 texObj, texImage, &retain);
1355 }
1356 }
1357 if (!retain && texImage->Data) {
1358 FREE(texImage->Data);
1359 texImage->Data = NULL;
1360 }
1361 }
1362 else {
1363 make_null_texture(texImage);
1364 if (ctx->Driver.TexImage3D) {
1365 GLboolean retain;
1366 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1367 GL_UNSIGNED_BYTE, texImage->Data,
1368 &_mesa_native_packing,
1369 texObj, texImage, &retain);
1370 }
1371 }
1372
1373 /* state update */
1374 gl_put_texobj_on_dirty_list( ctx, texObj );
1375 ctx->NewState |= NEW_TEXTURING;
1376 }
1377 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1378 /* Proxy texture: check for errors and update proxy state */
1379 if (texture_error_check( ctx, target, level, internalFormat,
1380 format, type, 3, width, height, depth,
1381 border )) {
1382 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1383 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1384 sizeof(struct gl_texture_image) );
1385 }
1386 }
1387 else {
1388 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1389 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1390 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
1391 ctx->Texture.Proxy3D->Image[level]->Border = border;
1392 ctx->Texture.Proxy3D->Image[level]->Width = width;
1393 ctx->Texture.Proxy3D->Image[level]->Height = height;
1394 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1395 }
1396 }
1397 else {
1398 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1399 return;
1400 }
1401 }
1402
1403
1404 void
1405 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1406 GLsizei width, GLsizei height, GLsizei depth,
1407 GLint border, GLenum format, GLenum type,
1408 const GLvoid *pixels )
1409 {
1410 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1411 depth, border, format, type, pixels);
1412 }
1413
1414
1415 /*
1416 * Fetch a texture image from the device driver.
1417 * Store the results in the given texture object at the given mipmap level.
1418 */
1419 void
1420 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1421 const struct gl_texture_object *texObj )
1422 {
1423 GLvoid *image;
1424 GLenum imgFormat, imgType;
1425 GLboolean freeImage;
1426 struct gl_texture_image *texImage;
1427 GLint destComponents, numPixels, srcBytesPerTexel;
1428
1429 if (!ctx->Driver.GetTexImage)
1430 return;
1431
1432 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
1433 &imgFormat, &imgType, &freeImage);
1434 if (!image)
1435 return;
1436
1437 texImage = texObj->Image[level];
1438 ASSERT(texImage);
1439 if (!texImage)
1440 return;
1441
1442 destComponents = components_in_intformat(texImage->Format);
1443 assert(destComponents > 0);
1444 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1445 assert(numPixels > 0);
1446 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1447 assert(srcBytesPerTexel > 0);
1448
1449 if (!texImage->Data) {
1450 /* Allocate memory for the texture image data */
1451 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1452 }
1453
1454 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1455 /* We got lucky! The driver's format and type match Mesa's format. */
1456 if (texImage->Data) {
1457 MEMCPY(texImage->Data, image, numPixels * destComponents);
1458 }
1459 }
1460 else {
1461 /* Convert the texture image from the driver's format to Mesa's
1462 * internal format.
1463 */
1464 const GLint width = texImage->Width;
1465 const GLint height = texImage->Height;
1466 const GLint depth = texImage->Depth;
1467 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1468 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1469 const GLenum dstType = GL_UNSIGNED_BYTE;
1470 const GLenum dstFormat = texImage->Format;
1471 const GLubyte *srcPtr = (const GLubyte *) image;
1472 GLubyte *destPtr = texImage->Data;
1473
1474 if (texImage->Format == GL_COLOR_INDEX) {
1475 /* color index texture */
1476 GLint img, row;
1477 assert(imgFormat == GL_COLOR_INDEX);
1478 for (img = 0; img < depth; img++) {
1479 for (row = 0; row < height; row++) {
1480 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1481 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1482 destPtr += destBytesPerRow;
1483 srcPtr += srcBytesPerRow;
1484 }
1485 }
1486 }
1487 else {
1488 /* color texture */
1489 GLint img, row;
1490 for (img = 0; img < depth; img++) {
1491 for (row = 0; row < height; row++) {
1492 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
1493 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1494 destPtr += destBytesPerRow;
1495 srcPtr += srcBytesPerRow;
1496 }
1497 }
1498 }
1499 }
1500
1501 if (freeImage)
1502 FREE(image);
1503 }
1504
1505
1506 void
1507 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1508 GLenum type, GLvoid *pixels )
1509 {
1510 GET_CURRENT_CONTEXT(ctx);
1511 const struct gl_texture_object *texObj;
1512 struct gl_texture_image *texImage;
1513 GLboolean discardImage;
1514
1515 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1516
1517 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1518 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1519 return;
1520 }
1521
1522 if (_mesa_sizeof_type(type) <= 0) {
1523 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1524 return;
1525 }
1526
1527 if (_mesa_components_in_format(format) <= 0) {
1528 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1529 return;
1530 }
1531
1532 if (!pixels)
1533 return;
1534
1535 switch (target) {
1536 case GL_TEXTURE_1D:
1537 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1538 break;
1539 case GL_TEXTURE_2D:
1540 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1541 break;
1542 case GL_TEXTURE_3D:
1543 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1544 break;
1545 default:
1546 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1547 return;
1548 }
1549
1550 texImage = texObj->Image[level];
1551 if (!texImage) {
1552 /* invalid mipmap level */
1553 return;
1554 }
1555
1556 if (!texImage->Data) {
1557 /* try to get the texture image from the device driver */
1558 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
1559 discardImage = GL_TRUE;
1560 }
1561 else {
1562 discardImage = GL_FALSE;
1563 }
1564
1565 if (texImage->Data) {
1566 GLint width = texImage->Width;
1567 GLint height = texImage->Height;
1568 GLint row;
1569
1570 for (row = 0; row < height; row++) {
1571 /* compute destination address in client memory */
1572 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1573 width, height,
1574 format, type, 0, row, 0);
1575
1576 assert(dest);
1577 if (texImage->Format == GL_RGBA) {
1578 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1579 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1580 format, type, dest, &ctx->Pack, GL_TRUE );
1581 }
1582 else {
1583 /* fetch RGBA row from texture image then pack it in client mem */
1584 GLubyte rgba[MAX_WIDTH][4];
1585 GLint i;
1586 const GLubyte *src;
1587 switch (texImage->Format) {
1588 case GL_ALPHA:
1589 src = texImage->Data + row * width * sizeof(GLubyte);
1590 for (i = 0; i < width; i++) {
1591 rgba[i][RCOMP] = 255;
1592 rgba[i][GCOMP] = 255;
1593 rgba[i][BCOMP] = 255;
1594 rgba[i][ACOMP] = src[i];
1595 }
1596 break;
1597 case GL_LUMINANCE:
1598 src = texImage->Data + row * width * sizeof(GLubyte);
1599 for (i = 0; i < width; i++) {
1600 rgba[i][RCOMP] = src[i];
1601 rgba[i][GCOMP] = src[i];
1602 rgba[i][BCOMP] = src[i];
1603 rgba[i][ACOMP] = 255;
1604 }
1605 break;
1606 case GL_LUMINANCE_ALPHA:
1607 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1608 for (i = 0; i < width; i++) {
1609 rgba[i][RCOMP] = src[i*2+0];
1610 rgba[i][GCOMP] = src[i*2+0];
1611 rgba[i][BCOMP] = src[i*2+0];
1612 rgba[i][ACOMP] = src[i*2+1];
1613 }
1614 break;
1615 case GL_INTENSITY:
1616 src = texImage->Data + row * width * sizeof(GLubyte);
1617 for (i = 0; i < width; i++) {
1618 rgba[i][RCOMP] = src[i];
1619 rgba[i][GCOMP] = src[i];
1620 rgba[i][BCOMP] = src[i];
1621 rgba[i][ACOMP] = 255;
1622 }
1623 break;
1624 case GL_RGB:
1625 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1626 for (i = 0; i < width; i++) {
1627 rgba[i][RCOMP] = src[i*3+0];
1628 rgba[i][GCOMP] = src[i*3+1];
1629 rgba[i][BCOMP] = src[i*3+2];
1630 rgba[i][ACOMP] = 255;
1631 }
1632 break;
1633 case GL_RGBA:
1634 /* this special case should have been handled above! */
1635 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1636 break;
1637 case GL_COLOR_INDEX:
1638 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1639 break;
1640 default:
1641 gl_problem( ctx, "bad format in gl_GetTexImage" );
1642 }
1643 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1644 format, type, dest, &ctx->Pack, GL_TRUE );
1645 }
1646 }
1647
1648 /* if we got the teximage from the device driver we'll discard it now */
1649 if (discardImage) {
1650 FREE(texImage->Data);
1651 texImage->Data = NULL;
1652 }
1653 }
1654 }
1655
1656
1657
1658 void
1659 _mesa_TexSubImage1D( GLenum target, GLint level,
1660 GLint xoffset, GLsizei width,
1661 GLenum format, GLenum type,
1662 const GLvoid *pixels )
1663 {
1664 GET_CURRENT_CONTEXT(ctx);
1665 struct gl_texture_unit *texUnit;
1666 struct gl_texture_object *texObj;
1667 struct gl_texture_image *texImage;
1668 GLboolean success = GL_FALSE;
1669
1670 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1671 width, 1, 1, format, type)) {
1672 return; /* error was detected */
1673 }
1674
1675 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1676 texObj = texUnit->CurrentD[1];
1677 texImage = texObj->Image[level];
1678 assert(texImage);
1679
1680 if (width == 0 || !pixels)
1681 return; /* no-op, not an error */
1682
1683
1684 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1685 && ctx->Driver.TexSubImage1D) {
1686 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1687 width, format, type, pixels,
1688 &ctx->Unpack, texObj, texImage );
1689 }
1690 if (!success) {
1691 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1692
1693 const GLint texComponents = components_in_intformat(texImage->Format);
1694 const GLenum texFormat = texImage->Format;
1695 const GLint xoffsetb = xoffset + texImage->Border;
1696 GLboolean retain = GL_TRUE;
1697 if (!texImage->Data) {
1698 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
1699 if (!texImage->Data) {
1700 make_null_texture(texImage);
1701 }
1702 if (!texImage->Data)
1703 return; /* we're really out of luck! */
1704 }
1705
1706 if (texFormat == GL_COLOR_INDEX) {
1707 /* color index texture */
1708 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1709 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1710 1, format, type, 0, 0, 0);
1711 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1712 type, src, &ctx->Unpack, GL_TRUE);
1713 }
1714 else {
1715 /* color texture */
1716 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1717 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1718 1, format, type, 0, 0, 0);
1719 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1720 type, src, &ctx->Unpack, GL_TRUE);
1721 }
1722
1723 if (ctx->Driver.TexImage1D) {
1724 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1725 GL_UNSIGNED_BYTE, texImage->Data,
1726 &_mesa_native_packing, texObj, texImage,
1727 &retain );
1728 }
1729
1730 if (!retain && texImage->Data) {
1731 FREE(texImage->Data);
1732 texImage->Data = NULL;
1733 }
1734 }
1735
1736 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
1737 }
1738
1739
1740 void
1741 _mesa_TexSubImage2D( GLenum target, GLint level,
1742 GLint xoffset, GLint yoffset,
1743 GLsizei width, GLsizei height,
1744 GLenum format, GLenum type,
1745 const GLvoid *pixels )
1746 {
1747 GET_CURRENT_CONTEXT(ctx);
1748 struct gl_texture_unit *texUnit;
1749 struct gl_texture_object *texObj;
1750 struct gl_texture_image *texImage;
1751 GLboolean success = GL_FALSE;
1752
1753 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1754 width, height, 1, format, type)) {
1755 return; /* error was detected */
1756 }
1757
1758 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1759 texObj = texUnit->CurrentD[2];
1760 texImage = texObj->Image[level];
1761 assert(texImage);
1762
1763 if (width == 0 || height == 0 || !pixels)
1764 return; /* no-op, not an error */
1765
1766 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1767 && ctx->Driver.TexSubImage2D) {
1768 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1769 yoffset, width, height, format, type,
1770 pixels, &ctx->Unpack, texObj, texImage );
1771 }
1772 if (!success) {
1773 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
1774
1775 const GLint texComponents = components_in_intformat(texImage->Format);
1776 const GLenum texFormat = texImage->Format;
1777 const GLint xoffsetb = xoffset + texImage->Border;
1778 const GLint yoffsetb = yoffset + texImage->Border;
1779 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1780 format, type);
1781 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1782 GLboolean retain = GL_TRUE;
1783
1784 if (!texImage->Data) {
1785 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
1786 if (!texImage->Data) {
1787 make_null_texture(texImage);
1788 }
1789 if (!texImage->Data)
1790 return; /* we're really out of luck! */
1791 }
1792
1793 if (texFormat == GL_COLOR_INDEX) {
1794 /* color index texture */
1795 GLubyte *dst = texImage->Data
1796 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1797 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1798 width, height, format, type, 0, 0, 0);
1799 GLint row;
1800 for (row = 0; row < height; row++) {
1801 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1802 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1803 src += srcStride;
1804 dst += dstStride;
1805 }
1806 }
1807 else {
1808 /* color texture */
1809 GLubyte *dst = texImage->Data
1810 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1811 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1812 width, height, format, type, 0, 0, 0);
1813 GLint row;
1814 for (row = 0; row < height; row++) {
1815 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1816 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1817 src += srcStride;
1818 dst += dstStride;
1819 }
1820 }
1821
1822 if (ctx->Driver.TexImage2D) {
1823 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1824 GL_UNSIGNED_BYTE, texImage->Data,
1825 &_mesa_native_packing, texObj, texImage,
1826 &retain);
1827 }
1828
1829 if (!retain && texImage->Data) {
1830 FREE(texImage->Data);
1831 texImage->Data = NULL;
1832 }
1833
1834 #ifdef OLD_DD_TEXTURE
1835 /* XXX this will be removed in the future */
1836 if (ctx->Driver.TexSubImage) {
1837 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1838 xoffset, yoffset, width, height,
1839 texImage->IntFormat, texImage);
1840 }
1841 else if (ctx->Driver.TexImage) {
1842 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
1843 level, texImage->IntFormat, texImage );
1844 }
1845 #endif
1846 }
1847 }
1848
1849
1850
1851 void
1852 _mesa_TexSubImage3D( GLenum target, GLint level,
1853 GLint xoffset, GLint yoffset, GLint zoffset,
1854 GLsizei width, GLsizei height, GLsizei depth,
1855 GLenum format, GLenum type,
1856 const GLvoid *pixels )
1857 {
1858 GET_CURRENT_CONTEXT(ctx);
1859 struct gl_texture_unit *texUnit;
1860 struct gl_texture_object *texObj;
1861 struct gl_texture_image *texImage;
1862 GLboolean success = GL_FALSE;
1863
1864 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1865 width, height, depth, format, type)) {
1866 return; /* error was detected */
1867 }
1868
1869 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1870 texObj = texUnit->CurrentD[3];
1871 texImage = texObj->Image[level];
1872 assert(texImage);
1873
1874 if (width == 0 || height == 0 || height == 0 || !pixels)
1875 return; /* no-op, not an error */
1876
1877 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1878 && ctx->Driver.TexSubImage3D) {
1879 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1880 yoffset, zoffset, width, height, depth, format,
1881 type, pixels, &ctx->Unpack, texObj, texImage );
1882 }
1883 if (!success) {
1884 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1885
1886 const GLint texComponents = components_in_intformat(texImage->Format);
1887 const GLenum texFormat = texImage->Format;
1888 const GLint xoffsetb = xoffset + texImage->Border;
1889 const GLint yoffsetb = yoffset + texImage->Border;
1890 const GLint zoffsetb = zoffset + texImage->Border;
1891 const GLint texWidth = texImage->Width;
1892 const GLint dstRectArea = texWidth * texImage->Height;
1893 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1894 width, format, type);
1895 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1896 GLboolean retain = GL_TRUE;
1897
1898 if (texFormat == GL_COLOR_INDEX) {
1899 /* color index texture */
1900 GLint img, row;
1901 for (img = 0; img < depth; img++) {
1902 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1903 width, height, format, type, img, 0, 0);
1904 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1905 + yoffsetb * texWidth + xoffsetb) * texComponents;
1906 for (row = 0; row < height; row++) {
1907 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1908 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1909 src += srcStride;
1910 dst += dstStride;
1911 }
1912 }
1913 }
1914 else {
1915 /* color texture */
1916 GLint img, row;
1917 for (img = 0; img < depth; img++) {
1918 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1919 width, height, format, type, img, 0, 0);
1920 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1921 + yoffsetb * texWidth + xoffsetb) * texComponents;
1922 for (row = 0; row < height; row++) {
1923 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1924 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1925 src += srcStride;
1926 dst += dstStride;
1927 }
1928 }
1929 }
1930
1931 if (ctx->Driver.TexImage3D) {
1932 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1933 GL_UNSIGNED_BYTE, texImage->Data,
1934 &_mesa_native_packing, texObj, texImage,
1935 &retain);
1936 }
1937
1938 if (!retain && texImage->Data) {
1939 FREE(texImage->Data);
1940 texImage->Data = NULL;
1941 }
1942 }
1943 }
1944
1945
1946
1947 /*
1948 * Read an RGBA image from the frame buffer.
1949 * This is used by glCopyTexSubImage[12]D().
1950 * Input: ctx - the context
1951 * x, y - lower left corner
1952 * width, height - size of region to read
1953 * Return: pointer to block of GL_RGBA, GLubyte data.
1954 */
1955 static GLubyte *
1956 read_color_image( GLcontext *ctx, GLint x, GLint y,
1957 GLsizei width, GLsizei height )
1958 {
1959 GLint stride, i;
1960 GLubyte *image, *dst;
1961
1962 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
1963 if (!image)
1964 return NULL;
1965
1966 /* Select buffer to read from */
1967 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1968 ctx->Pixel.DriverReadBuffer );
1969
1970 dst = image;
1971 stride = width * 4 * sizeof(GLubyte);
1972 for (i = 0; i < height; i++) {
1973 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1974 (GLubyte (*)[4]) dst );
1975 dst += stride;
1976 }
1977
1978 /* Read from draw buffer (the default) */
1979 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1980 ctx->Color.DriverDrawBuffer );
1981
1982 return image;
1983 }
1984
1985
1986
1987 void
1988 _mesa_CopyTexImage1D( GLenum target, GLint level,
1989 GLenum internalFormat,
1990 GLint x, GLint y,
1991 GLsizei width, GLint border )
1992 {
1993 GET_CURRENT_CONTEXT(ctx);
1994 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
1995
1996 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1997 width, 1, border))
1998 return;
1999
2000 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2001 || !ctx->Driver.CopyTexImage1D
2002 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2003 internalFormat, x, y, width, border))
2004 {
2005 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2006 if (!image) {
2007 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2008 return;
2009 }
2010 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2011 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2012 FREE(image);
2013 }
2014 }
2015
2016
2017
2018 void
2019 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2020 GLint x, GLint y, GLsizei width, GLsizei height,
2021 GLint border )
2022 {
2023 GET_CURRENT_CONTEXT(ctx);
2024 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2025
2026 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2027 width, height, border))
2028 return;
2029
2030 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2031 || !ctx->Driver.CopyTexImage2D
2032 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2033 internalFormat, x, y, width, height, border))
2034 {
2035 GLubyte *image = read_color_image( ctx, x, y, width, height );
2036 if (!image) {
2037 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2038 return;
2039 }
2040 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2041 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2042 FREE(image);
2043 }
2044 }
2045
2046
2047
2048 /*
2049 * Do the work of glCopyTexSubImage[123]D.
2050 */
2051 static void
2052 copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2053 GLint width, GLint height,
2054 GLint srcx, GLint srcy,
2055 GLint dstx, GLint dsty, GLint dstz )
2056 {
2057 GLint i;
2058 GLint format, components, rectarea;
2059 GLint texwidth, texheight, zoffset;
2060
2061 /* dst[xyz] may be negative if we have a texture border! */
2062 dstx += dest->Border;
2063 dsty += dest->Border;
2064 dstz += dest->Border;
2065 texwidth = dest->Width;
2066 texheight = dest->Height;
2067 rectarea = texwidth * texheight;
2068 zoffset = dstz * rectarea;
2069 format = dest->Format;
2070 components = components_in_intformat( format );
2071
2072 /* Select buffer to read from */
2073 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2074 ctx->Pixel.DriverReadBuffer );
2075
2076 for (i = 0;i < height; i++) {
2077 GLubyte rgba[MAX_WIDTH][4];
2078 GLubyte *dst;
2079 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
2080 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2081 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2082 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
2083 &_mesa_native_packing, GL_TRUE);
2084 }
2085
2086 /* Read from draw buffer (the default) */
2087 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2088 ctx->Color.DriverDrawBuffer );
2089 }
2090
2091
2092
2093
2094 void
2095 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2096 GLint xoffset, GLint x, GLint y, GLsizei width )
2097 {
2098 GET_CURRENT_CONTEXT(ctx);
2099 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2100
2101 if (copytexsubimage_error_check(ctx, 1, target, level,
2102 xoffset, 0, 0, width, 1))
2103 return;
2104
2105 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2106 || !ctx->Driver.CopyTexSubImage1D
2107 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2108 xoffset, x, y, width)) {
2109 struct gl_texture_unit *texUnit;
2110 struct gl_texture_image *teximage;
2111 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2112 teximage = texUnit->CurrentD[1]->Image[level];
2113 assert(teximage);
2114 if (teximage->Data) {
2115 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
2116 /* tell driver about the change */
2117 /* XXX this is obsolete */
2118 if (ctx->Driver.TexImage) {
2119 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2120 texUnit->CurrentD[1],
2121 level, teximage->IntFormat, teximage );
2122 }
2123 }
2124 }
2125 }
2126
2127
2128
2129 void
2130 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2131 GLint xoffset, GLint yoffset,
2132 GLint x, GLint y, GLsizei width, GLsizei height )
2133 {
2134 GET_CURRENT_CONTEXT(ctx);
2135 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2136
2137 if (copytexsubimage_error_check(ctx, 2, target, level,
2138 xoffset, yoffset, 0, width, height))
2139 return;
2140
2141 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2142 || !ctx->Driver.CopyTexSubImage2D
2143 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2144 xoffset, yoffset, x, y, width, height )) {
2145 struct gl_texture_unit *texUnit;
2146 struct gl_texture_image *teximage;
2147 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2148 teximage = texUnit->CurrentD[2]->Image[level];
2149 assert(teximage);
2150 if (teximage->Data) {
2151 copy_tex_sub_image(ctx, teximage, width, height,
2152 x, y, xoffset, yoffset, 0);
2153 /* tell driver about the change */
2154 /* XXX this is obsolete */
2155 if (ctx->Driver.TexImage) {
2156 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2157 texUnit->CurrentD[2],
2158 level, teximage->IntFormat, teximage );
2159 }
2160 }
2161 }
2162 }
2163
2164
2165
2166 void
2167 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2168 GLint xoffset, GLint yoffset, GLint zoffset,
2169 GLint x, GLint y, GLsizei width, GLsizei height )
2170 {
2171 GET_CURRENT_CONTEXT(ctx);
2172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2173
2174 if (copytexsubimage_error_check(ctx, 3, target, level,
2175 xoffset, yoffset, zoffset, width, height))
2176 return;
2177
2178 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2179 || !ctx->Driver.CopyTexSubImage3D
2180 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2181 xoffset, yoffset, zoffset, x, y, width, height )) {
2182 struct gl_texture_unit *texUnit;
2183 struct gl_texture_image *teximage;
2184 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2185 teximage = texUnit->CurrentD[3]->Image[level];
2186 assert(teximage);
2187 if (teximage->Data) {
2188 copy_tex_sub_image(ctx, teximage, width, height,
2189 x, y, xoffset, yoffset, zoffset);
2190 /* tell driver about the change */
2191 /* XXX this is obsolete */
2192 if (ctx->Driver.TexImage) {
2193 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2194 texUnit->CurrentD[3],
2195 level, teximage->IntFormat, teximage );
2196 }
2197 }
2198 }
2199 }