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