1 /* $Id: teximage.c,v 1.21 2000/03/20 23:40:12 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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.
46 * Mesa's native texture datatype is GLubyte. Native formats are
47 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
49 * Device drivers are free to implement any internal format they want.
54 * Default pixel packing of Mesa's internal texture images:
56 static struct gl_pixelstore_attrib DefaultPacking
= {
63 GL_FALSE
, /* SwapBytes */
64 GL_FALSE
/* LsbFirst */
70 * Compute log base 2 of n.
71 * If n isn't an exact power of two return -1.
99 * Given an internal texture format enum or 1, 2, 3, 4 return the
100 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
101 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
102 * Return -1 if invalid enum.
105 decode_internal_format( GLint format
)
122 case GL_LUMINANCE_ALPHA
:
123 case GL_LUMINANCE4_ALPHA4
:
124 case GL_LUMINANCE6_ALPHA2
:
125 case GL_LUMINANCE8_ALPHA8
:
126 case GL_LUMINANCE12_ALPHA4
:
127 case GL_LUMINANCE12_ALPHA12
:
128 case GL_LUMINANCE16_ALPHA16
:
129 return GL_LUMINANCE_ALPHA
;
157 case GL_COLOR_INDEX1_EXT
:
158 case GL_COLOR_INDEX2_EXT
:
159 case GL_COLOR_INDEX4_EXT
:
160 case GL_COLOR_INDEX8_EXT
:
161 case GL_COLOR_INDEX12_EXT
:
162 case GL_COLOR_INDEX16_EXT
:
163 return GL_COLOR_INDEX
;
165 return -1; /* error */
172 * Given an internal texture format enum or 1, 2, 3, 4 return the
173 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
174 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
175 * number of components for the format. Return -1 if invalid enum.
178 components_in_intformat( GLint format
)
195 case GL_LUMINANCE_ALPHA
:
196 case GL_LUMINANCE4_ALPHA4
:
197 case GL_LUMINANCE6_ALPHA2
:
198 case GL_LUMINANCE8_ALPHA8
:
199 case GL_LUMINANCE12_ALPHA4
:
200 case GL_LUMINANCE12_ALPHA12
:
201 case GL_LUMINANCE16_ALPHA16
:
230 case GL_COLOR_INDEX1_EXT
:
231 case GL_COLOR_INDEX2_EXT
:
232 case GL_COLOR_INDEX4_EXT
:
233 case GL_COLOR_INDEX8_EXT
:
234 case GL_COLOR_INDEX12_EXT
:
235 case GL_COLOR_INDEX16_EXT
:
238 return -1; /* error */
245 * Examine the texImage->Format field and set the Red, Green, Blue, etc
246 * texel component sizes to default values.
247 * These fields are set only here by core Mesa but device drivers may
248 * overwritting these fields to indicate true texel resolution.
251 set_teximage_component_sizes( struct gl_texture_image
*texImage
)
253 switch (texImage
->Format
) {
255 texImage
->RedBits
= 0;
256 texImage
->GreenBits
= 0;
257 texImage
->BlueBits
= 0;
258 texImage
->AlphaBits
= 8;
259 texImage
->IntensityBits
= 0;
260 texImage
->LuminanceBits
= 0;
261 texImage
->IndexBits
= 0;
264 texImage
->RedBits
= 0;
265 texImage
->GreenBits
= 0;
266 texImage
->BlueBits
= 0;
267 texImage
->AlphaBits
= 0;
268 texImage
->IntensityBits
= 0;
269 texImage
->LuminanceBits
= 8;
270 texImage
->IndexBits
= 0;
272 case GL_LUMINANCE_ALPHA
:
273 texImage
->RedBits
= 0;
274 texImage
->GreenBits
= 0;
275 texImage
->BlueBits
= 0;
276 texImage
->AlphaBits
= 8;
277 texImage
->IntensityBits
= 0;
278 texImage
->LuminanceBits
= 8;
279 texImage
->IndexBits
= 0;
282 texImage
->RedBits
= 0;
283 texImage
->GreenBits
= 0;
284 texImage
->BlueBits
= 0;
285 texImage
->AlphaBits
= 0;
286 texImage
->IntensityBits
= 8;
287 texImage
->LuminanceBits
= 0;
288 texImage
->IndexBits
= 0;
291 texImage
->RedBits
= 8;
292 texImage
->GreenBits
= 0;
293 texImage
->BlueBits
= 0;
294 texImage
->AlphaBits
= 0;
295 texImage
->IntensityBits
= 0;
296 texImage
->LuminanceBits
= 0;
297 texImage
->IndexBits
= 0;
300 texImage
->RedBits
= 0;
301 texImage
->GreenBits
= 8;
302 texImage
->BlueBits
= 0;
303 texImage
->AlphaBits
= 0;
304 texImage
->IntensityBits
= 0;
305 texImage
->LuminanceBits
= 0;
306 texImage
->IndexBits
= 0;
309 texImage
->RedBits
= 0;
310 texImage
->GreenBits
= 0;
311 texImage
->BlueBits
= 8;
312 texImage
->AlphaBits
= 0;
313 texImage
->IntensityBits
= 0;
314 texImage
->LuminanceBits
= 0;
315 texImage
->IndexBits
= 0;
319 texImage
->RedBits
= 8;
320 texImage
->GreenBits
= 8;
321 texImage
->BlueBits
= 8;
322 texImage
->AlphaBits
= 0;
323 texImage
->IntensityBits
= 0;
324 texImage
->LuminanceBits
= 0;
325 texImage
->IndexBits
= 0;
330 texImage
->RedBits
= 8;
331 texImage
->GreenBits
= 8;
332 texImage
->BlueBits
= 8;
333 texImage
->AlphaBits
= 8;
334 texImage
->IntensityBits
= 0;
335 texImage
->LuminanceBits
= 0;
336 texImage
->IndexBits
= 0;
339 texImage
->RedBits
= 0;
340 texImage
->GreenBits
= 0;
341 texImage
->BlueBits
= 0;
342 texImage
->AlphaBits
= 0;
343 texImage
->IntensityBits
= 0;
344 texImage
->LuminanceBits
= 0;
345 texImage
->IndexBits
= 8;
348 gl_problem(NULL
, "unexpected format in set_teximage_component_sizes");
355 * Return new gl_texture_image struct with all fields initialized to zero.
357 struct gl_texture_image
*
358 gl_alloc_texture_image( void )
360 return CALLOC_STRUCT(gl_texture_image
);
366 * Return a new gl_texture_image struct with most field initialized.
368 static struct gl_texture_image
*
369 new_texture_image( GLsizei width
, GLsizei height
, GLsizei depth
,
370 GLint border
, GLenum internalFormat
)
372 struct gl_texture_image
*img
= CALLOC_STRUCT(gl_texture_image
);
376 img
->Format
= (GLenum
) decode_internal_format(internalFormat
);
377 set_teximage_component_sizes( img
);
378 img
->IntFormat
= (GLenum
) internalFormat
;
379 img
->Border
= border
;
381 img
->Height
= height
;
383 img
->WidthLog2
= logbase2(width
- 2 * border
);
384 if (height
== 1) /* 1-D texture */
387 img
->HeightLog2
= logbase2(height
- 2 * border
);
388 if (depth
== 1) /* 2-D texture */
391 img
->DepthLog2
= logbase2(depth
- 2 * border
);
392 img
->Width2
= 1 << img
->WidthLog2
;
393 img
->Height2
= 1 << img
->HeightLog2
;
394 img
->Depth2
= 1 << img
->DepthLog2
;
395 img
->MaxLog2
= MAX2(img
->WidthLog2
, img
->HeightLog2
);
403 gl_free_texture_image( struct gl_texture_image
*teximage
)
405 if (teximage
->Data
) {
406 FREE( teximage
->Data
);
407 teximage
->Data
= NULL
;
414 /* Need this to prevent an out-of-bounds memory access when using
415 * X86 optimized code.
418 # define EXTRA_BYTE 1
420 # define EXTRA_BYTE 0
426 * This is called by glTexImage[123]D in order to build a gl_texture_image
427 * object given the client's parameters and image data.
429 * NOTES: Width, height and depth should include the border.
430 * All texture image parameters should have already been error checked.
432 static struct gl_texture_image
*
433 make_texture_image( GLcontext
*ctx
, GLint internalFormat
,
434 GLint width
, GLint height
, GLint depth
, GLint border
,
435 GLenum srcFormat
, GLenum srcType
, const GLvoid
*pixels
,
436 const struct gl_pixelstore_attrib
*unpacking
)
438 GLint components
, numPixels
;
439 struct gl_texture_image
*texImage
;
444 assert(border
== 0 || border
== 1);
450 * Allocate and initialize the texture_image struct
452 texImage
= new_texture_image(width
, height
, depth
, border
, internalFormat
);
456 components
= components_in_intformat(internalFormat
);
457 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
459 texImage
->Data
= (GLubyte
*) MALLOC(numPixels
* components
+ EXTRA_BYTE
);
461 if (!texImage
->Data
) {
463 gl_free_texture_image(texImage
);
469 * OK, the texture image struct has been initialized and the texture
470 * image memory has been allocated.
471 * Now fill in the texture image from the source data.
472 * This includes applying the pixel transfer operations.
475 /* try common 2D texture cases first */
476 if (!ctx
->Pixel
.ScaleOrBiasRGBA
&& !ctx
->Pixel
.MapColorFlag
477 && !ctx
->Pixel
.IndexOffset
&& !ctx
->Pixel
.IndexShift
478 && srcType
== GL_UNSIGNED_BYTE
&& depth
== 1) {
480 if (srcFormat
== internalFormat
) {
481 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
482 * GL_LUMINANCE_ALPHA, etc. texture formats.
484 const GLubyte
*src
= (const GLubyte
*) gl_pixel_addr_in_image(unpacking
,
485 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
486 const GLubyte
*src1
= (const GLubyte
*) gl_pixel_addr_in_image(unpacking
,
487 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
488 const GLint srcStride
= src1
- src
;
489 GLubyte
*dst
= texImage
->Data
;
490 GLint dstBytesPerRow
= width
* components
* sizeof(GLubyte
);
491 if (srcStride
== dstBytesPerRow
) {
492 MEMCPY(dst
, src
, height
* dstBytesPerRow
);
496 for (i
= 0; i
< height
; i
++) {
497 MEMCPY(dst
, src
, dstBytesPerRow
);
499 dst
+= dstBytesPerRow
;
502 return texImage
; /* all done */
504 else if (srcFormat
== GL_RGBA
&& internalFormat
== GL_RGB
) {
505 /* commonly used by Quake */
506 const GLubyte
*src
= (const GLubyte
*) gl_pixel_addr_in_image(unpacking
,
507 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
508 const GLubyte
*src1
= (const GLubyte
*) gl_pixel_addr_in_image(unpacking
,
509 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
510 const GLint srcStride
= src1
- src
;
511 GLubyte
*dst
= texImage
->Data
;
513 for (i
= 0; i
< height
; i
++) {
514 const GLubyte
*s
= src
;
515 for (j
= 0; j
< width
; j
++) {
516 *dst
++ = *s
++; /*red*/
517 *dst
++ = *s
++; /*green*/
518 *dst
++ = *s
++; /*blue*/
523 return texImage
; /* all done */
529 * General case solutions
531 if (texImage
->Format
== GL_COLOR_INDEX
) {
532 /* color index texture */
533 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
534 const GLenum dstType
= GL_UNSIGNED_BYTE
;
535 GLubyte
*dest
= texImage
->Data
;
537 for (img
= 0; img
< depth
; img
++) {
538 for (row
= 0; row
< height
; row
++) {
539 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
540 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
541 _mesa_unpack_index_span(ctx
, width
, dstType
, dest
,
542 srcType
, source
, unpacking
, GL_TRUE
);
543 dest
+= destBytesPerRow
;
548 /* regular, color texture */
549 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
550 const GLenum dstFormat
= texImage
->Format
;
551 GLubyte
*dest
= texImage
->Data
;
553 for (img
= 0; img
< depth
; img
++) {
554 for (row
= 0; row
< height
; row
++) {
555 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
556 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
557 _mesa_unpack_ubyte_color_span(ctx
, width
, dstFormat
, dest
,
558 srcFormat
, srcType
, source
, unpacking
, GL_TRUE
);
559 dest
+= destBytesPerRow
;
564 return texImage
; /* All done! */
570 * glTexImage[123]D can accept a NULL image pointer. In this case we
571 * create a texture image with unspecified image contents per the OpenGL
574 static struct gl_texture_image
*
575 make_null_texture( GLcontext
*ctx
, GLenum internalFormat
,
576 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
)
579 struct gl_texture_image
*texImage
;
583 /*internalFormat = decode_internal_format(internalFormat);*/
584 components
= components_in_intformat(internalFormat
);
585 numPixels
= width
* height
* depth
;
587 texImage
= new_texture_image(width
, height
, depth
, border
, internalFormat
);
589 /* It's easier later if we really do have a texture image, rather than
590 * a NULL image pointer.
592 texImage
->Data
= (GLubyte
*) MALLOC( numPixels
* components
+ EXTRA_BYTE
);
595 * Let's see if anyone finds this. If glTexImage2D() is called with
596 * a NULL image pointer then load the texture image with something
597 * interesting instead of leaving it indeterminate.
599 if (texImage
->Data
) {
600 static const char message
[8][32] = {
604 " X X XXXX XXX XXXXX ",
607 " X X XXXXX XXX X X ",
611 GLubyte
*imgPtr
= texImage
->Data
;
613 for (i
=0;i
<height
;i
++) {
614 GLint srcRow
= 7 - i
% 8;
615 for (j
=0;j
<width
;j
++) {
616 GLint srcCol
= j
% 32;
617 GLint texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
618 for (k
=0;k
<components
;k
++) {
619 *imgPtr
++ = (GLubyte
) texel
;
631 * Test glTexImage[123]D() parameters for errors.
633 * dimensions - must be 1 or 2 or 3
634 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
637 texture_error_check( GLcontext
*ctx
, GLenum target
,
638 GLint level
, GLint internalFormat
,
639 GLenum format
, GLenum type
,
641 GLint width
, GLint height
,
642 GLint depth
, GLint border
)
647 if (dimensions
== 1) {
648 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_1D
);
649 if (target
!= GL_TEXTURE_1D
&& !isProxy
) {
650 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
654 else if (dimensions
== 2) {
655 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_2D
);
656 if (target
!= GL_TEXTURE_2D
&& !isProxy
) {
657 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
661 else if (dimensions
== 3) {
662 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_3D
);
663 if (target
!= GL_TEXTURE_3D
&& !isProxy
) {
664 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
669 gl_problem( ctx
, "bad dims in texture_error_check" );
674 if (border
!=0 && border
!=1) {
677 sprintf(message
, "glTexImage%dD(border)", dimensions
);
678 gl_error(ctx
, GL_INVALID_VALUE
, message
);
684 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
685 || logbase2( width
- 2 * border
) < 0) {
688 sprintf(message
, "glTexImage%dD(width)", dimensions
);
689 gl_error(ctx
, GL_INVALID_VALUE
, message
);
695 if (dimensions
>= 2) {
696 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
697 || logbase2( height
- 2 * border
) < 0) {
700 sprintf(message
, "glTexImage%dD(height)", dimensions
);
701 gl_error(ctx
, GL_INVALID_VALUE
, message
);
708 if (dimensions
>= 3) {
709 if (depth
< 2 * border
|| depth
> 2 + ctx
->Const
.MaxTextureSize
710 || logbase2( depth
- 2 * border
) < 0) {
712 gl_error( ctx
, GL_INVALID_VALUE
, "glTexImage3D(depth)" );
719 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
722 sprintf(message
, "glTexImage%dD(level)", dimensions
);
723 gl_error(ctx
, GL_INVALID_VALUE
, message
);
728 iformat
= decode_internal_format( internalFormat
);
732 sprintf(message
, "glTexImage%dD(internalFormat)", dimensions
);
733 gl_error(ctx
, GL_INVALID_VALUE
, message
);
738 if (!gl_is_legal_format_and_type( format
, type
)) {
739 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
740 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
744 sprintf(message
, "glTexImage%dD(format or type)", dimensions
);
745 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
750 /* if we get here, the parameters are OK */
757 * Test glTexSubImage[123]D() parameters for errors.
759 * dimensions - must be 1 or 2 or 3
760 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
763 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
764 GLenum target
, GLint level
,
765 GLint xoffset
, GLint yoffset
, GLint zoffset
,
766 GLint width
, GLint height
, GLint depth
,
767 GLenum format
, GLenum type
)
769 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
770 struct gl_texture_image
*destTex
;
772 if (dimensions
== 1) {
773 if (target
!= GL_TEXTURE_1D
) {
774 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
778 else if (dimensions
== 2) {
779 if (target
!= GL_TEXTURE_2D
) {
780 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
784 else if (dimensions
== 3) {
785 if (target
!= GL_TEXTURE_3D
) {
786 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
791 gl_problem( ctx
, "bad dims in texture_error_check" );
795 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
796 gl_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level)");
802 sprintf(message
, "glTexSubImage%dD(width)", dimensions
);
803 gl_error(ctx
, GL_INVALID_VALUE
, message
);
806 if (height
< 0 && dimensions
> 1) {
808 sprintf(message
, "glTexSubImage%dD(height)", dimensions
);
809 gl_error(ctx
, GL_INVALID_VALUE
, message
);
812 if (depth
< 0 && dimensions
> 2) {
814 sprintf(message
, "glTexSubImage%dD(depth)", dimensions
);
815 gl_error(ctx
, GL_INVALID_VALUE
, message
);
819 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
821 gl_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage2D");
825 if (xoffset
< -((GLint
)destTex
->Border
)) {
826 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset)");
829 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
830 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset+width)");
833 if (dimensions
> 1) {
834 if (yoffset
< -((GLint
)destTex
->Border
)) {
835 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset)");
838 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
839 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset+height)");
843 if (dimensions
> 2) {
844 if (zoffset
< -((GLint
)destTex
->Border
)) {
845 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
848 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+destTex
->Border
)) {
849 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
854 if (!gl_is_legal_format_and_type(format
, type
)) {
856 sprintf(message
, "glTexSubImage%dD(format or type)", dimensions
);
857 gl_error(ctx
, GL_INVALID_ENUM
, message
);
866 * Test glCopyTexImage[12]D() parameters for errors.
867 * Input: dimensions - must be 1 or 2 or 3
868 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
871 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
872 GLenum target
, GLint level
, GLint internalFormat
,
873 GLint width
, GLint height
, GLint border
)
877 if (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) {
878 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1/2D(target)" );
882 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
883 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
886 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
887 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
892 if (border
!=0 && border
!=1) {
894 sprintf(message
, "glCopyTexImage%dD(border)", dimensions
);
895 gl_error(ctx
, GL_INVALID_VALUE
, message
);
900 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
901 || logbase2( width
- 2 * border
) < 0) {
903 sprintf(message
, "glCopyTexImage%dD(width)", dimensions
);
904 gl_error(ctx
, GL_INVALID_VALUE
, message
);
909 if (dimensions
>= 2) {
910 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
911 || logbase2( height
- 2 * border
) < 0) {
913 sprintf(message
, "glCopyTexImage%dD(height)", dimensions
);
914 gl_error(ctx
, GL_INVALID_VALUE
, message
);
920 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
922 sprintf(message
, "glCopyTexImage%dD(level)", dimensions
);
923 gl_error(ctx
, GL_INVALID_VALUE
, message
);
927 iformat
= decode_internal_format( internalFormat
);
930 sprintf(message
, "glCopyTexImage%dD(internalFormat)", dimensions
);
931 gl_error(ctx
, GL_INVALID_VALUE
, message
);
935 /* if we get here, the parameters are OK */
941 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
942 GLenum target
, GLint level
,
943 GLint xoffset
, GLint yoffset
, GLint zoffset
,
944 GLsizei width
, GLsizei height
)
946 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
947 struct gl_texture_image
*teximage
;
949 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
950 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
953 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
954 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
957 else if (dimensions
== 3 && target
!= GL_TEXTURE_3D
) {
958 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
962 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
964 sprintf(message
, "glCopyTexSubImage%dD(level)", dimensions
);
965 gl_error(ctx
, GL_INVALID_VALUE
, message
);
971 sprintf(message
, "glCopyTexSubImage%dD(width)", dimensions
);
972 gl_error(ctx
, GL_INVALID_VALUE
, message
);
975 if (dimensions
> 1 && height
< 0) {
977 sprintf(message
, "glCopyTexSubImage%dD(height)", dimensions
);
978 gl_error(ctx
, GL_INVALID_VALUE
, message
);
982 teximage
= texUnit
->CurrentD
[dimensions
]->Image
[level
];
985 sprintf(message
, "glCopyTexSubImage%dD(undefined texture)", dimensions
);
986 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
990 if (xoffset
< -((GLint
)teximage
->Border
)) {
992 sprintf(message
, "glCopyTexSubImage%dD(xoffset)", dimensions
);
993 gl_error(ctx
, GL_INVALID_VALUE
, message
);
996 if (xoffset
+width
> (GLint
) (teximage
->Width
+teximage
->Border
)) {
998 sprintf(message
, "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
999 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1002 if (dimensions
> 1) {
1003 if (yoffset
< -((GLint
)teximage
->Border
)) {
1005 sprintf(message
, "glCopyTexSubImage%dD(yoffset)", dimensions
);
1006 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1009 /* NOTE: we're adding the border here, not subtracting! */
1010 if (yoffset
+height
> (GLint
) (teximage
->Height
+teximage
->Border
)) {
1012 sprintf(message
, "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1013 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1018 if (dimensions
> 2) {
1019 if (zoffset
< -((GLint
)teximage
->Border
)) {
1021 sprintf(message
, "glCopyTexSubImage%dD(zoffset)", dimensions
);
1022 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1025 if (zoffset
> (GLint
) (teximage
->Depth
+teximage
->Border
)) {
1027 sprintf(message
, "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1028 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1033 /* if we get here, the parameters are OK */
1041 * Called from the API. Note that width includes the border.
1044 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalformat
,
1045 GLsizei width
, GLint border
, GLenum format
,
1046 GLenum type
, const GLvoid
*pixels
)
1048 GET_CURRENT_CONTEXT(ctx
);
1049 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage1D");
1051 if (target
==GL_TEXTURE_1D
) {
1052 struct gl_texture_unit
*texUnit
;
1053 struct gl_texture_image
*teximage
;
1055 if (texture_error_check( ctx
, target
, level
, internalformat
,
1056 format
, type
, 1, width
, 1, 1, border
)) {
1057 return; /* error in texture image was detected */
1060 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1062 /* free current texture image, if any */
1063 if (texUnit
->CurrentD
[1]->Image
[level
]) {
1064 gl_free_texture_image( texUnit
->CurrentD
[1]->Image
[level
] );
1067 /* make new texture from source image */
1069 teximage
= make_texture_image(ctx
, internalformat
, width
, 1, 1,
1070 border
, format
, type
, pixels
, &ctx
->Unpack
);
1073 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1074 width
, 1, 1, border
);
1077 /* install new texture image */
1078 texUnit
->CurrentD
[1]->Image
[level
] = teximage
;
1079 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1080 ctx
->NewState
|= NEW_TEXTURING
;
1082 /* tell driver about change */
1083 if (ctx
->Driver
.TexImage
) {
1084 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1085 texUnit
->CurrentD
[1],
1086 level
, internalformat
, teximage
);
1089 else if (target
==GL_PROXY_TEXTURE_1D
) {
1090 /* Proxy texture: check for errors and update proxy state */
1091 if (texture_error_check( ctx
, target
, level
, internalformat
,
1092 format
, type
, 1, width
, 1, 1, border
)) {
1093 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1094 MEMSET( ctx
->Texture
.Proxy1D
->Image
[level
], 0,
1095 sizeof(struct gl_texture_image
) );
1099 ctx
->Texture
.Proxy1D
->Image
[level
]->Format
= (GLenum
) format
;
1100 set_teximage_component_sizes( ctx
->Texture
.Proxy1D
->Image
[level
] );
1101 ctx
->Texture
.Proxy1D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1102 ctx
->Texture
.Proxy1D
->Image
[level
]->Border
= border
;
1103 ctx
->Texture
.Proxy1D
->Image
[level
]->Width
= width
;
1104 ctx
->Texture
.Proxy1D
->Image
[level
]->Height
= 1;
1105 ctx
->Texture
.Proxy1D
->Image
[level
]->Depth
= 1;
1109 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1116 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalformat
,
1117 GLsizei width
, GLsizei height
, GLint border
,
1118 GLenum format
, GLenum type
,
1119 const GLvoid
*pixels
)
1121 GET_CURRENT_CONTEXT(ctx
);
1122 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage2D");
1124 if (target
==GL_TEXTURE_2D
) {
1125 struct gl_texture_unit
*texUnit
;
1126 struct gl_texture_image
*teximage
;
1128 if (texture_error_check( ctx
, target
, level
, internalformat
,
1129 format
, type
, 2, width
, height
, 1, border
)) {
1130 return; /* error in texture image was detected */
1133 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1135 /* free current texture image, if any */
1136 if (texUnit
->CurrentD
[2]->Image
[level
]) {
1137 gl_free_texture_image( texUnit
->CurrentD
[2]->Image
[level
] );
1140 /* make new texture from source image */
1142 teximage
= make_texture_image(ctx
, internalformat
, width
, height
, 1,
1143 border
, format
, type
, pixels
, &ctx
->Unpack
);
1146 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1147 width
, height
, 1, border
);
1150 /* install new texture image */
1151 texUnit
->CurrentD
[2]->Image
[level
] = teximage
;
1152 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1153 ctx
->NewState
|= NEW_TEXTURING
;
1155 /* tell driver about change */
1156 if (ctx
->Driver
.TexImage
) {
1157 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1158 texUnit
->CurrentD
[2],
1159 level
, internalformat
, teximage
);
1162 else if (target
==GL_PROXY_TEXTURE_2D
) {
1163 /* Proxy texture: check for errors and update proxy state */
1164 if (texture_error_check( ctx
, target
, level
, internalformat
,
1165 format
, type
, 2, width
, height
, 1, border
)) {
1166 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1167 MEMSET( ctx
->Texture
.Proxy2D
->Image
[level
], 0,
1168 sizeof(struct gl_texture_image
) );
1172 ctx
->Texture
.Proxy2D
->Image
[level
]->Format
= (GLenum
) format
;
1173 set_teximage_component_sizes( ctx
->Texture
.Proxy2D
->Image
[level
] );
1174 ctx
->Texture
.Proxy2D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1175 ctx
->Texture
.Proxy2D
->Image
[level
]->Border
= border
;
1176 ctx
->Texture
.Proxy2D
->Image
[level
]->Width
= width
;
1177 ctx
->Texture
.Proxy2D
->Image
[level
]->Height
= height
;
1178 ctx
->Texture
.Proxy2D
->Image
[level
]->Depth
= 1;
1182 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
1190 * Called by the API or display list executor.
1191 * Note that width and height include the border.
1194 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalformat
,
1195 GLsizei width
, GLsizei height
, GLsizei depth
,
1196 GLint border
, GLenum format
, GLenum type
,
1197 const GLvoid
*pixels
)
1199 GET_CURRENT_CONTEXT(ctx
);
1200 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage3D");
1202 if (target
==GL_TEXTURE_3D_EXT
) {
1203 struct gl_texture_unit
*texUnit
;
1204 struct gl_texture_image
*teximage
;
1205 if (texture_error_check( ctx
, target
, level
, internalformat
,
1206 format
, type
, 3, width
, height
, depth
,
1208 return; /* error in texture image was detected */
1211 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1213 /* free current texture image, if any */
1214 if (texUnit
->CurrentD
[3]->Image
[level
]) {
1215 gl_free_texture_image( texUnit
->CurrentD
[3]->Image
[level
] );
1218 /* make new texture from source image */
1220 teximage
= make_texture_image(ctx
, internalformat
, width
, height
,
1221 depth
, border
, format
, type
, pixels
, &ctx
->Unpack
);
1224 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1225 width
, height
, depth
, border
);
1228 /* install new texture image */
1229 texUnit
->CurrentD
[3]->Image
[level
] = teximage
;
1230 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[3] );
1231 ctx
->NewState
|= NEW_TEXTURING
;
1233 /* tell driver about change */
1234 if (ctx
->Driver
.TexImage
) {
1235 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D_EXT
,
1236 texUnit
->CurrentD
[3],
1237 level
, internalformat
, teximage
);
1240 else if (target
==GL_PROXY_TEXTURE_3D_EXT
) {
1241 /* Proxy texture: check for errors and update proxy state */
1242 if (texture_error_check( ctx
, target
, level
, internalformat
,
1243 format
, type
, 3, width
, height
, depth
,
1245 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1246 MEMSET( ctx
->Texture
.Proxy3D
->Image
[level
], 0,
1247 sizeof(struct gl_texture_image
) );
1251 ctx
->Texture
.Proxy3D
->Image
[level
]->Format
= (GLenum
) format
;
1252 set_teximage_component_sizes( ctx
->Texture
.Proxy3D
->Image
[level
] );
1253 ctx
->Texture
.Proxy3D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1254 ctx
->Texture
.Proxy3D
->Image
[level
]->Border
= border
;
1255 ctx
->Texture
.Proxy3D
->Image
[level
]->Width
= width
;
1256 ctx
->Texture
.Proxy3D
->Image
[level
]->Height
= height
;
1257 ctx
->Texture
.Proxy3D
->Image
[level
]->Depth
= depth
;
1261 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1268 _mesa_TexImage3DEXT( GLenum target
, GLint level
, GLenum internalformat
,
1269 GLsizei width
, GLsizei height
, GLsizei depth
,
1270 GLint border
, GLenum format
, GLenum type
,
1271 const GLvoid
*pixels
)
1273 _mesa_TexImage3D(target
, level
, (GLint
) internalformat
, width
, height
,
1274 depth
, border
, format
, type
, pixels
);
1279 * Fetch a texture image from the device driver.
1280 * Store the results in the given texture object at the given mipmap level.
1283 get_teximage_from_driver( GLcontext
*ctx
, GLenum target
, GLint level
,
1284 const struct gl_texture_object
*texObj
)
1287 GLenum imgFormat
, imgType
;
1288 GLboolean freeImage
;
1289 struct gl_texture_image
*texImage
;
1290 GLint destComponents
, numPixels
, srcBytesPerTexel
;
1292 if (!ctx
->Driver
.GetTexImage
)
1295 image
= (*ctx
->Driver
.GetTexImage
)( ctx
, target
, level
,
1296 &imgFormat
, &imgType
, &freeImage
);
1300 texImage
= texObj
->Image
[level
];
1305 destComponents
= components_in_intformat(texImage
->Format
);
1306 assert(destComponents
> 0);
1307 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
1308 assert(numPixels
> 0);
1309 srcBytesPerTexel
= gl_bytes_per_pixel(imgFormat
, imgType
);
1310 assert(srcBytesPerTexel
> 0);
1312 if (!texImage
->Data
) {
1313 /* Allocate memory for the texture image data */
1314 texImage
->Data
= (GLubyte
*) MALLOC(numPixels
* destComponents
+ EXTRA_BYTE
);
1317 if (imgFormat
== texImage
->Format
&& imgType
== GL_UNSIGNED_BYTE
) {
1318 /* We got lucky! The driver's format and type match Mesa's format. */
1319 if (texImage
->Data
) {
1320 MEMCPY(texImage
->Data
, image
, numPixels
* destComponents
);
1324 /* Convert the texture image from the driver's format to Mesa's
1327 const GLint width
= texImage
->Width
;
1328 const GLint height
= texImage
->Height
;
1329 const GLint depth
= texImage
->Depth
;
1330 const GLint destBytesPerRow
= width
* destComponents
* sizeof(GLchan
);
1331 const GLint srcBytesPerRow
= width
* srcBytesPerTexel
;
1332 const GLenum dstType
= GL_UNSIGNED_BYTE
;
1333 const GLenum dstFormat
= texImage
->Format
;
1334 const GLubyte
*srcPtr
= (const GLubyte
*) image
;
1335 GLubyte
*destPtr
= texImage
->Data
;
1337 if (texImage
->Format
== GL_COLOR_INDEX
) {
1338 /* color index texture */
1340 assert(imgFormat
== GL_COLOR_INDEX
);
1341 for (img
= 0; img
< depth
; img
++) {
1342 for (row
= 0; row
< height
; row
++) {
1343 _mesa_unpack_index_span(ctx
, width
, dstType
, destPtr
,
1344 imgType
, srcPtr
, &DefaultPacking
, GL_FALSE
);
1345 destPtr
+= destBytesPerRow
;
1346 srcPtr
+= srcBytesPerRow
;
1353 for (img
= 0; img
< depth
; img
++) {
1354 for (row
= 0; row
< height
; row
++) {
1355 _mesa_unpack_ubyte_color_span(ctx
, width
, dstFormat
, destPtr
,
1356 imgFormat
, imgType
, srcPtr
, &DefaultPacking
, GL_FALSE
);
1357 destPtr
+= destBytesPerRow
;
1358 srcPtr
+= srcBytesPerRow
;
1370 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1371 GLenum type
, GLvoid
*pixels
)
1373 GET_CURRENT_CONTEXT(ctx
);
1374 const struct gl_texture_object
*texObj
;
1375 struct gl_texture_image
*texImage
;
1376 GLboolean discardImage
;
1378 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetTexImage");
1380 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1381 gl_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1385 if (gl_sizeof_type(type
) <= 0) {
1386 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1390 if (gl_components_in_format(format
) <= 0) {
1391 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1400 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[1];
1403 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[2];
1406 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[3];
1409 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)" );
1413 texImage
= texObj
->Image
[level
];
1415 /* invalid mipmap level */
1419 if (!texImage
->Data
) {
1420 /* try to get the texture image from the device driver */
1421 get_teximage_from_driver(ctx
, target
, level
, texObj
);
1422 discardImage
= GL_TRUE
;
1425 discardImage
= GL_FALSE
;
1428 if (texImage
->Data
) {
1429 GLint width
= texImage
->Width
;
1430 GLint height
= texImage
->Height
;
1433 for (row
= 0; row
< height
; row
++) {
1434 /* compute destination address in client memory */
1435 GLvoid
*dest
= gl_pixel_addr_in_image( &ctx
->Unpack
, pixels
,
1437 format
, type
, 0, row
, 0);
1440 if (texImage
->Format
== GL_RGBA
) {
1441 const GLubyte
*src
= texImage
->Data
+ row
* width
* 4 * sizeof(GLubyte
);
1442 gl_pack_rgba_span( ctx
, width
, (CONST
GLubyte (*)[4]) src
,
1444 &ctx
->Pack
, GL_TRUE
);
1447 /* fetch RGBA row from texture image then pack it in client mem */
1448 GLubyte rgba
[MAX_WIDTH
][4];
1451 switch (texImage
->Format
) {
1453 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1454 for (i
= 0; i
< width
; i
++) {
1455 rgba
[i
][RCOMP
] = 255;
1456 rgba
[i
][GCOMP
] = 255;
1457 rgba
[i
][BCOMP
] = 255;
1458 rgba
[i
][ACOMP
] = src
[i
];
1462 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1463 for (i
= 0; i
< width
; i
++) {
1464 rgba
[i
][RCOMP
] = src
[i
];
1465 rgba
[i
][GCOMP
] = src
[i
];
1466 rgba
[i
][BCOMP
] = src
[i
];
1467 rgba
[i
][ACOMP
] = 255;
1470 case GL_LUMINANCE_ALPHA
:
1471 src
= texImage
->Data
+ row
* 2 * width
* sizeof(GLubyte
);
1472 for (i
= 0; i
< width
; i
++) {
1473 rgba
[i
][RCOMP
] = src
[i
*2+0];
1474 rgba
[i
][GCOMP
] = src
[i
*2+0];
1475 rgba
[i
][BCOMP
] = src
[i
*2+0];
1476 rgba
[i
][ACOMP
] = src
[i
*2+1];
1480 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1481 for (i
= 0; i
< width
; i
++) {
1482 rgba
[i
][RCOMP
] = src
[i
];
1483 rgba
[i
][GCOMP
] = src
[i
];
1484 rgba
[i
][BCOMP
] = src
[i
];
1485 rgba
[i
][ACOMP
] = 255;
1489 src
= texImage
->Data
+ row
* 3 * width
* sizeof(GLubyte
);
1490 for (i
= 0; i
< width
; i
++) {
1491 rgba
[i
][RCOMP
] = src
[i
*3+0];
1492 rgba
[i
][GCOMP
] = src
[i
*3+1];
1493 rgba
[i
][BCOMP
] = src
[i
*3+2];
1494 rgba
[i
][ACOMP
] = 255;
1498 /* this special case should have been handled above! */
1499 gl_problem( ctx
, "error 1 in gl_GetTexImage" );
1501 case GL_COLOR_INDEX
:
1502 gl_problem( ctx
, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1505 gl_problem( ctx
, "bad format in gl_GetTexImage" );
1507 gl_pack_rgba_span( ctx
, width
, (const GLubyte (*)[4])rgba
,
1508 format
, type
, dest
, &ctx
->Pack
, GL_TRUE
);
1512 /* if we got the teximage from the device driver we'll discard it now */
1514 FREE(texImage
->Data
);
1515 texImage
->Data
= NULL
;
1523 _mesa_TexSubImage1D( GLenum target
, GLint level
,
1524 GLint xoffset
, GLsizei width
,
1525 GLenum format
, GLenum type
,
1526 const GLvoid
*pixels
)
1528 GET_CURRENT_CONTEXT(ctx
);
1529 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1530 struct gl_texture_image
*destTex
;
1532 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
1533 width
, 1, 1, format
, type
)) {
1534 return; /* error was detected */
1537 destTex
= texUnit
->CurrentD
[1]->Image
[level
];
1540 if (width
== 0 || !pixels
)
1541 return; /* no-op, not an error */
1545 * Replace the texture subimage
1548 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1549 const GLenum texFormat
= destTex
->Format
;
1550 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1551 GLubyte
*dst
= destTex
->Data
+ xoffsetb
* texComponents
;
1552 if (texFormat
== GL_COLOR_INDEX
) {
1553 /* color index texture */
1554 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1555 width
, 1, format
, type
, 0, 0, 0);
1556 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1557 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1561 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1562 width
, 1, format
, type
, 0, 0, 0);
1563 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1564 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1568 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1571 * Inform device driver of texture image change.
1573 if (ctx
->Driver
.TexSubImage
) {
1574 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1575 level
, xoffset
, 0, width
, 1,
1576 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1580 if (ctx
->Driver
.TexImage
) {
1581 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1583 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1591 _mesa_TexSubImage2D( GLenum target
, GLint level
,
1592 GLint xoffset
, GLint yoffset
,
1593 GLsizei width
, GLsizei height
,
1594 GLenum format
, GLenum type
,
1595 const GLvoid
*pixels
)
1597 GET_CURRENT_CONTEXT(ctx
);
1598 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1599 struct gl_texture_image
*destTex
;
1601 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
1602 width
, height
, 1, format
, type
)) {
1603 return; /* error was detected */
1606 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
1609 if (width
== 0 || height
== 0 || !pixels
)
1610 return; /* no-op, not an error */
1614 * Replace the texture subimage
1617 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1618 const GLenum texFormat
= destTex
->Format
;
1619 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1620 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1621 GLubyte
*dst
= destTex
->Data
1622 + (yoffsetb
* destTex
->Width
+ xoffsetb
) * texComponents
;
1623 if (texFormat
== GL_COLOR_INDEX
) {
1624 /* color index texture */
1625 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1627 for (row
= 0; row
< height
; row
++) {
1628 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1629 width
, height
, format
, type
, 0, row
, 0);
1630 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1631 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1637 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1639 for (row
= 0; row
< height
; row
++) {
1640 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1641 width
, height
, format
, type
, 0, row
, 0);
1642 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1643 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1649 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1652 * Inform device driver of texture image change.
1654 if (ctx
->Driver
.TexSubImage
) {
1655 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1656 level
, xoffset
, yoffset
, width
, height
,
1657 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1661 if (ctx
->Driver
.TexImage
) {
1662 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1664 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1673 _mesa_TexSubImage3D( GLenum target
, GLint level
,
1674 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1675 GLsizei width
, GLsizei height
, GLsizei depth
,
1676 GLenum format
, GLenum type
,
1677 const GLvoid
*pixels
)
1679 GET_CURRENT_CONTEXT(ctx
);
1680 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1681 struct gl_texture_image
*destTex
;
1683 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
1684 width
, height
, depth
, format
, type
)) {
1685 return; /* error was detected */
1688 destTex
= texUnit
->CurrentD
[3]->Image
[level
];
1691 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
1692 return; /* no-op, not an error */
1695 * Replace the texture subimage
1698 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1699 const GLenum texFormat
= destTex
->Format
;
1700 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1701 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1702 const GLint zoffsetb
= zoffset
+ destTex
->Border
;
1703 GLint dstRectArea
= destTex
->Width
* destTex
->Height
;
1704 GLubyte
*dst
= destTex
->Data
1705 + (zoffsetb
* dstRectArea
+ yoffsetb
* destTex
->Width
+ xoffsetb
)
1708 if (texFormat
== GL_COLOR_INDEX
) {
1709 /* color index texture */
1710 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1712 for (img
= 0; img
< depth
; img
++) {
1713 for (row
= 0; row
< height
; row
++) {
1714 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1715 width
, height
, format
, type
, img
, row
, 0);
1716 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1717 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1724 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1726 for (img
= 0; img
< depth
; img
++) {
1727 for (row
= 0; row
< height
; row
++) {
1728 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1729 width
, height
, format
, type
, img
, row
, 0);
1730 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1731 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1738 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1741 * Inform device driver of texture image change.
1749 * Read an RGBA image from the frame buffer.
1750 * This is used by glCopyTexSubImage[12]D().
1751 * Input: ctx - the context
1752 * x, y - lower left corner
1753 * width, height - size of region to read
1754 * Return: pointer to block of GL_RGBA, GLubyte data.
1757 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
1758 GLsizei width
, GLsizei height
)
1761 GLubyte
*image
, *dst
;
1763 image
= (GLubyte
*) MALLOC(width
* height
* 4 * sizeof(GLubyte
));
1767 /* Select buffer to read from */
1768 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->ReadBuffer
,
1769 ctx
->Pixel
.DriverReadBuffer
);
1772 stride
= width
* 4 * sizeof(GLubyte
);
1773 for (i
= 0; i
< height
; i
++) {
1774 gl_read_rgba_span( ctx
, ctx
->ReadBuffer
, width
, x
, y
+ i
,
1775 (GLubyte (*)[4]) dst
);
1779 /* Read from draw buffer (the default) */
1780 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->DrawBuffer
,
1781 ctx
->Color
.DriverDrawBuffer
);
1789 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
1790 GLenum internalFormat
,
1792 GLsizei width
, GLint border
)
1794 GET_CURRENT_CONTEXT(ctx
);
1795 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage1D");
1797 if (copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
1801 if (ctx
->Pixel
.MapColorFlag
|| ctx
->Pixel
.ScaleOrBiasRGBA
1802 || !ctx
->Driver
.CopyTexImage1D
1803 || !(*ctx
->Driver
.CopyTexImage1D
)(ctx
, target
, level
,
1804 internalFormat
, x
, y
, width
, border
))
1806 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, 1 );
1808 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D" );
1811 (*ctx
->Exec
->TexImage1D
)( target
, level
, internalFormat
, width
,
1812 border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1820 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
1821 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1824 GET_CURRENT_CONTEXT(ctx
);
1825 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage2D");
1827 if (copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
1828 width
, height
, border
))
1831 if (ctx
->Pixel
.MapColorFlag
|| ctx
->Pixel
.ScaleOrBiasRGBA
1832 || !ctx
->Driver
.CopyTexImage2D
1833 || !(*ctx
->Driver
.CopyTexImage2D
)(ctx
, target
, level
,
1834 internalFormat
, x
, y
, width
, height
, border
))
1836 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, height
);
1838 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D" );
1841 (ctx
->Exec
->TexImage2D
)( target
, level
, internalFormat
, width
,
1842 height
, border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1850 * Do the work of glCopyTexSubImage[123]D.
1853 copy_tex_sub_image( GLcontext
*ctx
, struct gl_texture_image
*dest
,
1854 GLint width
, GLint height
,
1855 GLint srcx
, GLint srcy
,
1856 GLint dstx
, GLint dsty
, GLint dstz
)
1858 static struct gl_pixelstore_attrib packing
= {
1863 0, /* ImageHeight */
1865 GL_FALSE
, /* SwapBytes */
1866 GL_FALSE
/* LsbFirst */
1870 GLint format
, components
, rectarea
;
1871 GLint texwidth
, texheight
, zoffset
;
1873 /* dst[xyz] may be negative if we have a texture border! */
1874 dstx
+= dest
->Border
;
1875 dsty
+= dest
->Border
;
1876 dstz
+= dest
->Border
;
1877 texwidth
= dest
->Width
;
1878 texheight
= dest
->Height
;
1879 rectarea
= texwidth
* texheight
;
1880 zoffset
= dstz
* rectarea
;
1881 format
= dest
->Format
;
1882 components
= components_in_intformat( format
);
1884 /* Select buffer to read from */
1885 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->ReadBuffer
,
1886 ctx
->Pixel
.DriverReadBuffer
);
1888 for (i
= 0;i
< height
; i
++) {
1889 GLubyte rgba
[MAX_WIDTH
][4];
1891 gl_read_rgba_span( ctx
, ctx
->ReadBuffer
, width
, srcx
, srcy
+ i
, rgba
);
1892 dst
= dest
->Data
+ ( zoffset
+ (dsty
+i
) * texwidth
+ dstx
) * components
;
1893 _mesa_unpack_ubyte_color_span(ctx
, width
, format
, dst
,
1894 GL_RGBA
, GL_UNSIGNED_BYTE
, rgba
,
1898 /* Read from draw buffer (the default) */
1899 (*ctx
->Driver
.SetReadBuffer
)( ctx
, ctx
->DrawBuffer
,
1900 ctx
->Color
.DriverDrawBuffer
);
1907 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
1908 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
1910 GET_CURRENT_CONTEXT(ctx
);
1911 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage1D");
1913 if (copytexsubimage_error_check(ctx
, 1, target
, level
,
1914 xoffset
, 0, 0, width
, 1))
1917 if (ctx
->Pixel
.MapColorFlag
|| ctx
->Pixel
.ScaleOrBiasRGBA
1918 || !ctx
->Driver
.CopyTexSubImage1D
1919 || !(*ctx
->Driver
.CopyTexSubImage1D
)(ctx
, target
, level
,
1920 xoffset
, x
, y
, width
)) {
1921 struct gl_texture_unit
*texUnit
;
1922 struct gl_texture_image
*teximage
;
1923 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1924 teximage
= texUnit
->CurrentD
[1]->Image
[level
];
1926 if (teximage
->Data
) {
1927 copy_tex_sub_image(ctx
, teximage
, width
, 1, x
, y
, xoffset
, 0, 0);
1928 /* tell driver about the change */
1929 if (ctx
->Driver
.TexImage
) {
1930 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1931 texUnit
->CurrentD
[1],
1932 level
, teximage
->IntFormat
, teximage
);
1941 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
1942 GLint xoffset
, GLint yoffset
,
1943 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1945 GET_CURRENT_CONTEXT(ctx
);
1946 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage2D");
1948 if (copytexsubimage_error_check(ctx
, 2, target
, level
,
1949 xoffset
, yoffset
, 0, width
, height
))
1952 if (ctx
->Pixel
.MapColorFlag
|| ctx
->Pixel
.ScaleOrBiasRGBA
1953 || !ctx
->Driver
.CopyTexSubImage2D
1954 || !(*ctx
->Driver
.CopyTexSubImage2D
)(ctx
, target
, level
,
1955 xoffset
, yoffset
, x
, y
, width
, height
)) {
1956 struct gl_texture_unit
*texUnit
;
1957 struct gl_texture_image
*teximage
;
1958 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1959 teximage
= texUnit
->CurrentD
[2]->Image
[level
];
1961 if (teximage
->Data
) {
1962 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1963 x
, y
, xoffset
, yoffset
, 0);
1964 /* tell driver about the change */
1965 if (ctx
->Driver
.TexImage
) {
1966 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1967 texUnit
->CurrentD
[2],
1968 level
, teximage
->IntFormat
, teximage
);
1977 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
1978 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1979 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1981 GET_CURRENT_CONTEXT(ctx
);
1982 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage3D");
1984 if (copytexsubimage_error_check(ctx
, 3, target
, level
,
1985 xoffset
, yoffset
, zoffset
, width
, height
))
1988 if (ctx
->Pixel
.MapColorFlag
|| ctx
->Pixel
.ScaleOrBiasRGBA
1989 || !ctx
->Driver
.CopyTexSubImage3D
1990 || !(*ctx
->Driver
.CopyTexSubImage3D
)(ctx
, target
, level
,
1991 xoffset
, yoffset
, zoffset
, x
, y
, width
, height
)) {
1992 struct gl_texture_unit
*texUnit
;
1993 struct gl_texture_image
*teximage
;
1994 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1995 teximage
= texUnit
->CurrentD
[3]->Image
[level
];
1997 if (teximage
->Data
) {
1998 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1999 x
, y
, xoffset
, yoffset
, zoffset
);
2000 /* tell driver about the change */
2001 if (ctx
->Driver
.TexImage
) {
2002 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D
,
2003 texUnit
->CurrentD
[3],
2004 level
, teximage
->IntFormat
, teximage
);