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