source: trunk/src/opengl/mesa/teximage.c@ 3993

Last change on this file since 3993 was 3598, checked in by jeroen, 25 years ago

* empty log message *

File size: 70.1 KB
Line 
1/* $Id: teximage.c,v 1.3 2000-05-23 20:40:55 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
31#include "glheader.h"
32#include "types.h"
33#include "context.h"
34#include "image.h"
35#include "mmath.h"
36#include "span.h"
37#include "teximage.h"
38#include "texstate.h"
39#include "mem.h"
40#endif
41
42
43/*
44 * NOTES:
45 *
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,
48 * and GL_COLOR_INDEX.
49 * Device drivers are free to implement any internal format they want.
50 */
51
52
53/*
54 * Compute log base 2 of n.
55 * If n isn't an exact power of two return -1.
56 * If n<0 return -1.
57 */
58static int
59logbase2( int n )
60{
61 GLint i = 1;
62 GLint log2 = 0;
63
64 if (n<0) {
65 return -1;
66 }
67
68 while ( n > i ) {
69 i *= 2;
70 log2++;
71 }
72 if (i != n) {
73 return -1;
74 }
75 else {
76 return log2;
77 }
78}
79
80
81
82/*
83 * Given an internal texture format enum or 1, 2, 3, 4 return the
84 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
85 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
86 * Return -1 if invalid enum.
87 */
88GLint
89_mesa_base_tex_format( GLint format )
90{
91 switch (format) {
92 case GL_ALPHA:
93 case GL_ALPHA4:
94 case GL_ALPHA8:
95 case GL_ALPHA12:
96 case GL_ALPHA16:
97 return GL_ALPHA;
98 case 1:
99 case GL_LUMINANCE:
100 case GL_LUMINANCE4:
101 case GL_LUMINANCE8:
102 case GL_LUMINANCE12:
103 case GL_LUMINANCE16:
104 return GL_LUMINANCE;
105 case 2:
106 case GL_LUMINANCE_ALPHA:
107 case GL_LUMINANCE4_ALPHA4:
108 case GL_LUMINANCE6_ALPHA2:
109 case GL_LUMINANCE8_ALPHA8:
110 case GL_LUMINANCE12_ALPHA4:
111 case GL_LUMINANCE12_ALPHA12:
112 case GL_LUMINANCE16_ALPHA16:
113 return GL_LUMINANCE_ALPHA;
114 case GL_INTENSITY:
115 case GL_INTENSITY4:
116 case GL_INTENSITY8:
117 case GL_INTENSITY12:
118 case GL_INTENSITY16:
119 return GL_INTENSITY;
120 case 3:
121 case GL_RGB:
122 case GL_R3_G3_B2:
123 case GL_RGB4:
124 case GL_RGB5:
125 case GL_RGB8:
126 case GL_RGB10:
127 case GL_RGB12:
128 case GL_RGB16:
129 return GL_RGB;
130 case 4:
131 case GL_RGBA:
132 case GL_RGBA2:
133 case GL_RGBA4:
134 case GL_RGB5_A1:
135 case GL_RGBA8:
136 case GL_RGB10_A2:
137 case GL_RGBA12:
138 case GL_RGBA16:
139 return GL_RGBA;
140 case GL_COLOR_INDEX:
141 case GL_COLOR_INDEX1_EXT:
142 case GL_COLOR_INDEX2_EXT:
143 case GL_COLOR_INDEX4_EXT:
144 case GL_COLOR_INDEX8_EXT:
145 case GL_COLOR_INDEX12_EXT:
146 case GL_COLOR_INDEX16_EXT:
147 return GL_COLOR_INDEX;
148 default:
149 return -1; /* error */
150 }
151}
152
153
154
155/*
156 * Given an internal texture format enum or 1, 2, 3, 4 return the
157 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
158 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
159 * number of components for the format. Return -1 if invalid enum.
160 */
161static GLint
162components_in_intformat( GLint format )
163{
164 switch (format) {
165 case GL_ALPHA:
166 case GL_ALPHA4:
167 case GL_ALPHA8:
168 case GL_ALPHA12:
169 case GL_ALPHA16:
170 return 1;
171 case 1:
172 case GL_LUMINANCE:
173 case GL_LUMINANCE4:
174 case GL_LUMINANCE8:
175 case GL_LUMINANCE12:
176 case GL_LUMINANCE16:
177 return 1;
178 case 2:
179 case GL_LUMINANCE_ALPHA:
180 case GL_LUMINANCE4_ALPHA4:
181 case GL_LUMINANCE6_ALPHA2:
182 case GL_LUMINANCE8_ALPHA8:
183 case GL_LUMINANCE12_ALPHA4:
184 case GL_LUMINANCE12_ALPHA12:
185 case GL_LUMINANCE16_ALPHA16:
186 return 2;
187 case GL_INTENSITY:
188 case GL_INTENSITY4:
189 case GL_INTENSITY8:
190 case GL_INTENSITY12:
191 case GL_INTENSITY16:
192 return 1;
193 case 3:
194 case GL_RGB:
195 case GL_R3_G3_B2:
196 case GL_RGB4:
197 case GL_RGB5:
198 case GL_RGB8:
199 case GL_RGB10:
200 case GL_RGB12:
201 case GL_RGB16:
202 return 3;
203 case 4:
204 case GL_RGBA:
205 case GL_RGBA2:
206 case GL_RGBA4:
207 case GL_RGB5_A1:
208 case GL_RGBA8:
209 case GL_RGB10_A2:
210 case GL_RGBA12:
211 case GL_RGBA16:
212 return 4;
213 case GL_COLOR_INDEX:
214 case GL_COLOR_INDEX1_EXT:
215 case GL_COLOR_INDEX2_EXT:
216 case GL_COLOR_INDEX4_EXT:
217 case GL_COLOR_INDEX8_EXT:
218 case GL_COLOR_INDEX12_EXT:
219 case GL_COLOR_INDEX16_EXT:
220 return 1;
221 default:
222 return -1; /* error */
223 }
224}
225
226
227
228/*
229 * Examine the texImage->Format field and set the Red, Green, Blue, etc
230 * texel component sizes to default values.
231 * These fields are set only here by core Mesa but device drivers may
232 * overwritting these fields to indicate true texel resolution.
233 */
234static void
235set_teximage_component_sizes( struct gl_texture_image *texImage )
236{
237 switch (texImage->Format) {
238 case GL_ALPHA:
239 texImage->RedBits = 0;
240 texImage->GreenBits = 0;
241 texImage->BlueBits = 0;
242 texImage->AlphaBits = 8;
243 texImage->IntensityBits = 0;
244 texImage->LuminanceBits = 0;
245 texImage->IndexBits = 0;
246 break;
247 case GL_LUMINANCE:
248 texImage->RedBits = 0;
249 texImage->GreenBits = 0;
250 texImage->BlueBits = 0;
251 texImage->AlphaBits = 0;
252 texImage->IntensityBits = 0;
253 texImage->LuminanceBits = 8;
254 texImage->IndexBits = 0;
255 break;
256 case GL_LUMINANCE_ALPHA:
257 texImage->RedBits = 0;
258 texImage->GreenBits = 0;
259 texImage->BlueBits = 0;
260 texImage->AlphaBits = 8;
261 texImage->IntensityBits = 0;
262 texImage->LuminanceBits = 8;
263 texImage->IndexBits = 0;
264 break;
265 case GL_INTENSITY:
266 texImage->RedBits = 0;
267 texImage->GreenBits = 0;
268 texImage->BlueBits = 0;
269 texImage->AlphaBits = 0;
270 texImage->IntensityBits = 8;
271 texImage->LuminanceBits = 0;
272 texImage->IndexBits = 0;
273 break;
274 case GL_RED:
275 texImage->RedBits = 8;
276 texImage->GreenBits = 0;
277 texImage->BlueBits = 0;
278 texImage->AlphaBits = 0;
279 texImage->IntensityBits = 0;
280 texImage->LuminanceBits = 0;
281 texImage->IndexBits = 0;
282 break;
283 case GL_GREEN:
284 texImage->RedBits = 0;
285 texImage->GreenBits = 8;
286 texImage->BlueBits = 0;
287 texImage->AlphaBits = 0;
288 texImage->IntensityBits = 0;
289 texImage->LuminanceBits = 0;
290 texImage->IndexBits = 0;
291 break;
292 case GL_BLUE:
293 texImage->RedBits = 0;
294 texImage->GreenBits = 0;
295 texImage->BlueBits = 8;
296 texImage->AlphaBits = 0;
297 texImage->IntensityBits = 0;
298 texImage->LuminanceBits = 0;
299 texImage->IndexBits = 0;
300 break;
301 case GL_RGB:
302 case GL_BGR:
303 texImage->RedBits = 8;
304 texImage->GreenBits = 8;
305 texImage->BlueBits = 8;
306 texImage->AlphaBits = 0;
307 texImage->IntensityBits = 0;
308 texImage->LuminanceBits = 0;
309 texImage->IndexBits = 0;
310 break;
311 case GL_RGBA:
312 case GL_BGRA:
313 case GL_ABGR_EXT:
314 texImage->RedBits = 8;
315 texImage->GreenBits = 8;
316 texImage->BlueBits = 8;
317 texImage->AlphaBits = 8;
318 texImage->IntensityBits = 0;
319 texImage->LuminanceBits = 0;
320 texImage->IndexBits = 0;
321 break;
322 case GL_COLOR_INDEX:
323 texImage->RedBits = 0;
324 texImage->GreenBits = 0;
325 texImage->BlueBits = 0;
326 texImage->AlphaBits = 0;
327 texImage->IntensityBits = 0;
328 texImage->LuminanceBits = 0;
329 texImage->IndexBits = 8;
330 break;
331 default:
332 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
333 }
334}
335
336
337
338/*
339 * Return new gl_texture_image struct with all fields initialized to zero.
340 */
341struct gl_texture_image *
342gl_alloc_texture_image( void )
343{
344 return CALLOC_STRUCT(gl_texture_image);
345}
346
347
348
349/*
350 * Initialize most fields of a gl_texture_image struct.
351 */
352static void
353init_texture_image( struct gl_texture_image *img,
354 GLsizei width, GLsizei height, GLsizei depth,
355 GLint border, GLenum internalFormat )
356{
357 ASSERT(img);
358 ASSERT(!img->Data);
359 img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
360 set_teximage_component_sizes( img );
361 img->IntFormat = (GLenum) internalFormat;
362 img->Border = border;
363 img->Width = width;
364 img->Height = height;
365 img->Depth = depth;
366 img->WidthLog2 = logbase2(width - 2 * border);
367 if (height == 1) /* 1-D texture */
368 img->HeightLog2 = 0;
369 else
370 img->HeightLog2 = logbase2(height - 2 * border);
371 if (depth == 1) /* 2-D texture */
372 img->DepthLog2 = 0;
373 else
374 img->DepthLog2 = logbase2(depth - 2 * border);
375 img->Width2 = 1 << img->WidthLog2;
376 img->Height2 = 1 << img->HeightLog2;
377 img->Depth2 = 1 << img->DepthLog2;
378 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
379}
380
381
382
383void
384gl_free_texture_image( struct gl_texture_image *teximage )
385{
386 if (teximage->Data) {
387 FREE( teximage->Data );
388 teximage->Data = NULL;
389 }
390 FREE( teximage );
391}
392
393
394
395/* Need this to prevent an out-of-bounds memory access when using
396 * X86 optimized code.
397 */
398#ifdef USE_X86_ASM
399# define EXTRA_BYTE 1
400#else
401# define EXTRA_BYTE 0
402#endif
403
404
405
406/*
407 * Called by glTexImage[123]D. Fill in a texture image with data given
408 * by the client. All pixel transfer and unpack modes are handled here.
409 * NOTE: All texture image parameters should have already been error checked.
410 */
411static void
412make_texture_image( GLcontext *ctx,
413 struct gl_texture_image *texImage,
414 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
415 const struct gl_pixelstore_attrib *unpacking)
416{
417 GLint components, numPixels;
418 GLint internalFormat, width, height, depth, border;
419
420 ASSERT(ctx);
421 ASSERT(texImage);
422 ASSERT(!texImage->Data);
423 ASSERT(pixels);
424 ASSERT(unpacking);
425
426 internalFormat = texImage->IntFormat;
427 width = texImage->Width;
428 height = texImage->Height;
429 depth = texImage->Depth;
430 border = texImage->Border;
431 components = components_in_intformat(internalFormat);
432
433 ASSERT(width > 0);
434 ASSERT(height > 0);
435 ASSERT(depth > 0);
436 ASSERT(border == 0 || border == 1);
437 ASSERT(pixels);
438 ASSERT(unpacking);
439 ASSERT(components);
440
441 numPixels = width * height * depth;
442
443 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
444 if (!texImage->Data)
445 return; /* out of memory */
446
447 /*
448 * OK, the texture image struct has been initialized and the texture
449 * image memory has been allocated.
450 * Now fill in the texture image from the source data.
451 * This includes applying the pixel transfer operations.
452 */
453
454 /* try common 2D texture cases first */
455 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
456 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
457 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
458
459 if (srcFormat == internalFormat ||
460 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
461 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
462 (srcFormat == GL_RGB && internalFormat == 3) ||
463 (srcFormat == GL_RGBA && internalFormat == 4)) {
464 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
465 * GL_LUMINANCE_ALPHA, etc. texture formats.
466 */
467 const GLubyte *src = (const GLubyte *) _mesa_image_address(
468 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
469 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
470 srcFormat, srcType);
471 GLubyte *dst = texImage->Data;
472 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
473 if (srcStride == dstBytesPerRow) {
474 MEMCPY(dst, src, height * dstBytesPerRow);
475 }
476 else {
477 GLint i;
478 for (i = 0; i < height; i++) {
479 MEMCPY(dst, src, dstBytesPerRow);
480 src += srcStride;
481 dst += dstBytesPerRow;
482 }
483 }
484 return; /* all done */
485 }
486 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
487 /* commonly used by Quake */
488 const GLubyte *src = (const GLubyte *) _mesa_image_address(
489 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
490 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
491 srcFormat, srcType);
492 GLubyte *dst = texImage->Data;
493 GLint i, j;
494 for (i = 0; i < height; i++) {
495 const GLubyte *s = src;
496 for (j = 0; j < width; j++) {
497 *dst++ = *s++; /*red*/
498 *dst++ = *s++; /*green*/
499 *dst++ = *s++; /*blue*/
500 s++; /*alpha*/
501 }
502 src += srcStride;
503 }
504 return; /* all done */
505 }
506 }
507
508
509 /*
510 * General case solutions
511 */
512 if (texImage->Format == GL_COLOR_INDEX) {
513 /* color index texture */
514 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
515 const GLenum dstType = GL_UNSIGNED_BYTE;
516 GLubyte *dest = texImage->Data;
517 GLint img, row;
518 for (img = 0; img < depth; img++) {
519 for (row = 0; row < height; row++) {
520 const GLvoid *source = _mesa_image_address(unpacking,
521 pixels, width, height, srcFormat, srcType, img, row, 0);
522 _mesa_unpack_index_span(ctx, width, dstType, dest,
523 srcType, source, unpacking, GL_TRUE);
524 dest += destBytesPerRow;
525 }
526 }
527 }
528 else {
529 /* regular, color texture */
530 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
531 const GLenum dstFormat = texImage->Format;
532 GLubyte *dest = texImage->Data;
533 GLint img, row;
534 for (img = 0; img < depth; img++) {
535 for (row = 0; row < height; row++) {
536 const GLvoid *source = _mesa_image_address(unpacking,
537 pixels, width, height, srcFormat, srcType, img, row, 0);
538 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
539 srcFormat, srcType, source, unpacking, GL_TRUE);
540 dest += destBytesPerRow;
541 }
542 }
543 }
544}
545
546
547
548/*
549 * glTexImage[123]D can accept a NULL image pointer. In this case we
550 * create a texture image with unspecified image contents per the OpenGL
551 * spec. This function creates an empty image for the given texture image.
552 */
553static void
554make_null_texture( struct gl_texture_image *texImage )
555{
556 GLint components;
557 GLint numPixels;
558
559 ASSERT(texImage);
560 ASSERT(!texImage->Data);
561
562 components = components_in_intformat(texImage->IntFormat);
563 numPixels = texImage->Width * texImage->Height * texImage->Depth;
564
565 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
566
567 /*
568 * Let's see if anyone finds this. If glTexImage2D() is called with
569 * a NULL image pointer then load the texture image with something
570 * interesting instead of leaving it indeterminate.
571 */
572 if (texImage->Data) {
573 static const char message[8][32] = {
574 " X X XXXXX XXX X ",
575 " XX XX X X X X X ",
576 " X X X X X X X ",
577 " X X XXXX XXX XXXXX ",
578 " X X X X X X ",
579 " X X X X X X X ",
580 " X X XXXXX XXX X X ",
581 " "
582 };
583
584 GLubyte *imgPtr = texImage->Data;
585 GLint i, j, k;
586 for (i = 0; i < texImage->Height; i++) {
587 GLint srcRow = 7 - i % 8;
588 for (j = 0; j < texImage->Width; j++) {
589 GLint srcCol = j % 32;
590 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
591 for (k=0;k<components;k++) {
592 *imgPtr++ = (GLubyte) texel;
593 }
594 }
595 }
596 }
597}
598
599
600
601/*
602 * Test glTexImage[123]D() parameters for errors.
603 * Input:
604 * dimensions - must be 1 or 2 or 3
605 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
606 */
607static GLboolean
608texture_error_check( GLcontext *ctx, GLenum target,
609 GLint level, GLint internalFormat,
610 GLenum format, GLenum type,
611 GLuint dimensions,
612 GLint width, GLint height,
613 GLint depth, GLint border )
614{
615 GLboolean isProxy;
616 GLint iformat;
617
618 if (dimensions == 1) {
619 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
620 if (target != GL_TEXTURE_1D && !isProxy) {
621 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
622 return GL_TRUE;
623 }
624 }
625 else if (dimensions == 2) {
626 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
627 if (target != GL_TEXTURE_2D && !isProxy) {
628 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
629 return GL_TRUE;
630 }
631 }
632 else if (dimensions == 3) {
633 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
634 if (target != GL_TEXTURE_3D && !isProxy) {
635 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
636 return GL_TRUE;
637 }
638 }
639 else {
640 gl_problem( ctx, "bad dims in texture_error_check" );
641 return GL_TRUE;
642 }
643
644 /* Border */
645 if (border != 0 && border != 1) {
646 if (!isProxy) {
647 char message[100];
648 sprintf(message, "glTexImage%dD(border)", dimensions);
649 gl_error(ctx, GL_INVALID_VALUE, message);
650 }
651 return GL_TRUE;
652 }
653
654 /* Width */
655 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
656 || logbase2( width - 2 * border ) < 0) {
657 if (!isProxy) {
658 char message[100];
659 sprintf(message, "glTexImage%dD(width)", dimensions);
660 gl_error(ctx, GL_INVALID_VALUE, message);
661 }
662 return GL_TRUE;
663 }
664
665 /* Height */
666 if (dimensions >= 2) {
667 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
668 || logbase2( height - 2 * border ) < 0) {
669 if (!isProxy) {
670 char message[100];
671 sprintf(message, "glTexImage%dD(height)", dimensions);
672 gl_error(ctx, GL_INVALID_VALUE, message);
673 }
674 return GL_TRUE;
675 }
676 }
677
678 /* Depth */
679 if (dimensions >= 3) {
680 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
681 || logbase2( depth - 2 * border ) < 0) {
682 if (!isProxy) {
683 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
684 }
685 return GL_TRUE;
686 }
687 }
688
689 /* Level */
690 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
691 if (!isProxy) {
692 char message[100];
693 sprintf(message, "glTexImage%dD(level)", dimensions);
694 gl_error(ctx, GL_INVALID_VALUE, message);
695 }
696 return GL_TRUE;
697 }
698
699 iformat = _mesa_base_tex_format( internalFormat );
700 if (iformat < 0) {
701 if (!isProxy) {
702 char message[100];
703 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
704 gl_error(ctx, GL_INVALID_VALUE, message);
705 }
706 return GL_TRUE;
707 }
708
709 if (!_mesa_is_legal_format_and_type( format, type )) {
710 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
711 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
712 */
713 if (!isProxy) {
714 char message[100];
715 sprintf(message, "glTexImage%dD(format or type)", dimensions);
716 gl_error(ctx, GL_INVALID_OPERATION, message);
717 }
718 return GL_TRUE;
719 }
720
721 /* if we get here, the parameters are OK */
722 return GL_FALSE;
723}
724
725
726
727/*
728 * Test glTexSubImage[123]D() parameters for errors.
729 * Input:
730 * dimensions - must be 1 or 2 or 3
731 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
732 */
733static GLboolean
734subtexture_error_check( GLcontext *ctx, GLuint dimensions,
735 GLenum target, GLint level,
736 GLint xoffset, GLint yoffset, GLint zoffset,
737 GLint width, GLint height, GLint depth,
738 GLenum format, GLenum type )
739{
740 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
741 struct gl_texture_image *destTex;
742
743 if (dimensions == 1) {
744 if (target != GL_TEXTURE_1D) {
745 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
746 return GL_TRUE;
747 }
748 }
749 else if (dimensions == 2) {
750 if (target != GL_TEXTURE_2D) {
751 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
752 return GL_TRUE;
753 }
754 }
755 else if (dimensions == 3) {
756 if (target != GL_TEXTURE_3D) {
757 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
758 return GL_TRUE;
759 }
760 }
761 else {
762 gl_problem( ctx, "bad dims in texture_error_check" );
763 return GL_TRUE;
764 }
765
766 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
767 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
768 return GL_TRUE;
769 }
770
771 if (width < 0) {
772 char message[100];
773 sprintf(message, "glTexSubImage%dD(width)", dimensions);
774 gl_error(ctx, GL_INVALID_VALUE, message);
775 return GL_TRUE;
776 }
777 if (height < 0 && dimensions > 1) {
778 char message[100];
779 sprintf(message, "glTexSubImage%dD(height)", dimensions);
780 gl_error(ctx, GL_INVALID_VALUE, message);
781 return GL_TRUE;
782 }
783 if (depth < 0 && dimensions > 2) {
784 char message[100];
785 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
786 gl_error(ctx, GL_INVALID_VALUE, message);
787 return GL_TRUE;
788 }
789
790 destTex = texUnit->CurrentD[2]->Image[level];
791 if (!destTex) {
792 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
793 return GL_TRUE;
794 }
795
796 if (xoffset < -((GLint)destTex->Border)) {
797 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
798 return GL_TRUE;
799 }
800 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
801 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
802 return GL_TRUE;
803 }
804 if (dimensions > 1) {
805 if (yoffset < -((GLint)destTex->Border)) {
806 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
807 return GL_TRUE;
808 }
809 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
810 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
811 return GL_TRUE;
812 }
813 }
814 if (dimensions > 2) {
815 if (zoffset < -((GLint)destTex->Border)) {
816 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
817 return GL_TRUE;
818 }
819 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
820 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
821 return GL_TRUE;
822 }
823 }
824
825 if (!_mesa_is_legal_format_and_type(format, type)) {
826 char message[100];
827 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
828 gl_error(ctx, GL_INVALID_ENUM, message);
829 return GL_TRUE;
830 }
831
832 return GL_FALSE;
833}
834
835
836/*
837 * Test glCopyTexImage[12]D() parameters for errors.
838 * Input: dimensions - must be 1 or 2 or 3
839 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
840 */
841static GLboolean
842copytexture_error_check( GLcontext *ctx, GLuint dimensions,
843 GLenum target, GLint level, GLint internalFormat,
844 GLint width, GLint height, GLint border )
845{
846 GLint iformat;
847
848 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
849 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
850 return GL_TRUE;
851 }
852
853 if (dimensions == 1 && target != GL_TEXTURE_1D) {
854 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
855 return GL_TRUE;
856 }
857 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
858 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
859 return GL_TRUE;
860 }
861
862 /* Border */
863 if (border!=0 && border!=1) {
864 char message[100];
865 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
866 gl_error(ctx, GL_INVALID_VALUE, message);
867 return GL_TRUE;
868 }
869
870 /* Width */
871 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
872 || logbase2( width - 2 * border ) < 0) {
873 char message[100];
874 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
875 gl_error(ctx, GL_INVALID_VALUE, message);
876 return GL_TRUE;
877 }
878
879 /* Height */
880 if (dimensions >= 2) {
881 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
882 || logbase2( height - 2 * border ) < 0) {
883 char message[100];
884 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
885 gl_error(ctx, GL_INVALID_VALUE, message);
886 return GL_TRUE;
887 }
888 }
889
890 /* Level */
891 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
892 char message[100];
893 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
894 gl_error(ctx, GL_INVALID_VALUE, message);
895 return GL_TRUE;
896 }
897
898 iformat = _mesa_base_tex_format( internalFormat );
899 if (iformat < 0) {
900 char message[100];
901 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
902 gl_error(ctx, GL_INVALID_VALUE, message);
903 return GL_TRUE;
904 }
905
906 /* if we get here, the parameters are OK */
907 return GL_FALSE;
908}
909
910
911static GLboolean
912copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
913 GLenum target, GLint level,
914 GLint xoffset, GLint yoffset, GLint zoffset,
915 GLsizei width, GLsizei height )
916{
917 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
918 struct gl_texture_image *teximage;
919
920 if (dimensions == 1 && target != GL_TEXTURE_1D) {
921 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
922 return GL_TRUE;
923 }
924 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
925 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
926 return GL_TRUE;
927 }
928 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
929 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
930 return GL_TRUE;
931 }
932
933 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
934 char message[100];
935 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
936 gl_error(ctx, GL_INVALID_VALUE, message);
937 return GL_TRUE;
938 }
939
940 if (width < 0) {
941 char message[100];
942 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
943 gl_error(ctx, GL_INVALID_VALUE, message);
944 return GL_TRUE;
945 }
946 if (dimensions > 1 && height < 0) {
947 char message[100];
948 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
949 gl_error(ctx, GL_INVALID_VALUE, message);
950 return GL_TRUE;
951 }
952
953 teximage = texUnit->CurrentD[dimensions]->Image[level];
954 if (!teximage) {
955 char message[100];
956 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
957 gl_error(ctx, GL_INVALID_OPERATION, message);
958 return GL_TRUE;
959 }
960
961 if (xoffset < -((GLint)teximage->Border)) {
962 char message[100];
963 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
964 gl_error(ctx, GL_INVALID_VALUE, message);
965 return GL_TRUE;
966 }
967 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
968 char message[100];
969 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
970 gl_error(ctx, GL_INVALID_VALUE, message);
971 return GL_TRUE;
972 }
973 if (dimensions > 1) {
974 if (yoffset < -((GLint)teximage->Border)) {
975 char message[100];
976 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
977 gl_error(ctx, GL_INVALID_VALUE, message);
978 return GL_TRUE;
979 }
980 /* NOTE: we're adding the border here, not subtracting! */
981 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
982 char message[100];
983 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
984 gl_error(ctx, GL_INVALID_VALUE, message);
985 return GL_TRUE;
986 }
987 }
988
989 if (dimensions > 2) {
990 if (zoffset < -((GLint)teximage->Border)) {
991 char message[100];
992 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
993 gl_error(ctx, GL_INVALID_VALUE, message);
994 return GL_TRUE;
995 }
996 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
997 char message[100];
998 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
999 gl_error(ctx, GL_INVALID_VALUE, message);
1000 return GL_TRUE;
1001 }
1002 }
1003
1004 /* if we get here, the parameters are OK */
1005 return GL_FALSE;
1006}
1007
1008
1009
1010
1011/*
1012 * Called from the API. Note that width includes the border.
1013 */
1014void
1015_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1016 GLsizei width, GLint border, GLenum format,
1017 GLenum type, const GLvoid *pixels )
1018{
1019 GET_CURRENT_CONTEXT(ctx);
1020 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1021
1022 if (target==GL_TEXTURE_1D) {
1023 struct gl_texture_unit *texUnit;
1024 struct gl_texture_object *texObj;
1025 struct gl_texture_image *texImage;
1026
1027 if (texture_error_check( ctx, target, level, internalFormat,
1028 format, type, 1, width, 1, 1, border )) {
1029 return; /* error in texture image was detected */
1030 }
1031
1032 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1033 texObj = texUnit->CurrentD[1];
1034 texImage = texObj->Image[level];
1035
1036 if (!texImage) {
1037 texImage = gl_alloc_texture_image();
1038 texObj->Image[level] = texImage;
1039 if (!texImage) {
1040 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1041 return;
1042 }
1043 }
1044 else if (texImage->Data) {
1045 FREE(texImage->Data);
1046 texImage->Data = NULL;
1047 }
1048
1049 /* setup the teximage struct's fields */
1050 init_texture_image(texImage, width, 1, 1, border, internalFormat);
1051
1052 /* process the texture image */
1053 if (pixels) {
1054 GLboolean retain = GL_TRUE;
1055 GLboolean success = GL_FALSE;
1056 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1057 && ctx->Driver.TexImage1D) {
1058 /* let device driver try to use raw image */
1059 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1060 type, pixels, &ctx->Unpack,
1061 texObj, texImage, &retain);
1062 }
1063 if (retain || !success) {
1064 /* make internal copy of the texture image */
1065 make_texture_image(ctx, texImage, format, type,
1066 pixels, &ctx->Unpack);
1067 if (!success && ctx->Driver.TexImage1D) {
1068 /* let device driver try to use unpacked image */
1069 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1070 GL_UNSIGNED_BYTE, texImage->Data,
1071 &_mesa_native_packing,
1072 texObj, texImage, &retain);
1073 }
1074 }
1075 if (!retain && texImage->Data) {
1076 FREE(texImage->Data);
1077 texImage->Data = NULL;
1078 }
1079 }
1080 else {
1081 make_null_texture(texImage);
1082 if (ctx->Driver.TexImage1D) {
1083 GLboolean retain;
1084 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1085 GL_UNSIGNED_BYTE, texImage->Data,
1086 &_mesa_native_packing,
1087 texObj, texImage, &retain);
1088 }
1089 }
1090
1091 /* state update */
1092 gl_put_texobj_on_dirty_list( ctx, texObj );
1093 ctx->NewState |= NEW_TEXTURING;
1094 }
1095 else if (target==GL_PROXY_TEXTURE_1D) {
1096 /* Proxy texture: check for errors and update proxy state */
1097 if (texture_error_check( ctx, target, level, internalFormat,
1098 format, type, 1, width, 1, 1, border )) {
1099 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1100 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1101 sizeof(struct gl_texture_image) );
1102 }
1103 }
1104 else {
1105 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1106 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1107 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
1108 ctx->Texture.Proxy1D->Image[level]->Border = border;
1109 ctx->Texture.Proxy1D->Image[level]->Width = width;
1110 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1111 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1112 }
1113 }
1114 else {
1115 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1116 return;
1117 }
1118}
1119
1120
1121void
1122_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1123 GLsizei width, GLsizei height, GLint border,
1124 GLenum format, GLenum type,
1125 const GLvoid *pixels )
1126{
1127 GET_CURRENT_CONTEXT(ctx);
1128 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1129
1130 if (target==GL_TEXTURE_2D) {
1131 struct gl_texture_unit *texUnit;
1132 struct gl_texture_object *texObj;
1133 struct gl_texture_image *texImage;
1134
1135 if (texture_error_check( ctx, target, level, internalFormat,
1136 format, type, 2, width, height, 1, border )) {
1137 return; /* error in texture image was detected */
1138 }
1139
1140 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1141 texObj = texUnit->CurrentD[2];
1142 texImage = texObj->Image[level];
1143
1144 if (!texImage) {
1145 texImage = gl_alloc_texture_image();
1146 texObj->Image[level] = texImage;
1147 if (!texImage) {
1148 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1149 return;
1150 }
1151 }
1152 else if (texImage->Data) {
1153 FREE(texImage->Data);
1154 texImage->Data = NULL;
1155 }
1156
1157 /* setup the teximage struct's fields */
1158 init_texture_image(texImage, width, height, 1, border, internalFormat);
1159
1160 /* process the texture image */
1161 if (pixels) {
1162 GLboolean retain = GL_TRUE;
1163 GLboolean success = GL_FALSE;
1164 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1165 && ctx->Driver.TexImage2D) {
1166 /* let device driver try to use raw image */
1167 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1168 type, pixels, &ctx->Unpack,
1169 texObj, texImage, &retain);
1170 }
1171 if (retain || !success) {
1172 /* make internal copy of the texture image */
1173 make_texture_image(ctx, texImage, format, type,
1174 pixels, &ctx->Unpack);
1175 if (!success && ctx->Driver.TexImage2D) {
1176 /* let device driver try to use unpacked image */
1177 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1178 GL_UNSIGNED_BYTE, texImage->Data,
1179 &_mesa_native_packing,
1180 texObj, texImage, &retain);
1181 }
1182 }
1183 if (!retain && texImage->Data) {
1184 FREE(texImage->Data);
1185 texImage->Data = NULL;
1186 }
1187 }
1188 else {
1189 make_null_texture(texImage);
1190 if (ctx->Driver.TexImage2D) {
1191 GLboolean retain;
1192 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1193 GL_UNSIGNED_BYTE, texImage->Data,
1194 &_mesa_native_packing,
1195 texObj, texImage, &retain);
1196 }
1197 }
1198
1199#define OLD_DD_TEXTURE
1200#ifdef OLD_DD_TEXTURE
1201 /* XXX this will be removed in the future */
1202 if (ctx->Driver.TexImage) {
1203 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1204 texImage );
1205 }
1206#endif
1207
1208 /* state update */
1209 gl_put_texobj_on_dirty_list( ctx, texObj );
1210 ctx->NewState |= NEW_TEXTURING;
1211 }
1212 else if (target==GL_PROXY_TEXTURE_2D) {
1213 /* Proxy texture: check for errors and update proxy state */
1214 if (texture_error_check( ctx, target, level, internalFormat,
1215 format, type, 2, width, height, 1, border )) {
1216 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1217 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1218 sizeof(struct gl_texture_image) );
1219 }
1220 }
1221 else {
1222 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1223 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1224 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
1225 ctx->Texture.Proxy2D->Image[level]->Border = border;
1226 ctx->Texture.Proxy2D->Image[level]->Width = width;
1227 ctx->Texture.Proxy2D->Image[level]->Height = height;
1228 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1229 }
1230 }
1231 else {
1232 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1233 return;
1234 }
1235}
1236
1237
1238
1239/*
1240 * Called by the API or display list executor.
1241 * Note that width and height include the border.
1242 */
1243void
1244_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1245 GLsizei width, GLsizei height, GLsizei depth,
1246 GLint border, GLenum format, GLenum type,
1247 const GLvoid *pixels )
1248{
1249 GET_CURRENT_CONTEXT(ctx);
1250 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1251
1252 if (target==GL_TEXTURE_3D_EXT) {
1253 struct gl_texture_unit *texUnit;
1254 struct gl_texture_object *texObj;
1255 struct gl_texture_image *texImage;
1256 if (texture_error_check( ctx, target, level, internalFormat,
1257 format, type, 3, width, height, depth,
1258 border )) {
1259 return; /* error in texture image was detected */
1260 }
1261
1262 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1263 texObj = texUnit->CurrentD[3];
1264 texImage = texObj->Image[level];
1265
1266 if (!texImage) {
1267 texImage = gl_alloc_texture_image();
1268 texObj->Image[level] = texImage;
1269 if (!texImage) {
1270 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1271 return;
1272 }
1273 }
1274 else if (texImage->Data) {
1275 FREE(texImage->Data);
1276 texImage->Data = NULL;
1277 }
1278
1279 /* setup the teximage struct's fields */
1280 init_texture_image(texImage, width, height, depth,
1281 border, internalFormat);
1282
1283 /* process the texture image */
1284 if (pixels) {
1285 GLboolean retain = GL_TRUE;
1286 GLboolean success = GL_FALSE;
1287 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1288 && ctx->Driver.TexImage3D) {
1289 /* let device driver try to use raw image */
1290 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1291 type, pixels, &ctx->Unpack,
1292 texObj, texImage, &retain);
1293 }
1294 if (retain || !success) {
1295 /* make internal copy of the texture image */
1296 make_texture_image(ctx, texImage, format, type,
1297 pixels, &ctx->Unpack);
1298 if (!success && ctx->Driver.TexImage3D) {
1299 /* let device driver try to use unpacked image */
1300 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1301 GL_UNSIGNED_BYTE, texImage->Data,
1302 &_mesa_native_packing,
1303 texObj, texImage, &retain);
1304 }
1305 }
1306 if (!retain && texImage->Data) {
1307 FREE(texImage->Data);
1308 texImage->Data = NULL;
1309 }
1310 }
1311 else {
1312 make_null_texture(texImage);
1313 if (ctx->Driver.TexImage3D) {
1314 GLboolean retain;
1315 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1316 GL_UNSIGNED_BYTE, texImage->Data,
1317 &_mesa_native_packing,
1318 texObj, texImage, &retain);
1319 }
1320 }
1321
1322 /* state update */
1323 gl_put_texobj_on_dirty_list( ctx, texObj );
1324 ctx->NewState |= NEW_TEXTURING;
1325 }
1326 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1327 /* Proxy texture: check for errors and update proxy state */
1328 if (texture_error_check( ctx, target, level, internalFormat,
1329 format, type, 3, width, height, depth,
1330 border )) {
1331 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1332 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1333 sizeof(struct gl_texture_image) );
1334 }
1335 }
1336 else {
1337 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1338 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1339 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
1340 ctx->Texture.Proxy3D->Image[level]->Border = border;
1341 ctx->Texture.Proxy3D->Image[level]->Width = width;
1342 ctx->Texture.Proxy3D->Image[level]->Height = height;
1343 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1344 }
1345 }
1346 else {
1347 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1348 return;
1349 }
1350}
1351
1352
1353void
1354_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1355 GLsizei width, GLsizei height, GLsizei depth,
1356 GLint border, GLenum format, GLenum type,
1357 const GLvoid *pixels )
1358{
1359 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1360 depth, border, format, type, pixels);
1361}
1362
1363
1364/*
1365 * Fetch a texture image from the device driver.
1366 * Store the results in the given texture object at the given mipmap level.
1367 */
1368static void
1369get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1370 const struct gl_texture_object *texObj )
1371{
1372 GLvoid *image;
1373 GLenum imgFormat, imgType;
1374 GLboolean freeImage;
1375 struct gl_texture_image *texImage;
1376 GLint destComponents, numPixels, srcBytesPerTexel;
1377
1378 if (!ctx->Driver.GetTexImage)
1379 return;
1380
1381 image = (*ctx->Driver.GetTexImage)( ctx, target, level,
1382 &imgFormat, &imgType, &freeImage);
1383 if (!image)
1384 return;
1385
1386 texImage = texObj->Image[level];
1387 ASSERT(texImage);
1388 if (!texImage)
1389 return;
1390
1391 destComponents = components_in_intformat(texImage->Format);
1392 ASSERT(destComponents > 0);
1393 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1394 ASSERT(numPixels > 0);
1395 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1396 ASSERT(srcBytesPerTexel > 0);
1397
1398 if (!texImage->Data) {
1399 /* Allocate memory for the texture image data */
1400 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1401 }
1402
1403 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1404 /* We got lucky! The driver's format and type match Mesa's format. */
1405 if (texImage->Data) {
1406 MEMCPY(texImage->Data, image, numPixels * destComponents);
1407 }
1408 }
1409 else {
1410 /* Convert the texture image from the driver's format to Mesa's
1411 * internal format.
1412 */
1413 const GLint width = texImage->Width;
1414 const GLint height = texImage->Height;
1415 const GLint depth = texImage->Depth;
1416 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1417 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1418 const GLenum dstType = GL_UNSIGNED_BYTE;
1419 const GLenum dstFormat = texImage->Format;
1420 const GLubyte *srcPtr = (const GLubyte *) image;
1421 GLubyte *destPtr = texImage->Data;
1422
1423 if (texImage->Format == GL_COLOR_INDEX) {
1424 /* color index texture */
1425 GLint img, row;
1426 ASSERT(imgFormat == GL_COLOR_INDEX);
1427 for (img = 0; img < depth; img++) {
1428 for (row = 0; row < height; row++) {
1429 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1430 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1431 destPtr += destBytesPerRow;
1432 srcPtr += srcBytesPerRow;
1433 }
1434 }
1435 }
1436 else {
1437 /* color texture */
1438 GLint img, row;
1439 for (img = 0; img < depth; img++) {
1440 for (row = 0; row < height; row++) {
1441 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
1442 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1443 destPtr += destBytesPerRow;
1444 srcPtr += srcBytesPerRow;
1445 }
1446 }
1447 }
1448 }
1449
1450 if (freeImage)
1451 FREE(image);
1452}
1453
1454
1455void
1456_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1457 GLenum type, GLvoid *pixels )
1458{
1459 GET_CURRENT_CONTEXT(ctx);
1460 const struct gl_texture_object *texObj;
1461 struct gl_texture_image *texImage;
1462 GLboolean discardImage;
1463
1464 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1465
1466 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1467 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1468 return;
1469 }
1470
1471 if (_mesa_sizeof_type(type) <= 0) {
1472 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1473 return;
1474 }
1475
1476 if (_mesa_components_in_format(format) <= 0) {
1477 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1478 return;
1479 }
1480
1481 if (!pixels)
1482 return;
1483
1484 switch (target) {
1485 case GL_TEXTURE_1D:
1486 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1487 break;
1488 case GL_TEXTURE_2D:
1489 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1490 break;
1491 case GL_TEXTURE_3D:
1492 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1493 break;
1494 default:
1495 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1496 return;
1497 }
1498
1499 texImage = texObj->Image[level];
1500 if (!texImage) {
1501 /* invalid mipmap level */
1502 return;
1503 }
1504
1505 if (!texImage->Data) {
1506 /* try to get the texture image from the device driver */
1507 get_teximage_from_driver(ctx, target, level, texObj);
1508 discardImage = GL_TRUE;
1509 }
1510 else {
1511 discardImage = GL_FALSE;
1512 }
1513
1514 if (texImage->Data) {
1515 GLint width = texImage->Width;
1516 GLint height = texImage->Height;
1517 GLint row;
1518
1519 for (row = 0; row < height; row++) {
1520 /* compute destination address in client memory */
1521 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1522 width, height,
1523 format, type, 0, row, 0);
1524
1525 ASSERT(dest);
1526 if (texImage->Format == GL_RGBA) {
1527 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1528 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1529 format, type, dest, &ctx->Pack, GL_TRUE );
1530 }
1531 else {
1532 /* fetch RGBA row from texture image then pack it in client mem */
1533 GLubyte rgba[MAX_WIDTH][4];
1534 GLint i;
1535 const GLubyte *src;
1536 switch (texImage->Format) {
1537 case GL_ALPHA:
1538 src = texImage->Data + row * width * sizeof(GLubyte);
1539 for (i = 0; i < width; i++) {
1540 rgba[i][RCOMP] = 255;
1541 rgba[i][GCOMP] = 255;
1542 rgba[i][BCOMP] = 255;
1543 rgba[i][ACOMP] = src[i];
1544 }
1545 break;
1546 case GL_LUMINANCE:
1547 src = texImage->Data + row * width * sizeof(GLubyte);
1548 for (i = 0; i < width; i++) {
1549 rgba[i][RCOMP] = src[i];
1550 rgba[i][GCOMP] = src[i];
1551 rgba[i][BCOMP] = src[i];
1552 rgba[i][ACOMP] = 255;
1553 }
1554 break;
1555 case GL_LUMINANCE_ALPHA:
1556 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1557 for (i = 0; i < width; i++) {
1558 rgba[i][RCOMP] = src[i*2+0];
1559 rgba[i][GCOMP] = src[i*2+0];
1560 rgba[i][BCOMP] = src[i*2+0];
1561 rgba[i][ACOMP] = src[i*2+1];
1562 }
1563 break;
1564 case GL_INTENSITY:
1565 src = texImage->Data + row * width * sizeof(GLubyte);
1566 for (i = 0; i < width; i++) {
1567 rgba[i][RCOMP] = src[i];
1568 rgba[i][GCOMP] = src[i];
1569 rgba[i][BCOMP] = src[i];
1570 rgba[i][ACOMP] = 255;
1571 }
1572 break;
1573 case GL_RGB:
1574 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1575 for (i = 0; i < width; i++) {
1576 rgba[i][RCOMP] = src[i*3+0];
1577 rgba[i][GCOMP] = src[i*3+1];
1578 rgba[i][BCOMP] = src[i*3+2];
1579 rgba[i][ACOMP] = 255;
1580 }
1581 break;
1582 case GL_RGBA:
1583 /* this special case should have been handled above! */
1584 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1585 break;
1586 case GL_COLOR_INDEX:
1587 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1588 break;
1589 default:
1590 gl_problem( ctx, "bad format in gl_GetTexImage" );
1591 }
1592 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1593 format, type, dest, &ctx->Pack, GL_TRUE );
1594 }
1595 }
1596
1597 /* if we got the teximage from the device driver we'll discard it now */
1598 if (discardImage) {
1599 FREE(texImage->Data);
1600 texImage->Data = NULL;
1601 }
1602 }
1603}
1604
1605
1606
1607void
1608_mesa_TexSubImage1D( GLenum target, GLint level,
1609 GLint xoffset, GLsizei width,
1610 GLenum format, GLenum type,
1611 const GLvoid *pixels )
1612{
1613 GET_CURRENT_CONTEXT(ctx);
1614 struct gl_texture_unit *texUnit;
1615 struct gl_texture_object *texObj;
1616 struct gl_texture_image *texImage;
1617 GLboolean success = GL_FALSE;
1618
1619 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1620 width, 1, 1, format, type)) {
1621 return; /* error was detected */
1622 }
1623
1624 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1625 texObj = texUnit->CurrentD[1];
1626 texImage = texObj->Image[level];
1627 ASSERT(texImage);
1628
1629 if (width == 0 || !pixels)
1630 return; /* no-op, not an error */
1631
1632
1633 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1634 && ctx->Driver.TexSubImage1D) {
1635 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1636 width, format, type, pixels,
1637 &ctx->Unpack, texObj, texImage );
1638 }
1639 if (!success) {
1640 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1641
1642 const GLint texComponents = components_in_intformat(texImage->Format);
1643 const GLenum texFormat = texImage->Format;
1644 const GLint xoffsetb = xoffset + texImage->Border;
1645 GLboolean retain = GL_TRUE;
1646 if (!texImage->Data) {
1647 get_teximage_from_driver( ctx, target, level, texObj );
1648 if (!texImage->Data) {
1649 make_null_texture(texImage);
1650 }
1651 if (!texImage->Data)
1652 return; /* we're really out of luck! */
1653 }
1654
1655 if (texFormat == GL_COLOR_INDEX) {
1656 /* color index texture */
1657 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1658 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1659 1, format, type, 0, 0, 0);
1660 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1661 type, src, &ctx->Unpack, GL_TRUE);
1662 }
1663 else {
1664 /* color texture */
1665 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1666 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1667 1, format, type, 0, 0, 0);
1668 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1669 type, src, &ctx->Unpack, GL_TRUE);
1670 }
1671
1672 if (ctx->Driver.TexImage1D) {
1673 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1674 GL_UNSIGNED_BYTE, texImage->Data,
1675 &_mesa_native_packing, texObj, texImage,
1676 &retain );
1677 }
1678
1679 if (!retain && texImage->Data) {
1680 FREE(texImage->Data);
1681 texImage->Data = NULL;
1682 }
1683 }
1684
1685 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
1686}
1687
1688
1689void
1690_mesa_TexSubImage2D( GLenum target, GLint level,
1691 GLint xoffset, GLint yoffset,
1692 GLsizei width, GLsizei height,
1693 GLenum format, GLenum type,
1694 const GLvoid *pixels )
1695{
1696 GET_CURRENT_CONTEXT(ctx);
1697 struct gl_texture_unit *texUnit;
1698 struct gl_texture_object *texObj;
1699 struct gl_texture_image *texImage;
1700 GLboolean success = GL_FALSE;
1701
1702 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1703 width, height, 1, format, type)) {
1704 return; /* error was detected */
1705 }
1706
1707 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1708 texObj = texUnit->CurrentD[2];
1709 texImage = texObj->Image[level];
1710 ASSERT(texImage);
1711
1712 if (width == 0 || height == 0 || !pixels)
1713 return; /* no-op, not an error */
1714
1715 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1716 && ctx->Driver.TexSubImage2D) {
1717 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1718 yoffset, width, height, format, type,
1719 pixels, &ctx->Unpack, texObj, texImage );
1720 }
1721 if (!success) {
1722 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
1723
1724 const GLint texComponents = components_in_intformat(texImage->Format);
1725 const GLenum texFormat = texImage->Format;
1726 const GLint xoffsetb = xoffset + texImage->Border;
1727 const GLint yoffsetb = yoffset + texImage->Border;
1728 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1729 format, type);
1730 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1731 GLboolean retain = GL_TRUE;
1732
1733 if (!texImage->Data) {
1734 get_teximage_from_driver( ctx, target, level, texObj );
1735 if (!texImage->Data) {
1736 make_null_texture(texImage);
1737 }
1738 if (!texImage->Data)
1739 return; /* we're really out of luck! */
1740 }
1741
1742 if (texFormat == GL_COLOR_INDEX) {
1743 /* color index texture */
1744 GLubyte *dst = texImage->Data
1745 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1746 const GLubyte *src = (const GLubyte *)_mesa_image_address(&ctx->Unpack, pixels,
1747 width, height, format, type, 0, 0, 0);
1748 GLint row;
1749 for (row = 0; row < height; row++) {
1750 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1751 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1752 src += srcStride;
1753 dst += dstStride;
1754 }
1755 }
1756 else {
1757 /* color texture */
1758 GLubyte *dst = texImage->Data
1759 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1760 const GLubyte *src = (const GLubyte *)_mesa_image_address(&ctx->Unpack, pixels,
1761 width, height, format, type, 0, 0, 0);
1762 GLint row;
1763 for (row = 0; row < height; row++) {
1764 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1765 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1766 src += srcStride;
1767 dst += dstStride;
1768 }
1769 }
1770
1771 if (ctx->Driver.TexImage2D) {
1772 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1773 GL_UNSIGNED_BYTE, texImage->Data,
1774 &_mesa_native_packing, texObj, texImage,
1775 &retain);
1776 }
1777
1778 if (!retain && texImage->Data) {
1779 FREE(texImage->Data);
1780 texImage->Data = NULL;
1781 }
1782
1783#ifdef OLD_DD_TEXTURE
1784 /* XXX this will be removed in the future */
1785 if (ctx->Driver.TexSubImage) {
1786 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1787 xoffset, yoffset, width, height,
1788 texImage->IntFormat, texImage);
1789 }
1790 else if (ctx->Driver.TexImage) {
1791 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
1792 level, texImage->IntFormat, texImage );
1793 }
1794#endif
1795 }
1796}
1797
1798
1799
1800void
1801_mesa_TexSubImage3D( GLenum target, GLint level,
1802 GLint xoffset, GLint yoffset, GLint zoffset,
1803 GLsizei width, GLsizei height, GLsizei depth,
1804 GLenum format, GLenum type,
1805 const GLvoid *pixels )
1806{
1807 GET_CURRENT_CONTEXT(ctx);
1808 struct gl_texture_unit *texUnit;
1809 struct gl_texture_object *texObj;
1810 struct gl_texture_image *texImage;
1811 GLboolean success = GL_FALSE;
1812
1813 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1814 width, height, depth, format, type)) {
1815 return; /* error was detected */
1816 }
1817
1818 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1819 texObj = texUnit->CurrentD[3];
1820 texImage = texObj->Image[level];
1821 ASSERT(texImage);
1822
1823 if (width == 0 || height == 0 || height == 0 || !pixels)
1824 return; /* no-op, not an error */
1825
1826 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1827 && ctx->Driver.TexSubImage3D) {
1828 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1829 yoffset, zoffset, width, height, depth, format,
1830 type, pixels, &ctx->Unpack, texObj, texImage );
1831 }
1832 if (!success) {
1833 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1834
1835 const GLint texComponents = components_in_intformat(texImage->Format);
1836 const GLenum texFormat = texImage->Format;
1837 const GLint xoffsetb = xoffset + texImage->Border;
1838 const GLint yoffsetb = yoffset + texImage->Border;
1839 const GLint zoffsetb = zoffset + texImage->Border;
1840 const GLint texWidth = texImage->Width;
1841 const GLint dstRectArea = texWidth * texImage->Height;
1842 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1843 width, format, type);
1844 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1845 GLboolean retain = GL_TRUE;
1846
1847 if (texFormat == GL_COLOR_INDEX) {
1848 /* color index texture */
1849 GLint img, row;
1850 for (img = 0; img < depth; img++) {
1851 const GLubyte *src = (const GLubyte *)_mesa_image_address(&ctx->Unpack, pixels,
1852 width, height, format, type, img, 0, 0);
1853 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1854 + yoffsetb * texWidth + xoffsetb) * texComponents;
1855 for (row = 0; row < height; row++) {
1856 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1857 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1858 src += srcStride;
1859 dst += dstStride;
1860 }
1861 }
1862 }
1863 else {
1864 /* color texture */
1865 GLint img, row;
1866 for (img = 0; img < depth; img++) {
1867 const GLubyte *src = (const GLubyte *)_mesa_image_address(&ctx->Unpack, pixels,
1868 width, height, format, type, img, 0, 0);
1869 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1870 + yoffsetb * texWidth + xoffsetb) * texComponents;
1871 for (row = 0; row < height; row++) {
1872 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1873 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1874 src += srcStride;
1875 dst += dstStride;
1876 }
1877 }
1878 }
1879
1880 if (ctx->Driver.TexImage3D) {
1881 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1882 GL_UNSIGNED_BYTE, texImage->Data,
1883 &_mesa_native_packing, texObj, texImage,
1884 &retain);
1885 }
1886
1887 if (!retain && texImage->Data) {
1888 FREE(texImage->Data);
1889 texImage->Data = NULL;
1890 }
1891 }
1892}
1893
1894
1895
1896/*
1897 * Read an RGBA image from the frame buffer.
1898 * This is used by glCopyTexSubImage[12]D().
1899 * Input: ctx - the context
1900 * x, y - lower left corner
1901 * width, height - size of region to read
1902 * Return: pointer to block of GL_RGBA, GLubyte data.
1903 */
1904static GLubyte *
1905read_color_image( GLcontext *ctx, GLint x, GLint y,
1906 GLsizei width, GLsizei height )
1907{
1908 GLint stride, i;
1909 GLubyte *image, *dst;
1910
1911 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
1912 if (!image)
1913 return NULL;
1914
1915 /* Select buffer to read from */
1916 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1917 ctx->Pixel.DriverReadBuffer );
1918
1919 dst = image;
1920 stride = width * 4 * sizeof(GLubyte);
1921 for (i = 0; i < height; i++) {
1922 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1923 (GLubyte (*)[4]) dst );
1924 dst += stride;
1925 }
1926
1927 /* Read from draw buffer (the default) */
1928 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1929 ctx->Color.DriverDrawBuffer );
1930
1931 return image;
1932}
1933
1934
1935
1936void
1937_mesa_CopyTexImage1D( GLenum target, GLint level,
1938 GLenum internalFormat,
1939 GLint x, GLint y,
1940 GLsizei width, GLint border )
1941{
1942 GET_CURRENT_CONTEXT(ctx);
1943 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
1944
1945 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1946 width, 1, border))
1947 return;
1948
1949 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1950 || !ctx->Driver.CopyTexImage1D
1951 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
1952 internalFormat, x, y, width, border))
1953 {
1954 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
1955 if (!image) {
1956 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1957 return;
1958 }
1959 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
1960 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
1961 FREE(image);
1962 }
1963}
1964
1965
1966
1967void
1968_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1969 GLint x, GLint y, GLsizei width, GLsizei height,
1970 GLint border )
1971{
1972 GET_CURRENT_CONTEXT(ctx);
1973 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
1974
1975 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1976 width, height, border))
1977 return;
1978
1979 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1980 || !ctx->Driver.CopyTexImage2D
1981 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
1982 internalFormat, x, y, width, height, border))
1983 {
1984 GLubyte *image = read_color_image( ctx, x, y, width, height );
1985 if (!image) {
1986 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1987 return;
1988 }
1989 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
1990 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
1991 FREE(image);
1992 }
1993}
1994
1995
1996
1997/*
1998 * Do the work of glCopyTexSubImage[123]D.
1999 */
2000static void
2001copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2002 GLint width, GLint height,
2003 GLint srcx, GLint srcy,
2004 GLint dstx, GLint dsty, GLint dstz )
2005{
2006 GLint i;
2007 GLint format, components, rectarea;
2008 GLint texwidth, texheight, zoffset;
2009
2010 /* dst[xyz] may be negative if we have a texture border! */
2011 dstx += dest->Border;
2012 dsty += dest->Border;
2013 dstz += dest->Border;
2014 texwidth = dest->Width;
2015 texheight = dest->Height;
2016 rectarea = texwidth * texheight;
2017 zoffset = dstz * rectarea;
2018 format = dest->Format;
2019 components = components_in_intformat( format );
2020
2021 /* Select buffer to read from */
2022 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2023 ctx->Pixel.DriverReadBuffer );
2024
2025 for (i = 0;i < height; i++) {
2026 GLubyte rgba[MAX_WIDTH][4];
2027 GLubyte *dst;
2028 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
2029 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2030 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2031 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
2032 &_mesa_native_packing, GL_TRUE);
2033 }
2034
2035 /* Read from draw buffer (the default) */
2036 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2037 ctx->Color.DriverDrawBuffer );
2038}
2039
2040
2041
2042
2043void
2044_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2045 GLint xoffset, GLint x, GLint y, GLsizei width )
2046{
2047 GET_CURRENT_CONTEXT(ctx);
2048 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2049
2050 if (copytexsubimage_error_check(ctx, 1, target, level,
2051 xoffset, 0, 0, width, 1))
2052 return;
2053
2054 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2055 || !ctx->Driver.CopyTexSubImage1D
2056 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2057 xoffset, x, y, width)) {
2058 struct gl_texture_unit *texUnit;
2059 struct gl_texture_image *teximage;
2060 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2061 teximage = texUnit->CurrentD[1]->Image[level];
2062 ASSERT(teximage);
2063 if (teximage->Data) {
2064 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
2065 /* tell driver about the change */
2066 /* XXX this is obsolete */
2067 if (ctx->Driver.TexImage) {
2068 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2069 texUnit->CurrentD[1],
2070 level, teximage->IntFormat, teximage );
2071 }
2072 }
2073 }
2074}
2075
2076
2077
2078void
2079_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2080 GLint xoffset, GLint yoffset,
2081 GLint x, GLint y, GLsizei width, GLsizei height )
2082{
2083 GET_CURRENT_CONTEXT(ctx);
2084 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2085
2086 if (copytexsubimage_error_check(ctx, 2, target, level,
2087 xoffset, yoffset, 0, width, height))
2088 return;
2089
2090 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2091 || !ctx->Driver.CopyTexSubImage2D
2092 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2093 xoffset, yoffset, x, y, width, height )) {
2094 struct gl_texture_unit *texUnit;
2095 struct gl_texture_image *teximage;
2096 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2097 teximage = texUnit->CurrentD[2]->Image[level];
2098 ASSERT(teximage);
2099 if (teximage->Data) {
2100 copy_tex_sub_image(ctx, teximage, width, height,
2101 x, y, xoffset, yoffset, 0);
2102 /* tell driver about the change */
2103 /* XXX this is obsolete */
2104 if (ctx->Driver.TexImage) {
2105 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2106 texUnit->CurrentD[2],
2107 level, teximage->IntFormat, teximage );
2108 }
2109 }
2110 }
2111}
2112
2113
2114
2115void
2116_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2117 GLint xoffset, GLint yoffset, GLint zoffset,
2118 GLint x, GLint y, GLsizei width, GLsizei height )
2119{
2120 GET_CURRENT_CONTEXT(ctx);
2121 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2122
2123 if (copytexsubimage_error_check(ctx, 3, target, level,
2124 xoffset, yoffset, zoffset, width, height))
2125 return;
2126
2127 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2128 || !ctx->Driver.CopyTexSubImage3D
2129 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2130 xoffset, yoffset, zoffset, x, y, width, height )) {
2131 struct gl_texture_unit *texUnit;
2132 struct gl_texture_image *teximage;
2133 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2134 teximage = texUnit->CurrentD[3]->Image[level];
2135 ASSERT(teximage);
2136 if (teximage->Data) {
2137 copy_tex_sub_image(ctx, teximage, width, height,
2138 x, y, xoffset, yoffset, zoffset);
2139 /* tell driver about the change */
2140 /* XXX this is obsolete */
2141 if (ctx->Driver.TexImage) {
2142 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2143 texUnit->CurrentD[3],
2144 level, teximage->IntFormat, teximage );
2145 }
2146 }
2147 }
2148}
Note: See TracBrowser for help on using the repository browser.