xref: /reactos/dll/opengl/mesa/teximage.c (revision 5f2bebf7)
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