blob: 5a60fa057fdff81c95309231566944f49cf6c21f [file] [log] [blame]
Brian Paul77ce6da2000-03-20 23:40:12 +00001/* $Id: teximage.c,v 1.21 2000/03/20 23:40:12 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00005 * Version: 3.3
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paul663049a2000-01-31 23:10:16 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
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
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000032#include "context.h"
33#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000034#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000035#include "mmath.h"
36#include "span.h"
37#include "teximage.h"
38#include "texstate.h"
39#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000040#endif
41
42
43/*
44 * NOTES:
45 *
Brian Paulc3f0a511999-11-03 17:27:05 +000046 * 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.
jtgafb833d1999-08-19 00:55:39 +000050 */
51
52
Brian Paulf7b57072000-03-20 14:37:52 +000053/*
54 * Default pixel packing of Mesa's internal texture images:
55 */
56static 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
jtgafb833d1999-08-19 00:55:39 +000068
jtgafb833d1999-08-19 00:55:39 +000069/*
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 */
Brian Paulfbd8f211999-11-11 01:22:25 +000074static int
75logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +000076{
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,
Brian Paulc3f0a511999-11-03 17:27:05 +0000101 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
102 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +0000103 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000104static GLint
105decode_internal_format( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000106{
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 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000177static GLint
178components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000179{
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
jtgafb833d1999-08-19 00:55:39 +0000244/*
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 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000250static void
251set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000252{
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;
Brian Paul91baaa31999-10-17 23:24:16 +0000290 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;
jtgafb833d1999-08-19 00:55:39 +0000317 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000318 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000319 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:
Brian Pauld53573d1999-10-19 20:36:20 +0000328 case GL_BGRA:
329 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000330 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
Brian Paul77ce6da2000-03-20 23:40:12 +0000353
354/*
355 * Return new gl_texture_image struct with all fields initialized to zero.
356 */
357struct gl_texture_image *
358gl_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 */
368static struct gl_texture_image *
369new_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
402void
403gl_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
jtgafb833d1999-08-19 00:55:39 +0000414/* 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
Brian Paulc3f0a511999-11-03 17:27:05 +0000424
jtgafb833d1999-08-19 00:55:39 +0000425/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000426 * 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.
jtgafb833d1999-08-19 00:55:39 +0000431 */
432static struct gl_texture_image *
Brian Paulc3f0a511999-11-03 17:27:05 +0000433make_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)
jtgafb833d1999-08-19 00:55:39 +0000437{
Brian Paulc3f0a511999-11-03 17:27:05 +0000438 GLint components, numPixels;
jtgafb833d1999-08-19 00:55:39 +0000439 struct gl_texture_image *texImage;
jtgafb833d1999-08-19 00:55:39 +0000440
Brian Paulc3f0a511999-11-03 17:27:05 +0000441 assert(width > 0);
442 assert(height > 0);
443 assert(depth > 0);
444 assert(border == 0 || border == 1);
445 assert(pixels);
446 assert(unpacking);
jtgafb833d1999-08-19 00:55:39 +0000447
jtgafb833d1999-08-19 00:55:39 +0000448
Brian Paulc3f0a511999-11-03 17:27:05 +0000449 /*
450 * Allocate and initialize the texture_image struct
451 */
Brian Paul77ce6da2000-03-20 23:40:12 +0000452 texImage = new_texture_image(width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +0000453 if (!texImage)
454 return NULL;
455
Brian Paulc3f0a511999-11-03 17:27:05 +0000456 components = components_in_intformat(internalFormat);
457 numPixels = texImage->Width * texImage->Height * texImage->Depth;
458
459 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
jtgafb833d1999-08-19 00:55:39 +0000460
461 if (!texImage->Data) {
462 /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000463 gl_free_texture_image(texImage);
jtgafb833d1999-08-19 00:55:39 +0000464 return NULL;
465 }
466
Brian Paulc3f0a511999-11-03 17:27:05 +0000467
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 */
Brian Paul959f8022000-03-19 01:10:11 +0000484 const GLubyte *src = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000485 pixels, width, height, srcFormat, srcType, 0, 0, 0);
Brian Paul959f8022000-03-19 01:10:11 +0000486 const GLubyte *src1 = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000487 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 */
Brian Paul959f8022000-03-19 01:10:11 +0000506 const GLubyte *src = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000507 pixels, width, height, srcFormat, srcType, 0, 0, 0);
Brian Paul959f8022000-03-19 01:10:11 +0000508 const GLubyte *src1 = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000509 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 }
jtgafb833d1999-08-19 00:55:39 +0000546 }
547 else {
Brian Paulc3f0a511999-11-03 17:27:05 +0000548 /* 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 }
jtgafb833d1999-08-19 00:55:39 +0000562 }
563
Brian Paulc3f0a511999-11-03 17:27:05 +0000564 return texImage; /* All done! */
jtgafb833d1999-08-19 00:55:39 +0000565}
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 */
574static struct gl_texture_image *
575make_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
Brian Paul77ce6da2000-03-20 23:40:12 +0000587 texImage = new_texture_image(width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +0000588
Brian Paul77ce6da2000-03-20 23:40:12 +0000589 /* It's easier later if we really do have a texture image, rather than
590 * a NULL image pointer.
591 */
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000592 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000593
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) {
Brian Paul65d54602000-03-01 23:28:20 +0000600 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000601 " 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;
Brian Paul5b37c321999-11-05 06:43:10 +0000617 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000618 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000619 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000620 }
621 }
622 }
623 }
624
625 return texImage;
626}
627
628
629
630/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000631 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +0000632 * Input:
633 * dimensions - must be 1 or 2 or 3
634 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
635 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000636static GLboolean
637texture_error_check( GLcontext *ctx, GLenum target,
638 GLint level, GLint internalFormat,
639 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +0000640 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000641 GLint width, GLint height,
642 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +0000643{
644 GLboolean isProxy;
645 GLint iformat;
646
647 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +0000648 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +0000649 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) {
Brian Paul5b37c321999-11-05 06:43:10 +0000655 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
jtgafb833d1999-08-19 00:55:39 +0000656 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) {
Brian Paul5b37c321999-11-05 06:43:10 +0000662 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +0000663 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) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000676 char message[100];
677 sprintf(message, "glTexImage%dD(border)", dimensions);
678 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000679 }
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) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000687 char message[100];
688 sprintf(message, "glTexImage%dD(width)", dimensions);
689 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000690 }
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) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000699 char message[100];
700 sprintf(message, "glTexImage%dD(height)", dimensions);
701 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000702 }
Brian Paulc3f0a511999-11-03 17:27:05 +0000703 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000704 }
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) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000720 if (!isProxy) {
721 char message[100];
722 sprintf(message, "glTexImage%dD(level)", dimensions);
723 gl_error(ctx, GL_INVALID_VALUE, message);
724 }
jtgafb833d1999-08-19 00:55:39 +0000725 return GL_TRUE;
726 }
727
728 iformat = decode_internal_format( internalFormat );
729 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000730 if (!isProxy) {
731 char message[100];
732 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
733 gl_error(ctx, GL_INVALID_VALUE, message);
734 }
jtgafb833d1999-08-19 00:55:39 +0000735 return GL_TRUE;
736 }
737
738 if (!gl_is_legal_format_and_type( format, type )) {
Brian Pauld53573d1999-10-19 20:36:20 +0000739 /* 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 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000742 if (!isProxy) {
743 char message[100];
744 sprintf(message, "glTexImage%dD(format or type)", dimensions);
745 gl_error(ctx, GL_INVALID_OPERATION, message);
746 }
jtgafb833d1999-08-19 00:55:39 +0000747 return GL_TRUE;
748 }
749
750 /* if we get here, the parameters are OK */
751 return GL_FALSE;
752}
753
754
755
756/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000757 * 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 */
762static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000763subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000764 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 */
870static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000871copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000872 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
940static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000941copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000942 GLenum target, GLint level,
943 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +0000944 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +0000945{
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
Brian Pauldf6a28d2000-02-21 16:34:21 +0000982 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +0000983 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/*
jtgafb833d1999-08-19 00:55:39 +00001041 * Called from the API. Note that width includes the border.
1042 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001043void
1044_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat,
1045 GLsizei width, GLint border, GLenum format,
1046 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001047{
Brian Paulfbd8f211999-11-11 01:22:25 +00001048 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001049 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1050
1051 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001052 struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00001053 struct gl_texture_image *teximage;
Brian Paulf7b57072000-03-20 14:37:52 +00001054
jtgafb833d1999-08-19 00:55:39 +00001055 if (texture_error_check( ctx, target, level, internalformat,
1056 format, type, 1, width, 1, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001057 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001058 }
1059
Brian Paulf7b57072000-03-20 14:37:52 +00001060 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1061
jtgafb833d1999-08-19 00:55:39 +00001062 /* 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 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001068 if (pixels) {
1069 teximage = make_texture_image(ctx, internalformat, width, 1, 1,
1070 border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001071 }
1072 else {
1073 teximage = make_null_texture(ctx, (GLenum) internalformat,
1074 width, 1, 1, border);
1075 }
1076
1077 /* install new texture image */
jtgafb833d1999-08-19 00:55:39 +00001078 texUnit->CurrentD[1]->Image[level] = teximage;
1079 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1080 ctx->NewState |= NEW_TEXTURING;
1081
jtgafb833d1999-08-19 00:55:39 +00001082 /* 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 }
jtgafb833d1999-08-19 00:55:39 +00001107 }
1108 else {
1109 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1110 return;
1111 }
1112}
1113
1114
Brian Paulfbd8f211999-11-11 01:22:25 +00001115void
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 )
jtgafb833d1999-08-19 00:55:39 +00001120{
Brian Paulfbd8f211999-11-11 01:22:25 +00001121 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001122 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1123
1124 if (target==GL_TEXTURE_2D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001125 struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00001126 struct gl_texture_image *teximage;
Brian Paulf7b57072000-03-20 14:37:52 +00001127
jtgafb833d1999-08-19 00:55:39 +00001128 if (texture_error_check( ctx, target, level, internalformat,
1129 format, type, 2, width, height, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001130 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001131 }
1132
Brian Paulf7b57072000-03-20 14:37:52 +00001133 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1134
jtgafb833d1999-08-19 00:55:39 +00001135 /* 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 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001141 if (pixels) {
1142 teximage = make_texture_image(ctx, internalformat, width, height, 1,
1143 border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001144 }
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
jtgafb833d1999-08-19 00:55:39 +00001155 /* 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 }
jtgafb833d1999-08-19 00:55:39 +00001180 }
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 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001193void
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 )
jtgafb833d1999-08-19 00:55:39 +00001198{
Brian Paulfbd8f211999-11-11 01:22:25 +00001199 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001200 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001201
Brian Paulfbd8f211999-11-11 01:22:25 +00001202 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001203 struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00001204 struct gl_texture_image *teximage;
1205 if (texture_error_check( ctx, target, level, internalformat,
1206 format, type, 3, width, height, depth,
1207 border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001208 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001209 }
1210
Brian Paulf7b57072000-03-20 14:37:52 +00001211 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1212
jtgafb833d1999-08-19 00:55:39 +00001213 /* 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 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001219 if (pixels) {
1220 teximage = make_texture_image(ctx, internalformat, width, height,
1221 depth, border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001222 }
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
jtgafb833d1999-08-19 00:55:39 +00001233 /* 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 }
jtgafb833d1999-08-19 00:55:39 +00001259 }
1260 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001261 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001262 return;
1263 }
1264}
1265
1266
Brian Paul663049a2000-01-31 23:10:16 +00001267void
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
Brian Paulf7b57072000-03-20 14:37:52 +00001278/*
1279 * Fetch a texture image from the device driver.
1280 * Store the results in the given texture object at the given mipmap level.
1281 */
1282static void
1283get_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
jtgafb833d1999-08-19 00:55:39 +00001368
Brian Paulfbd8f211999-11-11 01:22:25 +00001369void
1370_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1371 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001372{
Brian Paulfbd8f211999-11-11 01:22:25 +00001373 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001374 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00001375 struct gl_texture_image *texImage;
1376 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00001377
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)
Brian Paulf7b57072000-03-20 14:37:52 +00001396 return;
jtgafb833d1999-08-19 00:55:39 +00001397
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
Brian Paulf7b57072000-03-20 14:37:52 +00001413 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) {
jtgafb833d1999-08-19 00:55:39 +00001429 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);
Brian Paul959f8022000-03-19 01:10:11 +00001442 gl_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1443 format, type, dest,
jtgafb833d1999-08-19 00:55:39 +00001444 &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 }
Brian Paulf7b57072000-03-20 14:37:52 +00001511
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 }
jtgafb833d1999-08-19 00:55:39 +00001517 }
1518}
1519
1520
1521
Brian Paulfbd8f211999-11-11 01:22:25 +00001522void
1523_mesa_TexSubImage1D( GLenum target, GLint level,
1524 GLint xoffset, GLsizei width,
1525 GLenum format, GLenum type,
1526 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001527{
Brian Paulfbd8f211999-11-11 01:22:25 +00001528 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001529 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1530 struct gl_texture_image *destTex;
1531
Brian Paulc3f0a511999-11-03 17:27:05 +00001532 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1533 width, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001534 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001535 }
1536
1537 destTex = texUnit->CurrentD[1]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001538 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001539
Brian Paulc3f0a511999-11-03 17:27:05 +00001540 if (width == 0 || !pixels)
1541 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001542
Brian Paulc3f0a511999-11-03 17:27:05 +00001543
1544 /*
1545 * Replace the texture subimage
1546 */
1547 {
1548 const GLint texComponents = components_in_intformat(destTex->Format);
1549 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001550 const GLint xoffsetb = xoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001551 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);
jtgafb833d1999-08-19 00:55:39 +00001558 }
1559 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001560 /* 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);
jtgafb833d1999-08-19 00:55:39 +00001565 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001566 }
jtgafb833d1999-08-19 00:55:39 +00001567
Brian Paulc3f0a511999-11-03 17:27:05 +00001568 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
jtgafb833d1999-08-19 00:55:39 +00001569
Brian Paulc3f0a511999-11-03 17:27:05 +00001570 /*
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 );
jtgafb833d1999-08-19 00:55:39 +00001578 }
1579 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001580 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 );
jtgafb833d1999-08-19 00:55:39 +00001585 }
jtgafb833d1999-08-19 00:55:39 +00001586 }
1587}
1588
1589
Brian Paulfbd8f211999-11-11 01:22:25 +00001590void
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 )
jtgafb833d1999-08-19 00:55:39 +00001596{
Brian Paulfbd8f211999-11-11 01:22:25 +00001597 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001598 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1599 struct gl_texture_image *destTex;
1600
Brian Paulc3f0a511999-11-03 17:27:05 +00001601 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1602 width, height, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001603 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001604 }
1605
1606 destTex = texUnit->CurrentD[2]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001607 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001608
Brian Paulc3f0a511999-11-03 17:27:05 +00001609 if (width == 0 || height == 0 || !pixels)
1610 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001611
Brian Paulc3f0a511999-11-03 17:27:05 +00001612
1613 /*
1614 * Replace the texture subimage
1615 */
1616 {
1617 const GLint texComponents = components_in_intformat(destTex->Format);
1618 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001619 const GLint xoffsetb = xoffset + destTex->Border;
1620 const GLint yoffsetb = yoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001621 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;
Brian Paul64a79b21999-10-22 10:43:35 +00001633 }
1634 }
jtgafb833d1999-08-19 00:55:39 +00001635 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001636 /* 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;
jtgafb833d1999-08-19 00:55:39 +00001645 }
jtgafb833d1999-08-19 00:55:39 +00001646 }
1647 }
jtgafb833d1999-08-19 00:55:39 +00001648
Brian Paulc3f0a511999-11-03 17:27:05 +00001649 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 );
jtgafb833d1999-08-19 00:55:39 +00001666 }
jtgafb833d1999-08-19 00:55:39 +00001667 }
1668}
1669
1670
1671
Brian Paulfbd8f211999-11-11 01:22:25 +00001672void
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 )
jtgafb833d1999-08-19 00:55:39 +00001678{
Brian Paulfbd8f211999-11-11 01:22:25 +00001679 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001680 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1681 struct gl_texture_image *destTex;
1682
Brian Paulc3f0a511999-11-03 17:27:05 +00001683 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1684 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001685 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001686 }
1687
1688 destTex = texUnit->CurrentD[3]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001689 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001690
Brian Paulc3f0a511999-11-03 17:27:05 +00001691 if (width == 0 || height == 0 || height == 0 || !pixels)
1692 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001693
Brian Paulc3f0a511999-11-03 17:27:05 +00001694 /*
1695 * Replace the texture subimage
1696 */
1697 {
1698 const GLint texComponents = components_in_intformat(destTex->Format);
1699 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001700 const GLint xoffsetb = xoffset + destTex->Border;
1701 const GLint yoffsetb = yoffset + destTex->Border;
1702 const GLint zoffsetb = zoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001703 GLint dstRectArea = destTex->Width * destTex->Height;
1704 GLubyte *dst = destTex->Data
1705 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
1706 * texComponents;
jtgafb833d1999-08-19 00:55:39 +00001707
Brian Paulc3f0a511999-11-03 17:27:05 +00001708 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 }
jtgafb833d1999-08-19 00:55:39 +00001720 }
1721 }
1722 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001723 /* 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 }
jtgafb833d1999-08-19 00:55:39 +00001734 }
jtgafb833d1999-08-19 00:55:39 +00001735 }
1736 }
jtgafb833d1999-08-19 00:55:39 +00001737
Brian Paulc3f0a511999-11-03 17:27:05 +00001738 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1739
1740 /*
1741 * Inform device driver of texture image change.
1742 */
1743 /* XXX todo */
jtgafb833d1999-08-19 00:55:39 +00001744}
1745
1746
1747
1748/*
1749 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00001750 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00001751 * Input: ctx - the context
1752 * x, y - lower left corner
1753 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00001754 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00001755 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001756static GLubyte *
1757read_color_image( GLcontext *ctx, GLint x, GLint y,
1758 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00001759{
Brian Paulc3f0a511999-11-03 17:27:05 +00001760 GLint stride, i;
1761 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00001762
Brian Paul959f8022000-03-19 01:10:11 +00001763 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00001764 if (!image)
jtgafb833d1999-08-19 00:55:39 +00001765 return NULL;
jtgafb833d1999-08-19 00:55:39 +00001766
1767 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001768 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1769 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001770
Brian Paulc3f0a511999-11-03 17:27:05 +00001771 dst = image;
1772 stride = width * 4 * sizeof(GLubyte);
1773 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00001774 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1775 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00001776 dst += stride;
1777 }
jtgafb833d1999-08-19 00:55:39 +00001778
Brian Paulcea0e8e1999-11-25 17:36:48 +00001779 /* Read from draw buffer (the default) */
1780 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1781 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001782
1783 return image;
1784}
1785
1786
1787
Brian Paulfbd8f211999-11-11 01:22:25 +00001788void
1789_mesa_CopyTexImage1D( GLenum target, GLint level,
1790 GLenum internalFormat,
1791 GLint x, GLint y,
1792 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001793{
Brian Paulfbd8f211999-11-11 01:22:25 +00001794 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001795 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00001796
Brian Paulf7b57072000-03-20 14:37:52 +00001797 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 {
Brian Paulc3f0a511999-11-03 17:27:05 +00001806 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 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001811 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00001812 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001813 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001814 }
jtgafb833d1999-08-19 00:55:39 +00001815}
1816
1817
1818
Brian Paulfbd8f211999-11-11 01:22:25 +00001819void
1820_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1821 GLint x, GLint y, GLsizei width, GLsizei height,
1822 GLint border )
jtgafb833d1999-08-19 00:55:39 +00001823{
Brian Paulfbd8f211999-11-11 01:22:25 +00001824 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001825 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00001826
Brian Paulf7b57072000-03-20 14:37:52 +00001827 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 {
Brian Paulc3f0a511999-11-03 17:27:05 +00001836 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 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001841 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00001842 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001843 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001844 }
jtgafb833d1999-08-19 00:55:39 +00001845}
1846
1847
1848
jtgafb833d1999-08-19 00:55:39 +00001849/*
1850 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00001851 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001852static void
1853copy_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 )
jtgafb833d1999-08-19 00:55:39 +00001857{
Brian Paulc3f0a511999-11-03 17:27:05 +00001858 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;
jtgafb833d1999-08-19 00:55:39 +00001870 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00001871 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00001872
Brian Paul91baaa31999-10-17 23:24:16 +00001873 /* dst[xyz] may be negative if we have a texture border! */
1874 dstx += dest->Border;
1875 dsty += dest->Border;
1876 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00001877 texwidth = dest->Width;
1878 texheight = dest->Height;
1879 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00001880 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00001881 format = dest->Format;
1882 components = components_in_intformat( format );
1883
1884 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001885 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1886 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001887
Brian Paulc3f0a511999-11-03 17:27:05 +00001888 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00001889 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00001890 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00001891 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00001892 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 }
jtgafb833d1999-08-19 00:55:39 +00001897
Brian Paulcea0e8e1999-11-25 17:36:48 +00001898 /* Read from draw buffer (the default) */
1899 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1900 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001901}
1902
1903
1904
1905
Brian Paulfbd8f211999-11-11 01:22:25 +00001906void
1907_mesa_CopyTexSubImage1D( GLenum target, GLint level,
1908 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00001909{
Brian Paulfbd8f211999-11-11 01:22:25 +00001910 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001911 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00001912
Brian Paulf7b57072000-03-20 14:37:52 +00001913 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)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001921 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);
jtgafb833d1999-08-19 00:55:39 +00001926 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001927 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00001928 /* 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 }
jtgafb833d1999-08-19 00:55:39 +00001934 }
1935 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001936}
1937
1938
1939
Brian Paulfbd8f211999-11-11 01:22:25 +00001940void
1941_mesa_CopyTexSubImage2D( GLenum target, GLint level,
1942 GLint xoffset, GLint yoffset,
1943 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001944{
Brian Paulfbd8f211999-11-11 01:22:25 +00001945 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001946 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
1947
Brian Paulf7b57072000-03-20 14:37:52 +00001948 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 )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001956 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);
Brian Paulf7b57072000-03-20 14:37:52 +00001964 /* 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 );
Brian Paulc3f0a511999-11-03 17:27:05 +00001969 }
1970 }
1971 }
1972}
1973
1974
1975
Brian Paulfbd8f211999-11-11 01:22:25 +00001976void
1977_mesa_CopyTexSubImage3D( GLenum target, GLint level,
1978 GLint xoffset, GLint yoffset, GLint zoffset,
1979 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001980{
Brian Paulfbd8f211999-11-11 01:22:25 +00001981 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001982 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
1983
Brian Paulf7b57072000-03-20 14:37:52 +00001984 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,
Brian Paulc3f0a511999-11-03 17:27:05 +00001999 x, y, xoffset, yoffset, zoffset);
Brian Paulf7b57072000-03-20 14:37:52 +00002000 /* 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 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002006 }
jtgafb833d1999-08-19 00:55:39 +00002007 }
2008}