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