1 /* $Id: teximage.c,v 1.35 1998/02/07 14:36:41 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 2.6
6 * Copyright (C) 1995-1997 Brian Paul
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23
24 /*
25 * $Log: teximage.c,v $
26 * Revision 1.35 1998/02/07 14:36:41 brianp
27 * fixed bug when passing NULL proxy image to glTexImageXD() (Wes Bethel)
28 *
29 * Revision 1.34 1998/01/16 03:46:07 brianp
30 * fixed a few Windows compilation warnings (Theodore Jump)
31 *
32 * Revision 1.33 1997/12/31 06:10:03 brianp
33 * added Henk Kok's texture validation optimization (AnyDirty flag)
34 *
35 * Revision 1.32 1997/12/07 17:30:39 brianp
36 * added DavidB's patches for v0.21 driver (TexSubImage)
37 *
38 * Revision 1.31 1997/11/07 03:38:07 brianp
39 * added stdio.h include for SunOS 4.x
40 *
41 * Revision 1.30 1997/11/02 20:20:30 brianp
42 * rewrote gl_TexSubImage[123]D()
43 *
44 * Revision 1.29 1997/10/16 01:14:04 brianp
45 * removed teximage Dirty flag
46 *
47 * Revision 1.28 1997/10/14 00:40:20 brianp
48 * added DavidB's v19 fxmesa changes
49 *
50 * Revision 1.27 1997/09/29 23:28:14 brianp
51 * updated for new device driver texture functions
52 *
53 * Revision 1.26 1997/09/28 15:29:03 brianp
54 * initialize image->Depth = 1 in read_color_image() (Hiroki Honda)
55 *
56 * Revision 1.25 1997/09/27 00:14:39 brianp
57 * added GL_EXT_paletted_texture extension
58 *
59 * Revision 1.24 1997/09/03 13:17:17 brianp
60 * added a few pointer casts
61 *
62 * Revision 1.23 1997/08/23 18:40:46 brianp
63 * glTexImage[123]D() with NULL image pointer is correctly handled now
64 *
65 * Revision 1.22 1997/08/11 01:23:29 brianp
66 * added a few pointer casts
67 *
68 * Revision 1.21 1997/07/24 01:25:34 brianp
69 * changed precompiled header symbol from PCH to PC_HEADER
70 *
71 * Revision 1.20 1997/07/05 16:21:17 brianp
72 * fixed unitialized variable bug in gl_TexSubImage1D()
73 *
74 * Revision 1.19 1997/06/24 01:13:53 brianp
75 * call gl_free_image() in gl_TexSubImage[123]D() if ref count==0
76 *
77 * Revision 1.18 1997/06/04 00:33:14 brianp
78 * fixed reference count bug in gl_CopyTexImage1/2D() (Randy Frank)
79 *
80 * Revision 1.17 1997/05/28 03:26:49 brianp
81 * added precompiled header (PCH) support
82 *
83 * Revision 1.16 1997/05/03 00:52:19 brianp
84 * set texture object Dirty flag when changing texture image
85 *
86 * Revision 1.15 1997/04/20 20:29:11 brianp
87 * replaced abort() with gl_problem()
88 *
89 * Revision 1.14 1997/03/04 19:18:29 brianp
90 * added texture image Width2, Height2, and Depth2 fields
91 *
92 * Revision 1.13 1997/02/27 19:58:08 brianp
93 * call gl_problem() instead of gl_warning()
94 *
95 * Revision 1.12 1997/02/09 18:53:05 brianp
96 * added GL_EXT_texture3D support
97 *
98 * Revision 1.11 1997/01/16 03:35:10 brianp
99 * added calls to device driver TexImage() function
100 *
101 * Revision 1.10 1997/01/09 21:26:46 brianp
102 * gl_TexImage[12]D() didn't free the incoming image- a memory leak
103 *
104 * Revision 1.9 1997/01/09 19:55:52 brianp
105 * fixed a few error messages
106 *
107 * Revision 1.8 1997/01/09 19:49:18 brianp
108 * better error checking
109 *
110 * Revision 1.7 1996/12/02 18:59:54 brianp
111 * added code to handle GL_COLOR_INDEX textures, per Randy Frank
112 *
113 * Revision 1.6 1996/11/07 04:13:24 brianp
114 * all new texture image handling, now pixel scale, bias, mapping work
115 *
116 * Revision 1.5 1996/09/27 01:29:57 brianp
117 * removed unused variables, fixed cut&paste bug in color scaling
118 *
119 * Revision 1.4 1996/09/26 22:35:10 brianp
120 * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler
121 *
122 * Revision 1.3 1996/09/15 14:18:55 brianp
123 * now use GLframebuffer and GLvisual
124 *
125 * Revision 1.2 1996/09/15 01:48:58 brianp
126 * removed #define NULL 0
127 *
128 * Revision 1.1 1996/09/13 01:38:16 brianp
129 * Initial revision
130 *
131 */
132
133
134 #ifdef PC_HEADER
135 #include "all.h"
136 #else
137 #include <assert.h>
138 #include <stdio.h>
139 #include <stdlib.h>
140 #include <string.h>
141 #include "context.h"
142 #include "image.h"
143 #include "macros.h"
144 #include "pixel.h"
145 #include "span.h"
146 #include "teximage.h"
147 #include "types.h"
148 #endif
149
150
151 /*
152 * NOTES:
153 *
154 * The internal texture storage convension is an array of N GLubytes
155 * where N = width * height * components. There is no padding.
156 */
157
158
159
160
161 /*
162 * Compute log base 2 of n.
163 * If n isn't an exact power of two return -1.
164 * If n<0 return -1.
165 */
logbase2(int n)166 static int logbase2( int n )
167 {
168 GLint i = 1;
169 GLint log2 = 0;
170
171 if (n<0) {
172 return -1;
173 }
174
175 while ( n > i ) {
176 i *= 2;
177 log2++;
178 }
179 if (i != n) {
180 return -1;
181 }
182 else {
183 return log2;
184 }
185 }
186
187
188
189 /*
190 * Given an internal texture format enum or 1, 2, 3, 4 return the
191 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
192 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return -1 if
193 * invalid enum.
194 */
decode_internal_format(GLint format)195 static GLint decode_internal_format( GLint format )
196 {
197 switch (format) {
198 case GL_ALPHA:
199 case GL_ALPHA4:
200 case GL_ALPHA8:
201 case GL_ALPHA12:
202 case GL_ALPHA16:
203 return GL_ALPHA;
204 case 1:
205 case GL_LUMINANCE:
206 case GL_LUMINANCE4:
207 case GL_LUMINANCE8:
208 case GL_LUMINANCE12:
209 case GL_LUMINANCE16:
210 return GL_LUMINANCE;
211 case 2:
212 case GL_LUMINANCE_ALPHA:
213 case GL_LUMINANCE4_ALPHA4:
214 case GL_LUMINANCE6_ALPHA2:
215 case GL_LUMINANCE8_ALPHA8:
216 case GL_LUMINANCE12_ALPHA4:
217 case GL_LUMINANCE12_ALPHA12:
218 case GL_LUMINANCE16_ALPHA16:
219 return GL_LUMINANCE_ALPHA;
220 case GL_INTENSITY:
221 case GL_INTENSITY4:
222 case GL_INTENSITY8:
223 case GL_INTENSITY12:
224 case GL_INTENSITY16:
225 return GL_INTENSITY;
226 case 3:
227 case GL_RGB:
228 case GL_R3_G3_B2:
229 case GL_RGB4:
230 case GL_RGB5:
231 case GL_RGB8:
232 case GL_RGB10:
233 case GL_RGB12:
234 case GL_RGB16:
235 return GL_RGB;
236 case 4:
237 case GL_RGBA:
238 case GL_RGBA2:
239 case GL_RGBA4:
240 case GL_RGB5_A1:
241 case GL_RGBA8:
242 case GL_RGB10_A2:
243 case GL_RGBA12:
244 case GL_RGBA16:
245 return GL_RGBA;
246 case GL_COLOR_INDEX1_EXT:
247 case GL_COLOR_INDEX2_EXT:
248 case GL_COLOR_INDEX4_EXT:
249 case GL_COLOR_INDEX8_EXT:
250 case GL_COLOR_INDEX12_EXT:
251 case GL_COLOR_INDEX16_EXT:
252 return GL_COLOR_INDEX;
253 default:
254 return -1; /* error */
255 }
256 }
257
258
259
260 /*
261 * Given an internal texture format enum or 1, 2, 3, 4 return the
262 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
263 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
264 * number of components for the format. Return -1 if invalid enum.
265 */
components_in_intformat(GLint format)266 static GLint components_in_intformat( GLint format )
267 {
268 switch (format) {
269 case GL_ALPHA:
270 case GL_ALPHA4:
271 case GL_ALPHA8:
272 case GL_ALPHA12:
273 case GL_ALPHA16:
274 return 1;
275 case 1:
276 case GL_LUMINANCE:
277 case GL_LUMINANCE4:
278 case GL_LUMINANCE8:
279 case GL_LUMINANCE12:
280 case GL_LUMINANCE16:
281 return 1;
282 case 2:
283 case GL_LUMINANCE_ALPHA:
284 case GL_LUMINANCE4_ALPHA4:
285 case GL_LUMINANCE6_ALPHA2:
286 case GL_LUMINANCE8_ALPHA8:
287 case GL_LUMINANCE12_ALPHA4:
288 case GL_LUMINANCE12_ALPHA12:
289 case GL_LUMINANCE16_ALPHA16:
290 return 2;
291 case GL_INTENSITY:
292 case GL_INTENSITY4:
293 case GL_INTENSITY8:
294 case GL_INTENSITY12:
295 case GL_INTENSITY16:
296 return 1;
297 case 3:
298 case GL_RGB:
299 case GL_R3_G3_B2:
300 case GL_RGB4:
301 case GL_RGB5:
302 case GL_RGB8:
303 case GL_RGB10:
304 case GL_RGB12:
305 case GL_RGB16:
306 return 3;
307 case 4:
308 case GL_RGBA:
309 case GL_RGBA2:
310 case GL_RGBA4:
311 case GL_RGB5_A1:
312 case GL_RGBA8:
313 case GL_RGB10_A2:
314 case GL_RGBA12:
315 case GL_RGBA16:
316 return 4;
317 case GL_COLOR_INDEX1_EXT:
318 case GL_COLOR_INDEX2_EXT:
319 case GL_COLOR_INDEX4_EXT:
320 case GL_COLOR_INDEX8_EXT:
321 case GL_COLOR_INDEX12_EXT:
322 case GL_COLOR_INDEX16_EXT:
323 return 1;
324 default:
325 return -1; /* error */
326 }
327 }
328
329
330
gl_alloc_texture_image(void)331 struct gl_texture_image *gl_alloc_texture_image( void )
332 {
333 return (struct gl_texture_image *) calloc( 1, sizeof(struct gl_texture_image) );
334 }
335
336
337
gl_free_texture_image(struct gl_texture_image * teximage)338 void gl_free_texture_image( struct gl_texture_image *teximage )
339 {
340 if (teximage->Data) {
341 free( teximage->Data );
342 }
343 free( teximage );
344 }
345
346
347
348 /*
349 * Given a gl_image, apply the pixel transfer scale, bias, and mapping
350 * to produce a gl_texture_image. Convert image data to GLubytes.
351 * Input: image - the incoming gl_image
352 * internalFormat - desired format of resultant texture
353 * border - texture border width (0 or 1)
354 * Return: pointer to a gl_texture_image or NULL if an error occurs.
355 */
356 static struct gl_texture_image *
image_to_texture(GLcontext * ctx,const struct gl_image * image,GLenum internalFormat,GLint border)357 image_to_texture( GLcontext *ctx, const struct gl_image *image,
358 GLenum internalFormat, GLint border )
359 {
360 GLint components;
361 struct gl_texture_image *texImage;
362 GLint numPixels, pixel;
363 GLboolean scaleOrBias;
364
365 assert(image);
366 assert(image->Width>0);
367 assert(image->Height>0);
368
369 /* internalFormat = decode_internal_format(internalFormat);*/
370 components = components_in_intformat(internalFormat);
371 numPixels = image->Width * image->Height;
372
373 texImage = gl_alloc_texture_image();
374 if (!texImage)
375 return NULL;
376
377 texImage->Format = decode_internal_format(internalFormat);
378 texImage->IntFormat = internalFormat;
379 texImage->Border = border;
380 texImage->Width = image->Width;
381 texImage->Height = image->Height;
382 texImage->WidthLog2 = logbase2(image->Width - 2*border);
383 if (image->Height==1) /* 1-D texture */
384 texImage->HeightLog2 = 0;
385 else
386 texImage->HeightLog2 = logbase2(image->Height - 2*border);
387 texImage->Width2 = 1 << texImage->WidthLog2;
388 texImage->Height2 = 1 << texImage->HeightLog2;
389 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
390 texImage->Data = (GLubyte *) malloc( numPixels * components );
391
392 assert(texImage->WidthLog2>=0);
393 assert(texImage->HeightLog2>=0);
394
395 if (!texImage->Data) {
396 /* out of memory */
397 gl_free_texture_image( texImage );
398 return NULL;
399 }
400
401 /* Determine if scaling and/or biasing is needed */
402 if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F ||
403 ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F ||
404 ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F ||
405 ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) {
406 scaleOrBias = GL_TRUE;
407 }
408 else {
409 scaleOrBias = GL_FALSE;
410 }
411
412 switch (image->Type) {
413 case GL_BITMAP:
414 {
415 GLint shift = ctx->Pixel.IndexShift;
416 GLint offset = ctx->Pixel.IndexOffset;
417 /* MapIto[RGBA]Size must be powers of two */
418 GLint rMask = ctx->Pixel.MapItoRsize-1;
419 GLint gMask = ctx->Pixel.MapItoGsize-1;
420 GLint bMask = ctx->Pixel.MapItoBsize-1;
421 GLint aMask = ctx->Pixel.MapItoAsize-1;
422 GLint i, j;
423 GLubyte *srcPtr = (GLubyte *) image->Data;
424
425 assert( image->Format==GL_COLOR_INDEX );
426
427 for (j=0; j<image->Height; j++) {
428 GLubyte bitMask = 128;
429 for (i=0; i<image->Width; i++) {
430 GLint index;
431 GLubyte red, green, blue, alpha;
432
433 /* Fetch image color index */
434 index = (*srcPtr & bitMask) ? 1 : 0;
435 bitMask = bitMask >> 1;
436 if (bitMask==0) {
437 bitMask = 128;
438 srcPtr++;
439 }
440 /* apply index shift and offset */
441 if (shift>=0) {
442 index = (index << shift) + offset;
443 }
444 else {
445 index = (index >> -shift) + offset;
446 }
447 /* convert index to RGBA */
448 red = (GLint) (ctx->Pixel.MapItoR[index & rMask] * 255.0F);
449 green = (GLint) (ctx->Pixel.MapItoG[index & gMask] * 255.0F);
450 blue = (GLint) (ctx->Pixel.MapItoB[index & bMask] * 255.0F);
451 alpha = (GLint) (ctx->Pixel.MapItoA[index & aMask] * 255.0F);
452
453 /* store texel (components are GLubytes in [0,255]) */
454 pixel = j * image->Width + i;
455 switch (texImage->Format) {
456 case GL_ALPHA:
457 texImage->Data[pixel] = alpha;
458 break;
459 case GL_LUMINANCE:
460 texImage->Data[pixel] = red;
461 break;
462 case GL_LUMINANCE_ALPHA:
463 texImage->Data[pixel*2+0] = red;
464 texImage->Data[pixel*2+1] = alpha;
465 break;
466 case GL_INTENSITY:
467 texImage->Data[pixel] = red;
468 break;
469 case GL_RGB:
470 texImage->Data[pixel*3+0] = red;
471 texImage->Data[pixel*3+1] = green;
472 texImage->Data[pixel*3+2] = blue;
473 break;
474 case GL_RGBA:
475 texImage->Data[pixel*4+0] = red;
476 texImage->Data[pixel*4+1] = green;
477 texImage->Data[pixel*4+2] = blue;
478 texImage->Data[pixel*4+3] = alpha;
479 break;
480 default:
481 gl_problem(ctx,"Bad format in image_to_texture");
482 return NULL;
483 }
484 }
485 if (bitMask!=128) {
486 srcPtr++;
487 }
488 }
489 }
490 break;
491
492 case GL_UNSIGNED_BYTE:
493 for (pixel=0; pixel<numPixels; pixel++) {
494 GLubyte red, green, blue, alpha;
495 switch (image->Format) {
496 case GL_COLOR_INDEX:
497 if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) {
498 /* a paletted texture */
499 GLint index = ((GLubyte*)image->Data)[pixel];
500 red = index;
501 }
502 else {
503 /* convert color index to RGBA */
504 GLint index = ((GLubyte*)image->Data)[pixel];
505 red = 255.0F * ctx->Pixel.MapItoR[index];
506 green = 255.0F * ctx->Pixel.MapItoG[index];
507 blue = 255.0F * ctx->Pixel.MapItoB[index];
508 alpha = 255.0F * ctx->Pixel.MapItoA[index];
509 }
510 break;
511 case GL_RGB:
512 /* Fetch image RGBA values */
513 red = ((GLubyte*) image->Data)[pixel*3+0];
514 green = ((GLubyte*) image->Data)[pixel*3+1];
515 blue = ((GLubyte*) image->Data)[pixel*3+2];
516 alpha = 255;
517 break;
518 case GL_BGR_EXT:
519 blue = ((GLubyte*) image->Data)[pixel*3+0];
520 green = ((GLubyte*) image->Data)[pixel*3+1];
521 red = ((GLubyte*) image->Data)[pixel*3+2];
522 alpha = 255;
523 break;
524 case GL_RGBA:
525 red = ((GLubyte*) image->Data)[pixel*4+0];
526 green = ((GLubyte*) image->Data)[pixel*4+1];
527 blue = ((GLubyte*) image->Data)[pixel*4+2];
528 alpha = ((GLubyte*) image->Data)[pixel*4+3];
529 break;
530 case GL_BGRA_EXT:
531 blue = ((GLubyte*) image->Data)[pixel*4+0];
532 green = ((GLubyte*) image->Data)[pixel*4+1];
533 red = ((GLubyte*) image->Data)[pixel*4+2];
534 alpha = ((GLubyte*) image->Data)[pixel*4+3];
535 break;
536 case GL_RED:
537 red = ((GLubyte*) image->Data)[pixel];
538 green = 0;
539 blue = 0;
540 alpha = 255;
541 break;
542 case GL_GREEN:
543 red = 0;
544 green = ((GLubyte*) image->Data)[pixel];
545 blue = 0;
546 alpha = 255;
547 break;
548 case GL_BLUE:
549 red = 0;
550 green = 0;
551 blue = ((GLubyte*) image->Data)[pixel];
552 alpha = 255;
553 break;
554 case GL_ALPHA:
555 red = 0;
556 green = 0;
557 blue = 0;
558 alpha = ((GLubyte*) image->Data)[pixel];
559 break;
560 case GL_LUMINANCE:
561 red = ((GLubyte*) image->Data)[pixel];
562 green = red;
563 blue = red;
564 alpha = 255;
565 break;
566 case GL_LUMINANCE_ALPHA:
567 red = ((GLubyte*) image->Data)[pixel*2+0];
568 green = red;
569 blue = red;
570 alpha = ((GLubyte*) image->Data)[pixel*2+1];
571 break;
572 default:
573 gl_problem(ctx,"Bad format (2) in image_to_texture");
574 return NULL;
575 }
576
577 if (scaleOrBias || ctx->Pixel.MapColorFlag) {
578 /* Apply RGBA scale and bias */
579 GLfloat r = red * (1.0F/255.0F);
580 GLfloat g = green * (1.0F/255.0F);
581 GLfloat b = blue * (1.0F/255.0F);
582 GLfloat a = alpha * (1.0F/255.0F);
583 if (scaleOrBias) {
584 /* r,g,b,a now in [0,1] */
585 r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
586 g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
587 b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
588 a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
589 r = CLAMP( r, 0.0F, 1.0F );
590 g = CLAMP( g, 0.0F, 1.0F );
591 b = CLAMP( b, 0.0F, 1.0F );
592 a = CLAMP( a, 0.0F, 1.0F );
593 }
594 /* Apply pixel maps */
595 if (ctx->Pixel.MapColorFlag) {
596 GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize);
597 GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize);
598 GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize);
599 GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize);
600 r = ctx->Pixel.MapRtoR[ir];
601 g = ctx->Pixel.MapGtoG[ig];
602 b = ctx->Pixel.MapBtoB[ib];
603 a = ctx->Pixel.MapAtoA[ia];
604 }
605 red = (GLint) (r * 255.0F);
606 green = (GLint) (g * 255.0F);
607 blue = (GLint) (b * 255.0F);
608 alpha = (GLint) (a * 255.0F);
609 }
610
611 /* store texel (components are GLubytes in [0,255]) */
612 switch (texImage->Format) {
613 case GL_COLOR_INDEX:
614 texImage->Data[pixel] = red; /* really an index */
615 break;
616 case GL_ALPHA:
617 texImage->Data[pixel] = alpha;
618 break;
619 case GL_LUMINANCE:
620 texImage->Data[pixel] = red;
621 break;
622 case GL_LUMINANCE_ALPHA:
623 texImage->Data[pixel*2+0] = red;
624 texImage->Data[pixel*2+1] = alpha;
625 break;
626 case GL_INTENSITY:
627 texImage->Data[pixel] = red;
628 break;
629 case GL_RGB:
630 texImage->Data[pixel*3+0] = red;
631 texImage->Data[pixel*3+1] = green;
632 texImage->Data[pixel*3+2] = blue;
633 break;
634 case GL_RGBA:
635 texImage->Data[pixel*4+0] = red;
636 texImage->Data[pixel*4+1] = green;
637 texImage->Data[pixel*4+2] = blue;
638 texImage->Data[pixel*4+3] = alpha;
639 break;
640 default:
641 gl_problem(ctx,"Bad format (3) in image_to_texture");
642 return NULL;
643 }
644 }
645 break;
646
647 case GL_FLOAT:
648 for (pixel=0; pixel<numPixels; pixel++) {
649 GLfloat red, green, blue, alpha;
650 switch (texImage->Format) {
651 case GL_COLOR_INDEX:
652 if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) {
653 /* a paletted texture */
654 GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
655 red = index;
656 }
657 else {
658 GLint shift = ctx->Pixel.IndexShift;
659 GLint offset = ctx->Pixel.IndexOffset;
660 /* MapIto[RGBA]Size must be powers of two */
661 GLint rMask = ctx->Pixel.MapItoRsize-1;
662 GLint gMask = ctx->Pixel.MapItoGsize-1;
663 GLint bMask = ctx->Pixel.MapItoBsize-1;
664 GLint aMask = ctx->Pixel.MapItoAsize-1;
665 /* Fetch image color index */
666 GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
667 /* apply index shift and offset */
668 if (shift>=0) {
669 index = (index << shift) + offset;
670 }
671 else {
672 index = (index >> -shift) + offset;
673 }
674 /* convert index to RGBA */
675 red = ctx->Pixel.MapItoR[index & rMask];
676 green = ctx->Pixel.MapItoG[index & gMask];
677 blue = ctx->Pixel.MapItoB[index & bMask];
678 alpha = ctx->Pixel.MapItoA[index & aMask];
679 }
680 break;
681 case GL_RGB:
682 /* Fetch image RGBA values */
683 red = ((GLfloat*) image->Data)[pixel*3+0];
684 green = ((GLfloat*) image->Data)[pixel*3+1];
685 blue = ((GLfloat*) image->Data)[pixel*3+2];
686 alpha = 1.0;
687 break;
688 case GL_RGBA:
689 red = ((GLfloat*) image->Data)[pixel*4+0];
690 green = ((GLfloat*) image->Data)[pixel*4+1];
691 blue = ((GLfloat*) image->Data)[pixel*4+2];
692 alpha = ((GLfloat*) image->Data)[pixel*4+3];
693 break;
694 case GL_RED:
695 red = ((GLfloat*) image->Data)[pixel];
696 green = 0.0;
697 blue = 0.0;
698 alpha = 1.0;
699 break;
700 case GL_GREEN:
701 red = 0.0;
702 green = ((GLfloat*) image->Data)[pixel];
703 blue = 0.0;
704 alpha = 1.0;
705 break;
706 case GL_BLUE:
707 red = 0.0;
708 green = 0.0;
709 blue = ((GLfloat*) image->Data)[pixel];
710 alpha = 1.0;
711 break;
712 case GL_ALPHA:
713 red = 0.0;
714 green = 0.0;
715 blue = 0.0;
716 alpha = ((GLfloat*) image->Data)[pixel];
717 break;
718 case GL_LUMINANCE:
719 red = ((GLfloat*) image->Data)[pixel];
720 green = red;
721 blue = red;
722 alpha = 1.0;
723 break;
724 case GL_LUMINANCE_ALPHA:
725 red = ((GLfloat*) image->Data)[pixel*2+0];
726 green = red;
727 blue = red;
728 alpha = ((GLfloat*) image->Data)[pixel*2+1];
729 break;
730 default:
731 gl_problem(ctx,"Bad format (4) in image_to_texture");
732 return NULL;
733 }
734
735 if (image->Format!=GL_COLOR_INDEX) {
736 /* Apply RGBA scale and bias */
737 if (scaleOrBias) {
738 red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
739 green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
740 blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
741 alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
742 red = CLAMP( red, 0.0F, 1.0F );
743 green = CLAMP( green, 0.0F, 1.0F );
744 blue = CLAMP( blue, 0.0F, 1.0F );
745 alpha = CLAMP( alpha, 0.0F, 1.0F );
746 }
747 /* Apply pixel maps */
748 if (ctx->Pixel.MapColorFlag) {
749 GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize);
750 GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize);
751 GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize);
752 GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize);
753 red = ctx->Pixel.MapRtoR[ir];
754 green = ctx->Pixel.MapGtoG[ig];
755 blue = ctx->Pixel.MapBtoB[ib];
756 alpha = ctx->Pixel.MapAtoA[ia];
757 }
758 }
759
760 /* store texel (components are GLubytes in [0,255]) */
761 switch (texImage->Format) {
762 case GL_COLOR_INDEX:
763 /* a paletted texture */
764 texImage->Data[pixel] = (GLint) (red * 255.0F);
765 break;
766 case GL_ALPHA:
767 texImage->Data[pixel] = (GLint) (alpha * 255.0F);
768 break;
769 case GL_LUMINANCE:
770 texImage->Data[pixel] = (GLint) (red * 255.0F);
771 break;
772 case GL_LUMINANCE_ALPHA:
773 texImage->Data[pixel*2+0] = (GLint) (red * 255.0F);
774 texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F);
775 break;
776 case GL_INTENSITY:
777 texImage->Data[pixel] = (GLint) (red * 255.0F);
778 break;
779 case GL_RGB:
780 texImage->Data[pixel*3+0] = (GLint) (red * 255.0F);
781 texImage->Data[pixel*3+1] = (GLint) (green * 255.0F);
782 texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F);
783 break;
784 case GL_RGBA:
785 texImage->Data[pixel*4+0] = (GLint) (red * 255.0F);
786 texImage->Data[pixel*4+1] = (GLint) (green * 255.0F);
787 texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F);
788 texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F);
789 break;
790 default:
791 gl_problem(ctx,"Bad format (5) in image_to_texture");
792 return NULL;
793 }
794 }
795 break;
796
797 default:
798 gl_problem(ctx, "Bad image type in image_to_texture");
799 return NULL;
800 }
801
802 return texImage;
803 }
804
805
806
807 /*
808 * glTexImage[123]D can accept a NULL image pointer. In this case we
809 * create a texture image with unspecified image contents per the OpenGL
810 * spec.
811 */
812 static struct gl_texture_image *
make_null_texture(GLcontext * ctx,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border)813 make_null_texture( GLcontext *ctx, GLenum internalFormat,
814 GLsizei width, GLsizei height, GLsizei depth, GLint border )
815 {
816 GLint components;
817 struct gl_texture_image *texImage;
818 GLint numPixels;
819
820 /*internalFormat = decode_internal_format(internalFormat);*/
821 components = components_in_intformat(internalFormat);
822 numPixels = width * height * depth;
823
824 texImage = gl_alloc_texture_image();
825 if (!texImage)
826 return NULL;
827
828 texImage->Format = decode_internal_format(internalFormat);
829 texImage->IntFormat = internalFormat;
830 texImage->Border = border;
831 texImage->Width = width;
832 texImage->Height = height;
833 texImage->WidthLog2 = logbase2(width - 2*border);
834 if (height==1) /* 1-D texture */
835 texImage->HeightLog2 = 0;
836 else
837 texImage->HeightLog2 = logbase2(height - 2*border);
838 texImage->Width2 = 1 << texImage->WidthLog2;
839 texImage->Height2 = 1 << texImage->HeightLog2;
840 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
841
842 /* XXX should we really allocate memory for the image or let it be NULL? */
843 /*texImage->Data = NULL;*/
844
845 texImage->Data = (GLubyte *) malloc( numPixels * components );
846
847 /*
848 * Let's see if anyone finds this. If glTexImage2D() is called with
849 * a NULL image pointer then load the texture image with something
850 * interesting instead of leaving it indeterminate.
851 */
852 if (texImage->Data) {
853 char message[8][32] = {
854 " X X XXXXX XXX X ",
855 " XX XX X X X X X ",
856 " X X X X X X X ",
857 " X X XXXX XXX XXXXX ",
858 " X X X X X X ",
859 " X X X X X X X ",
860 " X X XXXXX XXX X X ",
861 " "
862 };
863
864 GLubyte *imgPtr = texImage->Data;
865 GLint i, j, k;
866 for (i=0;i<height;i++) {
867 GLint srcRow = 7 - i % 8;
868 for (j=0;j<width;j++) {
869 GLint srcCol = j % 32;
870 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
871 for (k=0;k<components;k++) {
872 *imgPtr++ = texel;
873 }
874 }
875 }
876 }
877
878 return texImage;
879 }
880
881
882
883
884 /*
885 * Test glTexImagee1D() parameters for errors.
886 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
887 */
texture_1d_error_check(GLcontext * ctx,GLenum target,GLint level,GLenum internalFormat,GLenum format,GLenum type,GLint width,GLint border)888 static GLboolean texture_1d_error_check( GLcontext *ctx, GLenum target,
889 GLint level, GLenum internalFormat,
890 GLenum format, GLenum type,
891 GLint width, GLint border )
892 {
893 GLint iformat;
894 if (target!=GL_TEXTURE_1D && target!=GL_PROXY_TEXTURE_1D) {
895 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D" );
896 return GL_TRUE;
897 }
898 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
899 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" );
900 return GL_TRUE;
901 }
902 iformat = decode_internal_format( internalFormat );
903 if (iformat<0) {
904 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" );
905 return GL_TRUE;
906 }
907 if (border!=0 && border!=1) {
908 if (target!=GL_PROXY_TEXTURE_1D) {
909 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" );
910 }
911 return GL_TRUE;
912 }
913 if (width<2*border || width>2+MAX_TEXTURE_SIZE) {
914 if (target!=GL_PROXY_TEXTURE_1D) {
915 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" );
916 }
917 return GL_TRUE;
918 }
919 if (logbase2( width-2*border )<0) {
920 gl_error( ctx, GL_INVALID_VALUE,
921 "glTexImage1D(width != 2^k + 2*border)");
922 return GL_TRUE;
923 }
924 switch (format) {
925 case GL_COLOR_INDEX:
926 case GL_RED:
927 case GL_GREEN:
928 case GL_BLUE:
929 case GL_ALPHA:
930 case GL_RGB:
931 case GL_BGR_EXT:
932 case GL_RGBA:
933 case GL_BGRA_EXT:
934 case GL_LUMINANCE:
935 case GL_LUMINANCE_ALPHA:
936 /* OK */
937 break;
938 default:
939 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(format)" );
940 return GL_TRUE;
941 }
942 switch (type) {
943 case GL_UNSIGNED_BYTE:
944 case GL_BYTE:
945 case GL_UNSIGNED_SHORT:
946 case GL_SHORT:
947 case GL_FLOAT:
948 /* OK */
949 break;
950 default:
951 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(type)" );
952 return GL_TRUE;
953 }
954 return GL_FALSE;
955 }
956
957
958 /*
959 * Test glTexImagee2D() parameters for errors.
960 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
961 */
texture_2d_error_check(GLcontext * ctx,GLenum target,GLint level,GLenum internalFormat,GLenum format,GLenum type,GLint width,GLint height,GLint border)962 static GLboolean texture_2d_error_check( GLcontext *ctx, GLenum target,
963 GLint level, GLenum internalFormat,
964 GLenum format, GLenum type,
965 GLint width, GLint height,
966 GLint border )
967 {
968 GLint iformat;
969 if (target!=GL_TEXTURE_2D && target!=GL_PROXY_TEXTURE_2D) {
970 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
971 return GL_TRUE;
972 }
973 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
974 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" );
975 return GL_TRUE;
976 }
977 iformat = decode_internal_format( internalFormat );
978 if (iformat<0) {
979 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" );
980 return GL_TRUE;
981 }
982 if (border!=0 && border!=1) {
983 if (target!=GL_PROXY_TEXTURE_2D) {
984 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" );
985 }
986 return GL_TRUE;
987 }
988 if (width<2*border || width>2+MAX_TEXTURE_SIZE) {
989 if (target!=GL_PROXY_TEXTURE_2D) {
990 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" );
991 }
992 return GL_TRUE;
993 }
994 if (height<2*border || height>2+MAX_TEXTURE_SIZE) {
995 if (target!=GL_PROXY_TEXTURE_2D) {
996 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" );
997 }
998 return GL_TRUE;
999 }
1000 if (logbase2( width-2*border )<0) {
1001 gl_error( ctx,GL_INVALID_VALUE,
1002 "glTexImage2D(width != 2^k + 2*border)");
1003 return GL_TRUE;
1004 }
1005 if (logbase2( height-2*border )<0) {
1006 gl_error( ctx,GL_INVALID_VALUE,
1007 "glTexImage2D(height != 2^k + 2*border)");
1008 return GL_TRUE;
1009 }
1010 switch (format) {
1011 case GL_COLOR_INDEX:
1012 case GL_RED:
1013 case GL_GREEN:
1014 case GL_BLUE:
1015 case GL_ALPHA:
1016 case GL_RGB:
1017 case GL_BGR_EXT:
1018 case GL_RGBA:
1019 case GL_BGRA_EXT:
1020 case GL_LUMINANCE:
1021 case GL_LUMINANCE_ALPHA:
1022 /* OK */
1023 break;
1024 default:
1025 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(format)" );
1026 return GL_TRUE;
1027 }
1028 switch (type) {
1029 case GL_UNSIGNED_BYTE:
1030 case GL_BYTE:
1031 case GL_UNSIGNED_SHORT:
1032 case GL_SHORT:
1033 case GL_UNSIGNED_INT:
1034 case GL_INT:
1035 case GL_FLOAT:
1036 /* OK */
1037 break;
1038 default:
1039 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(type)" );
1040 return GL_TRUE;
1041 }
1042 return GL_FALSE;
1043 }
1044
1045
1046 /*
1047 * Called from the API. Note that width includes the border.
1048 */
gl_TexImage1D(GLcontext * ctx,GLenum target,GLint level,GLint internalformat,GLsizei width,GLint border,GLenum format,GLenum type,struct gl_image * image)1049 void gl_TexImage1D( GLcontext *ctx,
1050 GLenum target, GLint level, GLint internalformat,
1051 GLsizei width, GLint border, GLenum format,
1052 GLenum type, struct gl_image *image )
1053 {
1054 if (INSIDE_BEGIN_END(ctx)) {
1055 gl_error( ctx, GL_INVALID_OPERATION, "glTexImage1D" );
1056 return;
1057 }
1058
1059 if (target==GL_TEXTURE_1D) {
1060 struct gl_texture_image *teximage;
1061 if (texture_1d_error_check( ctx, target, level, internalformat,
1062 format, type, width, border )) {
1063 /* error in texture image was detected */
1064 return;
1065 }
1066
1067 /* free current texture image, if any */
1068 if (ctx->Texture.Current1D->Image[level]) {
1069 gl_free_texture_image( ctx->Texture.Current1D->Image[level] );
1070 }
1071
1072 /* make new texture from source image */
1073 if (image) {
1074 teximage = image_to_texture(ctx, image, internalformat, border);
1075 }
1076 else {
1077 teximage = make_null_texture(ctx, internalformat,
1078 width, 1, 1, border);
1079 }
1080
1081 /* install new texture image */
1082 ctx->Texture.Current1D->Image[level] = teximage;
1083 ctx->Texture.Current1D->Dirty = GL_TRUE;
1084 ctx->Texture.AnyDirty = GL_TRUE;
1085 ctx->NewState |= NEW_TEXTURING;
1086
1087 /* free the source image */
1088 if (image && image->RefCount==0) {
1089 /* if RefCount>0 then image must be in a display list */
1090 gl_free_image(image);
1091 }
1092
1093 /* tell driver about change */
1094 if (ctx->Driver.TexImage) {
1095 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1096 ctx->Texture.Current1D,
1097 level, internalformat, teximage );
1098 }
1099 }
1100 else if (target==GL_PROXY_TEXTURE_1D) {
1101 /* Proxy texture: check for errors and update proxy state */
1102 if (texture_1d_error_check( ctx, target, level, internalformat,
1103 format, type, width, border )) {
1104 if (level>=0 && level<MAX_TEXTURE_LEVELS) {
1105 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1106 sizeof(struct gl_texture_image) );
1107 }
1108 }
1109 else {
1110 ctx->Texture.Proxy1D->Image[level]->Format = internalformat;
1111 ctx->Texture.Proxy1D->Image[level]->Border = border;
1112 ctx->Texture.Proxy1D->Image[level]->Width = width;
1113 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1114 }
1115 if (image && image->RefCount==0) {
1116 /* if RefCount>0 then image must be in a display list */
1117 gl_free_image(image);
1118 }
1119 }
1120 else {
1121 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1122 return;
1123 }
1124 }
1125
1126
1127
1128
1129 /*
1130 * Called by the API or display list executor.
1131 * Note that width and height include the border.
1132 */
gl_TexImage2D(GLcontext * ctx,GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,struct gl_image * image)1133 void gl_TexImage2D( GLcontext *ctx,
1134 GLenum target, GLint level, GLint internalformat,
1135 GLsizei width, GLsizei height, GLint border,
1136 GLenum format, GLenum type,
1137 struct gl_image *image )
1138 {
1139 if (INSIDE_BEGIN_END(ctx)) {
1140 gl_error( ctx, GL_INVALID_OPERATION, "glTexImage2D" );
1141 return;
1142 }
1143
1144 if (target==GL_TEXTURE_2D) {
1145 struct gl_texture_image *teximage;
1146 if (texture_2d_error_check( ctx, target, level, internalformat,
1147 format, type, width, height, border )) {
1148 /* error in texture image was detected */
1149 return;
1150 }
1151
1152 /* free current texture image, if any */
1153 if (ctx->Texture.Current2D->Image[level]) {
1154 gl_free_texture_image( ctx->Texture.Current2D->Image[level] );
1155 }
1156
1157 /* make new texture from source image */
1158 if (image) {
1159 teximage = image_to_texture(ctx, image, internalformat, border);
1160 }
1161 else {
1162 teximage = make_null_texture(ctx, internalformat,
1163 width, height, 1, border);
1164 }
1165
1166 /* install new texture image */
1167 ctx->Texture.Current2D->Image[level] = teximage;
1168 ctx->Texture.Current2D->Dirty = GL_TRUE;
1169 ctx->Texture.AnyDirty = GL_TRUE;
1170 ctx->NewState |= NEW_TEXTURING;
1171
1172 /* free the source image */
1173 if (image && image->RefCount==0) {
1174 /* if RefCount>0 then image must be in a display list */
1175 gl_free_image(image);
1176 }
1177
1178 /* tell driver about change */
1179 if (ctx->Driver.TexImage) {
1180 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
1181 ctx->Texture.Current2D,
1182 level, internalformat, teximage );
1183 }
1184 }
1185 else if (target==GL_PROXY_TEXTURE_2D) {
1186 /* Proxy texture: check for errors and update proxy state */
1187 if (texture_2d_error_check( ctx, target, level, internalformat,
1188 format, type, width, height, border )) {
1189 if (level>=0 && level<MAX_TEXTURE_LEVELS) {
1190 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1191 sizeof(struct gl_texture_image) );
1192 }
1193 }
1194 else {
1195 ctx->Texture.Proxy2D->Image[level]->Format = internalformat;
1196 ctx->Texture.Proxy2D->Image[level]->Border = border;
1197 ctx->Texture.Proxy2D->Image[level]->Width = width;
1198 ctx->Texture.Proxy2D->Image[level]->Height = height;
1199 }
1200 if (image && image->RefCount==0) {
1201 /* if RefCount>0 then image must be in a display list */
1202 gl_free_image(image);
1203 }
1204 }
1205 else {
1206 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1207 return;
1208 }
1209 }
1210
1211
1212
gl_GetTexImage(GLcontext * ctx,GLenum target,GLint level,GLenum format,GLenum type,GLvoid * pixels)1213 void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format,
1214 GLenum type, GLvoid *pixels )
1215 {
1216 gl_problem(ctx, "glGetTexImage not implemented");
1217 /* TODO */
1218 }
1219
1220
1221
1222
1223 /*
1224 * Unpack the image data given to glTexSubImage[123]D.
1225 * This function is just a wrapper for gl_unpack_image() but it does
1226 * some extra error checking.
1227 */
1228 struct gl_image *
gl_unpack_texsubimage(GLcontext * ctx,GLint width,GLint height,GLenum format,GLenum type,const GLvoid * pixels)1229 gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height,
1230 GLenum format, GLenum type, const GLvoid *pixels )
1231 {
1232 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1233 return NULL;
1234 }
1235
1236 if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){
1237 return NULL;
1238 }
1239
1240 if (gl_sizeof_type(type)<=0) {
1241 return NULL;
1242 }
1243
1244 return gl_unpack_image( ctx, width, height, format, type, pixels );
1245 }
1246
1247
1248
gl_TexSubImage1D(GLcontext * ctx,GLenum target,GLint level,GLint xoffset,GLsizei width,GLenum format,GLenum type,struct gl_image * image)1249 void gl_TexSubImage1D( GLcontext *ctx,
1250 GLenum target, GLint level, GLint xoffset,
1251 GLsizei width, GLenum format, GLenum type,
1252 struct gl_image *image )
1253 {
1254 struct gl_texture_image *destTex;
1255
1256 if (target!=GL_TEXTURE_1D) {
1257 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1258 return;
1259 }
1260 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1261 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" );
1262 return;
1263 }
1264
1265 destTex = ctx->Texture.Current1D->Image[level];
1266 if (!destTex) {
1267 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" );
1268 return;
1269 }
1270
1271 if (xoffset < -((GLint)destTex->Border)) {
1272 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" );
1273 return;
1274 }
1275 if (xoffset + width > destTex->Width + destTex->Border) {
1276 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" );
1277 return;
1278 }
1279
1280 if (image) {
1281 /* unpacking must have been error-free */
1282 GLint texcomponents = components_in_intformat(destTex->Format);
1283
1284 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1285 /* Simple case, just byte copy image data into texture image */
1286 /* row by row. */
1287 GLubyte *dst = destTex->Data + texcomponents * xoffset;
1288 GLubyte *src = (GLubyte *) image->Data;
1289 MEMCPY( dst, src, width * texcomponents );
1290 }
1291 else {
1292 /* General case, convert image pixels into texels, scale, bias, etc */
1293 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1294 destTex->IntFormat, destTex->Border);
1295 GLubyte *dst = destTex->Data + texcomponents * xoffset;
1296 GLubyte *src = subTexImg->Data;
1297 MEMCPY( dst, src, width * texcomponents );
1298 gl_free_texture_image(subTexImg);
1299 }
1300
1301 /* if the image's reference count is zero, delete it now */
1302 if (image->RefCount==0) {
1303 gl_free_image(image);
1304 }
1305
1306 ctx->Texture.Current1D->Dirty = GL_TRUE;
1307 ctx->Texture.AnyDirty = GL_TRUE;
1308
1309 /* tell driver about change */
1310 if (ctx->Driver.TexSubImage) {
1311 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
1312 ctx->Texture.Current1D, level,
1313 xoffset,0,width,1,
1314 ctx->Texture.Current1D->Image[level]->IntFormat,
1315 destTex );
1316 }
1317 else {
1318 if (ctx->Driver.TexImage) {
1319 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1320 ctx->Texture.Current1D,
1321 level, ctx->Texture.Current1D->Image[level]->IntFormat,
1322 destTex );
1323 }
1324 }
1325 }
1326 else {
1327 /* if no image, an error must have occured, do more testing now */
1328 GLint components, size;
1329
1330 if (width<0) {
1331 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" );
1332 return;
1333 }
1334 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1335 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1336 return;
1337 }
1338 components = components_in_intformat( format );
1339 if (components<0 || format==GL_STENCIL_INDEX
1340 || format==GL_DEPTH_COMPONENT){
1341 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1342 return;
1343 }
1344 size = gl_sizeof_type( type );
1345 if (size<=0) {
1346 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" );
1347 return;
1348 }
1349 /* if we get here, probably ran out of memory during unpacking */
1350 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" );
1351 }
1352 }
1353
1354
1355
gl_TexSubImage2D(GLcontext * ctx,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,struct gl_image * image)1356 void gl_TexSubImage2D( GLcontext *ctx,
1357 GLenum target, GLint level,
1358 GLint xoffset, GLint yoffset,
1359 GLsizei width, GLsizei height,
1360 GLenum format, GLenum type,
1361 struct gl_image *image )
1362 {
1363 struct gl_texture_image *destTex;
1364
1365 if (target!=GL_TEXTURE_2D) {
1366 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1367 return;
1368 }
1369 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1370 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" );
1371 return;
1372 }
1373
1374 destTex = ctx->Texture.Current2D->Image[level];
1375 if (!destTex) {
1376 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" );
1377 return;
1378 }
1379
1380 if (xoffset < -((GLint)destTex->Border)) {
1381 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" );
1382 return;
1383 }
1384 if (yoffset < -((GLint)destTex->Border)) {
1385 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" );
1386 return;
1387 }
1388 if (xoffset + width > destTex->Width + destTex->Border) {
1389 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" );
1390 return;
1391 }
1392 if (yoffset + height > destTex->Height + destTex->Border) {
1393 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" );
1394 return;
1395 }
1396
1397 if (image) {
1398 /* unpacking must have been error-free */
1399 GLint texcomponents = components_in_intformat(destTex->Format);
1400
1401 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
1402 /* Simple case, just byte copy image data into texture image */
1403 /* row by row. */
1404 GLubyte *dst = destTex->Data
1405 + (yoffset * destTex->Width + xoffset) * texcomponents;
1406 GLubyte *src = (GLubyte *) image->Data;
1407 GLint j;
1408 for (j=0;j<height;j++) {
1409 MEMCPY( dst, src, width * texcomponents );
1410 dst += destTex->Width * texcomponents * sizeof(GLubyte);
1411 src += width * texcomponents * sizeof(GLubyte);
1412 }
1413 }
1414 else {
1415 /* General case, convert image pixels into texels, scale, bias, etc */
1416 struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
1417 destTex->IntFormat, destTex->Border);
1418 GLubyte *dst = destTex->Data
1419 + (yoffset * destTex->Width + xoffset) * texcomponents;
1420 GLubyte *src = subTexImg->Data;
1421 GLint j;
1422 for (j=0;j<height;j++) {
1423 MEMCPY( dst, src, width * texcomponents );
1424 dst += destTex->Width * texcomponents * sizeof(GLubyte);
1425 src += width * texcomponents * sizeof(GLubyte);
1426 }
1427 gl_free_texture_image(subTexImg);
1428 }
1429
1430 /* if the image's reference count is zero, delete it now */
1431 if (image->RefCount==0) {
1432 gl_free_image(image);
1433 }
1434
1435 ctx->Texture.Current2D->Dirty = GL_TRUE;
1436 ctx->Texture.AnyDirty = GL_TRUE;
1437
1438 /* tell driver about change */
1439 if (ctx->Driver.TexSubImage) {
1440 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, ctx->Texture.Current2D, level,
1441 xoffset, yoffset, width, height,
1442 ctx->Texture.Current2D->Image[level]->IntFormat,
1443 destTex );
1444 }
1445 else {
1446 if (ctx->Driver.TexImage) {
1447 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, ctx->Texture.Current2D,
1448 level, ctx->Texture.Current2D->Image[level]->IntFormat,
1449 destTex );
1450 }
1451 }
1452 }
1453 else {
1454 /* if no image, an error must have occured, do more testing now */
1455 GLint components, size;
1456
1457 if (width<0) {
1458 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" );
1459 return;
1460 }
1461 if (height<0) {
1462 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" );
1463 return;
1464 }
1465 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
1466 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
1467 return;
1468 }
1469 components = gl_components_in_format( format );
1470 if (components<0 || format==GL_STENCIL_INDEX
1471 || format==GL_DEPTH_COMPONENT){
1472 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" );
1473 return;
1474 }
1475 size = gl_sizeof_type( type );
1476 if (size<=0) {
1477 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" );
1478 return;
1479 }
1480 /* if we get here, probably ran out of memory during unpacking */
1481 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" );
1482 }
1483 }
1484
1485 /*
1486 * Read an RGBA image from the frame buffer.
1487 * Input: ctx - the context
1488 * x, y - lower left corner
1489 * width, height - size of region to read
1490 * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc.
1491 * Return: gl_image pointer or NULL if out of memory
1492 */
read_color_image(GLcontext * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLint format)1493 static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y,
1494 GLsizei width, GLsizei height,
1495 GLint format )
1496 {
1497 struct gl_image *image;
1498 GLubyte *imgptr;
1499 GLint components;
1500 GLint i, j;
1501
1502 components = components_in_intformat( format );
1503
1504 /*
1505 * Allocate image struct and image data buffer
1506 */
1507 image = (struct gl_image *) malloc( sizeof(struct gl_image) );
1508 if (image) {
1509 image->Width = width;
1510 image->Height = height;
1511 image->Components = components;
1512 image->Format = format;
1513 image->Type = GL_UNSIGNED_BYTE;
1514 image->RefCount = 0;
1515 image->Data = (GLubyte *) malloc( width * height * components );
1516 if (!image->Data) {
1517 free(image);
1518 return NULL;
1519 }
1520 }
1521 else {
1522 return NULL;
1523 }
1524
1525 imgptr = (GLubyte *) image->Data;
1526
1527 /* Select buffer to read from */
1528 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.ReadBuffer );
1529
1530 for (j=0;j<height;j++) {
1531 GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
1532 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
1533 gl_read_color_span( ctx, width, x, y+j, red, green, blue, alpha );
1534
1535 if (!ctx->Visual->EightBitColor) {
1536 /* scale red, green, blue, alpha values to range [0,255] */
1537 GLfloat rscale = 255.0f * ctx->Visual->InvRedScale;
1538 GLfloat gscale = 255.0f * ctx->Visual->InvGreenScale;
1539 GLfloat bscale = 255.0f * ctx->Visual->InvBlueScale;
1540 GLfloat ascale = 255.0f * ctx->Visual->InvAlphaScale;
1541 for (i=0;i<width;i++) {
1542 red[i] = (GLubyte) (GLint) (red[i] * rscale);
1543 green[i] = (GLubyte) (GLint) (green[i] * gscale);
1544 blue[i] = (GLubyte) (GLint) (blue[i] * bscale);
1545 alpha[i] = (GLubyte) (GLint) (alpha[i] * ascale);
1546 }
1547 }
1548
1549 switch (format) {
1550 case GL_ALPHA:
1551 for (i=0;i<width;i++) {
1552 *imgptr++ = alpha[i];
1553 }
1554 break;
1555 case GL_LUMINANCE:
1556 for (i=0;i<width;i++) {
1557 *imgptr++ = red[i];
1558 }
1559 break;
1560 case GL_LUMINANCE_ALPHA:
1561 for (i=0;i<width;i++) {
1562 *imgptr++ = red[i];
1563 *imgptr++ = alpha[i];
1564 }
1565 break;
1566 case GL_INTENSITY:
1567 for (i=0;i<width;i++) {
1568 *imgptr++ = red[i];
1569 }
1570 break;
1571 case GL_RGB:
1572 for (i=0;i<width;i++) {
1573 *imgptr++ = red[i];
1574 *imgptr++ = green[i];
1575 *imgptr++ = blue[i];
1576 }
1577 break;
1578 case GL_RGBA:
1579 for (i=0;i<width;i++) {
1580 *imgptr++ = red[i];
1581 *imgptr++ = green[i];
1582 *imgptr++ = blue[i];
1583 *imgptr++ = alpha[i];
1584 }
1585 break;
1586 } /*switch*/
1587
1588 } /*for*/
1589
1590 /* Restore drawing buffer */
1591 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DrawBuffer );
1592
1593 return image;
1594 }
1595
1596
1597
1598
gl_CopyTexImage1D(GLcontext * ctx,GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLint border)1599 void gl_CopyTexImage1D( GLcontext *ctx,
1600 GLenum target, GLint level,
1601 GLenum internalformat,
1602 GLint x, GLint y,
1603 GLsizei width, GLint border )
1604 {
1605 GLint format;
1606 struct gl_image *teximage;
1607
1608 if (INSIDE_BEGIN_END(ctx)) {
1609 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexImage1D" );
1610 return;
1611 }
1612 if (target!=GL_TEXTURE_1D) {
1613 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1614 return;
1615 }
1616 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1617 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" );
1618 return;
1619 }
1620 if (border!=0 && border!=1) {
1621 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" );
1622 return;
1623 }
1624 if (width<2*border || width>2+MAX_TEXTURE_SIZE || width<0) {
1625 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" );
1626 return;
1627 }
1628 format = decode_internal_format( internalformat );
1629 if (format<0 || (internalformat>=1 && internalformat<=4)) {
1630 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" );
1631 return;
1632 }
1633
1634 teximage = read_color_image( ctx, x, y, width, 1, format );
1635 if (!teximage) {
1636 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1637 return;
1638 }
1639
1640 gl_TexImage1D( ctx, target, level, internalformat, width,
1641 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
1642
1643 /* teximage was freed in gl_TexImage1D */
1644 }
1645
1646
1647
gl_CopyTexImage2D(GLcontext * ctx,GLenum target,GLint level,GLenum internalformat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)1648 void gl_CopyTexImage2D( GLcontext *ctx,
1649 GLenum target, GLint level, GLenum internalformat,
1650 GLint x, GLint y, GLsizei width, GLsizei height,
1651 GLint border )
1652 {
1653 GLint format;
1654 struct gl_image *teximage;
1655
1656 if (INSIDE_BEGIN_END(ctx)) {
1657 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexImage2D" );
1658 return;
1659 }
1660 if (target!=GL_TEXTURE_2D) {
1661 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1662 return;
1663 }
1664 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1665 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" );
1666 return;
1667 }
1668 if (border!=0 && border!=1) {
1669 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" );
1670 return;
1671 }
1672 if (width<2*border || width>2+MAX_TEXTURE_SIZE || width<0) {
1673 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" );
1674 return;
1675 }
1676 if (height<2*border || height>2+MAX_TEXTURE_SIZE || height<0) {
1677 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" );
1678 return;
1679 }
1680 format = decode_internal_format( internalformat );
1681 if (format<0 || (internalformat>=1 && internalformat<=4)) {
1682 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" );
1683 return;
1684 }
1685
1686 teximage = read_color_image( ctx, x, y, width, height, format );
1687 if (!teximage) {
1688 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1689 return;
1690 }
1691
1692 gl_TexImage2D( ctx, target, level, internalformat, width, height,
1693 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
1694
1695 /* teximage was freed in gl_TexImage2D */
1696 }
1697
1698
1699
1700
1701 /*
1702 * Do the work of glCopyTexSubImage[12]D.
1703 * TODO: apply pixel bias scale and mapping.
1704 */
copy_tex_sub_image(GLcontext * ctx,struct gl_texture_image * dest,GLint width,GLint height,GLint srcx,GLint srcy,GLint dstx,GLint dsty)1705 static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
1706 GLint width, GLint height,
1707 GLint srcx, GLint srcy,
1708 GLint dstx, GLint dsty)
1709 {
1710 GLint i, j;
1711 GLint format, components;
1712
1713 format = dest->Format;
1714 components = components_in_intformat( format );
1715
1716 for (j=0;j<height;j++) {
1717 GLubyte red[MAX_WIDTH], green[MAX_WIDTH];
1718 GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];
1719 GLubyte *texptr;
1720
1721 gl_read_color_span( ctx, width, srcx, srcy+j, red, green, blue, alpha );
1722
1723 if (!ctx->Visual->EightBitColor) {
1724 /* scale red, green, blue, alpha values to range [0,255] */
1725 GLfloat rscale = 255.0f * ctx->Visual->InvRedScale;
1726 GLfloat gscale = 255.0f * ctx->Visual->InvGreenScale;
1727 GLfloat bscale = 255.0f * ctx->Visual->InvBlueScale;
1728 GLfloat ascale = 255.0f * ctx->Visual->InvAlphaScale;
1729 for (i=0;i<width;i++) {
1730 red[i] = (GLubyte) (GLint) (red[i] * rscale);
1731 green[i] = (GLubyte) (GLint) (green[i] * gscale);
1732 blue[i] = (GLubyte) (GLint) (blue[i] * bscale);
1733 alpha[i] = (GLubyte) (GLint) (alpha[i] * ascale);
1734 }
1735 }
1736
1737 texptr = dest->Data + ( (dsty+j) * width + dstx) * components;
1738
1739 switch (format) {
1740 case GL_ALPHA:
1741 for (i=0;i<width;i++) {
1742 *texptr++ = alpha[i];
1743 }
1744 break;
1745 case GL_LUMINANCE:
1746 for (i=0;i<width;i++) {
1747 *texptr++ = red[i];
1748 }
1749 break;
1750 case GL_LUMINANCE_ALPHA:
1751 for (i=0;i<width;i++) {
1752 *texptr++ = red[i];
1753 *texptr++ = alpha[i];
1754 }
1755 break;
1756 case GL_INTENSITY:
1757 for (i=0;i<width;i++) {
1758 *texptr++ = red[i];
1759 }
1760 break;
1761 case GL_RGB:
1762 for (i=0;i<width;i++) {
1763 *texptr++ = red[i];
1764 *texptr++ = green[i];
1765 *texptr++ = blue[i];
1766 }
1767 break;
1768 case GL_RGBA:
1769 for (i=0;i<width;i++) {
1770 *texptr++ = red[i];
1771 *texptr++ = green[i];
1772 *texptr++ = blue[i];
1773 *texptr++ = alpha[i];
1774 }
1775 break;
1776 } /*switch*/
1777 } /*for*/
1778 }
1779
1780
1781
1782
gl_CopyTexSubImage1D(GLcontext * ctx,GLenum target,GLint level,GLint xoffset,GLint x,GLint y,GLsizei width)1783 void gl_CopyTexSubImage1D( GLcontext *ctx,
1784 GLenum target, GLint level,
1785 GLint xoffset, GLint x, GLint y, GLsizei width )
1786 {
1787 struct gl_texture_image *teximage;
1788
1789 if (INSIDE_BEGIN_END(ctx)) {
1790 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" );
1791 return;
1792 }
1793 if (target!=GL_TEXTURE_1D) {
1794 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1795 return;
1796 }
1797 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1798 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" );
1799 return;
1800 }
1801 if (width<0) {
1802 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" );
1803 return;
1804 }
1805
1806 teximage = ctx->Texture.Current1D->Image[level];
1807
1808 if (teximage) {
1809 if (xoffset < -((GLint)teximage->Border)) {
1810 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" );
1811 return;
1812 }
1813 /* NOTE: we're adding the border here, not subtracting! */
1814 if (xoffset+width > teximage->Width+teximage->Border) {
1815 gl_error( ctx, GL_INVALID_VALUE,
1816 "glCopyTexSubImage1D(xoffset+width)" );
1817 return;
1818 }
1819 if (teximage->Data) {
1820 copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0);
1821 }
1822 }
1823 else {
1824 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" );
1825 }
1826 }
1827
1828
1829
gl_CopyTexSubImage2D(GLcontext * ctx,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)1830 void gl_CopyTexSubImage2D( GLcontext *ctx,
1831 GLenum target, GLint level,
1832 GLint xoffset, GLint yoffset,
1833 GLint x, GLint y, GLsizei width, GLsizei height )
1834 {
1835 struct gl_texture_image *teximage;
1836
1837 if (INSIDE_BEGIN_END(ctx)) {
1838 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" );
1839 return;
1840 }
1841 if (target!=GL_TEXTURE_2D) {
1842 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1843 return;
1844 }
1845 if (level<0 || level>=MAX_TEXTURE_LEVELS) {
1846 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" );
1847 return;
1848 }
1849 if (width<0) {
1850 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" );
1851 return;
1852 }
1853 if (height<0) {
1854 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" );
1855 return;
1856 }
1857
1858 teximage = ctx->Texture.Current2D->Image[level];
1859
1860 if (teximage) {
1861 if (xoffset < -((GLint)teximage->Border)) {
1862 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" );
1863 return;
1864 }
1865 if (yoffset < -((GLint)teximage->Border)) {
1866 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" );
1867 return;
1868 }
1869 /* NOTE: we're adding the border here, not subtracting! */
1870 if (xoffset+width > teximage->Width+teximage->Border) {
1871 gl_error( ctx, GL_INVALID_VALUE,
1872 "glCopyTexSubImage2D(xoffset+width)" );
1873 return;
1874 }
1875 if (yoffset+height > teximage->Height+teximage->Border) {
1876 gl_error( ctx, GL_INVALID_VALUE,
1877 "glCopyTexSubImage2D(yoffset+height)" );
1878 return;
1879 }
1880
1881 if (teximage->Data) {
1882 copy_tex_sub_image( ctx, teximage, width, height,
1883 x, y, xoffset, yoffset);
1884 }
1885 }
1886 else {
1887 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" );
1888 }
1889 }
1890
1891