1 /* $Id: teximage.c,v 1.12 1999/11/11 01:22:27 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.
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.
55 * Compute log base 2 of n.
56 * If n isn't an exact power of two return -1.
84 * Given an internal texture format enum or 1, 2, 3, 4 return the
85 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
86 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
87 * Return -1 if invalid enum.
90 decode_internal_format( GLint format
)
107 case GL_LUMINANCE_ALPHA
:
108 case GL_LUMINANCE4_ALPHA4
:
109 case GL_LUMINANCE6_ALPHA2
:
110 case GL_LUMINANCE8_ALPHA8
:
111 case GL_LUMINANCE12_ALPHA4
:
112 case GL_LUMINANCE12_ALPHA12
:
113 case GL_LUMINANCE16_ALPHA16
:
114 return GL_LUMINANCE_ALPHA
;
142 case GL_COLOR_INDEX1_EXT
:
143 case GL_COLOR_INDEX2_EXT
:
144 case GL_COLOR_INDEX4_EXT
:
145 case GL_COLOR_INDEX8_EXT
:
146 case GL_COLOR_INDEX12_EXT
:
147 case GL_COLOR_INDEX16_EXT
:
148 return GL_COLOR_INDEX
;
150 return -1; /* error */
157 * Given an internal texture format enum or 1, 2, 3, 4 return the
158 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
159 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
160 * number of components for the format. Return -1 if invalid enum.
163 components_in_intformat( GLint format
)
180 case GL_LUMINANCE_ALPHA
:
181 case GL_LUMINANCE4_ALPHA4
:
182 case GL_LUMINANCE6_ALPHA2
:
183 case GL_LUMINANCE8_ALPHA8
:
184 case GL_LUMINANCE12_ALPHA4
:
185 case GL_LUMINANCE12_ALPHA12
:
186 case GL_LUMINANCE16_ALPHA16
:
215 case GL_COLOR_INDEX1_EXT
:
216 case GL_COLOR_INDEX2_EXT
:
217 case GL_COLOR_INDEX4_EXT
:
218 case GL_COLOR_INDEX8_EXT
:
219 case GL_COLOR_INDEX12_EXT
:
220 case GL_COLOR_INDEX16_EXT
:
223 return -1; /* error */
229 struct gl_texture_image
*
230 gl_alloc_texture_image( void )
232 return CALLOC_STRUCT(gl_texture_image
);
238 gl_free_texture_image( struct gl_texture_image
*teximage
)
240 if (teximage
->Data
) {
241 FREE( teximage
->Data
);
242 teximage
->Data
= NULL
;
250 * Examine the texImage->Format field and set the Red, Green, Blue, etc
251 * texel component sizes to default values.
252 * These fields are set only here by core Mesa but device drivers may
253 * overwritting these fields to indicate true texel resolution.
256 set_teximage_component_sizes( struct gl_texture_image
*texImage
)
258 switch (texImage
->Format
) {
260 texImage
->RedBits
= 0;
261 texImage
->GreenBits
= 0;
262 texImage
->BlueBits
= 0;
263 texImage
->AlphaBits
= 8;
264 texImage
->IntensityBits
= 0;
265 texImage
->LuminanceBits
= 0;
266 texImage
->IndexBits
= 0;
269 texImage
->RedBits
= 0;
270 texImage
->GreenBits
= 0;
271 texImage
->BlueBits
= 0;
272 texImage
->AlphaBits
= 0;
273 texImage
->IntensityBits
= 0;
274 texImage
->LuminanceBits
= 8;
275 texImage
->IndexBits
= 0;
277 case GL_LUMINANCE_ALPHA
:
278 texImage
->RedBits
= 0;
279 texImage
->GreenBits
= 0;
280 texImage
->BlueBits
= 0;
281 texImage
->AlphaBits
= 8;
282 texImage
->IntensityBits
= 0;
283 texImage
->LuminanceBits
= 8;
284 texImage
->IndexBits
= 0;
287 texImage
->RedBits
= 0;
288 texImage
->GreenBits
= 0;
289 texImage
->BlueBits
= 0;
290 texImage
->AlphaBits
= 0;
291 texImage
->IntensityBits
= 8;
292 texImage
->LuminanceBits
= 0;
293 texImage
->IndexBits
= 0;
296 texImage
->RedBits
= 8;
297 texImage
->GreenBits
= 0;
298 texImage
->BlueBits
= 0;
299 texImage
->AlphaBits
= 0;
300 texImage
->IntensityBits
= 0;
301 texImage
->LuminanceBits
= 0;
302 texImage
->IndexBits
= 0;
305 texImage
->RedBits
= 0;
306 texImage
->GreenBits
= 8;
307 texImage
->BlueBits
= 0;
308 texImage
->AlphaBits
= 0;
309 texImage
->IntensityBits
= 0;
310 texImage
->LuminanceBits
= 0;
311 texImage
->IndexBits
= 0;
314 texImage
->RedBits
= 0;
315 texImage
->GreenBits
= 0;
316 texImage
->BlueBits
= 8;
317 texImage
->AlphaBits
= 0;
318 texImage
->IntensityBits
= 0;
319 texImage
->LuminanceBits
= 0;
320 texImage
->IndexBits
= 0;
324 texImage
->RedBits
= 8;
325 texImage
->GreenBits
= 8;
326 texImage
->BlueBits
= 8;
327 texImage
->AlphaBits
= 0;
328 texImage
->IntensityBits
= 0;
329 texImage
->LuminanceBits
= 0;
330 texImage
->IndexBits
= 0;
335 texImage
->RedBits
= 8;
336 texImage
->GreenBits
= 8;
337 texImage
->BlueBits
= 8;
338 texImage
->AlphaBits
= 8;
339 texImage
->IntensityBits
= 0;
340 texImage
->LuminanceBits
= 0;
341 texImage
->IndexBits
= 0;
344 texImage
->RedBits
= 0;
345 texImage
->GreenBits
= 0;
346 texImage
->BlueBits
= 0;
347 texImage
->AlphaBits
= 0;
348 texImage
->IntensityBits
= 0;
349 texImage
->LuminanceBits
= 0;
350 texImage
->IndexBits
= 8;
353 gl_problem(NULL
, "unexpected format in set_teximage_component_sizes");
358 /* Need this to prevent an out-of-bounds memory access when using
359 * X86 optimized code.
362 # define EXTRA_BYTE 1
364 # define EXTRA_BYTE 0
370 * This is called by glTexImage[123]D in order to build a gl_texture_image
371 * object given the client's parameters and image data.
373 * NOTES: Width, height and depth should include the border.
374 * All texture image parameters should have already been error checked.
376 static struct gl_texture_image
*
377 make_texture_image( GLcontext
*ctx
, GLint internalFormat
,
378 GLint width
, GLint height
, GLint depth
, GLint border
,
379 GLenum srcFormat
, GLenum srcType
, const GLvoid
*pixels
,
380 const struct gl_pixelstore_attrib
*unpacking
)
382 GLint components
, numPixels
;
383 struct gl_texture_image
*texImage
;
388 assert(border
== 0 || border
== 1);
394 * Allocate and initialize the texture_image struct
396 texImage
= gl_alloc_texture_image();
400 texImage
->Format
= (GLenum
) decode_internal_format(internalFormat
);
401 set_teximage_component_sizes( texImage
);
402 texImage
->IntFormat
= (GLenum
) internalFormat
;
403 texImage
->Border
= border
;
404 texImage
->Width
= width
;
405 texImage
->Height
= height
;
406 texImage
->Depth
= depth
;
407 texImage
->WidthLog2
= logbase2(width
- 2 * border
);
408 if (height
== 1) /* 1-D texture */
409 texImage
->HeightLog2
= 0;
411 texImage
->HeightLog2
= logbase2(height
- 2 * border
);
412 if (depth
== 1) /* 2-D texture */
413 texImage
->DepthLog2
= 0;
415 texImage
->DepthLog2
= logbase2(depth
- 2 * border
);
416 texImage
->Width2
= 1 << texImage
->WidthLog2
;
417 texImage
->Height2
= 1 << texImage
->HeightLog2
;
418 texImage
->Depth2
= 1 << texImage
->DepthLog2
;
419 texImage
->MaxLog2
= MAX2(texImage
->WidthLog2
, texImage
->HeightLog2
);
421 components
= components_in_intformat(internalFormat
);
422 numPixels
= texImage
->Width
* texImage
->Height
* texImage
->Depth
;
424 texImage
->Data
= (GLubyte
*) MALLOC(numPixels
* components
+ EXTRA_BYTE
);
426 if (!texImage
->Data
) {
428 gl_free_texture_image(texImage
);
434 * OK, the texture image struct has been initialized and the texture
435 * image memory has been allocated.
436 * Now fill in the texture image from the source data.
437 * This includes applying the pixel transfer operations.
440 /* try common 2D texture cases first */
441 if (!ctx
->Pixel
.ScaleOrBiasRGBA
&& !ctx
->Pixel
.MapColorFlag
442 && !ctx
->Pixel
.IndexOffset
&& !ctx
->Pixel
.IndexShift
443 && srcType
== GL_UNSIGNED_BYTE
&& depth
== 1) {
445 if (srcFormat
== internalFormat
) {
446 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
447 * GL_LUMINANCE_ALPHA, etc. texture formats.
449 const GLubyte
*src
= gl_pixel_addr_in_image(unpacking
,
450 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
451 const GLubyte
*src1
= gl_pixel_addr_in_image(unpacking
,
452 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
453 const GLint srcStride
= src1
- src
;
454 GLubyte
*dst
= texImage
->Data
;
455 GLint dstBytesPerRow
= width
* components
* sizeof(GLubyte
);
456 if (srcStride
== dstBytesPerRow
) {
457 MEMCPY(dst
, src
, height
* dstBytesPerRow
);
461 for (i
= 0; i
< height
; i
++) {
462 MEMCPY(dst
, src
, dstBytesPerRow
);
464 dst
+= dstBytesPerRow
;
467 return texImage
; /* all done */
469 else if (srcFormat
== GL_RGBA
&& internalFormat
== GL_RGB
) {
470 /* commonly used by Quake */
471 const GLubyte
*src
= gl_pixel_addr_in_image(unpacking
,
472 pixels
, width
, height
, srcFormat
, srcType
, 0, 0, 0);
473 const GLubyte
*src1
= gl_pixel_addr_in_image(unpacking
,
474 pixels
, width
, height
, srcFormat
, srcType
, 0, 1, 0);
475 const GLint srcStride
= src1
- src
;
476 GLubyte
*dst
= texImage
->Data
;
478 for (i
= 0; i
< height
; i
++) {
479 const GLubyte
*s
= src
;
480 for (j
= 0; j
< width
; j
++) {
481 *dst
++ = *s
++; /*red*/
482 *dst
++ = *s
++; /*green*/
483 *dst
++ = *s
++; /*blue*/
488 return texImage
; /* all done */
494 * General case solutions
496 if (texImage
->Format
== GL_COLOR_INDEX
) {
497 /* color index texture */
498 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
499 const GLenum dstType
= GL_UNSIGNED_BYTE
;
500 GLubyte
*dest
= texImage
->Data
;
502 for (img
= 0; img
< depth
; img
++) {
503 for (row
= 0; row
< height
; row
++) {
504 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
505 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
506 _mesa_unpack_index_span(ctx
, width
, dstType
, dest
,
507 srcType
, source
, unpacking
, GL_TRUE
);
508 dest
+= destBytesPerRow
;
513 /* regular, color texture */
514 const GLint destBytesPerRow
= width
* components
* sizeof(GLubyte
);
515 const GLenum dstFormat
= texImage
->Format
;
516 GLubyte
*dest
= texImage
->Data
;
518 for (img
= 0; img
< depth
; img
++) {
519 for (row
= 0; row
< height
; row
++) {
520 const GLvoid
*source
= gl_pixel_addr_in_image(unpacking
,
521 pixels
, width
, height
, srcFormat
, srcType
, img
, row
, 0);
522 _mesa_unpack_ubyte_color_span(ctx
, width
, dstFormat
, dest
,
523 srcFormat
, srcType
, source
, unpacking
, GL_TRUE
);
524 dest
+= destBytesPerRow
;
529 return texImage
; /* All done! */
535 * glTexImage[123]D can accept a NULL image pointer. In this case we
536 * create a texture image with unspecified image contents per the OpenGL
539 static struct gl_texture_image
*
540 make_null_texture( GLcontext
*ctx
, GLenum internalFormat
,
541 GLsizei width
, GLsizei height
, GLsizei depth
, GLint border
)
544 struct gl_texture_image
*texImage
;
548 /*internalFormat = decode_internal_format(internalFormat);*/
549 components
= components_in_intformat(internalFormat
);
550 numPixels
= width
* height
* depth
;
552 texImage
= gl_alloc_texture_image();
556 texImage
->Format
= (GLenum
) decode_internal_format(internalFormat
);
557 set_teximage_component_sizes( texImage
);
558 texImage
->IntFormat
= internalFormat
;
559 texImage
->Border
= border
;
560 texImage
->Width
= width
;
561 texImage
->Height
= height
;
562 texImage
->Depth
= depth
;
563 texImage
->WidthLog2
= logbase2(width
- 2*border
);
564 if (height
==1) /* 1-D texture */
565 texImage
->HeightLog2
= 0;
567 texImage
->HeightLog2
= logbase2(height
- 2*border
);
568 if (depth
==1) /* 2-D texture */
569 texImage
->DepthLog2
= 0;
571 texImage
->DepthLog2
= logbase2(depth
- 2*border
);
572 texImage
->Width2
= 1 << texImage
->WidthLog2
;
573 texImage
->Height2
= 1 << texImage
->HeightLog2
;
574 texImage
->Depth2
= 1 << texImage
->DepthLog2
;
575 texImage
->MaxLog2
= MAX2( texImage
->WidthLog2
, texImage
->HeightLog2
);
577 /* XXX should we really allocate memory for the image or let it be NULL? */
578 /*texImage->Data = NULL;*/
580 texImage
->Data
= (GLubyte
*) MALLOC( numPixels
* components
+ EXTRA_BYTE
);
583 * Let's see if anyone finds this. If glTexImage2D() is called with
584 * a NULL image pointer then load the texture image with something
585 * interesting instead of leaving it indeterminate.
587 if (texImage
->Data
) {
588 char message
[8][32] = {
592 " X X XXXX XXX XXXXX ",
595 " X X XXXXX XXX X X ",
599 GLubyte
*imgPtr
= texImage
->Data
;
601 for (i
=0;i
<height
;i
++) {
602 GLint srcRow
= 7 - i
% 8;
603 for (j
=0;j
<width
;j
++) {
604 GLint srcCol
= j
% 32;
605 GLint texel
= (message
[srcRow
][srcCol
]=='X') ? 255 : 70;
606 for (k
=0;k
<components
;k
++) {
607 *imgPtr
++ = (GLubyte
) texel
;
619 * Test glTexImage[123]D() parameters for errors.
621 * dimensions - must be 1 or 2 or 3
622 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
625 texture_error_check( GLcontext
*ctx
, GLenum target
,
626 GLint level
, GLint internalFormat
,
627 GLenum format
, GLenum type
,
629 GLint width
, GLint height
,
630 GLint depth
, GLint border
)
635 if (dimensions
== 1) {
636 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_1D
);
637 if (target
!= GL_TEXTURE_1D
&& !isProxy
) {
638 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
642 else if (dimensions
== 2) {
643 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_2D
);
644 if (target
!= GL_TEXTURE_2D
&& !isProxy
) {
645 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
649 else if (dimensions
== 3) {
650 isProxy
= (GLboolean
) (target
== GL_PROXY_TEXTURE_3D
);
651 if (target
!= GL_TEXTURE_3D
&& !isProxy
) {
652 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
657 gl_problem( ctx
, "bad dims in texture_error_check" );
662 if (border
!=0 && border
!=1) {
665 sprintf(message
, "glTexImage%dD(border)", dimensions
);
666 gl_error(ctx
, GL_INVALID_VALUE
, message
);
672 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
673 || logbase2( width
- 2 * border
) < 0) {
676 sprintf(message
, "glTexImage%dD(width)", dimensions
);
677 gl_error(ctx
, GL_INVALID_VALUE
, message
);
683 if (dimensions
>= 2) {
684 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
685 || logbase2( height
- 2 * border
) < 0) {
688 sprintf(message
, "glTexImage%dD(height)", dimensions
);
689 gl_error(ctx
, GL_INVALID_VALUE
, message
);
696 if (dimensions
>= 3) {
697 if (depth
< 2 * border
|| depth
> 2 + ctx
->Const
.MaxTextureSize
698 || logbase2( depth
- 2 * border
) < 0) {
700 gl_error( ctx
, GL_INVALID_VALUE
, "glTexImage3D(depth)" );
707 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
710 sprintf(message
, "glTexImage%dD(level)", dimensions
);
711 gl_error(ctx
, GL_INVALID_VALUE
, message
);
716 iformat
= decode_internal_format( internalFormat
);
720 sprintf(message
, "glTexImage%dD(internalFormat)", dimensions
);
721 gl_error(ctx
, GL_INVALID_VALUE
, message
);
726 if (!gl_is_legal_format_and_type( format
, type
)) {
727 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
728 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
732 sprintf(message
, "glTexImage%dD(format or type)", dimensions
);
733 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
738 /* if we get here, the parameters are OK */
745 * Test glTexSubImage[123]D() parameters for errors.
747 * dimensions - must be 1 or 2 or 3
748 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
751 subtexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
752 GLenum target
, GLint level
,
753 GLint xoffset
, GLint yoffset
, GLint zoffset
,
754 GLint width
, GLint height
, GLint depth
,
755 GLenum format
, GLenum type
)
757 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
758 struct gl_texture_image
*destTex
;
760 if (dimensions
== 1) {
761 if (target
!= GL_TEXTURE_1D
) {
762 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage1D(target)" );
766 else if (dimensions
== 2) {
767 if (target
!= GL_TEXTURE_2D
) {
768 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(target)" );
772 else if (dimensions
== 3) {
773 if (target
!= GL_TEXTURE_3D
) {
774 gl_error( ctx
, GL_INVALID_ENUM
, "glTexSubImage3D(target)" );
779 gl_problem( ctx
, "bad dims in texture_error_check" );
783 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
784 gl_error(ctx
, GL_INVALID_ENUM
, "glTexSubImage2D(level)");
790 sprintf(message
, "glTexSubImage%dD(width)", dimensions
);
791 gl_error(ctx
, GL_INVALID_VALUE
, message
);
794 if (height
< 0 && dimensions
> 1) {
796 sprintf(message
, "glTexSubImage%dD(height)", dimensions
);
797 gl_error(ctx
, GL_INVALID_VALUE
, message
);
800 if (depth
< 0 && dimensions
> 2) {
802 sprintf(message
, "glTexSubImage%dD(depth)", dimensions
);
803 gl_error(ctx
, GL_INVALID_VALUE
, message
);
807 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
809 gl_error(ctx
, GL_INVALID_OPERATION
, "glTexSubImage2D");
813 if (xoffset
< -((GLint
)destTex
->Border
)) {
814 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset)");
817 if (xoffset
+ width
> (GLint
) (destTex
->Width
+ destTex
->Border
)) {
818 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage1/2/3D(xoffset+width)");
821 if (dimensions
> 1) {
822 if (yoffset
< -((GLint
)destTex
->Border
)) {
823 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset)");
826 if (yoffset
+ height
> (GLint
) (destTex
->Height
+ destTex
->Border
)) {
827 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage2/3D(yoffset+height)");
831 if (dimensions
> 2) {
832 if (zoffset
< -((GLint
)destTex
->Border
)) {
833 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset)");
836 if (zoffset
+ depth
> (GLint
) (destTex
->Depth
+destTex
->Border
)) {
837 gl_error(ctx
, GL_INVALID_VALUE
, "glTexSubImage3D(zoffset+depth)");
842 if (!gl_is_legal_format_and_type(format
, type
)) {
844 sprintf(message
, "glTexSubImage%dD(format or type)", dimensions
);
845 gl_error(ctx
, GL_INVALID_ENUM
, message
);
854 * Test glCopyTexImage[12]D() parameters for errors.
855 * Input: dimensions - must be 1 or 2 or 3
856 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
859 copytexture_error_check( GLcontext
*ctx
, GLuint dimensions
,
860 GLenum target
, GLint level
, GLint internalFormat
,
861 GLint width
, GLint height
, GLint border
)
865 if (target
!= GL_TEXTURE_1D
&& target
!= GL_TEXTURE_2D
) {
866 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1/2D(target)" );
870 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
871 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage1D(target)" );
874 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
875 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexImage2D(target)" );
880 if (border
!=0 && border
!=1) {
882 sprintf(message
, "glCopyTexImage%dD(border)", dimensions
);
883 gl_error(ctx
, GL_INVALID_VALUE
, message
);
888 if (width
< 2 * border
|| width
> 2 + ctx
->Const
.MaxTextureSize
889 || logbase2( width
- 2 * border
) < 0) {
891 sprintf(message
, "glCopyTexImage%dD(width)", dimensions
);
892 gl_error(ctx
, GL_INVALID_VALUE
, message
);
897 if (dimensions
>= 2) {
898 if (height
< 2 * border
|| height
> 2 + ctx
->Const
.MaxTextureSize
899 || logbase2( height
- 2 * border
) < 0) {
901 sprintf(message
, "glCopyTexImage%dD(height)", dimensions
);
902 gl_error(ctx
, GL_INVALID_VALUE
, message
);
908 if (level
<0 || level
>=ctx
->Const
.MaxTextureLevels
) {
910 sprintf(message
, "glCopyTexImage%dD(level)", dimensions
);
911 gl_error(ctx
, GL_INVALID_VALUE
, message
);
915 iformat
= decode_internal_format( internalFormat
);
918 sprintf(message
, "glCopyTexImage%dD(internalFormat)", dimensions
);
919 gl_error(ctx
, GL_INVALID_VALUE
, message
);
923 /* if we get here, the parameters are OK */
929 copytexsubimage_error_check( GLcontext
*ctx
, GLuint dimensions
,
930 GLenum target
, GLint level
,
931 GLint xoffset
, GLint yoffset
, GLint zoffset
,
932 GLsizei width
, GLsizei height
)
934 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
935 struct gl_texture_image
*teximage
;
937 if (dimensions
== 1 && target
!= GL_TEXTURE_1D
) {
938 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage1D(target)" );
941 else if (dimensions
== 2 && target
!= GL_TEXTURE_2D
) {
942 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage2D(target)" );
945 else if (dimensions
== 3 && target
!= GL_TEXTURE_3D
) {
946 gl_error( ctx
, GL_INVALID_ENUM
, "glCopyTexSubImage3D(target)" );
950 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
952 sprintf(message
, "glCopyTexSubImage%dD(level)", dimensions
);
953 gl_error(ctx
, GL_INVALID_VALUE
, message
);
959 sprintf(message
, "glCopyTexSubImage%dD(width)", dimensions
);
960 gl_error(ctx
, GL_INVALID_VALUE
, message
);
963 if (dimensions
> 1 && height
< 0) {
965 sprintf(message
, "glCopyTexSubImage%dD(height)", dimensions
);
966 gl_error(ctx
, GL_INVALID_VALUE
, message
);
970 teximage
= texUnit
->CurrentD
[3]->Image
[level
];
973 sprintf(message
, "glCopyTexSubImage%dD(undefined texture)", dimensions
);
974 gl_error(ctx
, GL_INVALID_OPERATION
, message
);
978 if (xoffset
< -((GLint
)teximage
->Border
)) {
980 sprintf(message
, "glCopyTexSubImage%dD(xoffset)", dimensions
);
981 gl_error(ctx
, GL_INVALID_VALUE
, message
);
984 if (xoffset
+width
> (GLint
) (teximage
->Width
+teximage
->Border
)) {
986 sprintf(message
, "glCopyTexSubImage%dD(xoffset+width)", dimensions
);
987 gl_error(ctx
, GL_INVALID_VALUE
, message
);
990 if (dimensions
> 1) {
991 if (yoffset
< -((GLint
)teximage
->Border
)) {
993 sprintf(message
, "glCopyTexSubImage%dD(yoffset)", dimensions
);
994 gl_error(ctx
, GL_INVALID_VALUE
, message
);
997 /* NOTE: we're adding the border here, not subtracting! */
998 if (yoffset
+height
> (GLint
) (teximage
->Height
+teximage
->Border
)) {
1000 sprintf(message
, "glCopyTexSubImage%dD(yoffset+height)", dimensions
);
1001 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1006 if (dimensions
> 2) {
1007 if (zoffset
< -((GLint
)teximage
->Border
)) {
1009 sprintf(message
, "glCopyTexSubImage%dD(zoffset)", dimensions
);
1010 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1013 if (zoffset
> (GLint
) (teximage
->Depth
+teximage
->Border
)) {
1015 sprintf(message
, "glCopyTexSubImage%dD(zoffset+depth)", dimensions
);
1016 gl_error(ctx
, GL_INVALID_VALUE
, message
);
1021 /* if we get here, the parameters are OK */
1029 * Called from the API. Note that width includes the border.
1032 _mesa_TexImage1D( GLenum target
, GLint level
, GLint internalformat
,
1033 GLsizei width
, GLint border
, GLenum format
,
1034 GLenum type
, const GLvoid
*pixels
)
1036 GET_CURRENT_CONTEXT(ctx
);
1037 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1038 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage1D");
1040 if (target
==GL_TEXTURE_1D
) {
1041 struct gl_texture_image
*teximage
;
1042 if (texture_error_check( ctx
, target
, level
, internalformat
,
1043 format
, type
, 1, width
, 1, 1, border
)) {
1044 /* error in texture image was detected */
1048 /* free current texture image, if any */
1049 if (texUnit
->CurrentD
[1]->Image
[level
]) {
1050 gl_free_texture_image( texUnit
->CurrentD
[1]->Image
[level
] );
1053 /* make new texture from source image */
1055 teximage
= make_texture_image(ctx
, internalformat
, width
, 1, 1,
1056 border
, format
, type
, pixels
, &ctx
->Unpack
);
1059 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1060 width
, 1, 1, border
);
1063 /* install new texture image */
1064 texUnit
->CurrentD
[1]->Image
[level
] = teximage
;
1065 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1066 ctx
->NewState
|= NEW_TEXTURING
;
1068 /* tell driver about change */
1069 if (ctx
->Driver
.TexImage
) {
1070 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1071 texUnit
->CurrentD
[1],
1072 level
, internalformat
, teximage
);
1075 else if (target
==GL_PROXY_TEXTURE_1D
) {
1076 /* Proxy texture: check for errors and update proxy state */
1077 if (texture_error_check( ctx
, target
, level
, internalformat
,
1078 format
, type
, 1, width
, 1, 1, border
)) {
1079 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1080 MEMSET( ctx
->Texture
.Proxy1D
->Image
[level
], 0,
1081 sizeof(struct gl_texture_image
) );
1085 ctx
->Texture
.Proxy1D
->Image
[level
]->Format
= (GLenum
) format
;
1086 set_teximage_component_sizes( ctx
->Texture
.Proxy1D
->Image
[level
] );
1087 ctx
->Texture
.Proxy1D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1088 ctx
->Texture
.Proxy1D
->Image
[level
]->Border
= border
;
1089 ctx
->Texture
.Proxy1D
->Image
[level
]->Width
= width
;
1090 ctx
->Texture
.Proxy1D
->Image
[level
]->Height
= 1;
1091 ctx
->Texture
.Proxy1D
->Image
[level
]->Depth
= 1;
1095 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage1D(target)" );
1102 _mesa_TexImage2D( GLenum target
, GLint level
, GLint internalformat
,
1103 GLsizei width
, GLsizei height
, GLint border
,
1104 GLenum format
, GLenum type
,
1105 const GLvoid
*pixels
)
1107 GET_CURRENT_CONTEXT(ctx
);
1108 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1109 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage2D");
1111 if (target
==GL_TEXTURE_2D
) {
1112 struct gl_texture_image
*teximage
;
1113 if (texture_error_check( ctx
, target
, level
, internalformat
,
1114 format
, type
, 2, width
, height
, 1, border
)) {
1115 /* error in texture image was detected */
1119 /* free current texture image, if any */
1120 if (texUnit
->CurrentD
[2]->Image
[level
]) {
1121 gl_free_texture_image( texUnit
->CurrentD
[2]->Image
[level
] );
1124 /* make new texture from source image */
1126 teximage
= make_texture_image(ctx
, internalformat
, width
, height
, 1,
1127 border
, format
, type
, pixels
, &ctx
->Unpack
);
1130 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1131 width
, height
, 1, border
);
1134 /* install new texture image */
1135 texUnit
->CurrentD
[2]->Image
[level
] = teximage
;
1136 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1137 ctx
->NewState
|= NEW_TEXTURING
;
1139 /* tell driver about change */
1140 if (ctx
->Driver
.TexImage
) {
1141 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1142 texUnit
->CurrentD
[2],
1143 level
, internalformat
, teximage
);
1146 else if (target
==GL_PROXY_TEXTURE_2D
) {
1147 /* Proxy texture: check for errors and update proxy state */
1148 if (texture_error_check( ctx
, target
, level
, internalformat
,
1149 format
, type
, 2, width
, height
, 1, border
)) {
1150 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1151 MEMSET( ctx
->Texture
.Proxy2D
->Image
[level
], 0,
1152 sizeof(struct gl_texture_image
) );
1156 ctx
->Texture
.Proxy2D
->Image
[level
]->Format
= (GLenum
) format
;
1157 set_teximage_component_sizes( ctx
->Texture
.Proxy2D
->Image
[level
] );
1158 ctx
->Texture
.Proxy2D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1159 ctx
->Texture
.Proxy2D
->Image
[level
]->Border
= border
;
1160 ctx
->Texture
.Proxy2D
->Image
[level
]->Width
= width
;
1161 ctx
->Texture
.Proxy2D
->Image
[level
]->Height
= height
;
1162 ctx
->Texture
.Proxy2D
->Image
[level
]->Depth
= 1;
1166 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage2D(target)" );
1174 * Called by the API or display list executor.
1175 * Note that width and height include the border.
1178 _mesa_TexImage3D( GLenum target
, GLint level
, GLint internalformat
,
1179 GLsizei width
, GLsizei height
, GLsizei depth
,
1180 GLint border
, GLenum format
, GLenum type
,
1181 const GLvoid
*pixels
)
1183 GET_CURRENT_CONTEXT(ctx
);
1184 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1185 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glTexImage3DEXT");
1187 if (target
==GL_TEXTURE_3D_EXT
) {
1188 struct gl_texture_image
*teximage
;
1189 if (texture_error_check( ctx
, target
, level
, internalformat
,
1190 format
, type
, 3, width
, height
, depth
,
1192 /* error in texture image was detected */
1196 /* free current texture image, if any */
1197 if (texUnit
->CurrentD
[3]->Image
[level
]) {
1198 gl_free_texture_image( texUnit
->CurrentD
[3]->Image
[level
] );
1201 /* make new texture from source image */
1203 teximage
= make_texture_image(ctx
, internalformat
, width
, height
,
1204 depth
, border
, format
, type
, pixels
, &ctx
->Unpack
);
1207 teximage
= make_null_texture(ctx
, (GLenum
) internalformat
,
1208 width
, height
, depth
, border
);
1211 /* install new texture image */
1212 texUnit
->CurrentD
[3]->Image
[level
] = teximage
;
1213 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[3] );
1214 ctx
->NewState
|= NEW_TEXTURING
;
1216 /* tell driver about change */
1217 if (ctx
->Driver
.TexImage
) {
1218 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D_EXT
,
1219 texUnit
->CurrentD
[3],
1220 level
, internalformat
, teximage
);
1223 else if (target
==GL_PROXY_TEXTURE_3D_EXT
) {
1224 /* Proxy texture: check for errors and update proxy state */
1225 if (texture_error_check( ctx
, target
, level
, internalformat
,
1226 format
, type
, 3, width
, height
, depth
,
1228 if (level
>=0 && level
<ctx
->Const
.MaxTextureLevels
) {
1229 MEMSET( ctx
->Texture
.Proxy3D
->Image
[level
], 0,
1230 sizeof(struct gl_texture_image
) );
1234 ctx
->Texture
.Proxy3D
->Image
[level
]->Format
= (GLenum
) format
;
1235 set_teximage_component_sizes( ctx
->Texture
.Proxy3D
->Image
[level
] );
1236 ctx
->Texture
.Proxy3D
->Image
[level
]->IntFormat
= (GLenum
) internalformat
;
1237 ctx
->Texture
.Proxy3D
->Image
[level
]->Border
= border
;
1238 ctx
->Texture
.Proxy3D
->Image
[level
]->Width
= width
;
1239 ctx
->Texture
.Proxy3D
->Image
[level
]->Height
= height
;
1240 ctx
->Texture
.Proxy3D
->Image
[level
]->Depth
= depth
;
1244 gl_error( ctx
, GL_INVALID_ENUM
, "glTexImage3D(target)" );
1252 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
1253 GLenum type
, GLvoid
*pixels
)
1255 GET_CURRENT_CONTEXT(ctx
);
1256 const struct gl_texture_object
*texObj
;
1258 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glGetTexImage");
1260 if (level
< 0 || level
>= ctx
->Const
.MaxTextureLevels
) {
1261 gl_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
1265 if (gl_sizeof_type(type
) <= 0) {
1266 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
1270 if (gl_components_in_format(format
) <= 0) {
1271 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
1276 return; /* XXX generate an error??? */
1280 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[1];
1283 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[2];
1286 texObj
= ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
].CurrentD
[3];
1289 gl_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)" );
1293 if (texObj
->Image
[level
] && texObj
->Image
[level
]->Data
) {
1294 const struct gl_texture_image
*texImage
= texObj
->Image
[level
];
1295 GLint width
= texImage
->Width
;
1296 GLint height
= texImage
->Height
;
1299 for (row
= 0; row
< height
; row
++) {
1300 /* compute destination address in client memory */
1301 GLvoid
*dest
= gl_pixel_addr_in_image( &ctx
->Unpack
, pixels
,
1303 format
, type
, 0, row
, 0);
1306 if (texImage
->Format
== GL_RGBA
) {
1307 const GLubyte
*src
= texImage
->Data
+ row
* width
* 4 * sizeof(GLubyte
);
1308 gl_pack_rgba_span( ctx
, width
, (void *) src
, format
, type
, dest
,
1309 &ctx
->Pack
, GL_TRUE
);
1312 /* fetch RGBA row from texture image then pack it in client mem */
1313 GLubyte rgba
[MAX_WIDTH
][4];
1316 switch (texImage
->Format
) {
1318 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1319 for (i
= 0; i
< width
; i
++) {
1320 rgba
[i
][RCOMP
] = 255;
1321 rgba
[i
][GCOMP
] = 255;
1322 rgba
[i
][BCOMP
] = 255;
1323 rgba
[i
][ACOMP
] = src
[i
];
1327 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1328 for (i
= 0; i
< width
; i
++) {
1329 rgba
[i
][RCOMP
] = src
[i
];
1330 rgba
[i
][GCOMP
] = src
[i
];
1331 rgba
[i
][BCOMP
] = src
[i
];
1332 rgba
[i
][ACOMP
] = 255;
1335 case GL_LUMINANCE_ALPHA
:
1336 src
= texImage
->Data
+ row
* 2 * width
* sizeof(GLubyte
);
1337 for (i
= 0; i
< width
; i
++) {
1338 rgba
[i
][RCOMP
] = src
[i
*2+0];
1339 rgba
[i
][GCOMP
] = src
[i
*2+0];
1340 rgba
[i
][BCOMP
] = src
[i
*2+0];
1341 rgba
[i
][ACOMP
] = src
[i
*2+1];
1345 src
= texImage
->Data
+ row
* width
* sizeof(GLubyte
);
1346 for (i
= 0; i
< width
; i
++) {
1347 rgba
[i
][RCOMP
] = src
[i
];
1348 rgba
[i
][GCOMP
] = src
[i
];
1349 rgba
[i
][BCOMP
] = src
[i
];
1350 rgba
[i
][ACOMP
] = 255;
1354 src
= texImage
->Data
+ row
* 3 * width
* sizeof(GLubyte
);
1355 for (i
= 0; i
< width
; i
++) {
1356 rgba
[i
][RCOMP
] = src
[i
*3+0];
1357 rgba
[i
][GCOMP
] = src
[i
*3+1];
1358 rgba
[i
][BCOMP
] = src
[i
*3+2];
1359 rgba
[i
][ACOMP
] = 255;
1363 /* this special case should have been handled above! */
1364 gl_problem( ctx
, "error 1 in gl_GetTexImage" );
1366 case GL_COLOR_INDEX
:
1367 gl_problem( ctx
, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1370 gl_problem( ctx
, "bad format in gl_GetTexImage" );
1372 gl_pack_rgba_span( ctx
, width
, (const GLubyte (*)[4])rgba
,
1373 format
, type
, dest
, &ctx
->Pack
, GL_TRUE
);
1382 _mesa_TexSubImage1D( GLenum target
, GLint level
,
1383 GLint xoffset
, GLsizei width
,
1384 GLenum format
, GLenum type
,
1385 const GLvoid
*pixels
)
1387 GET_CURRENT_CONTEXT(ctx
);
1388 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1389 struct gl_texture_image
*destTex
;
1391 if (subtexture_error_check(ctx
, 1, target
, level
, xoffset
, 0, 0,
1392 width
, 1, 1, format
, type
)) {
1393 /* error was detected */
1397 destTex
= texUnit
->CurrentD
[1]->Image
[level
];
1400 if (width
== 0 || !pixels
)
1401 return; /* no-op, not an error */
1405 * Replace the texture subimage
1408 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1409 const GLenum texFormat
= destTex
->Format
;
1410 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1411 GLubyte
*dst
= destTex
->Data
+ xoffsetb
* texComponents
;
1412 if (texFormat
== GL_COLOR_INDEX
) {
1413 /* color index texture */
1414 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1415 width
, 1, format
, type
, 0, 0, 0);
1416 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1417 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1421 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1422 width
, 1, format
, type
, 0, 0, 0);
1423 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1424 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1428 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1431 * Inform device driver of texture image change.
1433 if (ctx
->Driver
.TexSubImage
) {
1434 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1435 level
, xoffset
, 0, width
, 1,
1436 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1440 if (ctx
->Driver
.TexImage
) {
1441 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_1D
, texUnit
->CurrentD
[1],
1443 texUnit
->CurrentD
[1]->Image
[level
]->IntFormat
,
1451 _mesa_TexSubImage2D( GLenum target
, GLint level
,
1452 GLint xoffset
, GLint yoffset
,
1453 GLsizei width
, GLsizei height
,
1454 GLenum format
, GLenum type
,
1455 const GLvoid
*pixels
)
1457 GET_CURRENT_CONTEXT(ctx
);
1458 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1459 struct gl_texture_image
*destTex
;
1461 if (subtexture_error_check(ctx
, 2, target
, level
, xoffset
, yoffset
, 0,
1462 width
, height
, 1, format
, type
)) {
1463 /* error was detected */
1467 destTex
= texUnit
->CurrentD
[2]->Image
[level
];
1470 if (width
== 0 || height
== 0 || !pixels
)
1471 return; /* no-op, not an error */
1475 * Replace the texture subimage
1478 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1479 const GLenum texFormat
= destTex
->Format
;
1480 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1481 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1482 GLubyte
*dst
= destTex
->Data
1483 + (yoffsetb
* destTex
->Width
+ xoffsetb
) * texComponents
;
1484 if (texFormat
== GL_COLOR_INDEX
) {
1485 /* color index texture */
1486 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1488 for (row
= 0; row
< height
; row
++) {
1489 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1490 width
, height
, format
, type
, 0, row
, 0);
1491 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1492 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1498 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1500 for (row
= 0; row
< height
; row
++) {
1501 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1502 width
, height
, format
, type
, 0, row
, 0);
1503 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1504 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1510 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[2] );
1513 * Inform device driver of texture image change.
1515 if (ctx
->Driver
.TexSubImage
) {
1516 (*ctx
->Driver
.TexSubImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1517 level
, xoffset
, yoffset
, width
, height
,
1518 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1522 if (ctx
->Driver
.TexImage
) {
1523 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, texUnit
->CurrentD
[2],
1525 texUnit
->CurrentD
[2]->Image
[level
]->IntFormat
,
1534 _mesa_TexSubImage3D( GLenum target
, GLint level
,
1535 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1536 GLsizei width
, GLsizei height
, GLsizei depth
,
1537 GLenum format
, GLenum type
,
1538 const GLvoid
*pixels
)
1540 GET_CURRENT_CONTEXT(ctx
);
1541 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1542 struct gl_texture_image
*destTex
;
1544 if (subtexture_error_check(ctx
, 3, target
, level
, xoffset
, yoffset
, zoffset
,
1545 width
, height
, depth
, format
, type
)) {
1546 /* error was detected */
1550 destTex
= texUnit
->CurrentD
[3]->Image
[level
];
1553 if (width
== 0 || height
== 0 || height
== 0 || !pixels
)
1554 return; /* no-op, not an error */
1557 * Replace the texture subimage
1560 const GLint texComponents
= components_in_intformat(destTex
->Format
);
1561 const GLenum texFormat
= destTex
->Format
;
1562 const GLint xoffsetb
= xoffset
+ destTex
->Border
;
1563 const GLint yoffsetb
= yoffset
+ destTex
->Border
;
1564 const GLint zoffsetb
= zoffset
+ destTex
->Border
;
1565 GLint dstRectArea
= destTex
->Width
* destTex
->Height
;
1566 GLubyte
*dst
= destTex
->Data
1567 + (zoffsetb
* dstRectArea
+ yoffsetb
* destTex
->Width
+ xoffsetb
)
1570 if (texFormat
== GL_COLOR_INDEX
) {
1571 /* color index texture */
1572 const GLint stride
= destTex
->Width
* sizeof(GLubyte
);
1574 for (img
= 0; img
< depth
; img
++) {
1575 for (row
= 0; row
< height
; row
++) {
1576 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1577 width
, height
, format
, type
, img
, row
, 0);
1578 _mesa_unpack_index_span(ctx
, width
, GL_UNSIGNED_BYTE
, dst
,
1579 type
, src
, &ctx
->Unpack
, GL_TRUE
);
1586 const GLint stride
= destTex
->Width
* texComponents
* sizeof(GLubyte
);
1588 for (img
= 0; img
< depth
; img
++) {
1589 for (row
= 0; row
< height
; row
++) {
1590 const GLvoid
*src
= gl_pixel_addr_in_image(&ctx
->Unpack
, pixels
,
1591 width
, height
, format
, type
, img
, row
, 0);
1592 _mesa_unpack_ubyte_color_span(ctx
, width
, texFormat
, dst
,
1593 format
, type
, src
, &ctx
->Unpack
, GL_TRUE
);
1600 gl_put_texobj_on_dirty_list( ctx
, texUnit
->CurrentD
[1] );
1603 * Inform device driver of texture image change.
1611 * Read an RGBA image from the frame buffer.
1612 * This is used by glCopyTexSubImage[12]D().
1613 * Input: ctx - the context
1614 * x, y - lower left corner
1615 * width, height - size of region to read
1616 * Return: pointer to block of GL_RGBA, GLubyte data.
1619 read_color_image( GLcontext
*ctx
, GLint x
, GLint y
,
1620 GLsizei width
, GLsizei height
)
1623 GLubyte
*image
, *dst
;
1625 image
= MALLOC(width
* height
* 4 * sizeof(GLubyte
));
1629 /* Select buffer to read from */
1630 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Pixel
.DriverReadBuffer
);
1633 stride
= width
* 4 * sizeof(GLubyte
);
1634 for (i
= 0; i
< height
; i
++) {
1635 gl_read_rgba_span( ctx
, width
, x
, y
+ i
, (GLubyte (*)[4]) dst
);
1639 /* Restore drawing buffer */
1640 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
1648 _mesa_CopyTexImage1D( GLenum target
, GLint level
,
1649 GLenum internalFormat
,
1651 GLsizei width
, GLint border
)
1653 GET_CURRENT_CONTEXT(ctx
);
1654 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage1D");
1656 if (!copytexture_error_check(ctx
, 1, target
, level
, internalFormat
,
1657 width
, 1, border
)) {
1658 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, 1 );
1660 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage1D" );
1663 (*ctx
->Exec
.TexImage1D
)( target
, level
, internalFormat
, width
,
1664 border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1672 _mesa_CopyTexImage2D( GLenum target
, GLint level
, GLenum internalFormat
,
1673 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1676 GET_CURRENT_CONTEXT(ctx
);
1677 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexImage2D");
1679 if (!copytexture_error_check(ctx
, 2, target
, level
, internalFormat
,
1680 width
, height
, border
)) {
1681 GLubyte
*image
= read_color_image( ctx
, x
, y
, width
, height
);
1683 gl_error( ctx
, GL_OUT_OF_MEMORY
, "glCopyTexImage2D" );
1686 (ctx
->Exec
.TexImage2D
)( target
, level
, internalFormat
, width
,
1687 height
, border
, GL_RGBA
, GL_UNSIGNED_BYTE
, image
);
1695 * Do the work of glCopyTexSubImage[123]D.
1698 copy_tex_sub_image( GLcontext
*ctx
, struct gl_texture_image
*dest
,
1699 GLint width
, GLint height
,
1700 GLint srcx
, GLint srcy
,
1701 GLint dstx
, GLint dsty
, GLint dstz
)
1703 static struct gl_pixelstore_attrib packing
= {
1708 0, /* ImageHeight */
1710 GL_FALSE
, /* SwapBytes */
1711 GL_FALSE
/* LsbFirst */
1715 GLint format
, components
, rectarea
;
1716 GLint texwidth
, texheight
, zoffset
;
1718 /* dst[xyz] may be negative if we have a texture border! */
1719 dstx
+= dest
->Border
;
1720 dsty
+= dest
->Border
;
1721 dstz
+= dest
->Border
;
1722 texwidth
= dest
->Width
;
1723 texheight
= dest
->Height
;
1724 rectarea
= texwidth
* texheight
;
1725 zoffset
= dstz
* rectarea
;
1726 format
= dest
->Format
;
1727 components
= components_in_intformat( format
);
1729 /* Select buffer to read from */
1730 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Pixel
.DriverReadBuffer
);
1732 for (i
= 0;i
< height
; i
++) {
1733 GLubyte rgba
[MAX_WIDTH
][4];
1735 gl_read_rgba_span( ctx
, width
, srcx
, srcy
+ i
, rgba
);
1736 dst
= dest
->Data
+ ( zoffset
+ (dsty
+i
) * texwidth
+ dstx
) * components
;
1737 _mesa_unpack_ubyte_color_span(ctx
, width
, format
, dst
,
1738 GL_RGBA
, GL_UNSIGNED_BYTE
, rgba
,
1742 /* Restore drawing buffer */
1743 (void) (*ctx
->Driver
.SetBuffer
)( ctx
, ctx
->Color
.DriverDrawBuffer
);
1750 _mesa_CopyTexSubImage1D( GLenum target
, GLint level
,
1751 GLint xoffset
, GLint x
, GLint y
, GLsizei width
)
1753 GET_CURRENT_CONTEXT(ctx
);
1754 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage1D");
1756 if (!copytexsubimage_error_check(ctx
, 1, target
, level
,
1757 xoffset
, 0, 0, width
, 1)) {
1758 struct gl_texture_unit
*texUnit
;
1759 struct gl_texture_image
*teximage
;
1760 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1761 teximage
= texUnit
->CurrentD
[1]->Image
[level
];
1763 if (teximage
->Data
) {
1764 copy_tex_sub_image(ctx
, teximage
, width
, 1, x
, y
, xoffset
, 0, 0);
1765 /* tell driver about the change */
1766 if (ctx
->Driver
.TexImage
) {
1767 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_1D
,
1768 texUnit
->CurrentD
[1],
1769 level
, teximage
->IntFormat
, teximage
);
1778 _mesa_CopyTexSubImage2D( GLenum target
, GLint level
,
1779 GLint xoffset
, GLint yoffset
,
1780 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1782 GET_CURRENT_CONTEXT(ctx
);
1783 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage2D");
1785 if (!copytexsubimage_error_check(ctx
, 2, target
, level
,
1786 xoffset
, yoffset
, 0, width
, height
)) {
1787 struct gl_texture_unit
*texUnit
;
1788 struct gl_texture_image
*teximage
;
1789 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1790 teximage
= texUnit
->CurrentD
[2]->Image
[level
];
1792 if (teximage
->Data
) {
1793 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1794 x
, y
, xoffset
, yoffset
, 0);
1795 /* tell driver about the change */
1796 if (ctx
->Driver
.TexImage
) {
1797 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_2D
,
1798 texUnit
->CurrentD
[2],
1799 level
, teximage
->IntFormat
, teximage
);
1808 _mesa_CopyTexSubImage3D( GLenum target
, GLint level
,
1809 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1810 GLint x
, GLint y
, GLsizei width
, GLsizei height
)
1812 GET_CURRENT_CONTEXT(ctx
);
1813 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glCopyTexSubImage3D");
1815 if (!copytexsubimage_error_check(ctx
, 3, target
, level
,
1816 xoffset
, yoffset
, zoffset
, width
, height
)) {
1817 struct gl_texture_unit
*texUnit
;
1818 struct gl_texture_image
*teximage
;
1819 texUnit
= &ctx
->Texture
.Unit
[ctx
->Texture
.CurrentUnit
];
1820 teximage
= texUnit
->CurrentD
[3]->Image
[level
];
1822 if (teximage
->Data
) {
1823 copy_tex_sub_image(ctx
, teximage
, width
, height
,
1824 x
, y
, xoffset
, yoffset
, zoffset
);
1825 /* tell driver about the change */
1826 if (ctx
->Driver
.TexImage
) {
1827 (*ctx
->Driver
.TexImage
)( ctx
, GL_TEXTURE_3D
,
1828 texUnit
->CurrentD
[3],
1829 level
, teximage
->IntFormat
, teximage
);