blob: ae50558bf26c0121a69b640b66132d380ce12729 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001
2/*
3 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00004 * Version: 3.3
jtgafb833d1999-08-19 00:55:39 +00005 *
Brian Paul663049a2000-01-31 23:10:16 +00006 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27#ifdef PC_HEADER
28#include "all.h"
29#else
Brian Paulfbd8f211999-11-11 01:22:25 +000030#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000031#include "context.h"
32#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000033#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000034#include "mmath.h"
35#include "span.h"
36#include "teximage.h"
37#include "texstate.h"
38#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000039#endif
40
41
42/*
43 * NOTES:
44 *
Brian Paulc3f0a511999-11-03 17:27:05 +000045 * Mesa's native texture datatype is GLubyte. Native formats are
46 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
47 * and GL_COLOR_INDEX.
48 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000049 */
50
51
Brian Paul48271792000-03-29 18:13:59 +000052#ifdef DEBUG
Brian Paule5d68a22000-03-30 18:37:51 +000053static void PrintTexture(const struct gl_texture_image *img)
Brian Paul48271792000-03-29 18:13:59 +000054{
Brian Paule5d68a22000-03-30 18:37:51 +000055 int i, j, c;
56 GLubyte *data = img->Data;
57
58 if (!data) {
59 printf("No texture data\n");
60 return;
61 }
62
63 switch (img->Format) {
64 case GL_ALPHA:
65 case GL_LUMINANCE:
66 case GL_INTENSITY:
67 case GL_COLOR_INDEX:
68 c = 1;
69 break;
70 case GL_LUMINANCE_ALPHA:
71 c = 2;
72 break;
73 case GL_RGB:
74 c = 3;
75 break;
76 case GL_RGBA:
77 c = 4;
78 break;
79 default:
80 gl_problem(NULL, "error in PrintTexture\n");
81 return;
82 }
83
84
85 for (i = 0; i < img->Height; i++) {
86 for (j = 0; j < img->Width; j++) {
Brian Paul48271792000-03-29 18:13:59 +000087 if (c==1)
88 printf("%02x ", data[0]);
89 else if (c==2)
Brian Paule5d68a22000-03-30 18:37:51 +000090 printf("%02x%02x ", data[0], data[1]);
Brian Paul48271792000-03-29 18:13:59 +000091 else if (c==3)
Brian Paule5d68a22000-03-30 18:37:51 +000092 printf("%02x%02x%02x ", data[0], data[1], data[2]);
Brian Paul48271792000-03-29 18:13:59 +000093 else if (c==4)
Brian Paule5d68a22000-03-30 18:37:51 +000094 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
Brian Paul48271792000-03-29 18:13:59 +000095 data += c;
96 }
97 printf("\n");
98 }
99}
100#endif
101
102
103
Brian Paulf7b57072000-03-20 14:37:52 +0000104/*
jtgafb833d1999-08-19 00:55:39 +0000105 * Compute log base 2 of n.
106 * If n isn't an exact power of two return -1.
107 * If n<0 return -1.
108 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000109static int
110logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +0000111{
112 GLint i = 1;
113 GLint log2 = 0;
114
115 if (n<0) {
116 return -1;
117 }
118
119 while ( n > i ) {
120 i *= 2;
121 log2++;
122 }
123 if (i != n) {
124 return -1;
125 }
126 else {
127 return log2;
128 }
129}
130
131
132
133/*
134 * Given an internal texture format enum or 1, 2, 3, 4 return the
135 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +0000136 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
137 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +0000138 */
Brian Paulb132e8d2000-03-23 16:23:14 +0000139GLint
140_mesa_base_tex_format( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000141{
142 switch (format) {
143 case GL_ALPHA:
144 case GL_ALPHA4:
145 case GL_ALPHA8:
146 case GL_ALPHA12:
147 case GL_ALPHA16:
148 return GL_ALPHA;
149 case 1:
150 case GL_LUMINANCE:
151 case GL_LUMINANCE4:
152 case GL_LUMINANCE8:
153 case GL_LUMINANCE12:
154 case GL_LUMINANCE16:
155 return GL_LUMINANCE;
156 case 2:
157 case GL_LUMINANCE_ALPHA:
158 case GL_LUMINANCE4_ALPHA4:
159 case GL_LUMINANCE6_ALPHA2:
160 case GL_LUMINANCE8_ALPHA8:
161 case GL_LUMINANCE12_ALPHA4:
162 case GL_LUMINANCE12_ALPHA12:
163 case GL_LUMINANCE16_ALPHA16:
164 return GL_LUMINANCE_ALPHA;
165 case GL_INTENSITY:
166 case GL_INTENSITY4:
167 case GL_INTENSITY8:
168 case GL_INTENSITY12:
169 case GL_INTENSITY16:
170 return GL_INTENSITY;
171 case 3:
172 case GL_RGB:
173 case GL_R3_G3_B2:
174 case GL_RGB4:
175 case GL_RGB5:
176 case GL_RGB8:
177 case GL_RGB10:
178 case GL_RGB12:
179 case GL_RGB16:
180 return GL_RGB;
181 case 4:
182 case GL_RGBA:
183 case GL_RGBA2:
184 case GL_RGBA4:
185 case GL_RGB5_A1:
186 case GL_RGBA8:
187 case GL_RGB10_A2:
188 case GL_RGBA12:
189 case GL_RGBA16:
190 return GL_RGBA;
191 case GL_COLOR_INDEX:
192 case GL_COLOR_INDEX1_EXT:
193 case GL_COLOR_INDEX2_EXT:
194 case GL_COLOR_INDEX4_EXT:
195 case GL_COLOR_INDEX8_EXT:
196 case GL_COLOR_INDEX12_EXT:
197 case GL_COLOR_INDEX16_EXT:
198 return GL_COLOR_INDEX;
199 default:
200 return -1; /* error */
201 }
202}
203
204
205
206/*
207 * Given an internal texture format enum or 1, 2, 3, 4 return the
208 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
209 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
210 * number of components for the format. Return -1 if invalid enum.
211 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000212static GLint
213components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000214{
215 switch (format) {
216 case GL_ALPHA:
217 case GL_ALPHA4:
218 case GL_ALPHA8:
219 case GL_ALPHA12:
220 case GL_ALPHA16:
221 return 1;
222 case 1:
223 case GL_LUMINANCE:
224 case GL_LUMINANCE4:
225 case GL_LUMINANCE8:
226 case GL_LUMINANCE12:
227 case GL_LUMINANCE16:
228 return 1;
229 case 2:
230 case GL_LUMINANCE_ALPHA:
231 case GL_LUMINANCE4_ALPHA4:
232 case GL_LUMINANCE6_ALPHA2:
233 case GL_LUMINANCE8_ALPHA8:
234 case GL_LUMINANCE12_ALPHA4:
235 case GL_LUMINANCE12_ALPHA12:
236 case GL_LUMINANCE16_ALPHA16:
237 return 2;
238 case GL_INTENSITY:
239 case GL_INTENSITY4:
240 case GL_INTENSITY8:
241 case GL_INTENSITY12:
242 case GL_INTENSITY16:
243 return 1;
244 case 3:
245 case GL_RGB:
246 case GL_R3_G3_B2:
247 case GL_RGB4:
248 case GL_RGB5:
249 case GL_RGB8:
250 case GL_RGB10:
251 case GL_RGB12:
252 case GL_RGB16:
253 return 3;
254 case 4:
255 case GL_RGBA:
256 case GL_RGBA2:
257 case GL_RGBA4:
258 case GL_RGB5_A1:
259 case GL_RGBA8:
260 case GL_RGB10_A2:
261 case GL_RGBA12:
262 case GL_RGBA16:
263 return 4;
264 case GL_COLOR_INDEX:
265 case GL_COLOR_INDEX1_EXT:
266 case GL_COLOR_INDEX2_EXT:
267 case GL_COLOR_INDEX4_EXT:
268 case GL_COLOR_INDEX8_EXT:
269 case GL_COLOR_INDEX12_EXT:
270 case GL_COLOR_INDEX16_EXT:
271 return 1;
272 default:
273 return -1; /* error */
274 }
275}
276
277
278
jtgafb833d1999-08-19 00:55:39 +0000279/*
280 * Examine the texImage->Format field and set the Red, Green, Blue, etc
281 * texel component sizes to default values.
282 * These fields are set only here by core Mesa but device drivers may
283 * overwritting these fields to indicate true texel resolution.
284 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000285static void
286set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000287{
288 switch (texImage->Format) {
289 case GL_ALPHA:
290 texImage->RedBits = 0;
291 texImage->GreenBits = 0;
292 texImage->BlueBits = 0;
293 texImage->AlphaBits = 8;
294 texImage->IntensityBits = 0;
295 texImage->LuminanceBits = 0;
296 texImage->IndexBits = 0;
297 break;
298 case GL_LUMINANCE:
299 texImage->RedBits = 0;
300 texImage->GreenBits = 0;
301 texImage->BlueBits = 0;
302 texImage->AlphaBits = 0;
303 texImage->IntensityBits = 0;
304 texImage->LuminanceBits = 8;
305 texImage->IndexBits = 0;
306 break;
307 case GL_LUMINANCE_ALPHA:
308 texImage->RedBits = 0;
309 texImage->GreenBits = 0;
310 texImage->BlueBits = 0;
311 texImage->AlphaBits = 8;
312 texImage->IntensityBits = 0;
313 texImage->LuminanceBits = 8;
314 texImage->IndexBits = 0;
315 break;
316 case GL_INTENSITY:
317 texImage->RedBits = 0;
318 texImage->GreenBits = 0;
319 texImage->BlueBits = 0;
320 texImage->AlphaBits = 0;
321 texImage->IntensityBits = 8;
322 texImage->LuminanceBits = 0;
323 texImage->IndexBits = 0;
324 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000325 case GL_RED:
326 texImage->RedBits = 8;
327 texImage->GreenBits = 0;
328 texImage->BlueBits = 0;
329 texImage->AlphaBits = 0;
330 texImage->IntensityBits = 0;
331 texImage->LuminanceBits = 0;
332 texImage->IndexBits = 0;
333 break;
334 case GL_GREEN:
335 texImage->RedBits = 0;
336 texImage->GreenBits = 8;
337 texImage->BlueBits = 0;
338 texImage->AlphaBits = 0;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 0;
341 texImage->IndexBits = 0;
342 break;
343 case GL_BLUE:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 8;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 0;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 0;
351 break;
jtgafb833d1999-08-19 00:55:39 +0000352 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000353 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000354 texImage->RedBits = 8;
355 texImage->GreenBits = 8;
356 texImage->BlueBits = 8;
357 texImage->AlphaBits = 0;
358 texImage->IntensityBits = 0;
359 texImage->LuminanceBits = 0;
360 texImage->IndexBits = 0;
361 break;
362 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000363 case GL_BGRA:
364 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000365 texImage->RedBits = 8;
366 texImage->GreenBits = 8;
367 texImage->BlueBits = 8;
368 texImage->AlphaBits = 8;
369 texImage->IntensityBits = 0;
370 texImage->LuminanceBits = 0;
371 texImage->IndexBits = 0;
372 break;
373 case GL_COLOR_INDEX:
374 texImage->RedBits = 0;
375 texImage->GreenBits = 0;
376 texImage->BlueBits = 0;
377 texImage->AlphaBits = 0;
378 texImage->IntensityBits = 0;
379 texImage->LuminanceBits = 0;
380 texImage->IndexBits = 8;
381 break;
382 default:
383 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
384 }
385}
386
387
Brian Paul77ce6da2000-03-20 23:40:12 +0000388
389/*
390 * Return new gl_texture_image struct with all fields initialized to zero.
391 */
392struct gl_texture_image *
Brian Paul021a5252000-03-27 17:54:17 +0000393_mesa_alloc_texture_image( void )
Brian Paul77ce6da2000-03-20 23:40:12 +0000394{
395 return CALLOC_STRUCT(gl_texture_image);
396}
397
398
399
400/*
Brian Paul02938782000-03-22 17:38:11 +0000401 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000402 */
Brian Paul02938782000-03-22 17:38:11 +0000403static void
404init_texture_image( struct gl_texture_image *img,
405 GLsizei width, GLsizei height, GLsizei depth,
406 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000407{
Brian Paul02938782000-03-22 17:38:11 +0000408 ASSERT(img);
409 ASSERT(!img->Data);
Brian Paulb132e8d2000-03-23 16:23:14 +0000410 img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000411 set_teximage_component_sizes( img );
412 img->IntFormat = (GLenum) internalFormat;
413 img->Border = border;
414 img->Width = width;
415 img->Height = height;
416 img->Depth = depth;
417 img->WidthLog2 = logbase2(width - 2 * border);
418 if (height == 1) /* 1-D texture */
419 img->HeightLog2 = 0;
420 else
421 img->HeightLog2 = logbase2(height - 2 * border);
422 if (depth == 1) /* 2-D texture */
423 img->DepthLog2 = 0;
424 else
425 img->DepthLog2 = logbase2(depth - 2 * border);
426 img->Width2 = 1 << img->WidthLog2;
427 img->Height2 = 1 << img->HeightLog2;
428 img->Depth2 = 1 << img->DepthLog2;
429 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paul77ce6da2000-03-20 23:40:12 +0000430}
431
432
433
434void
Brian Paul021a5252000-03-27 17:54:17 +0000435_mesa_free_texture_image( struct gl_texture_image *teximage )
Brian Paul77ce6da2000-03-20 23:40:12 +0000436{
437 if (teximage->Data) {
438 FREE( teximage->Data );
439 teximage->Data = NULL;
440 }
441 FREE( teximage );
442}
443
444
445
jtgafb833d1999-08-19 00:55:39 +0000446/* Need this to prevent an out-of-bounds memory access when using
447 * X86 optimized code.
448 */
449#ifdef USE_X86_ASM
450# define EXTRA_BYTE 1
451#else
452# define EXTRA_BYTE 0
453#endif
454
455
Brian Paulc3f0a511999-11-03 17:27:05 +0000456
jtgafb833d1999-08-19 00:55:39 +0000457/*
Brian Paul43911c82000-03-21 00:49:33 +0000458 * Called by glTexImage[123]D. Fill in a texture image with data given
459 * by the client. All pixel transfer and unpack modes are handled here.
460 * NOTE: All texture image parameters should have already been error checked.
jtgafb833d1999-08-19 00:55:39 +0000461 */
Brian Paul43911c82000-03-21 00:49:33 +0000462static void
463make_texture_image( GLcontext *ctx,
464 struct gl_texture_image *texImage,
Brian Paulc3f0a511999-11-03 17:27:05 +0000465 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
466 const struct gl_pixelstore_attrib *unpacking)
jtgafb833d1999-08-19 00:55:39 +0000467{
Brian Paulc3f0a511999-11-03 17:27:05 +0000468 GLint components, numPixels;
Brian Paul43911c82000-03-21 00:49:33 +0000469 GLint internalFormat, width, height, depth, border;
jtgafb833d1999-08-19 00:55:39 +0000470
Brian Paul43911c82000-03-21 00:49:33 +0000471 ASSERT(ctx);
472 ASSERT(texImage);
473 ASSERT(!texImage->Data);
474 ASSERT(pixels);
475 ASSERT(unpacking);
jtgafb833d1999-08-19 00:55:39 +0000476
Brian Paul43911c82000-03-21 00:49:33 +0000477 internalFormat = texImage->IntFormat;
478 width = texImage->Width;
479 height = texImage->Height;
480 depth = texImage->Depth;
481 border = texImage->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +0000482 components = components_in_intformat(internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +0000483
484 ASSERT(width > 0);
485 ASSERT(height > 0);
486 ASSERT(depth > 0);
487 ASSERT(border == 0 || border == 1);
488 ASSERT(pixels);
489 ASSERT(unpacking);
490 ASSERT(components);
491
492 numPixels = width * height * depth;
Brian Paulc3f0a511999-11-03 17:27:05 +0000493
494 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
Brian Paul43911c82000-03-21 00:49:33 +0000495 if (!texImage->Data)
496 return; /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000497
498 /*
499 * OK, the texture image struct has been initialized and the texture
500 * image memory has been allocated.
501 * Now fill in the texture image from the source data.
502 * This includes applying the pixel transfer operations.
503 */
504
505 /* try common 2D texture cases first */
506 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
507 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
508 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
509
Brian Paul43911c82000-03-21 00:49:33 +0000510 if (srcFormat == internalFormat ||
511 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
512 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
513 (srcFormat == GL_RGB && internalFormat == 3) ||
514 (srcFormat == GL_RGBA && internalFormat == 4)) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000515 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
516 * GL_LUMINANCE_ALPHA, etc. texture formats.
517 */
Brian Paulb7d076f2000-03-21 01:03:40 +0000518 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000519 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
520 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
521 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000522 GLubyte *dst = texImage->Data;
523 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
524 if (srcStride == dstBytesPerRow) {
525 MEMCPY(dst, src, height * dstBytesPerRow);
526 }
527 else {
528 GLint i;
529 for (i = 0; i < height; i++) {
530 MEMCPY(dst, src, dstBytesPerRow);
531 src += srcStride;
532 dst += dstBytesPerRow;
533 }
534 }
Brian Paul43911c82000-03-21 00:49:33 +0000535 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000536 }
537 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
538 /* commonly used by Quake */
Brian Paulb7d076f2000-03-21 01:03:40 +0000539 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000540 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
541 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
542 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000543 GLubyte *dst = texImage->Data;
544 GLint i, j;
545 for (i = 0; i < height; i++) {
546 const GLubyte *s = src;
547 for (j = 0; j < width; j++) {
548 *dst++ = *s++; /*red*/
549 *dst++ = *s++; /*green*/
550 *dst++ = *s++; /*blue*/
551 s++; /*alpha*/
552 }
553 src += srcStride;
554 }
Brian Paul43911c82000-03-21 00:49:33 +0000555 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000556 }
557 }
558
559
560 /*
561 * General case solutions
562 */
563 if (texImage->Format == GL_COLOR_INDEX) {
564 /* color index texture */
565 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
566 const GLenum dstType = GL_UNSIGNED_BYTE;
567 GLubyte *dest = texImage->Data;
568 GLint img, row;
569 for (img = 0; img < depth; img++) {
570 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000571 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000572 pixels, width, height, srcFormat, srcType, img, row, 0);
573 _mesa_unpack_index_span(ctx, width, dstType, dest,
574 srcType, source, unpacking, GL_TRUE);
575 dest += destBytesPerRow;
576 }
577 }
jtgafb833d1999-08-19 00:55:39 +0000578 }
579 else {
Brian Paulc3f0a511999-11-03 17:27:05 +0000580 /* regular, color texture */
581 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
582 const GLenum dstFormat = texImage->Format;
583 GLubyte *dest = texImage->Data;
584 GLint img, row;
585 for (img = 0; img < depth; img++) {
586 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000587 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000588 pixels, width, height, srcFormat, srcType, img, row, 0);
589 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
590 srcFormat, srcType, source, unpacking, GL_TRUE);
591 dest += destBytesPerRow;
592 }
593 }
jtgafb833d1999-08-19 00:55:39 +0000594 }
jtgafb833d1999-08-19 00:55:39 +0000595}
596
597
598
599/*
600 * glTexImage[123]D can accept a NULL image pointer. In this case we
601 * create a texture image with unspecified image contents per the OpenGL
Brian Paul43911c82000-03-21 00:49:33 +0000602 * spec. This function creates an empty image for the given texture image.
jtgafb833d1999-08-19 00:55:39 +0000603 */
Brian Paul43911c82000-03-21 00:49:33 +0000604static void
605make_null_texture( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000606{
607 GLint components;
jtgafb833d1999-08-19 00:55:39 +0000608 GLint numPixels;
jtgafb833d1999-08-19 00:55:39 +0000609
Brian Paul43911c82000-03-21 00:49:33 +0000610 ASSERT(texImage);
611 ASSERT(!texImage->Data);
jtgafb833d1999-08-19 00:55:39 +0000612
Brian Paul43911c82000-03-21 00:49:33 +0000613 components = components_in_intformat(texImage->IntFormat);
614 numPixels = texImage->Width * texImage->Height * texImage->Depth;
jtgafb833d1999-08-19 00:55:39 +0000615
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000616 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000617
618 /*
619 * Let's see if anyone finds this. If glTexImage2D() is called with
620 * a NULL image pointer then load the texture image with something
621 * interesting instead of leaving it indeterminate.
622 */
623 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000624 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000625 " X X XXXXX XXX X ",
626 " XX XX X X X X X ",
627 " X X X X X X X ",
628 " X X XXXX XXX XXXXX ",
629 " X X X X X X ",
630 " X X X X X X X ",
631 " X X XXXXX XXX X X ",
632 " "
633 };
634
635 GLubyte *imgPtr = texImage->Data;
636 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000637 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000638 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000639 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000640 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000641 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000642 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000643 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000644 }
645 }
646 }
647 }
jtgafb833d1999-08-19 00:55:39 +0000648}
649
650
651
652/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000653 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +0000654 * Input:
655 * dimensions - must be 1 or 2 or 3
656 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
657 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000658static GLboolean
659texture_error_check( GLcontext *ctx, GLenum target,
660 GLint level, GLint internalFormat,
661 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +0000662 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000663 GLint width, GLint height,
664 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +0000665{
666 GLboolean isProxy;
667 GLint iformat;
668
669 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +0000670 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +0000671 if (target != GL_TEXTURE_1D && !isProxy) {
672 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
673 return GL_TRUE;
674 }
675 }
676 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +0000677 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
jtgafb833d1999-08-19 00:55:39 +0000678 if (target != GL_TEXTURE_2D && !isProxy) {
679 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
680 return GL_TRUE;
681 }
682 }
683 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +0000684 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +0000685 if (target != GL_TEXTURE_3D && !isProxy) {
686 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
687 return GL_TRUE;
688 }
689 }
690 else {
691 gl_problem( ctx, "bad dims in texture_error_check" );
692 return GL_TRUE;
693 }
694
695 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000696 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +0000697 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000698 char message[100];
699 sprintf(message, "glTexImage%dD(border)", dimensions);
700 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000701 }
702 return GL_TRUE;
703 }
704
705 /* Width */
706 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
707 || logbase2( width - 2 * border ) < 0) {
708 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000709 char message[100];
710 sprintf(message, "glTexImage%dD(width)", dimensions);
711 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000712 }
713 return GL_TRUE;
714 }
715
716 /* Height */
717 if (dimensions >= 2) {
718 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
719 || logbase2( height - 2 * border ) < 0) {
720 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000721 char message[100];
722 sprintf(message, "glTexImage%dD(height)", dimensions);
723 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000724 }
Brian Paulc3f0a511999-11-03 17:27:05 +0000725 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000726 }
727 }
728
729 /* Depth */
730 if (dimensions >= 3) {
731 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
732 || logbase2( depth - 2 * border ) < 0) {
733 if (!isProxy) {
734 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
735 }
736 return GL_TRUE;
737 }
738 }
739
740 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000741 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000742 if (!isProxy) {
743 char message[100];
744 sprintf(message, "glTexImage%dD(level)", dimensions);
745 gl_error(ctx, GL_INVALID_VALUE, message);
746 }
jtgafb833d1999-08-19 00:55:39 +0000747 return GL_TRUE;
748 }
749
Brian Paulb132e8d2000-03-23 16:23:14 +0000750 iformat = _mesa_base_tex_format( internalFormat );
jtgafb833d1999-08-19 00:55:39 +0000751 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000752 if (!isProxy) {
753 char message[100];
754 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
755 gl_error(ctx, GL_INVALID_VALUE, message);
756 }
jtgafb833d1999-08-19 00:55:39 +0000757 return GL_TRUE;
758 }
759
Brian Paulb7d076f2000-03-21 01:03:40 +0000760 if (!_mesa_is_legal_format_and_type( format, type )) {
Brian Pauld53573d1999-10-19 20:36:20 +0000761 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
762 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
763 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000764 if (!isProxy) {
765 char message[100];
766 sprintf(message, "glTexImage%dD(format or type)", dimensions);
767 gl_error(ctx, GL_INVALID_OPERATION, message);
768 }
jtgafb833d1999-08-19 00:55:39 +0000769 return GL_TRUE;
770 }
771
772 /* if we get here, the parameters are OK */
773 return GL_FALSE;
774}
775
776
777
778/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000779 * Test glTexSubImage[123]D() parameters for errors.
780 * Input:
781 * dimensions - must be 1 or 2 or 3
782 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
783 */
784static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000785subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000786 GLenum target, GLint level,
787 GLint xoffset, GLint yoffset, GLint zoffset,
788 GLint width, GLint height, GLint depth,
789 GLenum format, GLenum type )
790{
791 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
792 struct gl_texture_image *destTex;
793
794 if (dimensions == 1) {
795 if (target != GL_TEXTURE_1D) {
796 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
797 return GL_TRUE;
798 }
799 }
800 else if (dimensions == 2) {
801 if (target != GL_TEXTURE_2D) {
802 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
803 return GL_TRUE;
804 }
805 }
806 else if (dimensions == 3) {
807 if (target != GL_TEXTURE_3D) {
808 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
809 return GL_TRUE;
810 }
811 }
812 else {
813 gl_problem( ctx, "bad dims in texture_error_check" );
814 return GL_TRUE;
815 }
816
817 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
818 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
819 return GL_TRUE;
820 }
821
822 if (width < 0) {
823 char message[100];
824 sprintf(message, "glTexSubImage%dD(width)", dimensions);
825 gl_error(ctx, GL_INVALID_VALUE, message);
826 return GL_TRUE;
827 }
828 if (height < 0 && dimensions > 1) {
829 char message[100];
830 sprintf(message, "glTexSubImage%dD(height)", dimensions);
831 gl_error(ctx, GL_INVALID_VALUE, message);
832 return GL_TRUE;
833 }
834 if (depth < 0 && dimensions > 2) {
835 char message[100];
836 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
837 gl_error(ctx, GL_INVALID_VALUE, message);
838 return GL_TRUE;
839 }
840
841 destTex = texUnit->CurrentD[2]->Image[level];
842 if (!destTex) {
843 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
844 return GL_TRUE;
845 }
846
847 if (xoffset < -((GLint)destTex->Border)) {
848 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
849 return GL_TRUE;
850 }
851 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
852 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
853 return GL_TRUE;
854 }
855 if (dimensions > 1) {
856 if (yoffset < -((GLint)destTex->Border)) {
857 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
858 return GL_TRUE;
859 }
860 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
861 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
862 return GL_TRUE;
863 }
864 }
865 if (dimensions > 2) {
866 if (zoffset < -((GLint)destTex->Border)) {
867 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
868 return GL_TRUE;
869 }
870 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
871 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
872 return GL_TRUE;
873 }
874 }
875
Brian Paulb7d076f2000-03-21 01:03:40 +0000876 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000877 char message[100];
878 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
879 gl_error(ctx, GL_INVALID_ENUM, message);
880 return GL_TRUE;
881 }
882
883 return GL_FALSE;
884}
885
886
887/*
888 * Test glCopyTexImage[12]D() parameters for errors.
889 * Input: dimensions - must be 1 or 2 or 3
890 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
891 */
892static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000893copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000894 GLenum target, GLint level, GLint internalFormat,
895 GLint width, GLint height, GLint border )
896{
897 GLint iformat;
898
899 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
900 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
901 return GL_TRUE;
902 }
903
904 if (dimensions == 1 && target != GL_TEXTURE_1D) {
905 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
906 return GL_TRUE;
907 }
908 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
909 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
910 return GL_TRUE;
911 }
912
913 /* Border */
914 if (border!=0 && border!=1) {
915 char message[100];
916 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
917 gl_error(ctx, GL_INVALID_VALUE, message);
918 return GL_TRUE;
919 }
920
921 /* Width */
922 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
923 || logbase2( width - 2 * border ) < 0) {
924 char message[100];
925 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
926 gl_error(ctx, GL_INVALID_VALUE, message);
927 return GL_TRUE;
928 }
929
930 /* Height */
931 if (dimensions >= 2) {
932 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
933 || logbase2( height - 2 * border ) < 0) {
934 char message[100];
935 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
936 gl_error(ctx, GL_INVALID_VALUE, message);
937 return GL_TRUE;
938 }
939 }
940
941 /* Level */
942 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
943 char message[100];
944 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
945 gl_error(ctx, GL_INVALID_VALUE, message);
946 return GL_TRUE;
947 }
948
Brian Paulb132e8d2000-03-23 16:23:14 +0000949 iformat = _mesa_base_tex_format( internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +0000950 if (iformat < 0) {
951 char message[100];
952 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
953 gl_error(ctx, GL_INVALID_VALUE, message);
954 return GL_TRUE;
955 }
956
957 /* if we get here, the parameters are OK */
958 return GL_FALSE;
959}
960
961
962static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000963copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000964 GLenum target, GLint level,
965 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +0000966 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +0000967{
968 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
969 struct gl_texture_image *teximage;
970
971 if (dimensions == 1 && target != GL_TEXTURE_1D) {
972 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
973 return GL_TRUE;
974 }
975 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
976 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
977 return GL_TRUE;
978 }
979 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
980 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
981 return GL_TRUE;
982 }
983
984 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
985 char message[100];
986 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
987 gl_error(ctx, GL_INVALID_VALUE, message);
988 return GL_TRUE;
989 }
990
991 if (width < 0) {
992 char message[100];
993 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
994 gl_error(ctx, GL_INVALID_VALUE, message);
995 return GL_TRUE;
996 }
997 if (dimensions > 1 && height < 0) {
998 char message[100];
999 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1000 gl_error(ctx, GL_INVALID_VALUE, message);
1001 return GL_TRUE;
1002 }
1003
Brian Pauldf6a28d2000-02-21 16:34:21 +00001004 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001005 if (!teximage) {
1006 char message[100];
1007 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1008 gl_error(ctx, GL_INVALID_OPERATION, message);
1009 return GL_TRUE;
1010 }
1011
1012 if (xoffset < -((GLint)teximage->Border)) {
1013 char message[100];
1014 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1015 gl_error(ctx, GL_INVALID_VALUE, message);
1016 return GL_TRUE;
1017 }
1018 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1019 char message[100];
1020 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1021 gl_error(ctx, GL_INVALID_VALUE, message);
1022 return GL_TRUE;
1023 }
1024 if (dimensions > 1) {
1025 if (yoffset < -((GLint)teximage->Border)) {
1026 char message[100];
1027 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1028 gl_error(ctx, GL_INVALID_VALUE, message);
1029 return GL_TRUE;
1030 }
1031 /* NOTE: we're adding the border here, not subtracting! */
1032 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1033 char message[100];
1034 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1035 gl_error(ctx, GL_INVALID_VALUE, message);
1036 return GL_TRUE;
1037 }
1038 }
1039
1040 if (dimensions > 2) {
1041 if (zoffset < -((GLint)teximage->Border)) {
1042 char message[100];
1043 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1044 gl_error(ctx, GL_INVALID_VALUE, message);
1045 return GL_TRUE;
1046 }
1047 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1048 char message[100];
1049 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1050 gl_error(ctx, GL_INVALID_VALUE, message);
1051 return GL_TRUE;
1052 }
1053 }
1054
1055 /* if we get here, the parameters are OK */
1056 return GL_FALSE;
1057}
1058
1059
1060
1061
1062/*
jtgafb833d1999-08-19 00:55:39 +00001063 * Called from the API. Note that width includes the border.
1064 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001065void
Brian Paul43911c82000-03-21 00:49:33 +00001066_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001067 GLsizei width, GLint border, GLenum format,
1068 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001069{
Brian Paulfbd8f211999-11-11 01:22:25 +00001070 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001071 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1072
1073 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001074 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001075 struct gl_texture_object *texObj;
1076 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001077
Brian Paul43911c82000-03-21 00:49:33 +00001078 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001079 format, type, 1, width, 1, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001080 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001081 }
1082
Brian Paulf7b57072000-03-20 14:37:52 +00001083 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001084 texObj = texUnit->CurrentD[1];
1085 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001086
Brian Paul02938782000-03-22 17:38:11 +00001087 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001088 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001089 texObj->Image[level] = texImage;
1090 if (!texImage) {
1091 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1092 return;
1093 }
1094 }
1095 else if (texImage->Data) {
1096 FREE(texImage->Data);
1097 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001098 }
1099
Brian Paul02938782000-03-22 17:38:11 +00001100 /* setup the teximage struct's fields */
1101 init_texture_image(texImage, width, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001102
Brian Paul02938782000-03-22 17:38:11 +00001103 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001104 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001105 GLboolean retain = GL_TRUE;
1106 GLboolean success = GL_FALSE;
1107 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1108 && ctx->Driver.TexImage1D) {
1109 /* let device driver try to use raw image */
1110 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1111 type, pixels, &ctx->Unpack,
1112 texObj, texImage, &retain);
1113 }
1114 if (retain || !success) {
1115 /* make internal copy of the texture image */
1116 make_texture_image(ctx, texImage, format, type,
1117 pixels, &ctx->Unpack);
1118 if (!success && ctx->Driver.TexImage1D) {
1119 /* let device driver try to use unpacked image */
1120 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1121 GL_UNSIGNED_BYTE, texImage->Data,
1122 &_mesa_native_packing,
1123 texObj, texImage, &retain);
1124 }
1125 }
1126 if (!retain && texImage->Data) {
1127 FREE(texImage->Data);
1128 texImage->Data = NULL;
1129 }
jtgafb833d1999-08-19 00:55:39 +00001130 }
1131 else {
Brian Paul02938782000-03-22 17:38:11 +00001132 make_null_texture(texImage);
1133 if (ctx->Driver.TexImage1D) {
1134 GLboolean retain;
1135 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1136 GL_UNSIGNED_BYTE, texImage->Data,
1137 &_mesa_native_packing,
1138 texObj, texImage, &retain);
1139 }
jtgafb833d1999-08-19 00:55:39 +00001140 }
1141
Brian Paul02938782000-03-22 17:38:11 +00001142 /* state update */
1143 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001144 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001145 }
1146 else if (target==GL_PROXY_TEXTURE_1D) {
1147 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001148 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001149 format, type, 1, width, 1, 1, border )) {
1150 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1151 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1152 sizeof(struct gl_texture_image) );
1153 }
1154 }
1155 else {
1156 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1157 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001158 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001159 ctx->Texture.Proxy1D->Image[level]->Border = border;
1160 ctx->Texture.Proxy1D->Image[level]->Width = width;
1161 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1162 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1163 }
jtgafb833d1999-08-19 00:55:39 +00001164 }
1165 else {
1166 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1167 return;
1168 }
1169}
1170
1171
Brian Paulfbd8f211999-11-11 01:22:25 +00001172void
Brian Paul43911c82000-03-21 00:49:33 +00001173_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001174 GLsizei width, GLsizei height, GLint border,
1175 GLenum format, GLenum type,
1176 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001177{
Brian Paulfbd8f211999-11-11 01:22:25 +00001178 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001179 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1180
1181 if (target==GL_TEXTURE_2D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001182 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001183 struct gl_texture_object *texObj;
1184 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001185
Brian Paul43911c82000-03-21 00:49:33 +00001186 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001187 format, type, 2, width, height, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001188 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001189 }
1190
Brian Paulf7b57072000-03-20 14:37:52 +00001191 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001192 texObj = texUnit->CurrentD[2];
1193 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001194
Brian Paul02938782000-03-22 17:38:11 +00001195 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001196 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001197 texObj->Image[level] = texImage;
1198 if (!texImage) {
1199 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1200 return;
1201 }
1202 }
1203 else if (texImage->Data) {
1204 FREE(texImage->Data);
1205 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001206 }
1207
Brian Paul02938782000-03-22 17:38:11 +00001208 /* setup the teximage struct's fields */
1209 init_texture_image(texImage, width, height, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001210
Brian Paul02938782000-03-22 17:38:11 +00001211 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001212 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001213 GLboolean retain = GL_TRUE;
1214 GLboolean success = GL_FALSE;
1215 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1216 && ctx->Driver.TexImage2D) {
1217 /* let device driver try to use raw image */
1218 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1219 type, pixels, &ctx->Unpack,
1220 texObj, texImage, &retain);
1221 }
1222 if (retain || !success) {
1223 /* make internal copy of the texture image */
1224 make_texture_image(ctx, texImage, format, type,
1225 pixels, &ctx->Unpack);
1226 if (!success && ctx->Driver.TexImage2D) {
1227 /* let device driver try to use unpacked image */
1228 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1229 GL_UNSIGNED_BYTE, texImage->Data,
1230 &_mesa_native_packing,
1231 texObj, texImage, &retain);
1232 }
1233 }
1234 if (!retain && texImage->Data) {
1235 FREE(texImage->Data);
1236 texImage->Data = NULL;
1237 }
jtgafb833d1999-08-19 00:55:39 +00001238 }
1239 else {
Brian Paul02938782000-03-22 17:38:11 +00001240 make_null_texture(texImage);
1241 if (ctx->Driver.TexImage2D) {
1242 GLboolean retain;
1243 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1244 GL_UNSIGNED_BYTE, texImage->Data,
1245 &_mesa_native_packing,
1246 texObj, texImage, &retain);
1247 }
jtgafb833d1999-08-19 00:55:39 +00001248 }
1249
Brian Paul02938782000-03-22 17:38:11 +00001250#define OLD_DD_TEXTURE
1251#ifdef OLD_DD_TEXTURE
1252 /* XXX this will be removed in the future */
jtgafb833d1999-08-19 00:55:39 +00001253 if (ctx->Driver.TexImage) {
Brian Paul02938782000-03-22 17:38:11 +00001254 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1255 texImage );
jtgafb833d1999-08-19 00:55:39 +00001256 }
Brian Paul02938782000-03-22 17:38:11 +00001257#endif
1258
1259 /* state update */
1260 gl_put_texobj_on_dirty_list( ctx, texObj );
1261 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001262 }
1263 else if (target==GL_PROXY_TEXTURE_2D) {
1264 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001265 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001266 format, type, 2, width, height, 1, border )) {
1267 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1268 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1269 sizeof(struct gl_texture_image) );
1270 }
1271 }
1272 else {
1273 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1274 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001275 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001276 ctx->Texture.Proxy2D->Image[level]->Border = border;
1277 ctx->Texture.Proxy2D->Image[level]->Width = width;
1278 ctx->Texture.Proxy2D->Image[level]->Height = height;
1279 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1280 }
jtgafb833d1999-08-19 00:55:39 +00001281 }
1282 else {
1283 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1284 return;
1285 }
1286}
1287
1288
1289
1290/*
1291 * Called by the API or display list executor.
1292 * Note that width and height include the border.
1293 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001294void
Brian Paul43911c82000-03-21 00:49:33 +00001295_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001296 GLsizei width, GLsizei height, GLsizei depth,
1297 GLint border, GLenum format, GLenum type,
1298 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001299{
Brian Paulfbd8f211999-11-11 01:22:25 +00001300 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001301 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001302
Brian Paulfbd8f211999-11-11 01:22:25 +00001303 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001304 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001305 struct gl_texture_object *texObj;
1306 struct gl_texture_image *texImage;
Brian Paul43911c82000-03-21 00:49:33 +00001307 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001308 format, type, 3, width, height, depth,
1309 border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001310 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001311 }
1312
Brian Paulf7b57072000-03-20 14:37:52 +00001313 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001314 texObj = texUnit->CurrentD[3];
1315 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001316
Brian Paul02938782000-03-22 17:38:11 +00001317 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001318 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001319 texObj->Image[level] = texImage;
1320 if (!texImage) {
1321 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1322 return;
1323 }
1324 }
1325 else if (texImage->Data) {
1326 FREE(texImage->Data);
1327 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001328 }
1329
Brian Paul02938782000-03-22 17:38:11 +00001330 /* setup the teximage struct's fields */
1331 init_texture_image(texImage, width, height, depth,
1332 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001333
Brian Paul02938782000-03-22 17:38:11 +00001334 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001335 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001336 GLboolean retain = GL_TRUE;
1337 GLboolean success = GL_FALSE;
1338 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1339 && ctx->Driver.TexImage3D) {
1340 /* let device driver try to use raw image */
1341 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1342 type, pixels, &ctx->Unpack,
1343 texObj, texImage, &retain);
1344 }
1345 if (retain || !success) {
1346 /* make internal copy of the texture image */
1347 make_texture_image(ctx, texImage, format, type,
1348 pixels, &ctx->Unpack);
1349 if (!success && ctx->Driver.TexImage3D) {
1350 /* let device driver try to use unpacked image */
1351 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1352 GL_UNSIGNED_BYTE, texImage->Data,
1353 &_mesa_native_packing,
1354 texObj, texImage, &retain);
1355 }
1356 }
1357 if (!retain && texImage->Data) {
1358 FREE(texImage->Data);
1359 texImage->Data = NULL;
1360 }
jtgafb833d1999-08-19 00:55:39 +00001361 }
1362 else {
Brian Paul02938782000-03-22 17:38:11 +00001363 make_null_texture(texImage);
1364 if (ctx->Driver.TexImage3D) {
1365 GLboolean retain;
1366 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1367 GL_UNSIGNED_BYTE, texImage->Data,
1368 &_mesa_native_packing,
1369 texObj, texImage, &retain);
1370 }
jtgafb833d1999-08-19 00:55:39 +00001371 }
1372
Brian Paul02938782000-03-22 17:38:11 +00001373 /* state update */
1374 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001375 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001376 }
1377 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1378 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001379 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001380 format, type, 3, width, height, depth,
1381 border )) {
1382 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1383 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1384 sizeof(struct gl_texture_image) );
1385 }
1386 }
1387 else {
1388 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1389 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001390 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001391 ctx->Texture.Proxy3D->Image[level]->Border = border;
1392 ctx->Texture.Proxy3D->Image[level]->Width = width;
1393 ctx->Texture.Proxy3D->Image[level]->Height = height;
1394 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1395 }
jtgafb833d1999-08-19 00:55:39 +00001396 }
1397 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001398 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001399 return;
1400 }
1401}
1402
1403
Brian Paul663049a2000-01-31 23:10:16 +00001404void
Brian Paul43911c82000-03-21 00:49:33 +00001405_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00001406 GLsizei width, GLsizei height, GLsizei depth,
1407 GLint border, GLenum format, GLenum type,
1408 const GLvoid *pixels )
1409{
Brian Paul43911c82000-03-21 00:49:33 +00001410 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00001411 depth, border, format, type, pixels);
1412}
1413
1414
Brian Paulf7b57072000-03-20 14:37:52 +00001415/*
1416 * Fetch a texture image from the device driver.
1417 * Store the results in the given texture object at the given mipmap level.
1418 */
Brian Paul021a5252000-03-27 17:54:17 +00001419void
1420_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1421 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00001422{
1423 GLvoid *image;
1424 GLenum imgFormat, imgType;
1425 GLboolean freeImage;
1426 struct gl_texture_image *texImage;
1427 GLint destComponents, numPixels, srcBytesPerTexel;
1428
1429 if (!ctx->Driver.GetTexImage)
1430 return;
1431
Brian Paul48271792000-03-29 18:13:59 +00001432 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00001433 &imgFormat, &imgType, &freeImage);
1434 if (!image)
1435 return;
1436
1437 texImage = texObj->Image[level];
1438 ASSERT(texImage);
1439 if (!texImage)
1440 return;
1441
1442 destComponents = components_in_intformat(texImage->Format);
1443 assert(destComponents > 0);
1444 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1445 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00001446 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00001447 assert(srcBytesPerTexel > 0);
1448
1449 if (!texImage->Data) {
1450 /* Allocate memory for the texture image data */
1451 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1452 }
1453
1454 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1455 /* We got lucky! The driver's format and type match Mesa's format. */
1456 if (texImage->Data) {
1457 MEMCPY(texImage->Data, image, numPixels * destComponents);
1458 }
1459 }
1460 else {
1461 /* Convert the texture image from the driver's format to Mesa's
1462 * internal format.
1463 */
1464 const GLint width = texImage->Width;
1465 const GLint height = texImage->Height;
1466 const GLint depth = texImage->Depth;
1467 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1468 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1469 const GLenum dstType = GL_UNSIGNED_BYTE;
1470 const GLenum dstFormat = texImage->Format;
1471 const GLubyte *srcPtr = (const GLubyte *) image;
1472 GLubyte *destPtr = texImage->Data;
1473
1474 if (texImage->Format == GL_COLOR_INDEX) {
1475 /* color index texture */
1476 GLint img, row;
1477 assert(imgFormat == GL_COLOR_INDEX);
1478 for (img = 0; img < depth; img++) {
1479 for (row = 0; row < height; row++) {
1480 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001481 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001482 destPtr += destBytesPerRow;
1483 srcPtr += srcBytesPerRow;
1484 }
1485 }
1486 }
1487 else {
1488 /* color texture */
1489 GLint img, row;
1490 for (img = 0; img < depth; img++) {
1491 for (row = 0; row < height; row++) {
1492 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001493 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001494 destPtr += destBytesPerRow;
1495 srcPtr += srcBytesPerRow;
1496 }
1497 }
1498 }
1499 }
1500
1501 if (freeImage)
1502 FREE(image);
1503}
1504
jtgafb833d1999-08-19 00:55:39 +00001505
Brian Paulfbd8f211999-11-11 01:22:25 +00001506void
1507_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1508 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001509{
Brian Paulfbd8f211999-11-11 01:22:25 +00001510 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001511 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00001512 struct gl_texture_image *texImage;
1513 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00001514
1515 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1516
1517 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1518 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1519 return;
1520 }
1521
Brian Paulb7d076f2000-03-21 01:03:40 +00001522 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001523 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1524 return;
1525 }
1526
Brian Paulb7d076f2000-03-21 01:03:40 +00001527 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001528 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1529 return;
1530 }
1531
1532 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00001533 return;
jtgafb833d1999-08-19 00:55:39 +00001534
1535 switch (target) {
1536 case GL_TEXTURE_1D:
1537 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1538 break;
1539 case GL_TEXTURE_2D:
1540 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1541 break;
1542 case GL_TEXTURE_3D:
1543 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1544 break;
1545 default:
1546 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1547 return;
1548 }
1549
Brian Paulf7b57072000-03-20 14:37:52 +00001550 texImage = texObj->Image[level];
1551 if (!texImage) {
1552 /* invalid mipmap level */
1553 return;
1554 }
1555
1556 if (!texImage->Data) {
1557 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00001558 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00001559 discardImage = GL_TRUE;
1560 }
1561 else {
1562 discardImage = GL_FALSE;
1563 }
1564
1565 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00001566 GLint width = texImage->Width;
1567 GLint height = texImage->Height;
1568 GLint row;
1569
1570 for (row = 0; row < height; row++) {
1571 /* compute destination address in client memory */
Brian Paulb7d076f2000-03-21 01:03:40 +00001572 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
jtgafb833d1999-08-19 00:55:39 +00001573 width, height,
1574 format, type, 0, row, 0);
1575
1576 assert(dest);
1577 if (texImage->Format == GL_RGBA) {
1578 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
Brian Paulb7d076f2000-03-21 01:03:40 +00001579 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1580 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001581 }
1582 else {
1583 /* fetch RGBA row from texture image then pack it in client mem */
1584 GLubyte rgba[MAX_WIDTH][4];
1585 GLint i;
1586 const GLubyte *src;
1587 switch (texImage->Format) {
1588 case GL_ALPHA:
1589 src = texImage->Data + row * width * sizeof(GLubyte);
1590 for (i = 0; i < width; i++) {
1591 rgba[i][RCOMP] = 255;
1592 rgba[i][GCOMP] = 255;
1593 rgba[i][BCOMP] = 255;
1594 rgba[i][ACOMP] = src[i];
1595 }
1596 break;
1597 case GL_LUMINANCE:
1598 src = texImage->Data + row * width * sizeof(GLubyte);
1599 for (i = 0; i < width; i++) {
1600 rgba[i][RCOMP] = src[i];
1601 rgba[i][GCOMP] = src[i];
1602 rgba[i][BCOMP] = src[i];
1603 rgba[i][ACOMP] = 255;
1604 }
1605 break;
1606 case GL_LUMINANCE_ALPHA:
1607 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1608 for (i = 0; i < width; i++) {
1609 rgba[i][RCOMP] = src[i*2+0];
1610 rgba[i][GCOMP] = src[i*2+0];
1611 rgba[i][BCOMP] = src[i*2+0];
1612 rgba[i][ACOMP] = src[i*2+1];
1613 }
1614 break;
1615 case GL_INTENSITY:
1616 src = texImage->Data + row * width * sizeof(GLubyte);
1617 for (i = 0; i < width; i++) {
1618 rgba[i][RCOMP] = src[i];
1619 rgba[i][GCOMP] = src[i];
1620 rgba[i][BCOMP] = src[i];
1621 rgba[i][ACOMP] = 255;
1622 }
1623 break;
1624 case GL_RGB:
1625 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1626 for (i = 0; i < width; i++) {
1627 rgba[i][RCOMP] = src[i*3+0];
1628 rgba[i][GCOMP] = src[i*3+1];
1629 rgba[i][BCOMP] = src[i*3+2];
1630 rgba[i][ACOMP] = 255;
1631 }
1632 break;
1633 case GL_RGBA:
1634 /* this special case should have been handled above! */
1635 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1636 break;
1637 case GL_COLOR_INDEX:
1638 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1639 break;
1640 default:
1641 gl_problem( ctx, "bad format in gl_GetTexImage" );
1642 }
Brian Paulb7d076f2000-03-21 01:03:40 +00001643 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1644 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001645 }
1646 }
Brian Paulf7b57072000-03-20 14:37:52 +00001647
1648 /* if we got the teximage from the device driver we'll discard it now */
1649 if (discardImage) {
1650 FREE(texImage->Data);
1651 texImage->Data = NULL;
1652 }
jtgafb833d1999-08-19 00:55:39 +00001653 }
1654}
1655
1656
1657
Brian Paulfbd8f211999-11-11 01:22:25 +00001658void
1659_mesa_TexSubImage1D( GLenum target, GLint level,
1660 GLint xoffset, GLsizei width,
1661 GLenum format, GLenum type,
1662 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001663{
Brian Paulfbd8f211999-11-11 01:22:25 +00001664 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001665 struct gl_texture_unit *texUnit;
1666 struct gl_texture_object *texObj;
1667 struct gl_texture_image *texImage;
1668 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001669
Brian Paulc3f0a511999-11-03 17:27:05 +00001670 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1671 width, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001672 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001673 }
1674
Brian Paul02938782000-03-22 17:38:11 +00001675 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1676 texObj = texUnit->CurrentD[1];
1677 texImage = texObj->Image[level];
1678 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001679
Brian Paulc3f0a511999-11-03 17:27:05 +00001680 if (width == 0 || !pixels)
1681 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001682
Brian Paulc3f0a511999-11-03 17:27:05 +00001683
Brian Paul02938782000-03-22 17:38:11 +00001684 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1685 && ctx->Driver.TexSubImage1D) {
1686 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1687 width, format, type, pixels,
1688 &ctx->Unpack, texObj, texImage );
1689 }
1690 if (!success) {
1691 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1692
1693 const GLint texComponents = components_in_intformat(texImage->Format);
1694 const GLenum texFormat = texImage->Format;
1695 const GLint xoffsetb = xoffset + texImage->Border;
1696 GLboolean retain = GL_TRUE;
1697 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00001698 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00001699 if (!texImage->Data) {
1700 make_null_texture(texImage);
1701 }
1702 if (!texImage->Data)
1703 return; /* we're really out of luck! */
1704 }
1705
Brian Paulc3f0a511999-11-03 17:27:05 +00001706 if (texFormat == GL_COLOR_INDEX) {
1707 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00001708 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1709 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1710 1, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001711 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00001712 type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001713 }
1714 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001715 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00001716 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1717 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1718 1, format, type, 0, 0, 0);
1719 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1720 type, src, &ctx->Unpack, GL_TRUE);
1721 }
1722
1723 if (ctx->Driver.TexImage1D) {
1724 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1725 GL_UNSIGNED_BYTE, texImage->Data,
1726 &_mesa_native_packing, texObj, texImage,
1727 &retain );
1728 }
1729
1730 if (!retain && texImage->Data) {
1731 FREE(texImage->Data);
1732 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001733 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001734 }
jtgafb833d1999-08-19 00:55:39 +00001735
Brian Paul02938782000-03-22 17:38:11 +00001736 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
jtgafb833d1999-08-19 00:55:39 +00001737}
1738
1739
Brian Paulfbd8f211999-11-11 01:22:25 +00001740void
1741_mesa_TexSubImage2D( GLenum target, GLint level,
1742 GLint xoffset, GLint yoffset,
1743 GLsizei width, GLsizei height,
1744 GLenum format, GLenum type,
1745 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001746{
Brian Paulfbd8f211999-11-11 01:22:25 +00001747 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001748 struct gl_texture_unit *texUnit;
1749 struct gl_texture_object *texObj;
1750 struct gl_texture_image *texImage;
1751 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001752
Brian Paulc3f0a511999-11-03 17:27:05 +00001753 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1754 width, height, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001755 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001756 }
1757
Brian Paul02938782000-03-22 17:38:11 +00001758 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1759 texObj = texUnit->CurrentD[2];
1760 texImage = texObj->Image[level];
1761 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001762
Brian Paulc3f0a511999-11-03 17:27:05 +00001763 if (width == 0 || height == 0 || !pixels)
1764 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001765
Brian Paul02938782000-03-22 17:38:11 +00001766 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1767 && ctx->Driver.TexSubImage2D) {
1768 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1769 yoffset, width, height, format, type,
1770 pixels, &ctx->Unpack, texObj, texImage );
1771 }
1772 if (!success) {
1773 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paulc3f0a511999-11-03 17:27:05 +00001774
Brian Paul02938782000-03-22 17:38:11 +00001775 const GLint texComponents = components_in_intformat(texImage->Format);
1776 const GLenum texFormat = texImage->Format;
1777 const GLint xoffsetb = xoffset + texImage->Border;
1778 const GLint yoffsetb = yoffset + texImage->Border;
1779 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1780 format, type);
1781 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1782 GLboolean retain = GL_TRUE;
1783
1784 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00001785 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00001786 if (!texImage->Data) {
1787 make_null_texture(texImage);
1788 }
1789 if (!texImage->Data)
1790 return; /* we're really out of luck! */
1791 }
1792
Brian Paulc3f0a511999-11-03 17:27:05 +00001793 if (texFormat == GL_COLOR_INDEX) {
1794 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00001795 GLubyte *dst = texImage->Data
1796 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1797 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1798 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001799 GLint row;
1800 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00001801 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1802 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1803 src += srcStride;
1804 dst += dstStride;
Brian Paul64a79b21999-10-22 10:43:35 +00001805 }
1806 }
jtgafb833d1999-08-19 00:55:39 +00001807 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001808 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00001809 GLubyte *dst = texImage->Data
1810 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1811 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1812 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001813 GLint row;
1814 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00001815 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1816 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1817 src += srcStride;
1818 dst += dstStride;
jtgafb833d1999-08-19 00:55:39 +00001819 }
jtgafb833d1999-08-19 00:55:39 +00001820 }
jtgafb833d1999-08-19 00:55:39 +00001821
Brian Paul02938782000-03-22 17:38:11 +00001822 if (ctx->Driver.TexImage2D) {
1823 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1824 GL_UNSIGNED_BYTE, texImage->Data,
1825 &_mesa_native_packing, texObj, texImage,
1826 &retain);
jtgafb833d1999-08-19 00:55:39 +00001827 }
Brian Paul02938782000-03-22 17:38:11 +00001828
1829 if (!retain && texImage->Data) {
1830 FREE(texImage->Data);
1831 texImage->Data = NULL;
1832 }
1833
1834#ifdef OLD_DD_TEXTURE
1835 /* XXX this will be removed in the future */
1836 if (ctx->Driver.TexSubImage) {
1837 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1838 xoffset, yoffset, width, height,
1839 texImage->IntFormat, texImage);
1840 }
1841 else if (ctx->Driver.TexImage) {
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001842 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
Brian Paul02938782000-03-22 17:38:11 +00001843 level, texImage->IntFormat, texImage );
1844 }
1845#endif
jtgafb833d1999-08-19 00:55:39 +00001846 }
1847}
1848
1849
1850
Brian Paulfbd8f211999-11-11 01:22:25 +00001851void
1852_mesa_TexSubImage3D( GLenum target, GLint level,
1853 GLint xoffset, GLint yoffset, GLint zoffset,
1854 GLsizei width, GLsizei height, GLsizei depth,
1855 GLenum format, GLenum type,
1856 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001857{
Brian Paulfbd8f211999-11-11 01:22:25 +00001858 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001859 struct gl_texture_unit *texUnit;
1860 struct gl_texture_object *texObj;
1861 struct gl_texture_image *texImage;
1862 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001863
Brian Paulc3f0a511999-11-03 17:27:05 +00001864 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1865 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001866 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001867 }
1868
Brian Paul02938782000-03-22 17:38:11 +00001869 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1870 texObj = texUnit->CurrentD[3];
1871 texImage = texObj->Image[level];
1872 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001873
Brian Paulc3f0a511999-11-03 17:27:05 +00001874 if (width == 0 || height == 0 || height == 0 || !pixels)
1875 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001876
Brian Paul02938782000-03-22 17:38:11 +00001877 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1878 && ctx->Driver.TexSubImage3D) {
1879 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1880 yoffset, zoffset, width, height, depth, format,
1881 type, pixels, &ctx->Unpack, texObj, texImage );
1882 }
1883 if (!success) {
1884 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1885
1886 const GLint texComponents = components_in_intformat(texImage->Format);
1887 const GLenum texFormat = texImage->Format;
1888 const GLint xoffsetb = xoffset + texImage->Border;
1889 const GLint yoffsetb = yoffset + texImage->Border;
1890 const GLint zoffsetb = zoffset + texImage->Border;
1891 const GLint texWidth = texImage->Width;
1892 const GLint dstRectArea = texWidth * texImage->Height;
1893 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1894 width, format, type);
1895 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1896 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00001897
Brian Paulc3f0a511999-11-03 17:27:05 +00001898 if (texFormat == GL_COLOR_INDEX) {
1899 /* color index texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00001900 GLint img, row;
1901 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00001902 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1903 width, height, format, type, img, 0, 0);
1904 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1905 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00001906 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001907 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00001908 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1909 src += srcStride;
1910 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00001911 }
jtgafb833d1999-08-19 00:55:39 +00001912 }
1913 }
1914 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001915 /* color texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00001916 GLint img, row;
1917 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00001918 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1919 width, height, format, type, img, 0, 0);
1920 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1921 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00001922 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001923 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
Brian Paul02938782000-03-22 17:38:11 +00001924 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1925 src += srcStride;
1926 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00001927 }
jtgafb833d1999-08-19 00:55:39 +00001928 }
jtgafb833d1999-08-19 00:55:39 +00001929 }
Brian Paul02938782000-03-22 17:38:11 +00001930
1931 if (ctx->Driver.TexImage3D) {
1932 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1933 GL_UNSIGNED_BYTE, texImage->Data,
1934 &_mesa_native_packing, texObj, texImage,
1935 &retain);
1936 }
1937
1938 if (!retain && texImage->Data) {
1939 FREE(texImage->Data);
1940 texImage->Data = NULL;
1941 }
jtgafb833d1999-08-19 00:55:39 +00001942 }
jtgafb833d1999-08-19 00:55:39 +00001943}
1944
1945
1946
1947/*
1948 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00001949 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00001950 * Input: ctx - the context
1951 * x, y - lower left corner
1952 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00001953 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00001954 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001955static GLubyte *
1956read_color_image( GLcontext *ctx, GLint x, GLint y,
1957 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00001958{
Brian Paulc3f0a511999-11-03 17:27:05 +00001959 GLint stride, i;
1960 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00001961
Brian Paul959f8022000-03-19 01:10:11 +00001962 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00001963 if (!image)
jtgafb833d1999-08-19 00:55:39 +00001964 return NULL;
jtgafb833d1999-08-19 00:55:39 +00001965
1966 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001967 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1968 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001969
Brian Paulc3f0a511999-11-03 17:27:05 +00001970 dst = image;
1971 stride = width * 4 * sizeof(GLubyte);
1972 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00001973 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1974 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00001975 dst += stride;
1976 }
jtgafb833d1999-08-19 00:55:39 +00001977
Brian Paulcea0e8e1999-11-25 17:36:48 +00001978 /* Read from draw buffer (the default) */
1979 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1980 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001981
1982 return image;
1983}
1984
1985
1986
Brian Paulfbd8f211999-11-11 01:22:25 +00001987void
1988_mesa_CopyTexImage1D( GLenum target, GLint level,
1989 GLenum internalFormat,
1990 GLint x, GLint y,
1991 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001992{
Brian Paulfbd8f211999-11-11 01:22:25 +00001993 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001994 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00001995
Brian Paulf7b57072000-03-20 14:37:52 +00001996 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1997 width, 1, border))
1998 return;
1999
2000 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2001 || !ctx->Driver.CopyTexImage1D
2002 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2003 internalFormat, x, y, width, border))
2004 {
Brian Paulc3f0a511999-11-03 17:27:05 +00002005 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2006 if (!image) {
2007 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2008 return;
2009 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002010 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002011 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00002012 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002013 }
jtgafb833d1999-08-19 00:55:39 +00002014}
2015
2016
2017
Brian Paulfbd8f211999-11-11 01:22:25 +00002018void
2019_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2020 GLint x, GLint y, GLsizei width, GLsizei height,
2021 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002022{
Brian Paulfbd8f211999-11-11 01:22:25 +00002023 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002024 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002025
Brian Paulf7b57072000-03-20 14:37:52 +00002026 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2027 width, height, border))
2028 return;
2029
2030 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2031 || !ctx->Driver.CopyTexImage2D
2032 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2033 internalFormat, x, y, width, height, border))
2034 {
Brian Paulc3f0a511999-11-03 17:27:05 +00002035 GLubyte *image = read_color_image( ctx, x, y, width, height );
2036 if (!image) {
2037 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2038 return;
2039 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002040 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002041 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00002042 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002043 }
jtgafb833d1999-08-19 00:55:39 +00002044}
2045
2046
2047
jtgafb833d1999-08-19 00:55:39 +00002048/*
2049 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00002050 */
Brian Paulc3f0a511999-11-03 17:27:05 +00002051static void
2052copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2053 GLint width, GLint height,
2054 GLint srcx, GLint srcy,
2055 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00002056{
Brian Paulc3f0a511999-11-03 17:27:05 +00002057 GLint i;
jtgafb833d1999-08-19 00:55:39 +00002058 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00002059 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00002060
Brian Paul91baaa31999-10-17 23:24:16 +00002061 /* dst[xyz] may be negative if we have a texture border! */
2062 dstx += dest->Border;
2063 dsty += dest->Border;
2064 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00002065 texwidth = dest->Width;
2066 texheight = dest->Height;
2067 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00002068 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00002069 format = dest->Format;
2070 components = components_in_intformat( format );
2071
2072 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002073 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2074 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002075
Brian Paulc3f0a511999-11-03 17:27:05 +00002076 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00002077 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00002078 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00002079 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00002080 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2081 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2082 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
Brian Paul02938782000-03-22 17:38:11 +00002083 &_mesa_native_packing, GL_TRUE);
Brian Paulc3f0a511999-11-03 17:27:05 +00002084 }
jtgafb833d1999-08-19 00:55:39 +00002085
Brian Paulcea0e8e1999-11-25 17:36:48 +00002086 /* Read from draw buffer (the default) */
2087 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2088 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002089}
2090
2091
2092
2093
Brian Paulfbd8f211999-11-11 01:22:25 +00002094void
2095_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2096 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002097{
Brian Paulfbd8f211999-11-11 01:22:25 +00002098 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002099 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002100
Brian Paulf7b57072000-03-20 14:37:52 +00002101 if (copytexsubimage_error_check(ctx, 1, target, level,
2102 xoffset, 0, 0, width, 1))
2103 return;
2104
2105 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2106 || !ctx->Driver.CopyTexSubImage1D
2107 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2108 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002109 struct gl_texture_unit *texUnit;
2110 struct gl_texture_image *teximage;
2111 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2112 teximage = texUnit->CurrentD[1]->Image[level];
2113 assert(teximage);
jtgafb833d1999-08-19 00:55:39 +00002114 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002115 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002116 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002117 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002118 if (ctx->Driver.TexImage) {
2119 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2120 texUnit->CurrentD[1],
2121 level, teximage->IntFormat, teximage );
2122 }
jtgafb833d1999-08-19 00:55:39 +00002123 }
2124 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002125}
2126
2127
2128
Brian Paulfbd8f211999-11-11 01:22:25 +00002129void
2130_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2131 GLint xoffset, GLint yoffset,
2132 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002133{
Brian Paulfbd8f211999-11-11 01:22:25 +00002134 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002135 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2136
Brian Paulf7b57072000-03-20 14:37:52 +00002137 if (copytexsubimage_error_check(ctx, 2, target, level,
2138 xoffset, yoffset, 0, width, height))
2139 return;
2140
2141 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2142 || !ctx->Driver.CopyTexSubImage2D
2143 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2144 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002145 struct gl_texture_unit *texUnit;
2146 struct gl_texture_image *teximage;
2147 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2148 teximage = texUnit->CurrentD[2]->Image[level];
2149 assert(teximage);
2150 if (teximage->Data) {
2151 copy_tex_sub_image(ctx, teximage, width, height,
2152 x, y, xoffset, yoffset, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002153 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002154 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002155 if (ctx->Driver.TexImage) {
2156 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2157 texUnit->CurrentD[2],
2158 level, teximage->IntFormat, teximage );
Brian Paulc3f0a511999-11-03 17:27:05 +00002159 }
2160 }
2161 }
2162}
2163
2164
2165
Brian Paulfbd8f211999-11-11 01:22:25 +00002166void
2167_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2168 GLint xoffset, GLint yoffset, GLint zoffset,
2169 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002170{
Brian Paulfbd8f211999-11-11 01:22:25 +00002171 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2173
Brian Paulf7b57072000-03-20 14:37:52 +00002174 if (copytexsubimage_error_check(ctx, 3, target, level,
2175 xoffset, yoffset, zoffset, width, height))
2176 return;
2177
Brian Paul02938782000-03-22 17:38:11 +00002178 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
Brian Paulf7b57072000-03-20 14:37:52 +00002179 || !ctx->Driver.CopyTexSubImage3D
2180 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002181 xoffset, yoffset, zoffset, x, y, width, height )) {
2182 struct gl_texture_unit *texUnit;
2183 struct gl_texture_image *teximage;
2184 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2185 teximage = texUnit->CurrentD[3]->Image[level];
2186 assert(teximage);
2187 if (teximage->Data) {
2188 copy_tex_sub_image(ctx, teximage, width, height,
Brian Paulc3f0a511999-11-03 17:27:05 +00002189 x, y, xoffset, yoffset, zoffset);
Brian Paul02938782000-03-22 17:38:11 +00002190 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002191 /* XXX this is obsolete */
Brian Paul02938782000-03-22 17:38:11 +00002192 if (ctx->Driver.TexImage) {
2193 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2194 texUnit->CurrentD[3],
2195 level, teximage->IntFormat, teximage );
Brian Paulf7b57072000-03-20 14:37:52 +00002196 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002197 }
jtgafb833d1999-08-19 00:55:39 +00002198 }
2199}