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