blob: a5d3ef97a57b062fee62d1d4fe062d92919b4cd4 [file] [log] [blame]
Brian Paulfc811e21999-10-21 12:45:03 +00001/* $Id: teximage.c,v 1.7 1999/10/21 12:45:03 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;
Brian Paulfc811e21999-10-21 12:45:03 +0000566 green = blue = alpha = 0; /* silence compiler warnings */
jtgafb833d1999-08-19 00:55:39 +0000567 }
568 else {
569 /* convert color index to RGBA */
570 GLint index = ((GLubyte*)image->Data)[pixel];
571 red = (GLint) (255.0F * ctx->Pixel.MapItoR[index]);
572 green = (GLint) (255.0F * ctx->Pixel.MapItoG[index]);
573 blue = (GLint) (255.0F * ctx->Pixel.MapItoB[index]);
574 alpha = (GLint) (255.0F * ctx->Pixel.MapItoA[index]);
575 }
576 break;
577 case GL_RGB:
578 /* Fetch image RGBA values */
579 red = ((GLubyte*) image->Data)[pixel*3+0];
580 green = ((GLubyte*) image->Data)[pixel*3+1];
581 blue = ((GLubyte*) image->Data)[pixel*3+2];
582 alpha = 255;
583 break;
584 case GL_RGBA:
585 red = ((GLubyte*) image->Data)[pixel*4+0];
586 green = ((GLubyte*) image->Data)[pixel*4+1];
587 blue = ((GLubyte*) image->Data)[pixel*4+2];
588 alpha = ((GLubyte*) image->Data)[pixel*4+3];
589 break;
590 case GL_RED:
591 red = ((GLubyte*) image->Data)[pixel];
592 green = 0;
593 blue = 0;
594 alpha = 255;
595 break;
596 case GL_GREEN:
597 red = 0;
598 green = ((GLubyte*) image->Data)[pixel];
599 blue = 0;
600 alpha = 255;
601 break;
602 case GL_BLUE:
603 red = 0;
604 green = 0;
605 blue = ((GLubyte*) image->Data)[pixel];
606 alpha = 255;
607 break;
608 case GL_ALPHA:
609 red = 0;
610 green = 0;
611 blue = 0;
612 alpha = ((GLubyte*) image->Data)[pixel];
613 break;
614 case GL_LUMINANCE:
615 red = ((GLubyte*) image->Data)[pixel];
616 green = red;
617 blue = red;
618 alpha = 255;
619 break;
620 case GL_LUMINANCE_ALPHA:
621 red = ((GLubyte*) image->Data)[pixel*2+0];
622 green = red;
623 blue = red;
624 alpha = ((GLubyte*) image->Data)[pixel*2+1];
625 break;
626 default:
Brian Paulfc811e21999-10-21 12:45:03 +0000627 red = green = blue = alpha = 0;
jtgafb833d1999-08-19 00:55:39 +0000628 gl_problem(ctx,"Bad format (2) in image_to_texture");
629 return NULL;
630 }
631
632 if (scaleOrBias || ctx->Pixel.MapColorFlag) {
633 /* Apply RGBA scale and bias */
634 GLfloat r = UBYTE_COLOR_TO_FLOAT_COLOR(red);
635 GLfloat g = UBYTE_COLOR_TO_FLOAT_COLOR(green);
636 GLfloat b = UBYTE_COLOR_TO_FLOAT_COLOR(blue);
637 GLfloat a = UBYTE_COLOR_TO_FLOAT_COLOR(alpha);
638 if (scaleOrBias) {
639 /* r,g,b,a now in [0,1] */
640 r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
641 g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
642 b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
643 a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
644 r = CLAMP( r, 0.0F, 1.0F );
645 g = CLAMP( g, 0.0F, 1.0F );
646 b = CLAMP( b, 0.0F, 1.0F );
647 a = CLAMP( a, 0.0F, 1.0F );
648 }
649 /* Apply pixel maps */
650 if (ctx->Pixel.MapColorFlag) {
651 GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize);
652 GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize);
653 GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize);
654 GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize);
655 r = ctx->Pixel.MapRtoR[ir];
656 g = ctx->Pixel.MapGtoG[ig];
657 b = ctx->Pixel.MapBtoB[ib];
658 a = ctx->Pixel.MapAtoA[ia];
659 }
660 red = (GLint) (r * 255.0F);
661 green = (GLint) (g * 255.0F);
662 blue = (GLint) (b * 255.0F);
663 alpha = (GLint) (a * 255.0F);
664 }
665
666 /* store texel (components are GLubytes in [0,255]) */
667 switch (texImage->Format) {
668 case GL_COLOR_INDEX:
669 texImage->Data[pixel] = red; /* really an index */
670 break;
671 case GL_ALPHA:
672 texImage->Data[pixel] = alpha;
673 break;
674 case GL_LUMINANCE:
675 texImage->Data[pixel] = red;
676 break;
677 case GL_LUMINANCE_ALPHA:
678 texImage->Data[pixel*2+0] = red;
679 texImage->Data[pixel*2+1] = alpha;
680 break;
681 case GL_INTENSITY:
682 texImage->Data[pixel] = red;
683 break;
684 case GL_RGB:
685 texImage->Data[pixel*3+0] = red;
686 texImage->Data[pixel*3+1] = green;
687 texImage->Data[pixel*3+2] = blue;
688 break;
689 case GL_RGBA:
690 texImage->Data[pixel*4+0] = red;
691 texImage->Data[pixel*4+1] = green;
692 texImage->Data[pixel*4+2] = blue;
693 texImage->Data[pixel*4+3] = alpha;
694 break;
695 default:
696 gl_problem(ctx,"Bad format (3) in image_to_texture");
697 return NULL;
698 }
699 }
700 break;
701
702 case GL_FLOAT:
703 for (pixel=0; pixel<numPixels; pixel++) {
704 GLfloat red, green, blue, alpha;
705 switch (image->Format) {
706 case GL_COLOR_INDEX:
707 if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) {
708 /* a paletted texture */
709 GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
710 red = index;
Brian Paulfc811e21999-10-21 12:45:03 +0000711 green = blue = alpha = 0; /* silence compiler warning */
jtgafb833d1999-08-19 00:55:39 +0000712 }
713 else {
714 GLint shift = ctx->Pixel.IndexShift;
715 GLint offset = ctx->Pixel.IndexOffset;
716 /* MapIto[RGBA]Size must be powers of two */
717 GLint rMask = ctx->Pixel.MapItoRsize-1;
718 GLint gMask = ctx->Pixel.MapItoGsize-1;
719 GLint bMask = ctx->Pixel.MapItoBsize-1;
720 GLint aMask = ctx->Pixel.MapItoAsize-1;
721 /* Fetch image color index */
722 GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
723 /* apply index shift and offset */
724 if (shift>=0) {
725 index = (index << shift) + offset;
726 }
727 else {
728 index = (index >> -shift) + offset;
729 }
730 /* convert index to RGBA */
731 red = ctx->Pixel.MapItoR[index & rMask];
732 green = ctx->Pixel.MapItoG[index & gMask];
733 blue = ctx->Pixel.MapItoB[index & bMask];
734 alpha = ctx->Pixel.MapItoA[index & aMask];
735 }
736 break;
737 case GL_RGB:
738 /* Fetch image RGBA values */
739 red = ((GLfloat*) image->Data)[pixel*3+0];
740 green = ((GLfloat*) image->Data)[pixel*3+1];
741 blue = ((GLfloat*) image->Data)[pixel*3+2];
742 alpha = 1.0;
743 break;
744 case GL_RGBA:
745 red = ((GLfloat*) image->Data)[pixel*4+0];
746 green = ((GLfloat*) image->Data)[pixel*4+1];
747 blue = ((GLfloat*) image->Data)[pixel*4+2];
748 alpha = ((GLfloat*) image->Data)[pixel*4+3];
749 break;
750 case GL_RED:
751 red = ((GLfloat*) image->Data)[pixel];
752 green = 0.0;
753 blue = 0.0;
754 alpha = 1.0;
755 break;
756 case GL_GREEN:
757 red = 0.0;
758 green = ((GLfloat*) image->Data)[pixel];
759 blue = 0.0;
760 alpha = 1.0;
761 break;
762 case GL_BLUE:
763 red = 0.0;
764 green = 0.0;
765 blue = ((GLfloat*) image->Data)[pixel];
766 alpha = 1.0;
767 break;
768 case GL_ALPHA:
769 red = 0.0;
770 green = 0.0;
771 blue = 0.0;
772 alpha = ((GLfloat*) image->Data)[pixel];
773 break;
774 case GL_LUMINANCE:
775 red = ((GLfloat*) image->Data)[pixel];
776 green = red;
777 blue = red;
778 alpha = 1.0;
779 break;
780 case GL_LUMINANCE_ALPHA:
781 red = ((GLfloat*) image->Data)[pixel*2+0];
782 green = red;
783 blue = red;
784 alpha = ((GLfloat*) image->Data)[pixel*2+1];
785 break;
786 default:
787 gl_problem(ctx,"Bad format (4) in image_to_texture");
788 return NULL;
789 }
790
791 if (image->Format!=GL_COLOR_INDEX) {
792 /* Apply RGBA scale and bias */
793 if (scaleOrBias) {
794 red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
795 green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
796 blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
797 alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
798 red = CLAMP( red, 0.0F, 1.0F );
799 green = CLAMP( green, 0.0F, 1.0F );
800 blue = CLAMP( blue, 0.0F, 1.0F );
801 alpha = CLAMP( alpha, 0.0F, 1.0F );
802 }
803 /* Apply pixel maps */
804 if (ctx->Pixel.MapColorFlag) {
805 GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize);
806 GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize);
807 GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize);
808 GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize);
809 red = ctx->Pixel.MapRtoR[ir];
810 green = ctx->Pixel.MapGtoG[ig];
811 blue = ctx->Pixel.MapBtoB[ib];
812 alpha = ctx->Pixel.MapAtoA[ia];
813 }
814 }
815
816 /* store texel (components are GLubytes in [0,255]) */
817 switch (texImage->Format) {
818 case GL_COLOR_INDEX:
819 /* a paletted texture */
820 texImage->Data[pixel] = (GLint) (red * 255.0F);
821 break;
822 case GL_ALPHA:
823 texImage->Data[pixel] = (GLint) (alpha * 255.0F);
824 break;
825 case GL_LUMINANCE:
826 texImage->Data[pixel] = (GLint) (red * 255.0F);
827 break;
828 case GL_LUMINANCE_ALPHA:
829 texImage->Data[pixel*2+0] = (GLint) (red * 255.0F);
830 texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F);
831 break;
832 case GL_INTENSITY:
833 texImage->Data[pixel] = (GLint) (red * 255.0F);
834 break;
835 case GL_RGB:
836 texImage->Data[pixel*3+0] = (GLint) (red * 255.0F);
837 texImage->Data[pixel*3+1] = (GLint) (green * 255.0F);
838 texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F);
839 break;
840 case GL_RGBA:
841 texImage->Data[pixel*4+0] = (GLint) (red * 255.0F);
842 texImage->Data[pixel*4+1] = (GLint) (green * 255.0F);
843 texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F);
844 texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F);
845 break;
846 default:
847 gl_problem(ctx,"Bad format (5) in image_to_texture");
848 return NULL;
849 }
850 }
851 break;
852
853 default:
854 gl_problem(ctx, "Bad image type in image_to_texture");
855 return NULL;
856 }
857
858 return texImage;
859}
860
861
862
863/*
864 * glTexImage[123]D can accept a NULL image pointer. In this case we
865 * create a texture image with unspecified image contents per the OpenGL
866 * spec.
867 */
868static struct gl_texture_image *
869make_null_texture( GLcontext *ctx, GLenum internalFormat,
870 GLsizei width, GLsizei height, GLsizei depth, GLint border )
871{
872 GLint components;
873 struct gl_texture_image *texImage;
874 GLint numPixels;
875 (void) ctx;
876
877 /*internalFormat = decode_internal_format(internalFormat);*/
878 components = components_in_intformat(internalFormat);
879 numPixels = width * height * depth;
880
881 texImage = gl_alloc_texture_image();
882 if (!texImage)
883 return NULL;
884
885 texImage->Format = (GLenum) decode_internal_format(internalFormat);
886 set_teximage_component_sizes( texImage );
887 texImage->IntFormat = internalFormat;
888 texImage->Border = border;
889 texImage->Width = width;
890 texImage->Height = height;
891 texImage->Depth = depth;
892 texImage->WidthLog2 = logbase2(width - 2*border);
893 if (height==1) /* 1-D texture */
894 texImage->HeightLog2 = 0;
895 else
896 texImage->HeightLog2 = logbase2(height - 2*border);
897 if (depth==1) /* 2-D texture */
898 texImage->DepthLog2 = 0;
899 else
900 texImage->DepthLog2 = logbase2(depth - 2*border);
901 texImage->Width2 = 1 << texImage->WidthLog2;
902 texImage->Height2 = 1 << texImage->HeightLog2;
903 texImage->Depth2 = 1 << texImage->DepthLog2;
904 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
905
906 /* XXX should we really allocate memory for the image or let it be NULL? */
907 /*texImage->Data = NULL;*/
908
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000909 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000910
911 /*
912 * Let's see if anyone finds this. If glTexImage2D() is called with
913 * a NULL image pointer then load the texture image with something
914 * interesting instead of leaving it indeterminate.
915 */
916 if (texImage->Data) {
917 char message[8][32] = {
918 " X X XXXXX XXX X ",
919 " XX XX X X X X X ",
920 " X X X X X X X ",
921 " X X XXXX XXX XXXXX ",
922 " X X X X X X ",
923 " X X X X X X X ",
924 " X X XXXXX XXX X X ",
925 " "
926 };
927
928 GLubyte *imgPtr = texImage->Data;
929 GLint i, j, k;
930 for (i=0;i<height;i++) {
931 GLint srcRow = 7 - i % 8;
932 for (j=0;j<width;j++) {
933 GLint srcCol = j % 32;
934 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
935 for (k=0;k<components;k++) {
936 *imgPtr++ = texel;
937 }
938 }
939 }
940 }
941
942 return texImage;
943}
944
945
946
947/*
948 * Test glTexImage() parameters for errors.
949 * Input:
950 * dimensions - must be 1 or 2 or 3
951 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
952 */
953static GLboolean texture_error_check( GLcontext *ctx, GLenum target,
954 GLint level, GLint internalFormat,
955 GLenum format, GLenum type,
956 GLint dimensions,
957 GLint width, GLint height,
958 GLint depth, GLint border )
959{
960 GLboolean isProxy;
961 GLint iformat;
962
963 if (dimensions == 1) {
964 isProxy = (target == GL_PROXY_TEXTURE_1D);
965 if (target != GL_TEXTURE_1D && !isProxy) {
966 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
967 return GL_TRUE;
968 }
969 }
970 else if (dimensions == 2) {
971 isProxy = (target == GL_PROXY_TEXTURE_2D);
972 if (target != GL_TEXTURE_2D && !isProxy) {
973 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
974 return GL_TRUE;
975 }
976 }
977 else if (dimensions == 3) {
978 isProxy = (target == GL_PROXY_TEXTURE_3D);
979 if (target != GL_TEXTURE_3D && !isProxy) {
980 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
981 return GL_TRUE;
982 }
983 }
984 else {
985 gl_problem( ctx, "bad dims in texture_error_check" );
986 return GL_TRUE;
987 }
988
989 /* Border */
990 if (border!=0 && border!=1) {
991 if (!isProxy) {
992 if (dimensions == 1)
993 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" );
994 else if (dimensions == 2)
995 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" );
996 else if (dimensions == 3)
997 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(border)" );
998 }
999 return GL_TRUE;
1000 }
1001
1002 /* Width */
1003 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1004 || logbase2( width - 2 * border ) < 0) {
1005 if (!isProxy) {
1006 if (dimensions == 1)
1007 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" );
1008 else if (dimensions == 2)
1009 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" );
1010 else if (dimensions == 3)
1011 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(width)" );
1012 }
1013 return GL_TRUE;
1014 }
1015
1016 /* Height */
1017 if (dimensions >= 2) {
1018 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1019 || logbase2( height - 2 * border ) < 0) {
1020 if (!isProxy) {
1021 if (dimensions == 2)
1022 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" );
1023 else if (dimensions == 3)
1024 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(height)" );
1025 return GL_TRUE;
1026 }
1027 }
1028 }
1029
1030 /* Depth */
1031 if (dimensions >= 3) {
1032 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1033 || logbase2( depth - 2 * border ) < 0) {
1034 if (!isProxy) {
1035 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1036 }
1037 return GL_TRUE;
1038 }
1039 }
1040
1041 /* Level */
1042 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1043 if (dimensions == 1)
1044 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" );
1045 else if (dimensions == 2)
1046 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" );
1047 else if (dimensions == 3)
1048 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(level)" );
1049 return GL_TRUE;
1050 }
1051
1052 iformat = decode_internal_format( internalFormat );
1053 if (iformat < 0) {
1054 if (dimensions == 1)
1055 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" );
1056 else if (dimensions == 2)
1057 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" );
1058 else if (dimensions == 3)
1059 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(internalFormat)" );
1060 return GL_TRUE;
1061 }
1062
1063 if (!gl_is_legal_format_and_type( format, type )) {
Brian Pauld53573d1999-10-19 20:36:20 +00001064 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1065 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1066 */
jtgafb833d1999-08-19 00:55:39 +00001067 if (dimensions == 1)
Brian Pauld53573d1999-10-19 20:36:20 +00001068 gl_error( ctx, GL_INVALID_OPERATION, "glTexImage1D(format or type)");
jtgafb833d1999-08-19 00:55:39 +00001069 else if (dimensions == 2)
Brian Pauld53573d1999-10-19 20:36:20 +00001070 gl_error( ctx, GL_INVALID_OPERATION, "glTexImage2D(format or type)");
jtgafb833d1999-08-19 00:55:39 +00001071 else if (dimensions == 3)
Brian Pauld53573d1999-10-19 20:36:20 +00001072 gl_error( ctx, GL_INVALID_OPERATION, "glTexImage3D(format or type)");
jtgafb833d1999-08-19 00:55:39 +00001073 return GL_TRUE;
1074 }
1075
1076 /* if we get here, the parameters are OK */
1077 return GL_FALSE;
1078}
1079
1080
1081
1082/*
1083 * Called from the API. Note that width includes the border.
1084 */
1085void gl_TexImage1D( GLcontext *ctx,
1086 GLenum target, GLint level, GLint internalformat,
1087 GLsizei width, GLint border, GLenum format,
1088 GLenum type, struct gl_image *image )
1089{
1090 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1091 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1092
1093 if (target==GL_TEXTURE_1D) {
1094 struct gl_texture_image *teximage;
1095 if (texture_error_check( ctx, target, level, internalformat,
1096 format, type, 1, width, 1, 1, border )) {
1097 /* error in texture image was detected */
1098 return;
1099 }
1100
1101 /* free current texture image, if any */
1102 if (texUnit->CurrentD[1]->Image[level]) {
1103 gl_free_texture_image( texUnit->CurrentD[1]->Image[level] );
1104 }
1105
1106 /* make new texture from source image */
1107 if (image) {
1108 teximage = image_to_texture(ctx, image, internalformat, border);
1109 }
1110 else {
1111 teximage = make_null_texture(ctx, (GLenum) internalformat,
1112 width, 1, 1, border);
1113 }
1114
1115 /* install new texture image */
1116
1117 texUnit->CurrentD[1]->Image[level] = teximage;
1118 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1119 ctx->NewState |= NEW_TEXTURING;
1120
1121 /* free the source image */
1122 if (image && image->RefCount==0) {
1123 /* if RefCount>0 then image must be in a display list */
1124 gl_free_image(image);
1125 }
1126
1127 /* tell driver about change */
1128 if (ctx->Driver.TexImage) {
1129 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1130 texUnit->CurrentD[1],
1131 level, internalformat, teximage );
1132 }
1133 }
1134 else if (target==GL_PROXY_TEXTURE_1D) {
1135 /* Proxy texture: check for errors and update proxy state */
1136 if (texture_error_check( ctx, target, level, internalformat,
1137 format, type, 1, width, 1, 1, border )) {
1138 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1139 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1140 sizeof(struct gl_texture_image) );
1141 }
1142 }
1143 else {
1144 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1145 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1146 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat;
1147 ctx->Texture.Proxy1D->Image[level]->Border = border;
1148 ctx->Texture.Proxy1D->Image[level]->Width = width;
1149 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1150 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1151 }
1152 if (image && image->RefCount==0) {
1153 /* if RefCount>0 then image must be in a display list */
1154 gl_free_image(image);
1155 }
1156 }
1157 else {
1158 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1159 return;
1160 }
1161}
1162
1163
1164
1165
1166/*
1167 * Called by the API or display list executor.
1168 * Note that width and height include the border.
1169 */
1170void gl_TexImage2D( GLcontext *ctx,
1171 GLenum target, GLint level, GLint internalformat,
1172 GLsizei width, GLsizei height, GLint border,
1173 GLenum format, GLenum type,
1174 struct gl_image *image )
1175{
1176 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1177 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1178
1179 if (target==GL_TEXTURE_2D) {
1180 struct gl_texture_image *teximage;
1181 if (texture_error_check( ctx, target, level, internalformat,
1182 format, type, 2, width, height, 1, border )) {
1183 /* error in texture image was detected */
1184 return;
1185 }
1186
1187 /* free current texture image, if any */
1188 if (texUnit->CurrentD[2]->Image[level]) {
1189 gl_free_texture_image( texUnit->CurrentD[2]->Image[level] );
1190 }
1191
1192 /* make new texture from source image */
1193 if (image) {
1194 teximage = image_to_texture(ctx, image, internalformat, border);
1195 }
1196 else {
1197 teximage = make_null_texture(ctx, (GLenum) internalformat,
1198 width, height, 1, border);
1199 }
1200
1201 /* install new texture image */
1202 texUnit->CurrentD[2]->Image[level] = teximage;
1203 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1204 ctx->NewState |= NEW_TEXTURING;
1205
1206 /* free the source image */
1207 if (image && image->RefCount==0) {
1208 /* if RefCount>0 then image must be in a display list */
1209 gl_free_image(image);
1210 }
1211
1212 /* tell driver about change */
1213 if (ctx->Driver.TexImage) {
1214 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
1215 texUnit->CurrentD[2],
1216 level, internalformat, teximage );
1217 }
1218 }
1219 else if (target==GL_PROXY_TEXTURE_2D) {
1220 /* Proxy texture: check for errors and update proxy state */
1221 if (texture_error_check( ctx, target, level, internalformat,
1222 format, type, 2, width, height, 1, border )) {
1223 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1224 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1225 sizeof(struct gl_texture_image) );
1226 }
1227 }
1228 else {
1229 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1230 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1231 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalformat;
1232 ctx->Texture.Proxy2D->Image[level]->Border = border;
1233 ctx->Texture.Proxy2D->Image[level]->Width = width;
1234 ctx->Texture.Proxy2D->Image[level]->Height = height;
1235 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1236 }
1237 if (image && image->RefCount==0) {
1238 /* if RefCount>0 then image must be in a display list */
1239 gl_free_image(image);
1240 }
1241 }
1242 else {
1243 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1244 return;
1245 }
1246}
1247
1248
1249
1250/*
1251 * Called by the API or display list executor.
1252 * Note that width and height include the border.
1253 */
1254void gl_TexImage3DEXT( GLcontext *ctx,
1255 GLenum target, GLint level, GLint internalformat,
1256 GLsizei width, GLsizei height, GLsizei depth,
1257 GLint border, GLenum format, GLenum type,
1258 struct gl_image *image )
1259{
1260 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1261 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT");
1262
1263 if (target==GL_TEXTURE_3D_EXT) {
1264 struct gl_texture_image *teximage;
1265 if (texture_error_check( ctx, target, level, internalformat,
1266 format, type, 3, width, height, depth,
1267 border )) {
1268 /* error in texture image was detected */
1269 return;
1270 }
1271
1272 /* free current texture image, if any */
1273 if (texUnit->CurrentD[3]->Image[level]) {
1274 gl_free_texture_image( texUnit->CurrentD[3]->Image[level] );
1275 }
1276
1277 /* make new texture from source image */
1278 if (image) {
1279 teximage = image_to_texture(ctx, image, internalformat, border);
1280 }
1281 else {
1282 teximage = make_null_texture(ctx, (GLenum) internalformat,
1283 width, height, depth, border);
1284 }
1285
1286 /* install new texture image */
1287 texUnit->CurrentD[3]->Image[level] = teximage;
1288 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
1289 ctx->NewState |= NEW_TEXTURING;
1290
1291 /* free the source image */
1292 if (image && image->RefCount==0) {
1293 /* if RefCount>0 then image must be in a display list */
1294 gl_free_image(image);
1295 }
1296
1297 /* tell driver about change */
1298 if (ctx->Driver.TexImage) {
1299 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT,
1300 texUnit->CurrentD[3],
1301 level, internalformat, teximage );
1302 }
1303 }
1304 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1305 /* Proxy texture: check for errors and update proxy state */
1306 if (texture_error_check( ctx, target, level, internalformat,
1307 format, type, 3, width, height, depth,
1308 border )) {
1309 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1310 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1311 sizeof(struct gl_texture_image) );
1312 }
1313 }
1314 else {
1315 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1316 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1317 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalformat;
1318 ctx->Texture.Proxy3D->Image[level]->Border = border;
1319 ctx->Texture.Proxy3D->Image[level]->Width = width;
1320 ctx->Texture.Proxy3D->Image[level]->Height = height;
1321 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1322 }
1323 if (image && image->RefCount==0) {
1324 /* if RefCount>0 then image must be in a display list */
1325 gl_free_image(image);
1326 }
1327 }
1328 else {
1329 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3DEXT(target)" );
1330 return;
1331 }
1332}
1333
1334
1335
1336void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format,
1337 GLenum type, GLvoid *pixels )
1338{
1339 const struct gl_texture_object *texObj;
1340
1341 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1342
1343 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1344 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1345 return;
1346 }
1347
1348 if (gl_sizeof_type(type) <= 0) {
1349 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1350 return;
1351 }
1352
1353 if (gl_components_in_format(format) <= 0) {
1354 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1355 return;
1356 }
1357
1358 if (!pixels)
1359 return; /* XXX generate an error??? */
1360
1361 switch (target) {
1362 case GL_TEXTURE_1D:
1363 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1364 break;
1365 case GL_TEXTURE_2D:
1366 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1367 break;
1368 case GL_TEXTURE_3D:
1369 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1370 break;
1371 default:
1372 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1373 return;
1374 }
1375
1376 if (texObj->Image[level] && texObj->Image[level]->Data) {
1377 const struct gl_texture_image *texImage = texObj->Image[level];
1378 GLint width = texImage->Width;
1379 GLint height = texImage->Height;
1380 GLint row;
1381
1382 for (row = 0; row < height; row++) {
1383 /* compute destination address in client memory */
1384 GLvoid *dest = gl_pixel_addr_in_image( &ctx->Unpack, pixels,
1385 width, height,
1386 format, type, 0, row, 0);
1387
1388 assert(dest);
1389 if (texImage->Format == GL_RGBA) {
1390 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1391 gl_pack_rgba_span( ctx, width, (void *) src, format, type, dest,
1392 &ctx->Pack, GL_TRUE );
1393 }
1394 else {
1395 /* fetch RGBA row from texture image then pack it in client mem */
1396 GLubyte rgba[MAX_WIDTH][4];
1397 GLint i;
1398 const GLubyte *src;
1399 switch (texImage->Format) {
1400 case GL_ALPHA:
1401 src = texImage->Data + row * width * sizeof(GLubyte);
1402 for (i = 0; i < width; i++) {
1403 rgba[i][RCOMP] = 255;
1404 rgba[i][GCOMP] = 255;
1405 rgba[i][BCOMP] = 255;
1406 rgba[i][ACOMP] = src[i];
1407 }
1408 break;
1409 case GL_LUMINANCE:
1410 src = texImage->Data + row * width * sizeof(GLubyte);
1411 for (i = 0; i < width; i++) {
1412 rgba[i][RCOMP] = src[i];
1413 rgba[i][GCOMP] = src[i];
1414 rgba[i][BCOMP] = src[i];
1415 rgba[i][ACOMP] = 255;
1416 }
1417 break;
1418 case GL_LUMINANCE_ALPHA:
1419 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1420 for (i = 0; i < width; i++) {
1421 rgba[i][RCOMP] = src[i*2+0];
1422 rgba[i][GCOMP] = src[i*2+0];
1423 rgba[i][BCOMP] = src[i*2+0];
1424 rgba[i][ACOMP] = src[i*2+1];
1425 }
1426 break;
1427 case GL_INTENSITY:
1428 src = texImage->Data + row * width * sizeof(GLubyte);
1429 for (i = 0; i < width; i++) {
1430 rgba[i][RCOMP] = src[i];
1431 rgba[i][GCOMP] = src[i];
1432 rgba[i][BCOMP] = src[i];
1433 rgba[i][ACOMP] = 255;
1434 }
1435 break;
1436 case GL_RGB:
1437 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1438 for (i = 0; i < width; i++) {
1439 rgba[i][RCOMP] = src[i*3+0];
1440 rgba[i][GCOMP] = src[i*3+1];
1441 rgba[i][BCOMP] = src[i*3+2];
1442 rgba[i][ACOMP] = 255;
1443 }
1444 break;
1445 case GL_RGBA:
1446 /* this special case should have been handled above! */
1447 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1448 break;
1449 case GL_COLOR_INDEX:
1450 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1451 break;
1452 default:
1453 gl_problem( ctx, "bad format in gl_GetTexImage" );
1454 }
1455 gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1456 format, type, dest, &ctx->Pack, GL_TRUE );
1457 }
1458 }
1459 }
1460}
1461
1462
1463
1464/*
1465 * Unpack the image data given to glTexSubImage[12]D.
1466 * This function is just a wrapper for gl_unpack_image() but it does
1467 * some extra error checking.
1468 */
1469struct gl_image *
1470gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height,
1471 GLenum format, GLenum type, const GLvoid *pixels )
1472{
1473 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1474 return NULL;
1475 }
1476
1477 if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){
1478 return NULL;
1479 }
1480
1481 if (gl_sizeof_type(type)<=0) {
1482 return NULL;
1483 }
1484
1485 return gl_unpack_image3D( ctx, width, height, 1, format, type, pixels, &ctx->Unpack );
1486}
1487
1488
1489/*
1490 * Unpack the image data given to glTexSubImage3D.
1491 * This function is just a wrapper for gl_unpack_image() but it does
1492 * some extra error checking.
1493 */
1494struct gl_image *
1495gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height,
1496 GLint depth, GLenum format, GLenum type,
1497 const GLvoid *pixels )
1498{
1499 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1500 return NULL;
1501 }
1502
1503 if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){
1504 return NULL;
1505 }
1506
1507 if (gl_sizeof_type(type)<=0) {
1508 return NULL;
1509 }
1510
1511 return gl_unpack_image3D( ctx, width, height, depth, format, type, pixels,
1512 &ctx->Unpack );
1513}
1514
1515
1516
1517void gl_TexSubImage1D( GLcontext *ctx,
1518 GLenum target, GLint level, GLint xoffset,
1519 GLsizei width, GLenum format, GLenum type,
1520 struct gl_image *image )
1521{
1522 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1523 struct gl_texture_image *destTex;
1524
1525 if (target!=GL_TEXTURE_1D) {
1526 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1527 return;
1528 }
1529 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1530 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" );
1531 return;
1532 }
1533
1534 destTex = texUnit->CurrentD[1]->Image[level];
1535 if (!destTex) {
1536 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" );
1537 return;
1538 }
1539
1540 if (xoffset < -((GLint)destTex->Border)) {
1541 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" );
1542 return;
1543 }
1544 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1545 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" );
1546 return;
1547 }
1548
1549 if (image) {
1550 /* unpacking must have been error-free */
Brian Paul91baaa31999-10-17 23:24:16 +00001551 const GLint texcomponents = components_in_intformat(destTex->Format);
1552 const GLint xoffsetb = xoffset + destTex->Border;
jtgafb833d1999-08-19 00:55:39 +00001553
1554 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1555 /* Simple case, just byte copy image data into texture image */
1556 /* row by row. */
Brian Paul91baaa31999-10-17 23:24:16 +00001557 GLubyte *dst = destTex->Data + texcomponents * xoffsetb;
jtgafb833d1999-08-19 00:55:39 +00001558 GLubyte *src = (GLubyte *) image->Data;
1559 MEMCPY( dst, src, width * texcomponents );
1560 }
1561 else {
1562 /* General case, convert image pixels into texels, scale, bias, etc */
1563 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1564 destTex->IntFormat, destTex->Border);
Brian Paul91baaa31999-10-17 23:24:16 +00001565 GLubyte *dst = destTex->Data + texcomponents * xoffsetb;
jtgafb833d1999-08-19 00:55:39 +00001566 GLubyte *src = subTexImg->Data;
1567 MEMCPY( dst, src, width * texcomponents );
1568 gl_free_texture_image(subTexImg);
1569 }
1570
1571 /* if the image's reference count is zero, delete it now */
1572 if (image->RefCount==0) {
1573 gl_free_image(image);
1574 }
1575
1576 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1577
1578 /* tell driver about change */
1579 if (ctx->Driver.TexSubImage) {
1580 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
1581 texUnit->CurrentD[1], level,
1582 xoffset,0,width,1,
1583 texUnit->CurrentD[1]->Image[level]->IntFormat,
1584 destTex );
1585 }
1586 else {
1587 if (ctx->Driver.TexImage) {
1588 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level,
1589 texUnit->CurrentD[1]->Image[level]->IntFormat,
1590 destTex );
1591 }
1592 }
1593 }
1594 else {
1595 /* if no image, an error must have occured, do more testing now */
1596 GLint components, size;
1597
1598 if (width<0) {
1599 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" );
1600 return;
1601 }
1602 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1603 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1604 return;
1605 }
1606 components = components_in_intformat( format );
1607 if (components<0 || format==GL_STENCIL_INDEX
1608 || format==GL_DEPTH_COMPONENT){
1609 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1610 return;
1611 }
1612 size = gl_sizeof_type( type );
1613 if (size<=0) {
1614 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" );
1615 return;
1616 }
1617 /* if we get here, probably ran out of memory during unpacking */
1618 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" );
1619 }
1620}
1621
1622
1623
1624void gl_TexSubImage2D( GLcontext *ctx,
1625 GLenum target, GLint level,
1626 GLint xoffset, GLint yoffset,
1627 GLsizei width, GLsizei height,
1628 GLenum format, GLenum type,
1629 struct gl_image *image )
1630{
1631 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1632 struct gl_texture_image *destTex;
1633
1634 if (target!=GL_TEXTURE_2D) {
1635 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1636 return;
1637 }
1638 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1639 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" );
1640 return;
1641 }
1642
1643 destTex = texUnit->CurrentD[2]->Image[level];
1644 if (!destTex) {
1645 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" );
1646 return;
1647 }
1648
1649 if (xoffset < -((GLint)destTex->Border)) {
1650 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" );
1651 return;
1652 }
1653 if (yoffset < -((GLint)destTex->Border)) {
1654 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" );
1655 return;
1656 }
1657 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1658 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" );
1659 return;
1660 }
1661 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1662 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" );
1663 return;
1664 }
1665
1666 if (image) {
1667 /* unpacking must have been error-free */
Brian Paul91baaa31999-10-17 23:24:16 +00001668 const GLint texcomponents = components_in_intformat(destTex->Format);
1669 const GLint xoffsetb = xoffset + destTex->Border;
1670 const GLint yoffsetb = yoffset + destTex->Border;
jtgafb833d1999-08-19 00:55:39 +00001671
1672 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1673 /* Simple case, just byte copy image data into texture image */
1674 /* row by row. */
1675 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001676 + (yoffsetb * destTex->Width + xoffsetb) * texcomponents;
jtgafb833d1999-08-19 00:55:39 +00001677 GLubyte *src = (GLubyte *) image->Data;
1678 GLint j;
1679 for (j=0;j<height;j++) {
1680 MEMCPY( dst, src, width * texcomponents );
1681 dst += destTex->Width * texcomponents * sizeof(GLubyte);
1682 src += width * texcomponents * sizeof(GLubyte);
1683 }
1684 }
1685 else {
1686 /* General case, convert image pixels into texels, scale, bias, etc */
1687 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1688 destTex->IntFormat, destTex->Border);
1689 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001690 + (yoffsetb * destTex->Width + xoffsetb) * texcomponents;
jtgafb833d1999-08-19 00:55:39 +00001691 GLubyte *src = subTexImg->Data;
1692 GLint j;
1693 for (j=0;j<height;j++) {
1694 MEMCPY( dst, src, width * texcomponents );
1695 dst += destTex->Width * texcomponents * sizeof(GLubyte);
1696 src += width * texcomponents * sizeof(GLubyte);
1697 }
1698 gl_free_texture_image(subTexImg);
1699 }
1700
1701 /* if the image's reference count is zero, delete it now */
1702 if (image->RefCount==0) {
1703 gl_free_image(image);
1704 }
1705
1706 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1707
1708 /* tell driver about change */
1709 if (ctx->Driver.TexSubImage) {
1710 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
1711 xoffset, yoffset, width, height,
1712 texUnit->CurrentD[2]->Image[level]->IntFormat,
1713 destTex );
1714 }
1715 else {
1716 if (ctx->Driver.TexImage) {
1717 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
1718 texUnit->CurrentD[2]->Image[level]->IntFormat,
1719 destTex );
1720 }
1721 }
1722 }
1723 else {
1724 /* if no image, an error must have occured, do more testing now */
1725 GLint components, size;
1726
1727 if (width<0) {
1728 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" );
1729 return;
1730 }
1731 if (height<0) {
1732 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" );
1733 return;
1734 }
1735 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1736 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1737 return;
1738 }
1739 components = gl_components_in_format( format );
1740 if (components<0 || format==GL_STENCIL_INDEX
1741 || format==GL_DEPTH_COMPONENT){
1742 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" );
1743 return;
1744 }
1745 size = gl_sizeof_packed_type( type );
1746 if (size<=0) {
1747 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" );
1748 return;
1749 }
1750 /* if we get here, probably ran out of memory during unpacking */
1751 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" );
1752 }
1753}
1754
1755
1756
1757void gl_TexSubImage3DEXT( GLcontext *ctx,
1758 GLenum target, GLint level,
1759 GLint xoffset, GLint yoffset, GLint zoffset,
1760 GLsizei width, GLsizei height, GLsizei depth,
1761 GLenum format, GLenum type,
1762 struct gl_image *image )
1763{
1764 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1765 struct gl_texture_image *destTex;
1766
1767 if (target!=GL_TEXTURE_3D_EXT) {
1768 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" );
1769 return;
1770 }
1771 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1772 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" );
1773 return;
1774 }
1775
1776 destTex = texUnit->CurrentD[3]->Image[level];
1777 if (!destTex) {
1778 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" );
1779 return;
1780 }
1781
1782 if (xoffset < -((GLint)destTex->Border)) {
1783 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" );
1784 return;
1785 }
1786 if (yoffset < -((GLint)destTex->Border)) {
1787 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" );
1788 return;
1789 }
1790 if (zoffset < -((GLint)destTex->Border)) {
1791 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" );
1792 return;
1793 }
1794 if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) {
1795 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" );
1796 return;
1797 }
1798 if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) {
1799 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" );
1800 return;
1801 }
1802 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1803 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" );
1804 return;
1805 }
1806
1807 if (image) {
1808 /* unpacking must have been error-free */
1809 GLint texcomponents = components_in_intformat(destTex->Format);
1810 GLint dstRectArea = destTex->Width * destTex->Height;
1811 GLint srcRectArea = width * height;
Brian Paul91baaa31999-10-17 23:24:16 +00001812 const GLint xoffsetb = xoffset + destTex->Border;
1813 const GLint yoffsetb = yoffset + destTex->Border;
1814 const GLint zoffsetb = zoffset + destTex->Border;
jtgafb833d1999-08-19 00:55:39 +00001815
1816 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1817 /* Simple case, just byte copy image data into texture image */
1818 /* row by row. */
1819 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001820 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
jtgafb833d1999-08-19 00:55:39 +00001821 * texcomponents;
1822 GLubyte *src = (GLubyte *) image->Data;
1823 GLint j, k;
1824 for(k=0;k<depth; k++) {
1825 for (j=0;j<height;j++) {
1826 MEMCPY( dst, src, width * texcomponents );
1827 dst += destTex->Width * texcomponents;
1828 src += width * texcomponents;
1829 }
1830 dst += dstRectArea * texcomponents * sizeof(GLubyte);
1831 src += srcRectArea * texcomponents * sizeof(GLubyte);
1832 }
1833 }
1834 else {
1835 /* General case, convert image pixels into texels, scale, bias, etc */
1836 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1837 destTex->IntFormat, destTex->Border);
1838 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001839 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
jtgafb833d1999-08-19 00:55:39 +00001840 * texcomponents;
1841 GLubyte *src = subTexImg->Data;
1842 GLint j, k;
1843 for(k=0;k<depth; k++) {
1844 for (j=0;j<height;j++) {
1845 MEMCPY( dst, src, width * texcomponents );
1846 dst += destTex->Width * texcomponents;
1847 src += width * texcomponents;
1848 }
1849 dst += dstRectArea * texcomponents * sizeof(GLubyte);
1850 src += srcRectArea * texcomponents * sizeof(GLubyte);
1851 }
1852 gl_free_texture_image(subTexImg);
1853 }
1854 /* if the image's reference count is zero, delete it now */
1855 if (image->RefCount==0) {
1856 gl_free_image(image);
1857 }
1858
1859 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
1860
1861 /* tell driver about change */
1862 if (ctx->Driver.TexImage) {
1863 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
1864 level, texUnit->CurrentD[3]->Image[level]->IntFormat,
1865 destTex );
1866 }
1867 }
1868 else {
1869 /* if no image, an error must have occured, do more testing now */
1870 GLint components, size;
1871
1872 if (width<0) {
1873 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" );
1874 return;
1875 }
1876 if (height<0) {
1877 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" );
1878 return;
1879 }
1880 if (depth<0) {
1881 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" );
1882 return;
1883 }
1884 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1885 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
1886 return;
1887 }
Brian Pauld53573d1999-10-19 20:36:20 +00001888 components = gl_components_in_format( format );
jtgafb833d1999-08-19 00:55:39 +00001889 if (components<0 || format==GL_STENCIL_INDEX
1890 || format==GL_DEPTH_COMPONENT){
1891 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
1892 return;
1893 }
Brian Pauld53573d1999-10-19 20:36:20 +00001894 size = gl_sizeof_packed_type( type );
jtgafb833d1999-08-19 00:55:39 +00001895 if (size<=0) {
1896 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" );
1897 return;
1898 }
1899 /* if we get here, probably ran out of memory during unpacking */
1900 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" );
1901 }
1902}
1903
1904
1905
1906/*
1907 * Read an RGBA image from the frame buffer.
1908 * Input: ctx - the context
1909 * x, y - lower left corner
1910 * width, height - size of region to read
1911 * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc.
1912 * Return: gl_image pointer or NULL if out of memory
1913 */
1914static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y,
1915 GLsizei width, GLsizei height,
1916 GLenum format )
1917{
1918 struct gl_image *image;
1919 GLubyte *imgptr;
1920 GLint components;
1921 GLint i, j;
1922
1923 components = components_in_intformat( format );
1924
1925 /*
1926 * Allocate image struct and image data buffer
1927 */
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001928 image = MALLOC_STRUCT( gl_image );
jtgafb833d1999-08-19 00:55:39 +00001929 if (image) {
1930 image->Width = width;
1931 image->Height = height;
1932 image->Depth = 1;
1933 image->Components = components;
1934 image->Format = format;
1935 image->Type = GL_UNSIGNED_BYTE;
1936 image->RefCount = 0;
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001937 image->Data = (GLubyte *) MALLOC( width * height * components );
jtgafb833d1999-08-19 00:55:39 +00001938 if (!image->Data) {
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001939 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001940 return NULL;
1941 }
1942 }
1943 else {
1944 return NULL;
1945 }
1946
1947 imgptr = (GLubyte *) image->Data;
1948
1949 /* Select buffer to read from */
1950 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
1951
1952 for (j=0;j<height;j++) {
1953 GLubyte rgba[MAX_WIDTH][4];
1954 gl_read_rgba_span( ctx, width, x, y+j, rgba );
1955
1956 switch (format) {
1957 case GL_ALPHA:
1958 for (i=0;i<width;i++) {
1959 *imgptr++ = rgba[i][ACOMP];
1960 }
1961 break;
1962 case GL_LUMINANCE:
1963 for (i=0;i<width;i++) {
1964 *imgptr++ = rgba[i][RCOMP];
1965 }
1966 break;
1967 case GL_LUMINANCE_ALPHA:
1968 for (i=0;i<width;i++) {
1969 *imgptr++ = rgba[i][RCOMP];
1970 *imgptr++ = rgba[i][ACOMP];
1971 }
1972 break;
1973 case GL_INTENSITY:
1974 for (i=0;i<width;i++) {
1975 *imgptr++ = rgba[i][RCOMP];
1976 }
1977 break;
1978 case GL_RGB:
1979 for (i=0;i<width;i++) {
1980 *imgptr++ = rgba[i][RCOMP];
1981 *imgptr++ = rgba[i][GCOMP];
1982 *imgptr++ = rgba[i][BCOMP];
1983 }
1984 break;
1985 case GL_RGBA:
1986 for (i=0;i<width;i++) {
1987 *imgptr++ = rgba[i][RCOMP];
1988 *imgptr++ = rgba[i][GCOMP];
1989 *imgptr++ = rgba[i][BCOMP];
1990 *imgptr++ = rgba[i][ACOMP];
1991 }
1992 break;
1993 default:
1994 gl_problem(ctx, "Bad format in read_color_image");
1995 break;
1996 } /*switch*/
1997
1998 } /*for*/
1999
2000 /* Restore drawing buffer */
2001 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
2002
2003 return image;
2004}
2005
2006
2007
2008
2009void gl_CopyTexImage1D( GLcontext *ctx,
2010 GLenum target, GLint level,
2011 GLenum internalformat,
2012 GLint x, GLint y,
2013 GLsizei width, GLint border )
2014{
2015 GLint format;
2016 struct gl_image *teximage;
2017
2018 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2019 if (target!=GL_TEXTURE_1D) {
2020 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
2021 return;
2022 }
2023 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2024 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" );
2025 return;
2026 }
2027 if (border!=0 && border!=1) {
2028 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" );
2029 return;
2030 }
2031 if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) {
2032 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" );
2033 return;
2034 }
2035 format = decode_internal_format( internalformat );
2036 if (format<0 || (internalformat>=1 && internalformat<=4)) {
2037 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" );
2038 return;
2039 }
2040
2041 teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format );
2042 if (!teximage) {
2043 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2044 return;
2045 }
2046
2047 gl_TexImage1D( ctx, target, level, internalformat, width,
2048 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
2049
2050 /* teximage was freed in gl_TexImage1D */
2051}
2052
2053
2054
2055void gl_CopyTexImage2D( GLcontext *ctx,
2056 GLenum target, GLint level, GLenum internalformat,
2057 GLint x, GLint y, GLsizei width, GLsizei height,
2058 GLint border )
2059{
2060 GLint format;
2061 struct gl_image *teximage;
2062
2063 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2064 if (target!=GL_TEXTURE_2D) {
2065 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
2066 return;
2067 }
2068 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2069 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" );
2070 return;
2071 }
2072 if (border!=0 && border!=1) {
2073 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" );
2074 return;
2075 }
2076 if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) {
2077 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" );
2078 return;
2079 }
2080 if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) {
2081 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" );
2082 return;
2083 }
2084 format = decode_internal_format( internalformat );
2085 if (format<0 || (internalformat>=1 && internalformat<=4)) {
2086 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" );
2087 return;
2088 }
2089
2090 teximage = read_color_image( ctx, x, y, width, height, (GLenum) format );
2091 if (!teximage) {
2092 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2093 return;
2094 }
2095
2096 gl_TexImage2D( ctx, target, level, internalformat, width, height,
2097 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
2098
2099 /* teximage was freed in gl_TexImage2D */
2100}
2101
2102
2103
2104
2105/*
2106 * Do the work of glCopyTexSubImage[123]D.
2107 * TODO: apply pixel bias scale and mapping.
2108 */
2109static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2110 GLint width, GLint height,
2111 GLint srcx, GLint srcy,
Brian Paul91baaa31999-10-17 23:24:16 +00002112 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00002113{
2114 GLint i, j;
2115 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00002116 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00002117
Brian Paul91baaa31999-10-17 23:24:16 +00002118 /* dst[xyz] may be negative if we have a texture border! */
2119 dstx += dest->Border;
2120 dsty += dest->Border;
2121 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00002122 texwidth = dest->Width;
2123 texheight = dest->Height;
2124 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00002125 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00002126 format = dest->Format;
2127 components = components_in_intformat( format );
2128
2129 /* Select buffer to read from */
2130 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
2131
2132 for (j=0;j<height;j++) {
2133 GLubyte rgba[MAX_WIDTH][4];
2134 GLubyte *texptr;
2135
2136 gl_read_rgba_span( ctx, width, srcx, srcy+j, rgba );
2137
2138 texptr = dest->Data + ( zoffset + (dsty+j) * texwidth + dstx) * components;
2139
2140 switch (format) {
2141 case GL_ALPHA:
2142 for (i=0;i<width;i++) {
2143 *texptr++ = rgba[i][ACOMP];
2144 }
2145 break;
2146 case GL_LUMINANCE:
2147 for (i=0;i<width;i++) {
2148 *texptr++ = rgba[i][RCOMP];
2149 }
2150 break;
2151 case GL_LUMINANCE_ALPHA:
2152 for (i=0;i<width;i++) {
2153 *texptr++ = rgba[i][RCOMP];
2154 *texptr++ = rgba[i][ACOMP];
2155 }
2156 break;
2157 case GL_INTENSITY:
2158 for (i=0;i<width;i++) {
2159 *texptr++ = rgba[i][RCOMP];
2160 }
2161 break;
2162 case GL_RGB:
2163 for (i=0;i<width;i++) {
2164 *texptr++ = rgba[i][RCOMP];
2165 *texptr++ = rgba[i][GCOMP];
2166 *texptr++ = rgba[i][BCOMP];
2167 }
2168 break;
2169 case GL_RGBA:
2170 for (i=0;i<width;i++) {
2171 *texptr++ = rgba[i][RCOMP];
2172 *texptr++ = rgba[i][GCOMP];
2173 *texptr++ = rgba[i][BCOMP];
2174 *texptr++ = rgba[i][ACOMP];
2175 }
2176 break;
2177 } /*switch*/
2178 } /*for*/
2179
2180
2181 /* Restore drawing buffer */
2182 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
2183}
2184
2185
2186
2187
2188void gl_CopyTexSubImage1D( GLcontext *ctx,
2189 GLenum target, GLint level,
2190 GLint xoffset, GLint x, GLint y, GLsizei width )
2191{
2192 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2193 struct gl_texture_image *teximage;
2194
2195 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2196 if (target!=GL_TEXTURE_1D) {
2197 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
2198 return;
2199 }
2200 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2201 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" );
2202 return;
2203 }
2204 if (width<0) {
2205 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" );
2206 return;
2207 }
2208
2209 teximage = texUnit->CurrentD[1]->Image[level];
2210
2211 if (teximage) {
2212 if (xoffset < -((GLint)teximage->Border)) {
2213 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" );
2214 return;
2215 }
2216 /* NOTE: we're adding the border here, not subtracting! */
2217 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2218 gl_error( ctx, GL_INVALID_VALUE,
2219 "glCopyTexSubImage1D(xoffset+width)" );
2220 return;
2221 }
2222 if (teximage->Data) {
2223 copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 );
2224
2225 /* tell driver about change */
2226 if (ctx->Driver.TexSubImage) {
2227 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
2228 texUnit->CurrentD[1], level,
2229 xoffset,0,width,1,
2230 teximage->IntFormat,
2231 teximage );
2232 }
2233 else {
2234 if (ctx->Driver.TexImage) {
2235 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level,
2236 teximage->IntFormat,
2237 teximage );
2238 }
2239 }
2240 }
2241 }
2242 else {
2243 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" );
2244 }
2245}
2246
2247
2248
2249void gl_CopyTexSubImage2D( GLcontext *ctx,
2250 GLenum target, GLint level,
2251 GLint xoffset, GLint yoffset,
2252 GLint x, GLint y, GLsizei width, GLsizei height )
2253{
2254 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2255 struct gl_texture_image *teximage;
2256
2257 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2258 if (target!=GL_TEXTURE_2D) {
2259 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2260 return;
2261 }
2262 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2263 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" );
2264 return;
2265 }
2266 if (width<0) {
2267 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" );
2268 return;
2269 }
2270 if (height<0) {
2271 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" );
2272 return;
2273 }
2274
2275 teximage = texUnit->CurrentD[2]->Image[level];
2276
2277 if (teximage) {
2278 if (xoffset < -((GLint)teximage->Border)) {
2279 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" );
2280 return;
2281 }
2282 if (yoffset < -((GLint)teximage->Border)) {
2283 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" );
2284 return;
2285 }
2286 /* NOTE: we're adding the border here, not subtracting! */
2287 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2288 gl_error( ctx, GL_INVALID_VALUE,
2289 "glCopyTexSubImage2D(xoffset+width)" );
2290 return;
2291 }
2292 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
2293 gl_error( ctx, GL_INVALID_VALUE,
2294 "glCopyTexSubImage2D(yoffset+height)" );
2295 return;
2296 }
2297
2298 if (teximage->Data) {
2299 copy_tex_sub_image( ctx, teximage, width, height,
2300 x, y, xoffset, yoffset, 0 );
2301 /* tell driver about change */
2302 if (ctx->Driver.TexSubImage) {
2303 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
2304 xoffset, yoffset, width, height,
2305 teximage->IntFormat,
2306 teximage );
2307 }
2308 else {
2309 if (ctx->Driver.TexImage) {
2310 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
2311 teximage->IntFormat,
2312 teximage );
2313 }
2314 }
2315 }
2316 }
2317 else {
2318 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" );
2319 }
2320}
2321
2322
2323
2324void gl_CopyTexSubImage3DEXT( GLcontext *ctx,
2325 GLenum target, GLint level,
2326 GLint xoffset, GLint yoffset, GLint zoffset,
2327 GLint x, GLint y, GLsizei width, GLsizei height )
2328{
2329 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2330 struct gl_texture_image *teximage;
2331
2332 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT");
Brian Pauld53573d1999-10-19 20:36:20 +00002333 if (target!=GL_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00002334 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" );
2335 return;
2336 }
2337 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2338 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" );
2339 return;
2340 }
2341 if (width<0) {
2342 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" );
2343 return;
2344 }
2345 if (height<0) {
2346 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" );
2347 return;
2348 }
2349
2350 teximage = texUnit->CurrentD[3]->Image[level];
2351 if (teximage) {
2352 if (xoffset < -((GLint)teximage->Border)) {
2353 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" );
2354 return;
2355 }
2356 if (yoffset < -((GLint)teximage->Border)) {
2357 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" );
2358 return;
2359 }
2360 if (zoffset < -((GLint)teximage->Border)) {
2361 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" );
2362 return;
2363 }
2364 /* NOTE: we're adding the border here, not subtracting! */
2365 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2366 gl_error( ctx, GL_INVALID_VALUE,
2367 "glCopyTexSubImage3DEXT(xoffset+width)" );
2368 return;
2369 }
2370 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
2371 gl_error( ctx, GL_INVALID_VALUE,
2372 "glCopyTexSubImage3DEXT(yoffset+height)" );
2373 return;
2374 }
2375 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
2376 gl_error( ctx, GL_INVALID_VALUE,
2377 "glCopyTexSubImage3DEXT(zoffset+depth)" );
2378 return;
2379 }
2380
2381 if (teximage->Data) {
2382 copy_tex_sub_image( ctx, teximage, width, height,
2383 x, y, xoffset, yoffset, zoffset);
2384
2385 /* tell driver about change */
2386 if (ctx->Driver.TexImage) {
2387 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
2388 level, teximage->IntFormat,
2389 teximage );
2390 }
2391 }
2392 }
2393 else {
2394 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" );
2395 }
2396}
2397