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

Last change on this file since 2938 was 2938, checked in by sandervl, 25 years ago

created

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