1 /* $Id: teximage.c,v 1.10 1999/11/05 06:43:11 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 #include "GL/xf86glx.h"
48 #include "GL/xf86glx.h"
56 * Mesa's native texture datatype is GLubyte. Native formats are
57 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
59 * Device drivers are free to implement any internal format they want.
64 static struct gl_pixelstore_attrib defaultPacking
= {
71 GL_FALSE
, /* SwapBytes */
72 GL_FALSE
/* LsbFirst */
78 * Compute log base 2 of n.
79 * If n isn't an exact power of two return -1.
82 static int logbase2( int n
)
106 * Given an internal texture format enum or 1, 2, 3, 4 return the
107 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
108 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
109 * Return -1 if invalid enum.
111 static GLint
decode_internal_format( GLint format
)
128 case GL_LUMINANCE_ALPHA
:
129 case GL_LUMINANCE4_ALPHA4
:
130 case GL_LUMINANCE6_ALPHA2
:
131 case GL_LUMINANCE8_ALPHA8
:
132 case GL_LUMINANCE12_ALPHA4
:
133 case GL_LUMINANCE12_ALPHA12
:
134 case GL_LUMINANCE16_ALPHA16
:
135 return GL_LUMINANCE_ALPHA
;
163 case GL_COLOR_INDEX1_EXT
:
164 case GL_COLOR_INDEX2_EXT
:
165 case GL_COLOR_INDEX4_EXT
:
166 case GL_COLOR_INDEX8_EXT
:
167 case GL_COLOR_INDEX12_EXT
:
168 case GL_COLOR_INDEX16_EXT
:
169 return GL_COLOR_INDEX
;
171 return -1; /* error */
178 * Given an internal texture format enum or 1, 2, 3, 4 return the
179 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
180 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
181 * number of components for the format. Return -1 if invalid enum.
183 static GLint
components_in_intformat( GLint format
)
200 case GL_LUMINANCE_ALPHA
:
201 case GL_LUMINANCE4_ALPHA4
:
202 case GL_LUMINANCE6_ALPHA2
:
203 case GL_LUMINANCE8_ALPHA8
:
204 case GL_LUMINANCE12_ALPHA4
:
205 case GL_LUMINANCE12_ALPHA12
:
206 case GL_LUMINANCE16_ALPHA16
:
235 case GL_COLOR_INDEX1_EXT
:
236 case GL_COLOR_INDEX2_EXT
:
237 case GL_COLOR_INDEX4_EXT
:
238 case GL_COLOR_INDEX8_EXT
:
239 case GL_COLOR_INDEX12_EXT
:
240 case GL_COLOR_INDEX16_EXT
:
243 return -1; /* error */
249 struct gl_texture_image
*gl_alloc_texture_image( void )
251 return CALLOC_STRUCT(gl_texture_image
);
256 void gl_free_texture_image( struct gl_texture_image
*teximage
)
258 if (teximage
->Data
) {
259 FREE( teximage
->Data
);
260 teximage
->Data
= NULL
;
268 * Examine the texImage->Format field and set the Red, Green, Blue, etc
269 * texel component sizes to default values.
270 * These fields are set only here by core Mesa but device drivers may
271 * overwritting these fields to indicate true texel resolution.
273 static void set_teximage_component_sizes( struct gl_texture_image
*texImage
)
275 switch (texImage
->Format
) {
277 texImage
->RedBits
= 0;
278 texImage
->GreenBits
= 0;
279 texImage
->BlueBits
= 0;
280 texImage
->AlphaBits
= 8;
281 texImage
->IntensityBits
= 0;
282 texImage
->LuminanceBits
= 0;
283 texImage
->IndexBits
= 0;
286 texImage
->RedBits
= 0;
287 texImage
->GreenBits
= 0;
288 texImage
->BlueBits
= 0;
289 texImage
->AlphaBits
= 0;
290 texImage
->IntensityBits
= 0;
291 texImage
->LuminanceBits
= 8;
292 texImage
->IndexBits
= 0;
294 case GL_LUMINANCE_ALPHA
:
295 texImage
->RedBits
= 0;
296 texImage
->GreenBits
= 0;
297 texImage
->BlueBits
= 0;
298 texImage
->AlphaBits
= 8;
299 texImage
->IntensityBits
= 0;
300 texImage
->LuminanceBits
= 8;
301 texImage
->IndexBits
= 0;
304 texImage
->RedBits
= 0;
305 texImage
->GreenBits
= 0;
306 texImage
->BlueBits
= 0;
307 texImage
->AlphaBits
= 0;
308 texImage
->IntensityBits
= 8;
309 texImage
->LuminanceBits
= 0;
310 texImage
->IndexBits
= 0;
313 texImage
->RedBits
= 8;
314 texImage
->GreenBits
= 0;
315 texImage
->BlueBits
= 0;
316 texImage
->AlphaBits
= 0;
317 texImage
->IntensityBits
= 0;
318 texImage
->LuminanceBits
= 0;
319 texImage
->IndexBits
= 0;
322 texImage
->RedBits
= 0;
323 texImage
->GreenBits
= 8;
324 texImage
->BlueBits
= 0;
325 texImage
->AlphaBits
= 0;
326 texImage
->IntensityBits
= 0;
327 texImage
->LuminanceBits
= 0;
328 texImage
->IndexBits
= 0;
331 texImage
->RedBits
= 0;
332 texImage
->GreenBits
= 0;
333 texImage
->BlueBits
= 8;
334 texImage
->AlphaBits
= 0;
335 texImage
->IntensityBits
= 0;
336 texImage
->LuminanceBits
= 0;
337 texImage
->IndexBits
= 0;
341 texImage
->RedBits
= 8;
342 texImage
->GreenBits
= 8;
343 texImage
->BlueBits
= 8;
344 texImage
->AlphaBits
= 0;
345 texImage
->IntensityBits
= 0;
346 texImage
->LuminanceBits
= 0;
347 texImage
->IndexBits
= 0;
352 texImage
->RedBits
= 8;
353 texImage
->GreenBits
= 8;
354 texImage
->BlueBits
= 8;
355 texImage
->AlphaBits
= 8;
356 texImage
->IntensityBits
= 0;
357 texImage
->LuminanceBits
= 0;
358 texImage
->IndexBits
= 0;
361 texImage
->RedBits
= 0;
362 texImage
->GreenBits
= 0;
363 texImage
->BlueBits
= 0;
364 texImage
->AlphaBits
= 0;
365 texImage
->IntensityBits
= 0;
366 texImage
->LuminanceBits
= 0;
367 texImage
->IndexBits
= 8;
370 gl_problem(NULL
, "unexpected format in set_teximage_component_sizes");
375 /* Need this to prevent an out-of-bounds memory access when using
376 * X86 optimized code.
379 # define EXTRA_BYTE 1
381 # define EXTRA_BYTE 0
387 * This is called by glTexImage[123]D in order to build a gl_texture_image
388 * object given the client's parameters and image data.
390 * NOTES: Width, height and depth should include the border.
391 * All texture image parameters should have already been error checked.
393 static struct gl_texture_image
*
394 make_texture_image( GLcontext
*ctx
, GLint internalFormat
,
395 GLint width
, GLint height
, GLint depth
, GLint border
,
396 GLenum srcFormat
, GLenum srcType
, const GLvoid
*pixels
,
397 const struct gl_pixelstore_attrib
*unpacking
)
399 GLint components
, numPixels
;
400 struct gl_texture_image
*texImage
;
405 assert(border
== 0 || border
== 1);
411 * Allocate and initialize the texture_image struct
413 texImage
= gl_alloc_texture_image();
417 texImage
->Format
= (GLenum
) decode_internal_format(internalFormat
);
418 set_teximage_component_sizes( texImage
);
419 texImage
->IntFormat
= (GLenum
) internalFormat
;
420 texImage
->Border
= border
;
421 texImage
->Width
= width
;
422 texImage
->Height
= height
;
423 texImage
->Depth
= depth
;
424 texImage
->WidthLog2
= logbase2(width
- 2 * border
);
425 if (height
== 1) /* 1-D texture */
426 texImage
->HeightLog2
= 0;
428 texImage
->HeightLog2
= logbase2(height
- 2 * border
);
429 if (depth
== 1) /* 2-D texture */
430 texImage
->DepthLog2
= 0;
432 texImage
->DepthLog2
= logbase2(depth
- 2 * border
);
433 texImage
->Width2
= 1 << texImage
->WidthLog2
;
434 texImage
->Height2
= 1 << texImage
->HeightLog2
;
435 texImage
->Depth2
= 1 << texImage
->DepthLog2
;
436 texImage
->MaxLog2
= MAX2(texImage
->WidthLog2
, texImage
->HeightLog2
);
438 components
= components_in_intformat(internalFormat
);
439 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
441 texImage
->Data
= (GLubyte
*) MALLOC(numPixels
* components
+ EXTRA_BYTE
);
443 if (!texImage
->Data
) {
445 gl_free_texture_image(texImage
);
451 * OK, the texture image struct has been initialized and the texture
452 * image memory has been allocated.
453 * Now fill in the texture image from the source data.
454 * This includes applying the pixel transfer operations.
457 /* try common 2D texture cases first */
458 if (!ctx
->Pixel
.ScaleOrBiasRGBA
&& !ctx
->Pixel
.MapColorFlag
459 && !ctx
->Pixel
.IndexOffset
&& !ctx
->Pixel
.IndexShift
460 && srcType
== GL_UNSIGNED_BYTE
&& depth
== 1) {
462 if (srcFormat
== internalFormat
) {
463 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
464 * GL_LUMINANCE_ALPHA, etc. texture formats.
466 const GLubyte
*src
= gl_pixel_addr_in_image(unpacking
,
467 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
468 const GLubyte
*src1
= gl_pixel_addr_in_image(unpacking
,
469 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
470 const GLint srcStride
= src1
- src
;
471 GLubyte
*dst
= texImage
->Data
;
472 GLint dstBytesPerRow
= width
* components
* sizeof(GLubyte
);
473 if (srcStride
== dstBytesPerRow
) {
474 MEMCPY(dst
, src
, height
* dstBytesPerRow
);
478 for (i
= 0; i
< height
; i
++) {
479 MEMCPY(dst
, src
, dstBytesPerRow
);
481 dst
+= dstBytesPerRow
;
484 return texImage
; /* all done */
486 else if (srcFormat
== GL_RGBA
&& internalFormat
== GL_RGB
) {
487 /* commonly used by Quake */
488 const GLubyte
*src
= gl_pixel_addr_in_image(unpacking
,
489 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
490 const GLubyte
*src1
= gl_pixel_addr_in_image(unpacking
,
491 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
492 const GLint srcStride
= src1
- src
;
493 GLubyte
*dst
= texImage
->Data
;
495 for (i
= 0; i
< height
; i
++) {
496 const GLubyte
*s
= src
;
497 for (j
= 0; j
< width
; j
++) {
498 *dst
++ = *s
++; /*red*/
499 *dst
++ = *s
++; /*green*/
500 *dst
++ = *s
++; /*blue*/
505 return texImage
; /* all done */
511 * General case solutions
513 if (texImage
->Format
== GL_COLOR_INDEX
) {
514 /* color index texture */
515 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
516 const GLenum dstType
= GL_UNSIGNED_BYTE
;
517 GLubyte
*dest
= texImage
->Data
;
519 for (img
= 0; img
< depth
; img
++) {
520 for (row
= 0; row
< height
; row
++) {
521 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
522 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
523 _mesa_unpack_index_span(ctx
, width
, dstType
, dest
,
524 srcType
, source
, unpacking
, GL_TRUE
);
525 dest
+= destBytesPerRow
;
530 /* regular, color texture */
531 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
532 const GLenum dstFormat
= texImage
->Format
;
533 GLubyte
*dest
= texImage
->Data
;
535 for (img
= 0; img
< depth
; img
++) {
536 for (row
= 0; row
< height
; row
++) {
537 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
538 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
539 _mesa_unpack_ubyte_color_span(ctx
, width
, dstFormat
, dest
,
540 srcFormat
, srcType
, source
, unpacking
, GL_TRUE
);
541 dest
+= destBytesPerRow
;
546 return texImage
; /* All done! */
552 * glTexImage[123]D can accept a NULL image pointer. In this case we
553 * create a texture image with unspecified image contents per the OpenGL
556 static struct gl_texture_image
*
557 make_null_texture( GLcontext
*ctx
, GLenum internalFormat
,
558 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
)
561 struct gl_texture_image
*texImage
;
565 /*internalFormat = decode_internal_format(internalFormat);*/
566 components
= components_in_intformat(internalFormat
);
567 numPixels
= width
* height
* depth
;
569 texImage
= gl_alloc_texture_image();
573 texImage
->Format
= (GLenum
) decode_internal_format(internalFormat
);
574 set_teximage_component_sizes( texImage
);
575 texImage
->IntFormat
= internalFormat
;
576 texImage
->Border
= border
;
577 texImage
->Width
= width
;
578 texImage
->Height
= height
;
579 texImage
->Depth
= depth
;
580 texImage
->WidthLog2
= logbase2(width
- 2*border
);
581 if (height
==1) /* 1-D texture */
582 texImage
->HeightLog2
= 0;
584 texImage
->HeightLog2
= logbase2(height
- 2*border
);
585 if (depth
==1) /* 2-D texture */
586 texImage
->DepthLog2
= 0;
588 texImage
->DepthLog2
= logbase2(depth
- 2*border
);
589 texImage
->Width2
= 1 << texImage
->WidthLog2
;
590 texImage
->Height2
= 1 << texImage
->HeightLog2
;
591 texImage
->Depth2
= 1 << texImage
->DepthLog2
;
592 texImage
->MaxLog2
= MAX2( texImage
->WidthLog2
, texImage
->HeightLog2
);
594 /* XXX should we really allocate memory for the image or let it be NULL? */
595 /*texImage->Data = NULL;*/
597 texImage
->Data
= (GLubyte
*) MALLOC( numPixels
* components
+ EXTRA_BYTE
);
600 * Let's see if anyone finds this. If glTexImage2D() is called with
601 * a NULL image pointer then load the texture image with something
602 * interesting instead of leaving it indeterminate.
604 if (texImage
->Data
) {
605 char message
[8][32] = {
609 " X X XXXX XXX XXXXX ",
612 " X X XXXXX XXX X X ",
616 GLubyte
*imgPtr
= texImage
->Data
;
618 for (i
=0;i
<height
;i
++) {
619 GLint srcRow
= 7 - i
% 8;
620 for (j
=0;j
<width
;j
++) {
621 GLint srcCol
= j
% 32;
622 GLint texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
623 for (k
=0;k
<components
;k
++) {
624 *imgPtr
++ = (GLubyte
) texel
;
636 * Test glTexImage[123]D() parameters for errors.
638 * dimensions - must be 1 or 2 or 3
639 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
642 texture_error_check( GLcontext
*ctx
, GLenum target
,
643 GLint level
, GLint internalFormat
,
644 GLenum format
, GLenum type
,
646 GLint width
, GLint height
,
647 GLint depth
, GLint border
)
652 if (dimensions
== 1) {
653 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_1D
);
654 if (target
!= GL_TEXTURE_1D
&& !isProxy
) {
655 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
659 else if (dimensions
== 2) {
660 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_2D
);
661 if (target
!= GL_TEXTURE_2D
&& !isProxy
) {
662 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
666 else if (dimensions
== 3) {
667 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_3D
);
668 if (target
!= GL_TEXTURE_3D
&& !isProxy
) {
669 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
674 gl_problem( ctx
, "bad dims in texture_error_check" );
679 if (border
!=0 && border
!=1) {
682 sprintf(message
, "glTexImage%dD(border)", dimensions
);
683 gl_error(ctx
, GL_INVALID_VALUE
, message
);
689 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
690 || logbase2( width
- 2 * border
) < 0) {
693 sprintf(message
, "glTexImage%dD(width)", dimensions
);
694 gl_error(ctx
, GL_INVALID_VALUE
, message
);
700 if (dimensions
>= 2) {
701 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
702 || logbase2( height
- 2 * border
) < 0) {
705 sprintf(message
, "glTexImage%dD(height)", dimensions
);
706 gl_error(ctx
, GL_INVALID_VALUE
, message
);
713 if (dimensions
>= 3) {
714 if (depth
< 2 * border
|| depth
> 2 + ctx
->Const
.MaxTextureSize
715 || logbase2( depth
- 2 * border
) < 0) {
717 gl_error( ctx
, GL_INVALID_VALUE
, "glTexImage3D(depth)" );
724 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
727 sprintf(message
, "glTexImage%dD(level)", dimensions
);
728 gl_error(ctx
, GL_INVALID_VALUE
, message
);
733 iformat
= decode_internal_format( internalFormat
);
737 sprintf(message
, "glTexImage%dD(internalFormat)", dimensions
);
738 gl_error(ctx
, GL_INVALID_VALUE
, message
);
743 if (!gl_is_legal_format_and_type( format
, type
)) {
744 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
745 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
749 sprintf(message
, "glTexImage%dD(format or type)", dimensions
);
750 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
755 /* if we get here, the parameters are OK */
762 * Test glTexSubImage[123]D() parameters for errors.
764 * dimensions - must be 1 or 2 or 3
765 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
768 subtexture_error_check( GLcontext
*ctx
, GLint dimensions
,
769 GLenum target
, GLint level
,
770 GLint xoffset
, GLint yoffset
, GLint zoffset
,
771 GLint width
, GLint height
, GLint depth
,
772 GLenum format
, GLenum type
)
774 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
775 struct gl_texture_image
*destTex
;
777 if (dimensions
== 1) {
778 if (target
!= GL_TEXTURE_1D
) {
779 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
783 else if (dimensions
== 2) {
784 if (target
!= GL_TEXTURE_2D
) {
785 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
789 else if (dimensions
== 3) {
790 if (target
!= GL_TEXTURE_3D
) {
791 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
796 gl_problem( ctx
, "bad dims in texture_error_check" );
800 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
801 gl_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level)");
807 sprintf(message
, "glTexSubImage%dD(width)", dimensions
);
808 gl_error(ctx
, GL_INVALID_VALUE
, message
);
811 if (height
< 0 && dimensions
> 1) {
813 sprintf(message
, "glTexSubImage%dD(height)", dimensions
);
814 gl_error(ctx
, GL_INVALID_VALUE
, message
);
817 if (depth
< 0 && dimensions
> 2) {
819 sprintf(message
, "glTexSubImage%dD(depth)", dimensions
);
820 gl_error(ctx
, GL_INVALID_VALUE
, message
);
824 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
826 gl_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage2D");
830 if (xoffset
< -((GLint
)destTex
->Border
)) {
831 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset)");
834 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
835 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset+width)");
838 if (dimensions
> 1) {
839 if (yoffset
< -((GLint
)destTex
->Border
)) {
840 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset)");
843 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
844 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset+height)");
848 if (dimensions
> 2) {
849 if (zoffset
< -((GLint
)destTex
->Border
)) {
850 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
853 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+destTex
->Border
)) {
854 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
859 if (!gl_is_legal_format_and_type(format
, type
)) {
861 sprintf(message
, "glTexSubImage%dD(format or type)", dimensions
);
862 gl_error(ctx
, GL_INVALID_ENUM
, message
);
871 * Test glCopyTexImage[12]D() parameters for errors.
872 * Input: dimensions - must be 1 or 2 or 3
873 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
876 copytexture_error_check( GLcontext
*ctx
, GLint dimensions
,
877 GLenum target
, GLint level
, GLint internalFormat
,
878 GLint width
, GLint height
, GLint border
)
882 if (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) {
883 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1/2D(target)" );
887 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
888 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
891 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
892 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
897 if (border
!=0 && border
!=1) {
899 sprintf(message
, "glCopyTexImage%dD(border)", dimensions
);
900 gl_error(ctx
, GL_INVALID_VALUE
, message
);
905 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
906 || logbase2( width
- 2 * border
) < 0) {
908 sprintf(message
, "glCopyTexImage%dD(width)", dimensions
);
909 gl_error(ctx
, GL_INVALID_VALUE
, message
);
914 if (dimensions
>= 2) {
915 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
916 || logbase2( height
- 2 * border
) < 0) {
918 sprintf(message
, "glCopyTexImage%dD(height)", dimensions
);
919 gl_error(ctx
, GL_INVALID_VALUE
, message
);
925 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
927 sprintf(message
, "glCopyTexImage%dD(level)", dimensions
);
928 gl_error(ctx
, GL_INVALID_VALUE
, message
);
932 iformat
= decode_internal_format( internalFormat
);
935 sprintf(message
, "glCopyTexImage%dD(internalFormat)", dimensions
);
936 gl_error(ctx
, GL_INVALID_VALUE
, message
);
940 /* if we get here, the parameters are OK */
946 copytexsubimage_error_check( GLcontext
*ctx
, GLint dimensions
,
947 GLenum target
, GLint level
,
948 GLint xoffset
, GLint yoffset
, GLint zoffset
,
949 GLsizei width
, GLsizei height
)
951 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
952 struct gl_texture_image
*teximage
;
954 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
955 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
958 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
959 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
962 else if (dimensions
== 3 && target
!= GL_TEXTURE_3D
) {
963 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
967 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
969 sprintf(message
, "glCopyTexSubImage%dD(level)", dimensions
);
970 gl_error(ctx
, GL_INVALID_VALUE
, message
);
976 sprintf(message
, "glCopyTexSubImage%dD(width)", dimensions
);
977 gl_error(ctx
, GL_INVALID_VALUE
, message
);
980 if (dimensions
> 1 && height
< 0) {
982 sprintf(message
, "glCopyTexSubImage%dD(height)", dimensions
);
983 gl_error(ctx
, GL_INVALID_VALUE
, message
);
987 teximage
= texUnit
->CurrentD
[dimensions
]->Image
[level
];
990 sprintf(message
, "glCopyTexSubImage%dD(undefined texture)", dimensions
);
991 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
995 if (xoffset
< -((GLint
)teximage
->Border
)) {
997 sprintf(message
, "glCopyTexSubImage%dD(xoffset)", dimensions
);
998 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1001 if (xoffset
+width
> (GLint
) (teximage
->Width
+teximage
->Border
)) {
1003 sprintf(message
, "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
1004 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1007 if (dimensions
> 1) {
1008 if (yoffset
< -((GLint
)teximage
->Border
)) {
1010 sprintf(message
, "glCopyTexSubImage%dD(yoffset)", dimensions
);
1011 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1014 /* NOTE: we're adding the border here, not subtracting! */
1015 if (yoffset
+height
> (GLint
) (teximage
->Height
+teximage
->Border
)) {
1017 sprintf(message
, "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1018 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1023 if (dimensions
> 2) {
1024 if (zoffset
< -((GLint
)teximage
->Border
)) {
1026 sprintf(message
, "glCopyTexSubImage%dD(zoffset)", dimensions
);
1027 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1030 if (zoffset
> (GLint
) (teximage
->Depth
+teximage
->Border
)) {
1032 sprintf(message
, "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1033 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1038 /* if we get here, the parameters are OK */
1046 * Called from the API. Note that width includes the border.
1048 void gl_TexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1049 GLint internalformat
,
1050 GLsizei width
, GLint border
, GLenum format
,
1051 GLenum type
, const GLvoid
*pixels
)
1053 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1054 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage1D");
1056 if (target
==GL_TEXTURE_1D
) {
1057 struct gl_texture_image
*teximage
;
1058 if (texture_error_check( ctx
, target
, level
, internalformat
,
1059 format
, type
, 1, width
, 1, 1, border
)) {
1060 /* error in texture image was detected */
1064 /* free current texture image, if any */
1065 if (texUnit
->CurrentD
[1]->Image
[level
]) {
1066 gl_free_texture_image( texUnit
->CurrentD
[1]->Image
[level
] );
1069 /* make new texture from source image */
1071 teximage
= make_texture_image(ctx
, internalformat
, width
, 1, 1,
1072 border
, format
, type
, pixels
, &ctx
->Unpack
);
1075 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1076 width
, 1, 1, border
);
1079 /* install new texture image */
1080 texUnit
->CurrentD
[1]->Image
[level
] = teximage
;
1081 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1082 ctx
->NewState
|= NEW_TEXTURING
;
1084 /* tell driver about change */
1085 if (ctx
->Driver
.TexImage
) {
1086 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1087 texUnit
->CurrentD
[1],
1088 level
, internalformat
, teximage
);
1091 else if (target
==GL_PROXY_TEXTURE_1D
) {
1092 /* Proxy texture: check for errors and update proxy state */
1093 if (texture_error_check( ctx
, target
, level
, internalformat
,
1094 format
, type
, 1, width
, 1, 1, border
)) {
1095 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1096 MEMSET( ctx
->Texture
.Proxy1D
->Image
[level
], 0,
1097 sizeof(struct gl_texture_image
) );
1101 ctx
->Texture
.Proxy1D
->Image
[level
]->Format
= (GLenum
) format
;
1102 set_teximage_component_sizes( ctx
->Texture
.Proxy1D
->Image
[level
] );
1103 ctx
->Texture
.Proxy1D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1104 ctx
->Texture
.Proxy1D
->Image
[level
]->Border
= border
;
1105 ctx
->Texture
.Proxy1D
->Image
[level
]->Width
= width
;
1106 ctx
->Texture
.Proxy1D
->Image
[level
]->Height
= 1;
1107 ctx
->Texture
.Proxy1D
->Image
[level
]->Depth
= 1;
1111 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1117 void gl_TexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1118 GLint internalformat
,
1119 GLsizei width
, GLsizei height
, GLint border
,
1120 GLenum format
, GLenum type
,
1121 const GLvoid
*pixels
)
1123 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1124 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage2D");
1126 if (target
==GL_TEXTURE_2D
) {
1127 struct gl_texture_image
*teximage
;
1128 if (texture_error_check( ctx
, target
, level
, internalformat
,
1129 format
, type
, 2, width
, height
, 1, border
)) {
1130 /* error in texture image was detected */
1134 /* free current texture image, if any */
1135 if (texUnit
->CurrentD
[2]->Image
[level
]) {
1136 gl_free_texture_image( texUnit
->CurrentD
[2]->Image
[level
] );
1139 /* make new texture from source image */
1141 teximage
= make_texture_image(ctx
, internalformat
, width
, height
, 1,
1142 border
, format
, type
, pixels
, &ctx
->Unpack
);
1145 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1146 width
, height
, 1, border
);
1149 /* install new texture image */
1150 texUnit
->CurrentD
[2]->Image
[level
] = teximage
;
1151 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1152 ctx
->NewState
|= NEW_TEXTURING
;
1154 /* tell driver about change */
1155 if (ctx
->Driver
.TexImage
) {
1156 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1157 texUnit
->CurrentD
[2],
1158 level
, internalformat
, teximage
);
1161 else if (target
==GL_PROXY_TEXTURE_2D
) {
1162 /* Proxy texture: check for errors and update proxy state */
1163 if (texture_error_check( ctx
, target
, level
, internalformat
,
1164 format
, type
, 2, width
, height
, 1, border
)) {
1165 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1166 MEMSET( ctx
->Texture
.Proxy2D
->Image
[level
], 0,
1167 sizeof(struct gl_texture_image
) );
1171 ctx
->Texture
.Proxy2D
->Image
[level
]->Format
= (GLenum
) format
;
1172 set_teximage_component_sizes( ctx
->Texture
.Proxy2D
->Image
[level
] );
1173 ctx
->Texture
.Proxy2D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1174 ctx
->Texture
.Proxy2D
->Image
[level
]->Border
= border
;
1175 ctx
->Texture
.Proxy2D
->Image
[level
]->Width
= width
;
1176 ctx
->Texture
.Proxy2D
->Image
[level
]->Height
= height
;
1177 ctx
->Texture
.Proxy2D
->Image
[level
]->Depth
= 1;
1181 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
1189 * Called by the API or display list executor.
1190 * Note that width and height include the border.
1192 void gl_TexImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
1193 GLint internalformat
,
1194 GLsizei width
, GLsizei height
, GLsizei depth
,
1195 GLint border
, GLenum format
, GLenum type
,
1196 const GLvoid
*pixels
)
1198 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1199 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage3D");
1201 if (target
==GL_TEXTURE_3D
) {
1202 struct gl_texture_image
*teximage
;
1203 if (texture_error_check( ctx
, target
, level
, internalformat
,
1204 format
, type
, 3, width
, height
, depth
,
1206 /* error in texture image was detected */
1210 /* free current texture image, if any */
1211 if (texUnit
->CurrentD
[3]->Image
[level
]) {
1212 gl_free_texture_image( texUnit
->CurrentD
[3]->Image
[level
] );
1215 /* make new texture from source image */
1217 teximage
= make_texture_image(ctx
, internalformat
, width
, height
,
1218 depth
, border
, format
, type
, pixels
, &ctx
->Unpack
);
1221 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1222 width
, height
, depth
, border
);
1225 /* install new texture image */
1226 texUnit
->CurrentD
[3]->Image
[level
] = teximage
;
1227 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[3] );
1228 ctx
->NewState
|= NEW_TEXTURING
;
1230 /* tell driver about change */
1231 if (ctx
->Driver
.TexImage
) {
1232 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D_EXT
,
1233 texUnit
->CurrentD
[3],
1234 level
, internalformat
, teximage
);
1237 else if (target
==GL_PROXY_TEXTURE_3D_EXT
) {
1238 /* Proxy texture: check for errors and update proxy state */
1239 if (texture_error_check( ctx
, target
, level
, internalformat
,
1240 format
, type
, 3, width
, height
, depth
,
1242 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1243 MEMSET( ctx
->Texture
.Proxy3D
->Image
[level
], 0,
1244 sizeof(struct gl_texture_image
) );
1248 ctx
->Texture
.Proxy3D
->Image
[level
]->Format
= (GLenum
) format
;
1249 set_teximage_component_sizes( ctx
->Texture
.Proxy3D
->Image
[level
] );
1250 ctx
->Texture
.Proxy3D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1251 ctx
->Texture
.Proxy3D
->Image
[level
]->Border
= border
;
1252 ctx
->Texture
.Proxy3D
->Image
[level
]->Width
= width
;
1253 ctx
->Texture
.Proxy3D
->Image
[level
]->Height
= height
;
1254 ctx
->Texture
.Proxy3D
->Image
[level
]->Depth
= depth
;
1258 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1265 void gl_GetTexImage( GLcontext
*ctx
, GLenum target
, GLint level
, GLenum format
,
1266 GLenum type
, GLvoid
*pixels
)
1268 const struct gl_texture_object
*texObj
;
1270 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetTexImage");
1272 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1273 gl_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1277 if (gl_sizeof_type(type
) <= 0) {
1278 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1282 if (gl_components_in_format(format
) <= 0) {
1283 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1288 return; /* XXX generate an error??? */
1292 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[1];
1295 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[2];
1298 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[3];
1301 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)" );
1305 if (texObj
->Image
[level
] && texObj
->Image
[level
]->Data
) {
1306 const struct gl_texture_image
*texImage
= texObj
->Image
[level
];
1307 GLint width
= texImage
->Width
;
1308 GLint height
= texImage
->Height
;
1311 for (row
= 0; row
< height
; row
++) {
1312 /* compute destination address in client memory */
1313 GLvoid
*dest
= gl_pixel_addr_in_image( &ctx
->Unpack
, pixels
,
1315 format
, type
, 0, row
, 0);
1318 if (texImage
->Format
== GL_RGBA
) {
1319 const GLubyte
*src
= texImage
->Data
+ row
* width
* 4 * sizeof(GLubyte
);
1320 gl_pack_rgba_span( ctx
, width
, (void *) src
, format
, type
, dest
,
1321 &ctx
->Pack
, GL_TRUE
);
1324 /* fetch RGBA row from texture image then pack it in client mem */
1325 GLubyte rgba
[MAX_WIDTH
][4];
1328 switch (texImage
->Format
) {
1330 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1331 for (i
= 0; i
< width
; i
++) {
1332 rgba
[i
][RCOMP
] = 255;
1333 rgba
[i
][GCOMP
] = 255;
1334 rgba
[i
][BCOMP
] = 255;
1335 rgba
[i
][ACOMP
] = src
[i
];
1339 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1340 for (i
= 0; i
< width
; i
++) {
1341 rgba
[i
][RCOMP
] = src
[i
];
1342 rgba
[i
][GCOMP
] = src
[i
];
1343 rgba
[i
][BCOMP
] = src
[i
];
1344 rgba
[i
][ACOMP
] = 255;
1347 case GL_LUMINANCE_ALPHA
:
1348 src
= texImage
->Data
+ row
* 2 * width
* sizeof(GLubyte
);
1349 for (i
= 0; i
< width
; i
++) {
1350 rgba
[i
][RCOMP
] = src
[i
*2+0];
1351 rgba
[i
][GCOMP
] = src
[i
*2+0];
1352 rgba
[i
][BCOMP
] = src
[i
*2+0];
1353 rgba
[i
][ACOMP
] = src
[i
*2+1];
1357 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1358 for (i
= 0; i
< width
; i
++) {
1359 rgba
[i
][RCOMP
] = src
[i
];
1360 rgba
[i
][GCOMP
] = src
[i
];
1361 rgba
[i
][BCOMP
] = src
[i
];
1362 rgba
[i
][ACOMP
] = 255;
1366 src
= texImage
->Data
+ row
* 3 * width
* sizeof(GLubyte
);
1367 for (i
= 0; i
< width
; i
++) {
1368 rgba
[i
][RCOMP
] = src
[i
*3+0];
1369 rgba
[i
][GCOMP
] = src
[i
*3+1];
1370 rgba
[i
][BCOMP
] = src
[i
*3+2];
1371 rgba
[i
][ACOMP
] = 255;
1375 /* this special case should have been handled above! */
1376 gl_problem( ctx
, "error 1 in gl_GetTexImage" );
1378 case GL_COLOR_INDEX
:
1379 gl_problem( ctx
, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1382 gl_problem( ctx
, "bad format in gl_GetTexImage" );
1384 gl_pack_rgba_span( ctx
, width
, (const GLubyte (*)[4])rgba
,
1385 format
, type
, dest
, &ctx
->Pack
, GL_TRUE
);
1393 void gl_TexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1394 GLint xoffset
, GLsizei width
,
1395 GLenum format
, GLenum type
,
1396 const GLvoid
*pixels
)
1398 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1399 struct gl_texture_image
*destTex
;
1401 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
1402 width
, 1, 1, format
, type
)) {
1403 /* error was detected */
1407 destTex
= texUnit
->CurrentD
[1]->Image
[level
];
1410 if (width
== 0 || !pixels
)
1411 return; /* no-op, not an error */
1415 * Replace the texture subimage
1418 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1419 const GLenum texFormat
= destTex
->Format
;
1420 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1421 GLubyte
*dst
= destTex
->Data
+ xoffsetb
* texComponents
;
1422 if (texFormat
== GL_COLOR_INDEX
) {
1423 /* color index texture */
1424 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1425 width
, 1, format
, type
, 0, 0, 0);
1426 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1427 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1431 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1432 width
, 1, format
, type
, 0, 0, 0);
1433 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1434 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1438 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1441 * Inform device driver of texture image change.
1443 if (ctx
->Driver
.TexSubImage
) {
1444 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1445 level
, xoffset
, 0, width
, 1,
1446 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1450 if (ctx
->Driver
.TexImage
) {
1451 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1453 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1460 void gl_TexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1461 GLint xoffset
, GLint yoffset
,
1462 GLsizei width
, GLsizei height
,
1463 GLenum format
, GLenum type
,
1464 const GLvoid
*pixels
)
1466 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1467 struct gl_texture_image
*destTex
;
1469 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
1470 width
, height
, 1, format
, type
)) {
1471 /* error was detected */
1475 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
1478 if (width
== 0 || height
== 0 || !pixels
)
1479 return; /* no-op, not an error */
1483 * Replace the texture subimage
1486 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1487 const GLenum texFormat
= destTex
->Format
;
1488 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1489 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1490 GLubyte
*dst
= destTex
->Data
1491 + (yoffsetb
* destTex
->Width
+ xoffsetb
) * texComponents
;
1492 if (texFormat
== GL_COLOR_INDEX
) {
1493 /* color index texture */
1494 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1496 for (row
= 0; row
< height
; row
++) {
1497 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1498 width
, height
, format
, type
, 0, row
, 0);
1499 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1500 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1506 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1508 for (row
= 0; row
< height
; row
++) {
1509 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1510 width
, height
, format
, type
, 0, row
, 0);
1511 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1512 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1518 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1521 * Inform device driver of texture image change.
1523 if (ctx
->Driver
.TexSubImage
) {
1524 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1525 level
, xoffset
, yoffset
, width
, height
,
1526 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1530 if (ctx
->Driver
.TexImage
) {
1531 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1533 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1541 void gl_TexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
1542 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1543 GLsizei width
, GLsizei height
, GLsizei depth
,
1544 GLenum format
, GLenum type
,
1545 const GLvoid
*pixels
)
1547 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1548 struct gl_texture_image
*destTex
;
1550 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
1551 width
, height
, depth
, format
, type
)) {
1552 /* error was detected */
1556 destTex
= texUnit
->CurrentD
[3]->Image
[level
];
1559 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
1560 return; /* no-op, not an error */
1563 * Replace the texture subimage
1566 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1567 const GLenum texFormat
= destTex
->Format
;
1568 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1569 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1570 const GLint zoffsetb
= zoffset
+ destTex
->Border
;
1571 GLint dstRectArea
= destTex
->Width
* destTex
->Height
;
1572 GLubyte
*dst
= destTex
->Data
1573 + (zoffsetb
* dstRectArea
+ yoffsetb
* destTex
->Width
+ xoffsetb
)
1576 if (texFormat
== GL_COLOR_INDEX
) {
1577 /* color index texture */
1578 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1580 for (img
= 0; img
< depth
; img
++) {
1581 for (row
= 0; row
< height
; row
++) {
1582 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1583 width
, height
, format
, type
, img
, row
, 0);
1584 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1585 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1592 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1594 for (img
= 0; img
< depth
; img
++) {
1595 for (row
= 0; row
< height
; row
++) {
1596 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1597 width
, height
, format
, type
, img
, row
, 0);
1598 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1599 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1606 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1609 * Inform device driver of texture image change.
1617 * Read an RGBA image from the frame buffer.
1618 * This is used by glCopyTexSubImage[12]D().
1619 * Input: ctx - the context
1620 * x, y - lower left corner
1621 * width, height - size of region to read
1622 * Return: pointer to block of GL_RGBA, GLubyte data.
1625 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
1626 GLsizei width
, GLsizei height
)
1629 GLubyte
*image
, *dst
;
1631 image
= MALLOC(width
* height
* 4 * sizeof(GLubyte
));
1635 /* Select buffer to read from */
1636 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Pixel
.DriverReadBuffer
);
1639 stride
= width
* 4 * sizeof(GLubyte
);
1640 for (i
= 0; i
< height
; i
++) {
1641 gl_read_rgba_span( ctx
, width
, x
, y
+ i
, (GLubyte (*)[4]) dst
);
1645 /* Restore drawing buffer */
1646 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
1653 void gl_CopyTexImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1654 GLenum internalFormat
,
1656 GLsizei width
, GLint border
)
1658 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage1D");
1660 if (!copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
1661 width
, 1, border
)) {
1662 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, 1 );
1664 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D" );
1667 (*ctx
->Exec
.TexImage1D
)( ctx
, target
, level
, internalFormat
, width
,
1668 border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1675 void gl_CopyTexImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1676 GLenum internalFormat
,
1677 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1680 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage2D");
1682 if (!copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
1683 width
, height
, border
)) {
1684 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, height
);
1686 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D" );
1690 struct gl_pixelstore_attrib save
= ctx
->Unpack
;
1691 ctx
->Unpack
= defaultPacking
;
1692 (ctx
->Exec
.TexImage2D
)( ctx
, target
, level
, internalFormat
, width
,
1693 height
, border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1694 ctx
->Unpack
= save
; /* restore */
1703 * Do the work of glCopyTexSubImage[123]D.
1706 copy_tex_sub_image( GLcontext
*ctx
, struct gl_texture_image
*dest
,
1707 GLint width
, GLint height
,
1708 GLint srcx
, GLint srcy
,
1709 GLint dstx
, GLint dsty
, GLint dstz
)
1711 static struct gl_pixelstore_attrib packing
= {
1716 0, /* ImageHeight */
1718 GL_FALSE
, /* SwapBytes */
1719 GL_FALSE
/* LsbFirst */
1723 GLint format
, components
, rectarea
;
1724 GLint texwidth
, texheight
, zoffset
;
1726 /* dst[xyz] may be negative if we have a texture border! */
1727 dstx
+= dest
->Border
;
1728 dsty
+= dest
->Border
;
1729 dstz
+= dest
->Border
;
1730 texwidth
= dest
->Width
;
1731 texheight
= dest
->Height
;
1732 rectarea
= texwidth
* texheight
;
1733 zoffset
= dstz
* rectarea
;
1734 format
= dest
->Format
;
1735 components
= components_in_intformat( format
);
1737 /* Select buffer to read from */
1738 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Pixel
.DriverReadBuffer
);
1740 for (i
= 0;i
< height
; i
++) {
1741 GLubyte rgba
[MAX_WIDTH
][4];
1743 gl_read_rgba_span( ctx
, width
, srcx
, srcy
+ i
, rgba
);
1744 dst
= dest
->Data
+ ( zoffset
+ (dsty
+i
) * texwidth
+ dstx
) * components
;
1745 _mesa_unpack_ubyte_color_span(ctx
, width
, format
, dst
,
1746 GL_RGBA
, GL_UNSIGNED_BYTE
, rgba
,
1750 /* Restore drawing buffer */
1751 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
1757 void gl_CopyTexSubImage1D( GLcontext
*ctx
, GLenum target
, GLint level
,
1758 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
1760 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage1D");
1762 if (!copytexsubimage_error_check(ctx
, 1, target
, level
,
1763 xoffset
, 0, 0, width
, 1)) {
1764 struct gl_texture_unit
*texUnit
;
1765 struct gl_texture_image
*teximage
;
1766 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1767 teximage
= texUnit
->CurrentD
[1]->Image
[level
];
1769 if (teximage
->Data
) {
1770 copy_tex_sub_image(ctx
, teximage
, width
, 1, x
, y
, xoffset
, 0, 0);
1771 /* tell driver about the change */
1772 if (ctx
->Driver
.TexImage
) {
1773 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1774 texUnit
->CurrentD
[1],
1775 level
, teximage
->IntFormat
, teximage
);
1783 void gl_CopyTexSubImage2D( GLcontext
*ctx
, GLenum target
, GLint level
,
1784 GLint xoffset
, GLint yoffset
,
1785 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1787 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage2D");
1789 if (!copytexsubimage_error_check(ctx
, 2, target
, level
,
1790 xoffset
, yoffset
, 0, width
, height
)) {
1791 struct gl_texture_unit
*texUnit
;
1792 struct gl_texture_image
*teximage
;
1793 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1794 teximage
= texUnit
->CurrentD
[2]->Image
[level
];
1796 if (teximage
->Data
) {
1797 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1798 x
, y
, xoffset
, yoffset
, 0);
1799 /* tell driver about the change */
1800 if (ctx
->Driver
.TexImage
) {
1801 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1802 texUnit
->CurrentD
[2],
1803 level
, teximage
->IntFormat
, teximage
);
1811 void gl_CopyTexSubImage3D( GLcontext
*ctx
, GLenum target
, GLint level
,
1812 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1813 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1815 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage3D");
1817 if (!copytexsubimage_error_check(ctx
, 3, target
, level
,
1818 xoffset
, yoffset
, zoffset
, width
, height
)) {
1819 struct gl_texture_unit
*texUnit
;
1820 struct gl_texture_image
*teximage
;
1821 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1822 teximage
= texUnit
->CurrentD
[3]->Image
[level
];
1824 if (teximage
->Data
) {
1825 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1826 x
, y
, xoffset
, yoffset
, zoffset
);
1827 /* tell driver about the change */
1828 if (ctx
->Driver
.TexImage
) {
1829 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D
,
1830 texUnit
->CurrentD
[3],
1831 level
, teximage
->IntFormat
, teximage
);