blob: 0f6bde4bb017ed06bfb2c49999afa39a6a2fcc3e [file] [log] [blame]
Brian Paul64a79b21999-10-22 10:43:35 +00001/* $Id: teximage.c,v 1.8 1999/10/22 10:43:35 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;
Brian Paul64a79b21999-10-22 10:43:35 +00001677 const GLubyte *src = (const GLubyte *) image->Data;
jtgafb833d1999-08-19 00:55:39 +00001678 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 }
Brian Paul64a79b21999-10-22 10:43:35 +00001685 else if (image->Type==GL_UNSIGNED_BYTE
1686 && texcomponents==3 && image->Components == 4 ) {
1687 /* 32 bit (padded) to 24 bit case, used heavily by quake */
1688 GLubyte *dst = destTex->Data
1689 + (yoffsetb * destTex->Width + xoffsetb) * texcomponents;
1690 const GLubyte *src = (const GLubyte *) image->Data;
1691 GLint j;
1692 for (j=0;j<height;j++) {
1693 const GLubyte *stop = src + (width << 2);
1694 for ( ; src != stop ; ) {
1695 dst[0] = src[0];
1696 dst[1] = src[1];
1697 dst[2] = src[2];
1698 dst += 3;
1699 src += 4;
1700 }
1701 dst += (destTex->Width - width) * texcomponents * sizeof(GLubyte);
1702 }
1703 }
jtgafb833d1999-08-19 00:55:39 +00001704 else {
1705 /* General case, convert image pixels into texels, scale, bias, etc */
1706 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1707 destTex->IntFormat, destTex->Border);
1708 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001709 + (yoffsetb * destTex->Width + xoffsetb) * texcomponents;
Brian Paul64a79b21999-10-22 10:43:35 +00001710 const GLubyte *src = subTexImg->Data;
jtgafb833d1999-08-19 00:55:39 +00001711 GLint j;
1712 for (j=0;j<height;j++) {
1713 MEMCPY( dst, src, width * texcomponents );
1714 dst += destTex->Width * texcomponents * sizeof(GLubyte);
1715 src += width * texcomponents * sizeof(GLubyte);
1716 }
1717 gl_free_texture_image(subTexImg);
1718 }
1719
1720 /* if the image's reference count is zero, delete it now */
1721 if (image->RefCount==0) {
1722 gl_free_image(image);
1723 }
1724
1725 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1726
1727 /* tell driver about change */
1728 if (ctx->Driver.TexSubImage) {
1729 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
1730 xoffset, yoffset, width, height,
1731 texUnit->CurrentD[2]->Image[level]->IntFormat,
1732 destTex );
1733 }
1734 else {
1735 if (ctx->Driver.TexImage) {
1736 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
1737 texUnit->CurrentD[2]->Image[level]->IntFormat,
1738 destTex );
1739 }
1740 }
1741 }
1742 else {
1743 /* if no image, an error must have occured, do more testing now */
1744 GLint components, size;
1745
1746 if (width<0) {
1747 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" );
1748 return;
1749 }
1750 if (height<0) {
1751 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" );
1752 return;
1753 }
1754 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1755 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1756 return;
1757 }
1758 components = gl_components_in_format( format );
1759 if (components<0 || format==GL_STENCIL_INDEX
1760 || format==GL_DEPTH_COMPONENT){
1761 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" );
1762 return;
1763 }
1764 size = gl_sizeof_packed_type( type );
1765 if (size<=0) {
1766 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" );
1767 return;
1768 }
1769 /* if we get here, probably ran out of memory during unpacking */
1770 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" );
1771 }
1772}
1773
1774
1775
1776void gl_TexSubImage3DEXT( GLcontext *ctx,
1777 GLenum target, GLint level,
1778 GLint xoffset, GLint yoffset, GLint zoffset,
1779 GLsizei width, GLsizei height, GLsizei depth,
1780 GLenum format, GLenum type,
1781 struct gl_image *image )
1782{
1783 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1784 struct gl_texture_image *destTex;
1785
1786 if (target!=GL_TEXTURE_3D_EXT) {
1787 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" );
1788 return;
1789 }
1790 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1791 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" );
1792 return;
1793 }
1794
1795 destTex = texUnit->CurrentD[3]->Image[level];
1796 if (!destTex) {
1797 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" );
1798 return;
1799 }
1800
1801 if (xoffset < -((GLint)destTex->Border)) {
1802 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" );
1803 return;
1804 }
1805 if (yoffset < -((GLint)destTex->Border)) {
1806 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" );
1807 return;
1808 }
1809 if (zoffset < -((GLint)destTex->Border)) {
1810 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" );
1811 return;
1812 }
1813 if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) {
1814 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" );
1815 return;
1816 }
1817 if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) {
1818 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" );
1819 return;
1820 }
1821 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1822 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" );
1823 return;
1824 }
1825
1826 if (image) {
1827 /* unpacking must have been error-free */
1828 GLint texcomponents = components_in_intformat(destTex->Format);
1829 GLint dstRectArea = destTex->Width * destTex->Height;
1830 GLint srcRectArea = width * height;
Brian Paul91baaa31999-10-17 23:24:16 +00001831 const GLint xoffsetb = xoffset + destTex->Border;
1832 const GLint yoffsetb = yoffset + destTex->Border;
1833 const GLint zoffsetb = zoffset + destTex->Border;
jtgafb833d1999-08-19 00:55:39 +00001834
1835 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1836 /* Simple case, just byte copy image data into texture image */
1837 /* row by row. */
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 = (GLubyte *) image->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 }
1853 else {
1854 /* General case, convert image pixels into texels, scale, bias, etc */
1855 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1856 destTex->IntFormat, destTex->Border);
1857 GLubyte *dst = destTex->Data
Brian Paul91baaa31999-10-17 23:24:16 +00001858 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
jtgafb833d1999-08-19 00:55:39 +00001859 * texcomponents;
1860 GLubyte *src = subTexImg->Data;
1861 GLint j, k;
1862 for(k=0;k<depth; k++) {
1863 for (j=0;j<height;j++) {
1864 MEMCPY( dst, src, width * texcomponents );
1865 dst += destTex->Width * texcomponents;
1866 src += width * texcomponents;
1867 }
1868 dst += dstRectArea * texcomponents * sizeof(GLubyte);
1869 src += srcRectArea * texcomponents * sizeof(GLubyte);
1870 }
1871 gl_free_texture_image(subTexImg);
1872 }
1873 /* if the image's reference count is zero, delete it now */
1874 if (image->RefCount==0) {
1875 gl_free_image(image);
1876 }
1877
1878 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
1879
1880 /* tell driver about change */
1881 if (ctx->Driver.TexImage) {
1882 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
1883 level, texUnit->CurrentD[3]->Image[level]->IntFormat,
1884 destTex );
1885 }
1886 }
1887 else {
1888 /* if no image, an error must have occured, do more testing now */
1889 GLint components, size;
1890
1891 if (width<0) {
1892 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" );
1893 return;
1894 }
1895 if (height<0) {
1896 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" );
1897 return;
1898 }
1899 if (depth<0) {
1900 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" );
1901 return;
1902 }
1903 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1904 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
1905 return;
1906 }
Brian Pauld53573d1999-10-19 20:36:20 +00001907 components = gl_components_in_format( format );
jtgafb833d1999-08-19 00:55:39 +00001908 if (components<0 || format==GL_STENCIL_INDEX
1909 || format==GL_DEPTH_COMPONENT){
1910 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
1911 return;
1912 }
Brian Pauld53573d1999-10-19 20:36:20 +00001913 size = gl_sizeof_packed_type( type );
jtgafb833d1999-08-19 00:55:39 +00001914 if (size<=0) {
1915 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" );
1916 return;
1917 }
1918 /* if we get here, probably ran out of memory during unpacking */
1919 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" );
1920 }
1921}
1922
1923
1924
1925/*
1926 * Read an RGBA image from the frame buffer.
1927 * Input: ctx - the context
1928 * x, y - lower left corner
1929 * width, height - size of region to read
1930 * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc.
1931 * Return: gl_image pointer or NULL if out of memory
1932 */
1933static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y,
1934 GLsizei width, GLsizei height,
1935 GLenum format )
1936{
1937 struct gl_image *image;
1938 GLubyte *imgptr;
1939 GLint components;
1940 GLint i, j;
1941
1942 components = components_in_intformat( format );
1943
1944 /*
1945 * Allocate image struct and image data buffer
1946 */
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001947 image = MALLOC_STRUCT( gl_image );
jtgafb833d1999-08-19 00:55:39 +00001948 if (image) {
1949 image->Width = width;
1950 image->Height = height;
1951 image->Depth = 1;
1952 image->Components = components;
1953 image->Format = format;
1954 image->Type = GL_UNSIGNED_BYTE;
1955 image->RefCount = 0;
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001956 image->Data = (GLubyte *) MALLOC( width * height * components );
jtgafb833d1999-08-19 00:55:39 +00001957 if (!image->Data) {
Brian Paulbd5cdaf1999-10-13 18:42:49 +00001958 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001959 return NULL;
1960 }
1961 }
1962 else {
1963 return NULL;
1964 }
1965
1966 imgptr = (GLubyte *) image->Data;
1967
1968 /* Select buffer to read from */
1969 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
1970
1971 for (j=0;j<height;j++) {
1972 GLubyte rgba[MAX_WIDTH][4];
1973 gl_read_rgba_span( ctx, width, x, y+j, rgba );
1974
1975 switch (format) {
1976 case GL_ALPHA:
1977 for (i=0;i<width;i++) {
1978 *imgptr++ = rgba[i][ACOMP];
1979 }
1980 break;
1981 case GL_LUMINANCE:
1982 for (i=0;i<width;i++) {
1983 *imgptr++ = rgba[i][RCOMP];
1984 }
1985 break;
1986 case GL_LUMINANCE_ALPHA:
1987 for (i=0;i<width;i++) {
1988 *imgptr++ = rgba[i][RCOMP];
1989 *imgptr++ = rgba[i][ACOMP];
1990 }
1991 break;
1992 case GL_INTENSITY:
1993 for (i=0;i<width;i++) {
1994 *imgptr++ = rgba[i][RCOMP];
1995 }
1996 break;
1997 case GL_RGB:
1998 for (i=0;i<width;i++) {
1999 *imgptr++ = rgba[i][RCOMP];
2000 *imgptr++ = rgba[i][GCOMP];
2001 *imgptr++ = rgba[i][BCOMP];
2002 }
2003 break;
2004 case GL_RGBA:
2005 for (i=0;i<width;i++) {
2006 *imgptr++ = rgba[i][RCOMP];
2007 *imgptr++ = rgba[i][GCOMP];
2008 *imgptr++ = rgba[i][BCOMP];
2009 *imgptr++ = rgba[i][ACOMP];
2010 }
2011 break;
2012 default:
2013 gl_problem(ctx, "Bad format in read_color_image");
2014 break;
2015 } /*switch*/
2016
2017 } /*for*/
2018
2019 /* Restore drawing buffer */
2020 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
2021
2022 return image;
2023}
2024
2025
2026
2027
2028void gl_CopyTexImage1D( GLcontext *ctx,
2029 GLenum target, GLint level,
2030 GLenum internalformat,
2031 GLint x, GLint y,
2032 GLsizei width, GLint border )
2033{
2034 GLint format;
2035 struct gl_image *teximage;
2036
2037 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2038 if (target!=GL_TEXTURE_1D) {
2039 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
2040 return;
2041 }
2042 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2043 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" );
2044 return;
2045 }
2046 if (border!=0 && border!=1) {
2047 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" );
2048 return;
2049 }
2050 if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) {
2051 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" );
2052 return;
2053 }
2054 format = decode_internal_format( internalformat );
2055 if (format<0 || (internalformat>=1 && internalformat<=4)) {
2056 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" );
2057 return;
2058 }
2059
2060 teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format );
2061 if (!teximage) {
2062 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2063 return;
2064 }
2065
2066 gl_TexImage1D( ctx, target, level, internalformat, width,
2067 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
2068
2069 /* teximage was freed in gl_TexImage1D */
2070}
2071
2072
2073
2074void gl_CopyTexImage2D( GLcontext *ctx,
2075 GLenum target, GLint level, GLenum internalformat,
2076 GLint x, GLint y, GLsizei width, GLsizei height,
2077 GLint border )
2078{
2079 GLint format;
2080 struct gl_image *teximage;
2081
2082 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2083 if (target!=GL_TEXTURE_2D) {
2084 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
2085 return;
2086 }
2087 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2088 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" );
2089 return;
2090 }
2091 if (border!=0 && border!=1) {
2092 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" );
2093 return;
2094 }
2095 if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) {
2096 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" );
2097 return;
2098 }
2099 if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) {
2100 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" );
2101 return;
2102 }
2103 format = decode_internal_format( internalformat );
2104 if (format<0 || (internalformat>=1 && internalformat<=4)) {
2105 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" );
2106 return;
2107 }
2108
2109 teximage = read_color_image( ctx, x, y, width, height, (GLenum) format );
2110 if (!teximage) {
2111 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2112 return;
2113 }
2114
2115 gl_TexImage2D( ctx, target, level, internalformat, width, height,
2116 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
2117
2118 /* teximage was freed in gl_TexImage2D */
2119}
2120
2121
2122
2123
2124/*
2125 * Do the work of glCopyTexSubImage[123]D.
2126 * TODO: apply pixel bias scale and mapping.
2127 */
2128static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2129 GLint width, GLint height,
2130 GLint srcx, GLint srcy,
Brian Paul91baaa31999-10-17 23:24:16 +00002131 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00002132{
2133 GLint i, j;
2134 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00002135 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00002136
Brian Paul91baaa31999-10-17 23:24:16 +00002137 /* dst[xyz] may be negative if we have a texture border! */
2138 dstx += dest->Border;
2139 dsty += dest->Border;
2140 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00002141 texwidth = dest->Width;
2142 texheight = dest->Height;
2143 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00002144 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00002145 format = dest->Format;
2146 components = components_in_intformat( format );
2147
2148 /* Select buffer to read from */
2149 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
2150
2151 for (j=0;j<height;j++) {
2152 GLubyte rgba[MAX_WIDTH][4];
2153 GLubyte *texptr;
2154
2155 gl_read_rgba_span( ctx, width, srcx, srcy+j, rgba );
2156
2157 texptr = dest->Data + ( zoffset + (dsty+j) * texwidth + dstx) * components;
2158
2159 switch (format) {
2160 case GL_ALPHA:
2161 for (i=0;i<width;i++) {
2162 *texptr++ = rgba[i][ACOMP];
2163 }
2164 break;
2165 case GL_LUMINANCE:
2166 for (i=0;i<width;i++) {
2167 *texptr++ = rgba[i][RCOMP];
2168 }
2169 break;
2170 case GL_LUMINANCE_ALPHA:
2171 for (i=0;i<width;i++) {
2172 *texptr++ = rgba[i][RCOMP];
2173 *texptr++ = rgba[i][ACOMP];
2174 }
2175 break;
2176 case GL_INTENSITY:
2177 for (i=0;i<width;i++) {
2178 *texptr++ = rgba[i][RCOMP];
2179 }
2180 break;
2181 case GL_RGB:
2182 for (i=0;i<width;i++) {
2183 *texptr++ = rgba[i][RCOMP];
2184 *texptr++ = rgba[i][GCOMP];
2185 *texptr++ = rgba[i][BCOMP];
2186 }
2187 break;
2188 case GL_RGBA:
2189 for (i=0;i<width;i++) {
2190 *texptr++ = rgba[i][RCOMP];
2191 *texptr++ = rgba[i][GCOMP];
2192 *texptr++ = rgba[i][BCOMP];
2193 *texptr++ = rgba[i][ACOMP];
2194 }
2195 break;
2196 } /*switch*/
2197 } /*for*/
2198
2199
2200 /* Restore drawing buffer */
2201 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
2202}
2203
2204
2205
2206
2207void gl_CopyTexSubImage1D( GLcontext *ctx,
2208 GLenum target, GLint level,
2209 GLint xoffset, GLint x, GLint y, GLsizei width )
2210{
2211 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2212 struct gl_texture_image *teximage;
2213
2214 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2215 if (target!=GL_TEXTURE_1D) {
2216 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
2217 return;
2218 }
2219 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2220 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" );
2221 return;
2222 }
2223 if (width<0) {
2224 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" );
2225 return;
2226 }
2227
2228 teximage = texUnit->CurrentD[1]->Image[level];
2229
2230 if (teximage) {
2231 if (xoffset < -((GLint)teximage->Border)) {
2232 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" );
2233 return;
2234 }
2235 /* NOTE: we're adding the border here, not subtracting! */
2236 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2237 gl_error( ctx, GL_INVALID_VALUE,
2238 "glCopyTexSubImage1D(xoffset+width)" );
2239 return;
2240 }
2241 if (teximage->Data) {
2242 copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 );
2243
2244 /* tell driver about change */
2245 if (ctx->Driver.TexSubImage) {
2246 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
2247 texUnit->CurrentD[1], level,
2248 xoffset,0,width,1,
2249 teximage->IntFormat,
2250 teximage );
2251 }
2252 else {
2253 if (ctx->Driver.TexImage) {
2254 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level,
2255 teximage->IntFormat,
2256 teximage );
2257 }
2258 }
2259 }
2260 }
2261 else {
2262 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" );
2263 }
2264}
2265
2266
2267
2268void gl_CopyTexSubImage2D( GLcontext *ctx,
2269 GLenum target, GLint level,
2270 GLint xoffset, GLint yoffset,
2271 GLint x, GLint y, GLsizei width, GLsizei height )
2272{
2273 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2274 struct gl_texture_image *teximage;
2275
2276 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2277 if (target!=GL_TEXTURE_2D) {
2278 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
2279 return;
2280 }
2281 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2282 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" );
2283 return;
2284 }
2285 if (width<0) {
2286 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" );
2287 return;
2288 }
2289 if (height<0) {
2290 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" );
2291 return;
2292 }
2293
2294 teximage = texUnit->CurrentD[2]->Image[level];
2295
2296 if (teximage) {
2297 if (xoffset < -((GLint)teximage->Border)) {
2298 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" );
2299 return;
2300 }
2301 if (yoffset < -((GLint)teximage->Border)) {
2302 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" );
2303 return;
2304 }
2305 /* NOTE: we're adding the border here, not subtracting! */
2306 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2307 gl_error( ctx, GL_INVALID_VALUE,
2308 "glCopyTexSubImage2D(xoffset+width)" );
2309 return;
2310 }
2311 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
2312 gl_error( ctx, GL_INVALID_VALUE,
2313 "glCopyTexSubImage2D(yoffset+height)" );
2314 return;
2315 }
2316
2317 if (teximage->Data) {
2318 copy_tex_sub_image( ctx, teximage, width, height,
2319 x, y, xoffset, yoffset, 0 );
2320 /* tell driver about change */
2321 if (ctx->Driver.TexSubImage) {
2322 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
2323 xoffset, yoffset, width, height,
2324 teximage->IntFormat,
2325 teximage );
2326 }
2327 else {
2328 if (ctx->Driver.TexImage) {
2329 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
2330 teximage->IntFormat,
2331 teximage );
2332 }
2333 }
2334 }
2335 }
2336 else {
2337 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" );
2338 }
2339}
2340
2341
2342
2343void gl_CopyTexSubImage3DEXT( GLcontext *ctx,
2344 GLenum target, GLint level,
2345 GLint xoffset, GLint yoffset, GLint zoffset,
2346 GLint x, GLint y, GLsizei width, GLsizei height )
2347{
2348 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2349 struct gl_texture_image *teximage;
2350
2351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT");
Brian Pauld53573d1999-10-19 20:36:20 +00002352 if (target!=GL_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00002353 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" );
2354 return;
2355 }
2356 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
2357 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" );
2358 return;
2359 }
2360 if (width<0) {
2361 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" );
2362 return;
2363 }
2364 if (height<0) {
2365 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" );
2366 return;
2367 }
2368
2369 teximage = texUnit->CurrentD[3]->Image[level];
2370 if (teximage) {
2371 if (xoffset < -((GLint)teximage->Border)) {
2372 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" );
2373 return;
2374 }
2375 if (yoffset < -((GLint)teximage->Border)) {
2376 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" );
2377 return;
2378 }
2379 if (zoffset < -((GLint)teximage->Border)) {
2380 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" );
2381 return;
2382 }
2383 /* NOTE: we're adding the border here, not subtracting! */
2384 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
2385 gl_error( ctx, GL_INVALID_VALUE,
2386 "glCopyTexSubImage3DEXT(xoffset+width)" );
2387 return;
2388 }
2389 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
2390 gl_error( ctx, GL_INVALID_VALUE,
2391 "glCopyTexSubImage3DEXT(yoffset+height)" );
2392 return;
2393 }
2394 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
2395 gl_error( ctx, GL_INVALID_VALUE,
2396 "glCopyTexSubImage3DEXT(zoffset+depth)" );
2397 return;
2398 }
2399
2400 if (teximage->Data) {
2401 copy_tex_sub_image( ctx, teximage, width, height,
2402 x, y, xoffset, yoffset, zoffset);
2403
2404 /* tell driver about change */
2405 if (ctx->Driver.TexImage) {
2406 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
2407 level, teximage->IntFormat,
2408 teximage );
2409 }
2410 }
2411 }
2412 else {
2413 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" );
2414 }
2415}
2416