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