blob: b0db866561129d87c33233ed770dc083de387cd4 [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
Brian Paulaea66b12000-05-24 14:04:06 +0000140_mesa_base_tex_format( GLcontext *ctx, GLint format )
jtgafb833d1999-08-19 00:55:39 +0000141{
142 switch (format) {
Brian Paulaea66b12000-05-24 14:04:06 +0000143 case GL_COMPRESSED_ALPHA_ARB:
144 if (ctx && !ctx->Extensions.HaveTextureCompression)
145 return -1;
146 /* fall-through */
jtgafb833d1999-08-19 00:55:39 +0000147 case GL_ALPHA:
148 case GL_ALPHA4:
149 case GL_ALPHA8:
150 case GL_ALPHA12:
151 case GL_ALPHA16:
152 return GL_ALPHA;
Brian Paulaea66b12000-05-24 14:04:06 +0000153 case GL_COMPRESSED_LUMINANCE_ARB:
154 if (ctx && !ctx->Extensions.HaveTextureCompression)
155 return -1;
156 /* fall-through */
jtgafb833d1999-08-19 00:55:39 +0000157 case 1:
158 case GL_LUMINANCE:
159 case GL_LUMINANCE4:
160 case GL_LUMINANCE8:
161 case GL_LUMINANCE12:
162 case GL_LUMINANCE16:
163 return GL_LUMINANCE;
Brian Paulaea66b12000-05-24 14:04:06 +0000164 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
165 if (ctx && !ctx->Extensions.HaveTextureCompression)
166 return -1;
167 /* fall-through */
jtgafb833d1999-08-19 00:55:39 +0000168 case 2:
169 case GL_LUMINANCE_ALPHA:
170 case GL_LUMINANCE4_ALPHA4:
171 case GL_LUMINANCE6_ALPHA2:
172 case GL_LUMINANCE8_ALPHA8:
173 case GL_LUMINANCE12_ALPHA4:
174 case GL_LUMINANCE12_ALPHA12:
175 case GL_LUMINANCE16_ALPHA16:
176 return GL_LUMINANCE_ALPHA;
Brian Paulaea66b12000-05-24 14:04:06 +0000177 case GL_COMPRESSED_INTENSITY_ARB:
178 if (ctx && !ctx->Extensions.HaveTextureCompression)
179 return -1;
180 /* fall-through */
jtgafb833d1999-08-19 00:55:39 +0000181 case GL_INTENSITY:
182 case GL_INTENSITY4:
183 case GL_INTENSITY8:
184 case GL_INTENSITY12:
185 case GL_INTENSITY16:
186 return GL_INTENSITY;
Brian Paulaea66b12000-05-24 14:04:06 +0000187 case GL_COMPRESSED_RGB_ARB:
188 if (ctx && ctx->Extensions.HaveTextureCompression)
189 return GL_RGB;
190 else
191 return -1;
192 case GL_COMPRESSED_RGB_FXT1_3DFX:
193 if (ctx && ctx->Extensions.HaveTextureCompressionFXT1)
194 return GL_RGB;
195 else
196 return -1;
197 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
198 if (ctx && ctx->Extensions.HaveTextureCompressionS3TC)
199 return GL_RGB;
200 else
201 return -1;
jtgafb833d1999-08-19 00:55:39 +0000202 case 3:
203 case GL_RGB:
204 case GL_R3_G3_B2:
205 case GL_RGB4:
206 case GL_RGB5:
207 case GL_RGB8:
208 case GL_RGB10:
209 case GL_RGB12:
210 case GL_RGB16:
211 return GL_RGB;
Brian Paulaea66b12000-05-24 14:04:06 +0000212 case GL_COMPRESSED_RGBA_ARB:
213 if (ctx && ctx->Extensions.HaveTextureCompression)
214 return GL_RGBA;
215 else
216 return -1;
217 case GL_COMPRESSED_RGBA_FXT1_3DFX:
218 if (ctx && ctx->Extensions.HaveTextureCompressionFXT1)
219 return GL_RGBA;
220 else
221 return -1;
222 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
223 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
224 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
225 if (ctx && ctx->Extensions.HaveTextureCompressionS3TC)
226 return GL_RGBA;
227 else
228 return -1;
jtgafb833d1999-08-19 00:55:39 +0000229 case 4:
230 case GL_RGBA:
231 case GL_RGBA2:
232 case GL_RGBA4:
233 case GL_RGB5_A1:
234 case GL_RGBA8:
235 case GL_RGB10_A2:
236 case GL_RGBA12:
237 case GL_RGBA16:
238 return GL_RGBA;
239 case GL_COLOR_INDEX:
240 case GL_COLOR_INDEX1_EXT:
241 case GL_COLOR_INDEX2_EXT:
242 case GL_COLOR_INDEX4_EXT:
243 case GL_COLOR_INDEX8_EXT:
244 case GL_COLOR_INDEX12_EXT:
245 case GL_COLOR_INDEX16_EXT:
246 return GL_COLOR_INDEX;
247 default:
248 return -1; /* error */
249 }
250}
251
252
253
254/*
255 * Given an internal texture format enum or 1, 2, 3, 4 return the
256 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
257 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
258 * number of components for the format. Return -1 if invalid enum.
259 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000260static GLint
261components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000262{
263 switch (format) {
264 case GL_ALPHA:
265 case GL_ALPHA4:
266 case GL_ALPHA8:
267 case GL_ALPHA12:
268 case GL_ALPHA16:
269 return 1;
270 case 1:
271 case GL_LUMINANCE:
272 case GL_LUMINANCE4:
273 case GL_LUMINANCE8:
274 case GL_LUMINANCE12:
275 case GL_LUMINANCE16:
276 return 1;
277 case 2:
278 case GL_LUMINANCE_ALPHA:
279 case GL_LUMINANCE4_ALPHA4:
280 case GL_LUMINANCE6_ALPHA2:
281 case GL_LUMINANCE8_ALPHA8:
282 case GL_LUMINANCE12_ALPHA4:
283 case GL_LUMINANCE12_ALPHA12:
284 case GL_LUMINANCE16_ALPHA16:
285 return 2;
286 case GL_INTENSITY:
287 case GL_INTENSITY4:
288 case GL_INTENSITY8:
289 case GL_INTENSITY12:
290 case GL_INTENSITY16:
291 return 1;
292 case 3:
293 case GL_RGB:
294 case GL_R3_G3_B2:
295 case GL_RGB4:
296 case GL_RGB5:
297 case GL_RGB8:
298 case GL_RGB10:
299 case GL_RGB12:
300 case GL_RGB16:
301 return 3;
302 case 4:
303 case GL_RGBA:
304 case GL_RGBA2:
305 case GL_RGBA4:
306 case GL_RGB5_A1:
307 case GL_RGBA8:
308 case GL_RGB10_A2:
309 case GL_RGBA12:
310 case GL_RGBA16:
311 return 4;
312 case GL_COLOR_INDEX:
313 case GL_COLOR_INDEX1_EXT:
314 case GL_COLOR_INDEX2_EXT:
315 case GL_COLOR_INDEX4_EXT:
316 case GL_COLOR_INDEX8_EXT:
317 case GL_COLOR_INDEX12_EXT:
318 case GL_COLOR_INDEX16_EXT:
319 return 1;
320 default:
321 return -1; /* error */
322 }
323}
324
325
Brian Paulaea66b12000-05-24 14:04:06 +0000326/*
327 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
328 * otherwise.
329 */
330static GLboolean
331is_compressed_format(GLenum internalFormat)
332{
333 switch (internalFormat) {
334 case GL_COMPRESSED_ALPHA_ARB:
335 case GL_COMPRESSED_LUMINANCE_ARB:
336 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
337 case GL_COMPRESSED_INTENSITY_ARB:
338 case GL_COMPRESSED_RGB_ARB:
339 case GL_COMPRESSED_RGBA_ARB:
340 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
341 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
342 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
343 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
344 case GL_COMPRESSED_RGB_FXT1_3DFX:
345 case GL_COMPRESSED_RGBA_FXT1_3DFX:
346 return GL_TRUE;
347 default:
348 return GL_FALSE;
349 }
350}
351
352
jtgafb833d1999-08-19 00:55:39 +0000353
jtgafb833d1999-08-19 00:55:39 +0000354/*
355 * Examine the texImage->Format field and set the Red, Green, Blue, etc
356 * texel component sizes to default values.
357 * These fields are set only here by core Mesa but device drivers may
358 * overwritting these fields to indicate true texel resolution.
359 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000360static void
361set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000362{
363 switch (texImage->Format) {
364 case GL_ALPHA:
365 texImage->RedBits = 0;
366 texImage->GreenBits = 0;
367 texImage->BlueBits = 0;
368 texImage->AlphaBits = 8;
369 texImage->IntensityBits = 0;
370 texImage->LuminanceBits = 0;
371 texImage->IndexBits = 0;
372 break;
373 case GL_LUMINANCE:
374 texImage->RedBits = 0;
375 texImage->GreenBits = 0;
376 texImage->BlueBits = 0;
377 texImage->AlphaBits = 0;
378 texImage->IntensityBits = 0;
379 texImage->LuminanceBits = 8;
380 texImage->IndexBits = 0;
381 break;
382 case GL_LUMINANCE_ALPHA:
383 texImage->RedBits = 0;
384 texImage->GreenBits = 0;
385 texImage->BlueBits = 0;
386 texImage->AlphaBits = 8;
387 texImage->IntensityBits = 0;
388 texImage->LuminanceBits = 8;
389 texImage->IndexBits = 0;
390 break;
391 case GL_INTENSITY:
392 texImage->RedBits = 0;
393 texImage->GreenBits = 0;
394 texImage->BlueBits = 0;
395 texImage->AlphaBits = 0;
396 texImage->IntensityBits = 8;
397 texImage->LuminanceBits = 0;
398 texImage->IndexBits = 0;
399 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000400 case GL_RED:
401 texImage->RedBits = 8;
402 texImage->GreenBits = 0;
403 texImage->BlueBits = 0;
404 texImage->AlphaBits = 0;
405 texImage->IntensityBits = 0;
406 texImage->LuminanceBits = 0;
407 texImage->IndexBits = 0;
408 break;
409 case GL_GREEN:
410 texImage->RedBits = 0;
411 texImage->GreenBits = 8;
412 texImage->BlueBits = 0;
413 texImage->AlphaBits = 0;
414 texImage->IntensityBits = 0;
415 texImage->LuminanceBits = 0;
416 texImage->IndexBits = 0;
417 break;
418 case GL_BLUE:
419 texImage->RedBits = 0;
420 texImage->GreenBits = 0;
421 texImage->BlueBits = 8;
422 texImage->AlphaBits = 0;
423 texImage->IntensityBits = 0;
424 texImage->LuminanceBits = 0;
425 texImage->IndexBits = 0;
426 break;
jtgafb833d1999-08-19 00:55:39 +0000427 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000428 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000429 texImage->RedBits = 8;
430 texImage->GreenBits = 8;
431 texImage->BlueBits = 8;
432 texImage->AlphaBits = 0;
433 texImage->IntensityBits = 0;
434 texImage->LuminanceBits = 0;
435 texImage->IndexBits = 0;
436 break;
437 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000438 case GL_BGRA:
439 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000440 texImage->RedBits = 8;
441 texImage->GreenBits = 8;
442 texImage->BlueBits = 8;
443 texImage->AlphaBits = 8;
444 texImage->IntensityBits = 0;
445 texImage->LuminanceBits = 0;
446 texImage->IndexBits = 0;
447 break;
448 case GL_COLOR_INDEX:
449 texImage->RedBits = 0;
450 texImage->GreenBits = 0;
451 texImage->BlueBits = 0;
452 texImage->AlphaBits = 0;
453 texImage->IntensityBits = 0;
454 texImage->LuminanceBits = 0;
455 texImage->IndexBits = 8;
456 break;
457 default:
458 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
459 }
460}
461
462
Brian Paulfc4b4432000-05-23 15:17:12 +0000463static void
464set_tex_image(struct gl_texture_object *tObj,
465 GLenum target, GLint level,
466 struct gl_texture_image *texImage)
467{
468 ASSERT(tObj);
469 ASSERT(texImage);
470 switch (target) {
471 case GL_TEXTURE_2D:
472 tObj->Image[level] = texImage;
473 return;
474 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
475 tObj->PosX[level] = texImage;
476 return;
477 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
478 tObj->NegX[level] = texImage;
479 return;
480 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
481 tObj->PosY[level] = texImage;
482 return;
483 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
484 tObj->NegY[level] = texImage;
485 return;
486 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
487 tObj->PosZ[level] = texImage;
488 return;
489 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
490 tObj->NegZ[level] = texImage;
491 return;
492 default:
493 gl_problem(NULL, "bad target in set_tex_image()");
494 return;
495 }
496}
497
498
Brian Paul77ce6da2000-03-20 23:40:12 +0000499/*
500 * Return new gl_texture_image struct with all fields initialized to zero.
501 */
502struct gl_texture_image *
Brian Paul021a5252000-03-27 17:54:17 +0000503_mesa_alloc_texture_image( void )
Brian Paul77ce6da2000-03-20 23:40:12 +0000504{
505 return CALLOC_STRUCT(gl_texture_image);
506}
507
508
509
510/*
Brian Paul02938782000-03-22 17:38:11 +0000511 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000512 */
Brian Paul02938782000-03-22 17:38:11 +0000513static void
514init_texture_image( struct gl_texture_image *img,
515 GLsizei width, GLsizei height, GLsizei depth,
516 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000517{
Brian Paul02938782000-03-22 17:38:11 +0000518 ASSERT(img);
519 ASSERT(!img->Data);
Brian Paulaea66b12000-05-24 14:04:06 +0000520 img->Format = (GLenum) _mesa_base_tex_format(NULL, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000521 set_teximage_component_sizes( img );
522 img->IntFormat = (GLenum) internalFormat;
523 img->Border = border;
524 img->Width = width;
525 img->Height = height;
526 img->Depth = depth;
527 img->WidthLog2 = logbase2(width - 2 * border);
528 if (height == 1) /* 1-D texture */
529 img->HeightLog2 = 0;
530 else
531 img->HeightLog2 = logbase2(height - 2 * border);
532 if (depth == 1) /* 2-D texture */
533 img->DepthLog2 = 0;
534 else
535 img->DepthLog2 = logbase2(depth - 2 * border);
536 img->Width2 = 1 << img->WidthLog2;
537 img->Height2 = 1 << img->HeightLog2;
538 img->Depth2 = 1 << img->DepthLog2;
539 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paulaea66b12000-05-24 14:04:06 +0000540 img->IsCompressed = is_compressed_format(internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000541}
542
543
544
545void
Brian Paul021a5252000-03-27 17:54:17 +0000546_mesa_free_texture_image( struct gl_texture_image *teximage )
Brian Paul77ce6da2000-03-20 23:40:12 +0000547{
548 if (teximage->Data) {
549 FREE( teximage->Data );
550 teximage->Data = NULL;
551 }
552 FREE( teximage );
553}
554
555
556
Brian Paulfc4b4432000-05-23 15:17:12 +0000557/*
Brian Paulaea66b12000-05-24 14:04:06 +0000558 * Return number of bytes of storage needed to store a compressed texture
559 * image.
560 */
561GLuint
562_mesa_compressed_image_size(GLenum internalFormat,
563 GLint width, GLint height, GLint depth)
564{
565 return 0;
566}
567
568
569
570/*
Brian Paul35d53012000-05-23 17:14:49 +0000571 * Given a texture unit and a texture target, return the corresponding
572 * texture object.
573 */
574struct gl_texture_object *
575_mesa_select_tex_object(GLcontext *ctx, struct gl_texture_unit *texUnit,
576 GLenum target)
577{
578 switch (target) {
579 case GL_TEXTURE_1D:
580 return texUnit->CurrentD[1];
581 case GL_PROXY_TEXTURE_1D:
582 return ctx->Texture.Proxy1D;
583 case GL_TEXTURE_2D:
584 return texUnit->CurrentD[2];
585 case GL_PROXY_TEXTURE_2D:
586 return ctx->Texture.Proxy2D;
587 case GL_TEXTURE_3D:
588 return texUnit->CurrentD[3];
589 case GL_PROXY_TEXTURE_3D:
590 return ctx->Texture.Proxy3D;
591 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
592 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
593 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
594 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
595 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
597 return ctx->Extensions.HaveTextureCubeMap
598 ? texUnit->CurrentCubeMap : NULL;
599 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
600 return ctx->Extensions.HaveTextureCubeMap
601 ? ctx->Texture.ProxyCubeMap : NULL;
602 default:
603 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
604 return NULL;
605 }
606}
607
608
609/*
Brian Paulfc4b4432000-05-23 15:17:12 +0000610 * Return the texture image struct which corresponds to target and level
611 * for the given texture unit.
612 */
613struct gl_texture_image *
614_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
615 GLenum target, GLint level)
616{
617 ASSERT(texUnit);
618 switch (target) {
619 case GL_TEXTURE_1D:
620 return texUnit->CurrentD[1]->Image[level];
621 case GL_PROXY_TEXTURE_1D:
622 return ctx->Texture.Proxy1D->Image[level];
623 case GL_TEXTURE_2D:
624 return texUnit->CurrentD[2]->Image[level];
625 case GL_PROXY_TEXTURE_2D:
626 return ctx->Texture.Proxy2D->Image[level];
627 case GL_TEXTURE_3D:
628 return texUnit->CurrentD[3]->Image[level];
629 case GL_PROXY_TEXTURE_3D:
630 return ctx->Texture.Proxy3D->Image[level];
631 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
632 if (ctx->Extensions.HaveTextureCubeMap)
633 return texUnit->CurrentCubeMap->PosX[level];
634 else
635 return NULL;
636 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
637 if (ctx->Extensions.HaveTextureCubeMap)
638 return texUnit->CurrentCubeMap->NegX[level];
639 else
640 return NULL;
641 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
642 if (ctx->Extensions.HaveTextureCubeMap)
643 return texUnit->CurrentCubeMap->PosY[level];
644 else
645 return NULL;
646 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
647 if (ctx->Extensions.HaveTextureCubeMap)
648 return texUnit->CurrentCubeMap->NegY[level];
649 else
650 return NULL;
651 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
652 if (ctx->Extensions.HaveTextureCubeMap)
653 return texUnit->CurrentCubeMap->PosZ[level];
654 else
655 return NULL;
656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
657 if (ctx->Extensions.HaveTextureCubeMap)
658 return texUnit->CurrentCubeMap->NegZ[level];
659 else
660 return NULL;
661 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
662 if (ctx->Extensions.HaveTextureCubeMap)
663 return ctx->Texture.ProxyCubeMap->PosX[level];
664 else
665 return NULL;
666 default:
667 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
668 return NULL;
669 }
670}
671
672
673
jtgafb833d1999-08-19 00:55:39 +0000674/* Need this to prevent an out-of-bounds memory access when using
675 * X86 optimized code.
676 */
677#ifdef USE_X86_ASM
678# define EXTRA_BYTE 1
679#else
680# define EXTRA_BYTE 0
681#endif
682
683
Brian Paulc3f0a511999-11-03 17:27:05 +0000684
jtgafb833d1999-08-19 00:55:39 +0000685/*
Brian Paul43911c82000-03-21 00:49:33 +0000686 * Called by glTexImage[123]D. Fill in a texture image with data given
687 * by the client. All pixel transfer and unpack modes are handled here.
688 * NOTE: All texture image parameters should have already been error checked.
jtgafb833d1999-08-19 00:55:39 +0000689 */
Brian Paul43911c82000-03-21 00:49:33 +0000690static void
691make_texture_image( GLcontext *ctx,
692 struct gl_texture_image *texImage,
Brian Paulc3f0a511999-11-03 17:27:05 +0000693 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
694 const struct gl_pixelstore_attrib *unpacking)
jtgafb833d1999-08-19 00:55:39 +0000695{
Brian Paulc3f0a511999-11-03 17:27:05 +0000696 GLint components, numPixels;
Brian Paul43911c82000-03-21 00:49:33 +0000697 GLint internalFormat, width, height, depth, border;
jtgafb833d1999-08-19 00:55:39 +0000698
Brian Paul43911c82000-03-21 00:49:33 +0000699 ASSERT(ctx);
700 ASSERT(texImage);
701 ASSERT(!texImage->Data);
702 ASSERT(pixels);
703 ASSERT(unpacking);
jtgafb833d1999-08-19 00:55:39 +0000704
Brian Paul43911c82000-03-21 00:49:33 +0000705 internalFormat = texImage->IntFormat;
706 width = texImage->Width;
707 height = texImage->Height;
708 depth = texImage->Depth;
709 border = texImage->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +0000710 components = components_in_intformat(internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +0000711
712 ASSERT(width > 0);
713 ASSERT(height > 0);
714 ASSERT(depth > 0);
715 ASSERT(border == 0 || border == 1);
716 ASSERT(pixels);
717 ASSERT(unpacking);
718 ASSERT(components);
719
720 numPixels = width * height * depth;
Brian Paulc3f0a511999-11-03 17:27:05 +0000721
722 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
Brian Paul43911c82000-03-21 00:49:33 +0000723 if (!texImage->Data)
724 return; /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000725
726 /*
727 * OK, the texture image struct has been initialized and the texture
728 * image memory has been allocated.
729 * Now fill in the texture image from the source data.
730 * This includes applying the pixel transfer operations.
731 */
732
733 /* try common 2D texture cases first */
734 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
735 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
736 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
737
Brian Paul43911c82000-03-21 00:49:33 +0000738 if (srcFormat == internalFormat ||
739 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
740 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
741 (srcFormat == GL_RGB && internalFormat == 3) ||
742 (srcFormat == GL_RGBA && internalFormat == 4)) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000743 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
744 * GL_LUMINANCE_ALPHA, etc. texture formats.
745 */
Brian Paulb7d076f2000-03-21 01:03:40 +0000746 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000747 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
748 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
749 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000750 GLubyte *dst = texImage->Data;
751 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
752 if (srcStride == dstBytesPerRow) {
753 MEMCPY(dst, src, height * dstBytesPerRow);
754 }
755 else {
756 GLint i;
757 for (i = 0; i < height; i++) {
758 MEMCPY(dst, src, dstBytesPerRow);
759 src += srcStride;
760 dst += dstBytesPerRow;
761 }
762 }
Brian Paul43911c82000-03-21 00:49:33 +0000763 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000764 }
765 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
766 /* commonly used by Quake */
Brian Paulb7d076f2000-03-21 01:03:40 +0000767 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000768 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
769 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
770 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000771 GLubyte *dst = texImage->Data;
772 GLint i, j;
773 for (i = 0; i < height; i++) {
774 const GLubyte *s = src;
775 for (j = 0; j < width; j++) {
776 *dst++ = *s++; /*red*/
777 *dst++ = *s++; /*green*/
778 *dst++ = *s++; /*blue*/
779 s++; /*alpha*/
780 }
781 src += srcStride;
782 }
Brian Paul43911c82000-03-21 00:49:33 +0000783 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000784 }
785 }
786
787
788 /*
789 * General case solutions
790 */
791 if (texImage->Format == GL_COLOR_INDEX) {
792 /* color index texture */
793 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
794 const GLenum dstType = GL_UNSIGNED_BYTE;
795 GLubyte *dest = texImage->Data;
796 GLint img, row;
797 for (img = 0; img < depth; img++) {
798 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000799 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000800 pixels, width, height, srcFormat, srcType, img, row, 0);
801 _mesa_unpack_index_span(ctx, width, dstType, dest,
802 srcType, source, unpacking, GL_TRUE);
803 dest += destBytesPerRow;
804 }
805 }
jtgafb833d1999-08-19 00:55:39 +0000806 }
807 else {
Brian Paulc3f0a511999-11-03 17:27:05 +0000808 /* regular, color texture */
809 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
810 const GLenum dstFormat = texImage->Format;
811 GLubyte *dest = texImage->Data;
812 GLint img, row;
813 for (img = 0; img < depth; img++) {
814 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000815 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000816 pixels, width, height, srcFormat, srcType, img, row, 0);
817 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
818 srcFormat, srcType, source, unpacking, GL_TRUE);
819 dest += destBytesPerRow;
820 }
821 }
jtgafb833d1999-08-19 00:55:39 +0000822 }
jtgafb833d1999-08-19 00:55:39 +0000823}
824
825
826
827/*
828 * glTexImage[123]D can accept a NULL image pointer. In this case we
829 * create a texture image with unspecified image contents per the OpenGL
Brian Paul43911c82000-03-21 00:49:33 +0000830 * spec. This function creates an empty image for the given texture image.
jtgafb833d1999-08-19 00:55:39 +0000831 */
Brian Paul43911c82000-03-21 00:49:33 +0000832static void
833make_null_texture( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000834{
835 GLint components;
jtgafb833d1999-08-19 00:55:39 +0000836 GLint numPixels;
jtgafb833d1999-08-19 00:55:39 +0000837
Brian Paul43911c82000-03-21 00:49:33 +0000838 ASSERT(texImage);
839 ASSERT(!texImage->Data);
jtgafb833d1999-08-19 00:55:39 +0000840
Brian Paul43911c82000-03-21 00:49:33 +0000841 components = components_in_intformat(texImage->IntFormat);
842 numPixels = texImage->Width * texImage->Height * texImage->Depth;
jtgafb833d1999-08-19 00:55:39 +0000843
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000844 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000845
846 /*
847 * Let's see if anyone finds this. If glTexImage2D() is called with
848 * a NULL image pointer then load the texture image with something
849 * interesting instead of leaving it indeterminate.
850 */
851 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000852 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000853 " X X XXXXX XXX X ",
854 " XX XX X X X X X ",
855 " X X X X X X X ",
856 " X X XXXX XXX XXXXX ",
857 " X X X X X X ",
858 " X X X X X X X ",
859 " X X XXXXX XXX X X ",
860 " "
861 };
862
863 GLubyte *imgPtr = texImage->Data;
864 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000865 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000866 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000867 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000868 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000869 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000870 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000871 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000872 }
873 }
874 }
875 }
jtgafb833d1999-08-19 00:55:39 +0000876}
877
878
879
880/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000881 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +0000882 * Input:
883 * dimensions - must be 1 or 2 or 3
884 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
885 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000886static GLboolean
887texture_error_check( GLcontext *ctx, GLenum target,
888 GLint level, GLint internalFormat,
889 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +0000890 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000891 GLint width, GLint height,
892 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +0000893{
894 GLboolean isProxy;
895 GLint iformat;
896
897 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +0000898 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +0000899 if (target != GL_TEXTURE_1D && !isProxy) {
900 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
901 return GL_TRUE;
902 }
903 }
904 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +0000905 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
jtgafb833d1999-08-19 00:55:39 +0000906 if (target != GL_TEXTURE_2D && !isProxy) {
907 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
908 return GL_TRUE;
909 }
910 }
911 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +0000912 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +0000913 if (target != GL_TEXTURE_3D && !isProxy) {
914 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
915 return GL_TRUE;
916 }
917 }
918 else {
919 gl_problem( ctx, "bad dims in texture_error_check" );
920 return GL_TRUE;
921 }
922
923 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000924 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +0000925 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000926 char message[100];
927 sprintf(message, "glTexImage%dD(border)", dimensions);
928 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000929 }
930 return GL_TRUE;
931 }
932
933 /* Width */
934 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
935 || logbase2( width - 2 * border ) < 0) {
936 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000937 char message[100];
938 sprintf(message, "glTexImage%dD(width)", dimensions);
939 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000940 }
941 return GL_TRUE;
942 }
943
944 /* Height */
945 if (dimensions >= 2) {
946 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
947 || logbase2( height - 2 * border ) < 0) {
948 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000949 char message[100];
950 sprintf(message, "glTexImage%dD(height)", dimensions);
951 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000952 }
Brian Paulc3f0a511999-11-03 17:27:05 +0000953 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000954 }
955 }
956
957 /* Depth */
958 if (dimensions >= 3) {
959 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
960 || logbase2( depth - 2 * border ) < 0) {
961 if (!isProxy) {
962 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
963 }
964 return GL_TRUE;
965 }
966 }
967
968 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000969 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000970 if (!isProxy) {
971 char message[100];
972 sprintf(message, "glTexImage%dD(level)", dimensions);
973 gl_error(ctx, GL_INVALID_VALUE, message);
974 }
jtgafb833d1999-08-19 00:55:39 +0000975 return GL_TRUE;
976 }
977
Brian Paulaea66b12000-05-24 14:04:06 +0000978 iformat = _mesa_base_tex_format( ctx, internalFormat );
jtgafb833d1999-08-19 00:55:39 +0000979 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000980 if (!isProxy) {
981 char message[100];
982 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
983 gl_error(ctx, GL_INVALID_VALUE, message);
984 }
jtgafb833d1999-08-19 00:55:39 +0000985 return GL_TRUE;
986 }
987
Brian Paulaea66b12000-05-24 14:04:06 +0000988 if (!is_compressed_format(internalFormat)) {
989 if (!_mesa_is_legal_format_and_type( format, type )) {
990 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
991 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
992 */
993 if (!isProxy) {
994 char message[100];
995 sprintf(message, "glTexImage%dD(format or type)", dimensions);
996 gl_error(ctx, GL_INVALID_OPERATION, message);
997 }
998 return GL_TRUE;
Brian Paulc3f0a511999-11-03 17:27:05 +0000999 }
jtgafb833d1999-08-19 00:55:39 +00001000 }
1001
1002 /* if we get here, the parameters are OK */
1003 return GL_FALSE;
1004}
1005
1006
1007
1008/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001009 * Test glTexSubImage[123]D() parameters for errors.
1010 * Input:
1011 * dimensions - must be 1 or 2 or 3
1012 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1013 */
1014static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001015subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001016 GLenum target, GLint level,
1017 GLint xoffset, GLint yoffset, GLint zoffset,
1018 GLint width, GLint height, GLint depth,
1019 GLenum format, GLenum type )
1020{
1021 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1022 struct gl_texture_image *destTex;
1023
1024 if (dimensions == 1) {
1025 if (target != GL_TEXTURE_1D) {
1026 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1027 return GL_TRUE;
1028 }
1029 }
1030 else if (dimensions == 2) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001031 if (ctx->Extensions.HaveTextureCubeMap) {
1032 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1033 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1034 target != GL_TEXTURE_2D) {
1035 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1036 return GL_TRUE;
1037 }
1038 }
1039 else if (target != GL_TEXTURE_2D) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001040 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1041 return GL_TRUE;
1042 }
1043 }
1044 else if (dimensions == 3) {
1045 if (target != GL_TEXTURE_3D) {
1046 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1047 return GL_TRUE;
1048 }
1049 }
1050 else {
1051 gl_problem( ctx, "bad dims in texture_error_check" );
1052 return GL_TRUE;
1053 }
1054
1055 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1056 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1057 return GL_TRUE;
1058 }
1059
1060 if (width < 0) {
1061 char message[100];
1062 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1063 gl_error(ctx, GL_INVALID_VALUE, message);
1064 return GL_TRUE;
1065 }
1066 if (height < 0 && dimensions > 1) {
1067 char message[100];
1068 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1069 gl_error(ctx, GL_INVALID_VALUE, message);
1070 return GL_TRUE;
1071 }
1072 if (depth < 0 && dimensions > 2) {
1073 char message[100];
1074 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1075 gl_error(ctx, GL_INVALID_VALUE, message);
1076 return GL_TRUE;
1077 }
1078
1079 destTex = texUnit->CurrentD[2]->Image[level];
1080 if (!destTex) {
1081 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1082 return GL_TRUE;
1083 }
1084
1085 if (xoffset < -((GLint)destTex->Border)) {
1086 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1087 return GL_TRUE;
1088 }
1089 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1090 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1091 return GL_TRUE;
1092 }
1093 if (dimensions > 1) {
1094 if (yoffset < -((GLint)destTex->Border)) {
1095 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1096 return GL_TRUE;
1097 }
1098 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1099 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1100 return GL_TRUE;
1101 }
1102 }
1103 if (dimensions > 2) {
1104 if (zoffset < -((GLint)destTex->Border)) {
1105 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1106 return GL_TRUE;
1107 }
1108 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1109 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1110 return GL_TRUE;
1111 }
1112 }
1113
Brian Paulb7d076f2000-03-21 01:03:40 +00001114 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001115 char message[100];
1116 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1117 gl_error(ctx, GL_INVALID_ENUM, message);
1118 return GL_TRUE;
1119 }
1120
1121 return GL_FALSE;
1122}
1123
1124
1125/*
1126 * Test glCopyTexImage[12]D() parameters for errors.
1127 * Input: dimensions - must be 1 or 2 or 3
1128 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1129 */
1130static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001131copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001132 GLenum target, GLint level, GLint internalFormat,
1133 GLint width, GLint height, GLint border )
1134{
1135 GLint iformat;
1136
Brian Paulfc4b4432000-05-23 15:17:12 +00001137 if (dimensions == 1) {
1138 if (target != GL_TEXTURE_1D) {
1139 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1140 return GL_TRUE;
1141 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001142 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001143 else if (dimensions == 2) {
1144 if (ctx->Extensions.HaveTextureCubeMap) {
1145 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1146 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1147 target != GL_TEXTURE_2D) {
1148 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1149 return GL_TRUE;
1150 }
1151 }
1152 else if (target != GL_TEXTURE_2D) {
1153 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1154 return GL_TRUE;
1155 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001156 }
1157
1158 /* Border */
1159 if (border!=0 && border!=1) {
1160 char message[100];
1161 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1162 gl_error(ctx, GL_INVALID_VALUE, message);
1163 return GL_TRUE;
1164 }
1165
1166 /* Width */
1167 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1168 || logbase2( width - 2 * border ) < 0) {
1169 char message[100];
1170 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1171 gl_error(ctx, GL_INVALID_VALUE, message);
1172 return GL_TRUE;
1173 }
1174
1175 /* Height */
1176 if (dimensions >= 2) {
1177 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1178 || logbase2( height - 2 * border ) < 0) {
1179 char message[100];
1180 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1181 gl_error(ctx, GL_INVALID_VALUE, message);
1182 return GL_TRUE;
1183 }
1184 }
1185
1186 /* Level */
1187 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1188 char message[100];
1189 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1190 gl_error(ctx, GL_INVALID_VALUE, message);
1191 return GL_TRUE;
1192 }
1193
Brian Paulaea66b12000-05-24 14:04:06 +00001194 iformat = _mesa_base_tex_format( ctx, internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +00001195 if (iformat < 0) {
1196 char message[100];
1197 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1198 gl_error(ctx, GL_INVALID_VALUE, message);
1199 return GL_TRUE;
1200 }
1201
1202 /* if we get here, the parameters are OK */
1203 return GL_FALSE;
1204}
1205
1206
1207static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001208copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001209 GLenum target, GLint level,
1210 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +00001211 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001212{
1213 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1214 struct gl_texture_image *teximage;
1215
Brian Paulfc4b4432000-05-23 15:17:12 +00001216 if (dimensions == 1) {
1217 if (target != GL_TEXTURE_1D) {
1218 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1219 return GL_TRUE;
1220 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001221 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001222 else if (dimensions == 2) {
1223 if (ctx->Extensions.HaveTextureCubeMap) {
1224 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1225 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1226 target != GL_TEXTURE_2D) {
1227 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1228 return GL_TRUE;
1229 }
1230 }
1231 else if (target != GL_TEXTURE_2D) {
1232 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1233 return GL_TRUE;
1234 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001235 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001236 else if (dimensions == 3) {
1237 if (target != GL_TEXTURE_3D) {
1238 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1239 return GL_TRUE;
1240 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001241 }
1242
1243 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1244 char message[100];
1245 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1246 gl_error(ctx, GL_INVALID_VALUE, message);
1247 return GL_TRUE;
1248 }
1249
1250 if (width < 0) {
1251 char message[100];
1252 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1253 gl_error(ctx, GL_INVALID_VALUE, message);
1254 return GL_TRUE;
1255 }
1256 if (dimensions > 1 && height < 0) {
1257 char message[100];
1258 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1259 gl_error(ctx, GL_INVALID_VALUE, message);
1260 return GL_TRUE;
1261 }
1262
Brian Pauldf6a28d2000-02-21 16:34:21 +00001263 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001264 if (!teximage) {
1265 char message[100];
1266 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1267 gl_error(ctx, GL_INVALID_OPERATION, message);
1268 return GL_TRUE;
1269 }
1270
1271 if (xoffset < -((GLint)teximage->Border)) {
1272 char message[100];
1273 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1274 gl_error(ctx, GL_INVALID_VALUE, message);
1275 return GL_TRUE;
1276 }
1277 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1278 char message[100];
1279 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1280 gl_error(ctx, GL_INVALID_VALUE, message);
1281 return GL_TRUE;
1282 }
1283 if (dimensions > 1) {
1284 if (yoffset < -((GLint)teximage->Border)) {
1285 char message[100];
1286 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1287 gl_error(ctx, GL_INVALID_VALUE, message);
1288 return GL_TRUE;
1289 }
1290 /* NOTE: we're adding the border here, not subtracting! */
1291 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1292 char message[100];
1293 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1294 gl_error(ctx, GL_INVALID_VALUE, message);
1295 return GL_TRUE;
1296 }
1297 }
1298
1299 if (dimensions > 2) {
1300 if (zoffset < -((GLint)teximage->Border)) {
1301 char message[100];
1302 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1303 gl_error(ctx, GL_INVALID_VALUE, message);
1304 return GL_TRUE;
1305 }
1306 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1307 char message[100];
1308 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1309 gl_error(ctx, GL_INVALID_VALUE, message);
1310 return GL_TRUE;
1311 }
1312 }
1313
1314 /* if we get here, the parameters are OK */
1315 return GL_FALSE;
1316}
1317
1318
1319
1320
1321/*
jtgafb833d1999-08-19 00:55:39 +00001322 * Called from the API. Note that width includes the border.
1323 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001324void
Brian Paul43911c82000-03-21 00:49:33 +00001325_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001326 GLsizei width, GLint border, GLenum format,
1327 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001328{
Brian Paulfbd8f211999-11-11 01:22:25 +00001329 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001330 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1331
1332 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001333 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001334 struct gl_texture_object *texObj;
1335 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001336
Brian Paulaea66b12000-05-24 14:04:06 +00001337 if (texture_error_check(ctx, target, level, internalFormat,
1338 format, type, 1, width, 1, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001339 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001340 }
1341
Brian Paulf7b57072000-03-20 14:37:52 +00001342 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001343 texObj = texUnit->CurrentD[1];
1344 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001345
Brian Paul02938782000-03-22 17:38:11 +00001346 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001347 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001348 texObj->Image[level] = texImage;
1349 if (!texImage) {
1350 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1351 return;
1352 }
1353 }
1354 else if (texImage->Data) {
1355 FREE(texImage->Data);
1356 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001357 }
1358
Brian Paul02938782000-03-22 17:38:11 +00001359 /* setup the teximage struct's fields */
1360 init_texture_image(texImage, width, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001361
Brian Paul02938782000-03-22 17:38:11 +00001362 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001363 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001364 GLboolean retain = GL_TRUE;
1365 GLboolean success = GL_FALSE;
1366 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1367 && ctx->Driver.TexImage1D) {
1368 /* let device driver try to use raw image */
1369 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1370 type, pixels, &ctx->Unpack,
1371 texObj, texImage, &retain);
1372 }
1373 if (retain || !success) {
1374 /* make internal copy of the texture image */
1375 make_texture_image(ctx, texImage, format, type,
1376 pixels, &ctx->Unpack);
1377 if (!success && ctx->Driver.TexImage1D) {
1378 /* let device driver try to use unpacked image */
1379 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1380 GL_UNSIGNED_BYTE, texImage->Data,
1381 &_mesa_native_packing,
1382 texObj, texImage, &retain);
1383 }
1384 }
1385 if (!retain && texImage->Data) {
1386 FREE(texImage->Data);
1387 texImage->Data = NULL;
1388 }
jtgafb833d1999-08-19 00:55:39 +00001389 }
1390 else {
Brian Paul02938782000-03-22 17:38:11 +00001391 make_null_texture(texImage);
1392 if (ctx->Driver.TexImage1D) {
1393 GLboolean retain;
1394 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1395 GL_UNSIGNED_BYTE, texImage->Data,
1396 &_mesa_native_packing,
1397 texObj, texImage, &retain);
1398 }
jtgafb833d1999-08-19 00:55:39 +00001399 }
1400
Brian Paul02938782000-03-22 17:38:11 +00001401 /* state update */
1402 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001403 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001404 }
1405 else if (target==GL_PROXY_TEXTURE_1D) {
1406 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001407 if (texture_error_check(ctx, target, level, internalFormat,
1408 format, type, 1, width, 1, 1, border)) {
1409 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001410 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1411 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1412 sizeof(struct gl_texture_image) );
1413 }
1414 }
1415 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001416 /* if no error, update proxy texture image parameters */
1417 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1418 width, 1, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001419 }
jtgafb833d1999-08-19 00:55:39 +00001420 }
1421 else {
1422 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1423 return;
1424 }
1425}
1426
1427
Brian Paulfbd8f211999-11-11 01:22:25 +00001428void
Brian Paul43911c82000-03-21 00:49:33 +00001429_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001430 GLsizei width, GLsizei height, GLint border,
1431 GLenum format, GLenum type,
1432 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001433{
Brian Paulfbd8f211999-11-11 01:22:25 +00001434 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001435 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1436
Brian Paulfc4b4432000-05-23 15:17:12 +00001437 if (target==GL_TEXTURE_2D ||
1438 (ctx->Extensions.HaveTextureCubeMap &&
1439 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1440 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001441 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001442 struct gl_texture_object *texObj;
1443 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001444
Brian Paulaea66b12000-05-24 14:04:06 +00001445 if (texture_error_check(ctx, target, level, internalFormat,
1446 format, type, 2, width, height, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001447 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001448 }
1449
Brian Paulf7b57072000-03-20 14:37:52 +00001450 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00001451 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paulfc4b4432000-05-23 15:17:12 +00001452 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00001453
Brian Paul02938782000-03-22 17:38:11 +00001454 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001455 texImage = _mesa_alloc_texture_image();
Brian Paulfc4b4432000-05-23 15:17:12 +00001456 set_tex_image(texObj, target, level, texImage);
1457 /*texObj->Image[level] = texImage;*/
Brian Paul02938782000-03-22 17:38:11 +00001458 if (!texImage) {
1459 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1460 return;
1461 }
1462 }
1463 else if (texImage->Data) {
1464 FREE(texImage->Data);
1465 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001466 }
1467
Brian Paul02938782000-03-22 17:38:11 +00001468 /* setup the teximage struct's fields */
1469 init_texture_image(texImage, width, height, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001470
Brian Paul02938782000-03-22 17:38:11 +00001471 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001472 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001473 GLboolean retain = GL_TRUE;
1474 GLboolean success = GL_FALSE;
1475 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1476 && ctx->Driver.TexImage2D) {
1477 /* let device driver try to use raw image */
1478 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1479 type, pixels, &ctx->Unpack,
1480 texObj, texImage, &retain);
1481 }
1482 if (retain || !success) {
1483 /* make internal copy of the texture image */
1484 make_texture_image(ctx, texImage, format, type,
1485 pixels, &ctx->Unpack);
1486 if (!success && ctx->Driver.TexImage2D) {
1487 /* let device driver try to use unpacked image */
1488 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1489 GL_UNSIGNED_BYTE, texImage->Data,
1490 &_mesa_native_packing,
1491 texObj, texImage, &retain);
1492 }
1493 }
1494 if (!retain && texImage->Data) {
1495 FREE(texImage->Data);
1496 texImage->Data = NULL;
1497 }
jtgafb833d1999-08-19 00:55:39 +00001498 }
1499 else {
Brian Paul02938782000-03-22 17:38:11 +00001500 make_null_texture(texImage);
1501 if (ctx->Driver.TexImage2D) {
1502 GLboolean retain;
1503 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1504 GL_UNSIGNED_BYTE, texImage->Data,
1505 &_mesa_native_packing,
1506 texObj, texImage, &retain);
1507 }
jtgafb833d1999-08-19 00:55:39 +00001508 }
1509
Brian Paul02938782000-03-22 17:38:11 +00001510#define OLD_DD_TEXTURE
1511#ifdef OLD_DD_TEXTURE
1512 /* XXX this will be removed in the future */
jtgafb833d1999-08-19 00:55:39 +00001513 if (ctx->Driver.TexImage) {
Brian Paul02938782000-03-22 17:38:11 +00001514 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1515 texImage );
jtgafb833d1999-08-19 00:55:39 +00001516 }
Brian Paul02938782000-03-22 17:38:11 +00001517#endif
1518
1519 /* state update */
1520 gl_put_texobj_on_dirty_list( ctx, texObj );
1521 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001522 }
1523 else if (target==GL_PROXY_TEXTURE_2D) {
1524 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001525 if (texture_error_check(ctx, target, level, internalFormat,
1526 format, type, 2, width, height, 1, border)) {
1527 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001528 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1529 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1530 sizeof(struct gl_texture_image) );
1531 }
1532 }
1533 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001534 /* if no error, update proxy texture image parameters */
1535 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1536 width, height, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001537 }
jtgafb833d1999-08-19 00:55:39 +00001538 }
1539 else {
1540 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1541 return;
1542 }
1543}
1544
1545
1546
1547/*
1548 * Called by the API or display list executor.
1549 * Note that width and height include the border.
1550 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001551void
Brian Paul43911c82000-03-21 00:49:33 +00001552_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001553 GLsizei width, GLsizei height, GLsizei depth,
1554 GLint border, GLenum format, GLenum type,
1555 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001556{
Brian Paulfbd8f211999-11-11 01:22:25 +00001557 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001558 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001559
Brian Paulfbd8f211999-11-11 01:22:25 +00001560 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001561 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001562 struct gl_texture_object *texObj;
1563 struct gl_texture_image *texImage;
Brian Paulaea66b12000-05-24 14:04:06 +00001564 if (texture_error_check(ctx, target, level, internalFormat,
1565 format, type, 3, width, height, depth, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001566 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001567 }
1568
Brian Paulf7b57072000-03-20 14:37:52 +00001569 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001570 texObj = texUnit->CurrentD[3];
1571 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001572
Brian Paul02938782000-03-22 17:38:11 +00001573 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001574 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001575 texObj->Image[level] = texImage;
1576 if (!texImage) {
1577 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1578 return;
1579 }
1580 }
1581 else if (texImage->Data) {
1582 FREE(texImage->Data);
1583 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001584 }
1585
Brian Paul02938782000-03-22 17:38:11 +00001586 /* setup the teximage struct's fields */
1587 init_texture_image(texImage, width, height, depth,
1588 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001589
Brian Paul02938782000-03-22 17:38:11 +00001590 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001591 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001592 GLboolean retain = GL_TRUE;
1593 GLboolean success = GL_FALSE;
1594 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1595 && ctx->Driver.TexImage3D) {
1596 /* let device driver try to use raw image */
1597 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1598 type, pixels, &ctx->Unpack,
1599 texObj, texImage, &retain);
1600 }
1601 if (retain || !success) {
1602 /* make internal copy of the texture image */
1603 make_texture_image(ctx, texImage, format, type,
1604 pixels, &ctx->Unpack);
1605 if (!success && ctx->Driver.TexImage3D) {
1606 /* let device driver try to use unpacked image */
1607 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1608 GL_UNSIGNED_BYTE, texImage->Data,
1609 &_mesa_native_packing,
1610 texObj, texImage, &retain);
1611 }
1612 }
1613 if (!retain && texImage->Data) {
1614 FREE(texImage->Data);
1615 texImage->Data = NULL;
1616 }
jtgafb833d1999-08-19 00:55:39 +00001617 }
1618 else {
Brian Paul02938782000-03-22 17:38:11 +00001619 make_null_texture(texImage);
1620 if (ctx->Driver.TexImage3D) {
1621 GLboolean retain;
1622 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1623 GL_UNSIGNED_BYTE, texImage->Data,
1624 &_mesa_native_packing,
1625 texObj, texImage, &retain);
1626 }
jtgafb833d1999-08-19 00:55:39 +00001627 }
1628
Brian Paul02938782000-03-22 17:38:11 +00001629 /* state update */
1630 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001631 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001632 }
Brian Paulaea66b12000-05-24 14:04:06 +00001633 else if (target==GL_PROXY_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00001634 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001635 if (texture_error_check(ctx, target, level, internalFormat,
1636 format, type, 3, width, height, depth, border)) {
1637 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001638 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1639 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1640 sizeof(struct gl_texture_image) );
1641 }
1642 }
1643 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001644 /* if no error, update proxy texture image parameters */
1645 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1646 width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001647 }
jtgafb833d1999-08-19 00:55:39 +00001648 }
1649 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001650 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001651 return;
1652 }
1653}
1654
1655
Brian Paul663049a2000-01-31 23:10:16 +00001656void
Brian Paul43911c82000-03-21 00:49:33 +00001657_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00001658 GLsizei width, GLsizei height, GLsizei depth,
1659 GLint border, GLenum format, GLenum type,
1660 const GLvoid *pixels )
1661{
Brian Paul43911c82000-03-21 00:49:33 +00001662 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00001663 depth, border, format, type, pixels);
1664}
1665
1666
Brian Paulf7b57072000-03-20 14:37:52 +00001667/*
1668 * Fetch a texture image from the device driver.
1669 * Store the results in the given texture object at the given mipmap level.
1670 */
Brian Paul021a5252000-03-27 17:54:17 +00001671void
1672_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1673 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00001674{
1675 GLvoid *image;
1676 GLenum imgFormat, imgType;
1677 GLboolean freeImage;
1678 struct gl_texture_image *texImage;
1679 GLint destComponents, numPixels, srcBytesPerTexel;
1680
1681 if (!ctx->Driver.GetTexImage)
1682 return;
1683
Brian Paul48271792000-03-29 18:13:59 +00001684 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00001685 &imgFormat, &imgType, &freeImage);
1686 if (!image)
1687 return;
1688
1689 texImage = texObj->Image[level];
1690 ASSERT(texImage);
1691 if (!texImage)
1692 return;
1693
1694 destComponents = components_in_intformat(texImage->Format);
1695 assert(destComponents > 0);
1696 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1697 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00001698 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00001699 assert(srcBytesPerTexel > 0);
1700
1701 if (!texImage->Data) {
1702 /* Allocate memory for the texture image data */
1703 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1704 }
1705
1706 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1707 /* We got lucky! The driver's format and type match Mesa's format. */
1708 if (texImage->Data) {
1709 MEMCPY(texImage->Data, image, numPixels * destComponents);
1710 }
1711 }
1712 else {
1713 /* Convert the texture image from the driver's format to Mesa's
1714 * internal format.
1715 */
1716 const GLint width = texImage->Width;
1717 const GLint height = texImage->Height;
1718 const GLint depth = texImage->Depth;
1719 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1720 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1721 const GLenum dstType = GL_UNSIGNED_BYTE;
1722 const GLenum dstFormat = texImage->Format;
1723 const GLubyte *srcPtr = (const GLubyte *) image;
1724 GLubyte *destPtr = texImage->Data;
1725
1726 if (texImage->Format == GL_COLOR_INDEX) {
1727 /* color index texture */
1728 GLint img, row;
1729 assert(imgFormat == GL_COLOR_INDEX);
1730 for (img = 0; img < depth; img++) {
1731 for (row = 0; row < height; row++) {
1732 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001733 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001734 destPtr += destBytesPerRow;
1735 srcPtr += srcBytesPerRow;
1736 }
1737 }
1738 }
1739 else {
1740 /* color texture */
1741 GLint img, row;
1742 for (img = 0; img < depth; img++) {
1743 for (row = 0; row < height; row++) {
1744 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001745 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001746 destPtr += destBytesPerRow;
1747 srcPtr += srcBytesPerRow;
1748 }
1749 }
1750 }
1751 }
1752
1753 if (freeImage)
1754 FREE(image);
1755}
1756
jtgafb833d1999-08-19 00:55:39 +00001757
Brian Paulfbd8f211999-11-11 01:22:25 +00001758void
1759_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1760 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001761{
Brian Paulfbd8f211999-11-11 01:22:25 +00001762 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001763 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00001764 struct gl_texture_image *texImage;
1765 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00001766
1767 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1768
1769 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1770 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1771 return;
1772 }
1773
Brian Paulb7d076f2000-03-21 01:03:40 +00001774 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001775 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1776 return;
1777 }
1778
Brian Paulb7d076f2000-03-21 01:03:40 +00001779 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001780 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1781 return;
1782 }
1783
1784 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00001785 return;
jtgafb833d1999-08-19 00:55:39 +00001786
1787 switch (target) {
1788 case GL_TEXTURE_1D:
1789 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1790 break;
1791 case GL_TEXTURE_2D:
1792 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1793 break;
1794 case GL_TEXTURE_3D:
1795 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1796 break;
1797 default:
1798 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1799 return;
1800 }
1801
Brian Paulf7b57072000-03-20 14:37:52 +00001802 texImage = texObj->Image[level];
1803 if (!texImage) {
1804 /* invalid mipmap level */
1805 return;
1806 }
1807
1808 if (!texImage->Data) {
1809 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00001810 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00001811 discardImage = GL_TRUE;
1812 }
1813 else {
1814 discardImage = GL_FALSE;
1815 }
1816
1817 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00001818 GLint width = texImage->Width;
1819 GLint height = texImage->Height;
1820 GLint row;
1821
1822 for (row = 0; row < height; row++) {
1823 /* compute destination address in client memory */
Brian Paulb7d076f2000-03-21 01:03:40 +00001824 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
jtgafb833d1999-08-19 00:55:39 +00001825 width, height,
1826 format, type, 0, row, 0);
1827
1828 assert(dest);
1829 if (texImage->Format == GL_RGBA) {
1830 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
Brian Paulb7d076f2000-03-21 01:03:40 +00001831 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1832 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001833 }
1834 else {
1835 /* fetch RGBA row from texture image then pack it in client mem */
1836 GLubyte rgba[MAX_WIDTH][4];
1837 GLint i;
1838 const GLubyte *src;
1839 switch (texImage->Format) {
1840 case GL_ALPHA:
1841 src = texImage->Data + row * width * sizeof(GLubyte);
1842 for (i = 0; i < width; i++) {
1843 rgba[i][RCOMP] = 255;
1844 rgba[i][GCOMP] = 255;
1845 rgba[i][BCOMP] = 255;
1846 rgba[i][ACOMP] = src[i];
1847 }
1848 break;
1849 case GL_LUMINANCE:
1850 src = texImage->Data + row * width * sizeof(GLubyte);
1851 for (i = 0; i < width; i++) {
1852 rgba[i][RCOMP] = src[i];
1853 rgba[i][GCOMP] = src[i];
1854 rgba[i][BCOMP] = src[i];
1855 rgba[i][ACOMP] = 255;
1856 }
1857 break;
1858 case GL_LUMINANCE_ALPHA:
1859 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1860 for (i = 0; i < width; i++) {
1861 rgba[i][RCOMP] = src[i*2+0];
1862 rgba[i][GCOMP] = src[i*2+0];
1863 rgba[i][BCOMP] = src[i*2+0];
1864 rgba[i][ACOMP] = src[i*2+1];
1865 }
1866 break;
1867 case GL_INTENSITY:
1868 src = texImage->Data + row * width * sizeof(GLubyte);
1869 for (i = 0; i < width; i++) {
1870 rgba[i][RCOMP] = src[i];
1871 rgba[i][GCOMP] = src[i];
1872 rgba[i][BCOMP] = src[i];
1873 rgba[i][ACOMP] = 255;
1874 }
1875 break;
1876 case GL_RGB:
1877 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1878 for (i = 0; i < width; i++) {
1879 rgba[i][RCOMP] = src[i*3+0];
1880 rgba[i][GCOMP] = src[i*3+1];
1881 rgba[i][BCOMP] = src[i*3+2];
1882 rgba[i][ACOMP] = 255;
1883 }
1884 break;
1885 case GL_RGBA:
1886 /* this special case should have been handled above! */
1887 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1888 break;
1889 case GL_COLOR_INDEX:
1890 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1891 break;
1892 default:
1893 gl_problem( ctx, "bad format in gl_GetTexImage" );
1894 }
Brian Paulb7d076f2000-03-21 01:03:40 +00001895 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1896 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001897 }
1898 }
Brian Paulf7b57072000-03-20 14:37:52 +00001899
1900 /* if we got the teximage from the device driver we'll discard it now */
1901 if (discardImage) {
1902 FREE(texImage->Data);
1903 texImage->Data = NULL;
1904 }
jtgafb833d1999-08-19 00:55:39 +00001905 }
1906}
1907
1908
1909
Brian Paulfbd8f211999-11-11 01:22:25 +00001910void
1911_mesa_TexSubImage1D( GLenum target, GLint level,
1912 GLint xoffset, GLsizei width,
1913 GLenum format, GLenum type,
1914 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001915{
Brian Paulfbd8f211999-11-11 01:22:25 +00001916 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001917 struct gl_texture_unit *texUnit;
1918 struct gl_texture_object *texObj;
1919 struct gl_texture_image *texImage;
1920 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001921
Brian Paulc3f0a511999-11-03 17:27:05 +00001922 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1923 width, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001924 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001925 }
1926
Brian Paul02938782000-03-22 17:38:11 +00001927 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1928 texObj = texUnit->CurrentD[1];
1929 texImage = texObj->Image[level];
1930 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001931
Brian Paulc3f0a511999-11-03 17:27:05 +00001932 if (width == 0 || !pixels)
1933 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001934
Brian Paulc3f0a511999-11-03 17:27:05 +00001935
Brian Paul02938782000-03-22 17:38:11 +00001936 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1937 && ctx->Driver.TexSubImage1D) {
1938 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1939 width, format, type, pixels,
1940 &ctx->Unpack, texObj, texImage );
1941 }
1942 if (!success) {
1943 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1944
1945 const GLint texComponents = components_in_intformat(texImage->Format);
1946 const GLenum texFormat = texImage->Format;
1947 const GLint xoffsetb = xoffset + texImage->Border;
1948 GLboolean retain = GL_TRUE;
1949 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00001950 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00001951 if (!texImage->Data) {
1952 make_null_texture(texImage);
1953 }
1954 if (!texImage->Data)
1955 return; /* we're really out of luck! */
1956 }
1957
Brian Paulc3f0a511999-11-03 17:27:05 +00001958 if (texFormat == GL_COLOR_INDEX) {
1959 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00001960 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1961 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1962 1, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001963 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00001964 type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001965 }
1966 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001967 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00001968 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1969 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1970 1, format, type, 0, 0, 0);
1971 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1972 type, src, &ctx->Unpack, GL_TRUE);
1973 }
1974
1975 if (ctx->Driver.TexImage1D) {
1976 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1977 GL_UNSIGNED_BYTE, texImage->Data,
1978 &_mesa_native_packing, texObj, texImage,
1979 &retain );
1980 }
1981
1982 if (!retain && texImage->Data) {
1983 FREE(texImage->Data);
1984 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001985 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001986 }
jtgafb833d1999-08-19 00:55:39 +00001987
Brian Paul02938782000-03-22 17:38:11 +00001988 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
jtgafb833d1999-08-19 00:55:39 +00001989}
1990
1991
Brian Paulfbd8f211999-11-11 01:22:25 +00001992void
1993_mesa_TexSubImage2D( GLenum target, GLint level,
1994 GLint xoffset, GLint yoffset,
1995 GLsizei width, GLsizei height,
1996 GLenum format, GLenum type,
1997 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001998{
Brian Paulfbd8f211999-11-11 01:22:25 +00001999 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002000 struct gl_texture_unit *texUnit;
2001 struct gl_texture_object *texObj;
2002 struct gl_texture_image *texImage;
2003 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002004
Brian Paulc3f0a511999-11-03 17:27:05 +00002005 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2006 width, height, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002007 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002008 }
2009
Brian Paul02938782000-03-22 17:38:11 +00002010 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00002011 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paul02938782000-03-22 17:38:11 +00002012 texImage = texObj->Image[level];
2013 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002014
Brian Paulc3f0a511999-11-03 17:27:05 +00002015 if (width == 0 || height == 0 || !pixels)
2016 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002017
Brian Paul02938782000-03-22 17:38:11 +00002018 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
2019 && ctx->Driver.TexSubImage2D) {
2020 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2021 yoffset, width, height, format, type,
2022 pixels, &ctx->Unpack, texObj, texImage );
2023 }
2024 if (!success) {
2025 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paulc3f0a511999-11-03 17:27:05 +00002026
Brian Paul02938782000-03-22 17:38:11 +00002027 const GLint texComponents = components_in_intformat(texImage->Format);
2028 const GLenum texFormat = texImage->Format;
2029 const GLint xoffsetb = xoffset + texImage->Border;
2030 const GLint yoffsetb = yoffset + texImage->Border;
2031 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
2032 format, type);
2033 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
2034 GLboolean retain = GL_TRUE;
2035
2036 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002037 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002038 if (!texImage->Data) {
2039 make_null_texture(texImage);
2040 }
2041 if (!texImage->Data)
2042 return; /* we're really out of luck! */
2043 }
2044
Brian Paulc3f0a511999-11-03 17:27:05 +00002045 if (texFormat == GL_COLOR_INDEX) {
2046 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00002047 GLubyte *dst = texImage->Data
2048 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2049 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2050 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00002051 GLint row;
2052 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00002053 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
2054 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2055 src += srcStride;
2056 dst += dstStride;
Brian Paul64a79b21999-10-22 10:43:35 +00002057 }
2058 }
jtgafb833d1999-08-19 00:55:39 +00002059 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00002060 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00002061 GLubyte *dst = texImage->Data
2062 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2063 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2064 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00002065 GLint row;
2066 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00002067 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
2068 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2069 src += srcStride;
2070 dst += dstStride;
jtgafb833d1999-08-19 00:55:39 +00002071 }
jtgafb833d1999-08-19 00:55:39 +00002072 }
jtgafb833d1999-08-19 00:55:39 +00002073
Brian Paul02938782000-03-22 17:38:11 +00002074 if (ctx->Driver.TexImage2D) {
2075 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2076 GL_UNSIGNED_BYTE, texImage->Data,
2077 &_mesa_native_packing, texObj, texImage,
2078 &retain);
jtgafb833d1999-08-19 00:55:39 +00002079 }
Brian Paul02938782000-03-22 17:38:11 +00002080
2081 if (!retain && texImage->Data) {
2082 FREE(texImage->Data);
2083 texImage->Data = NULL;
2084 }
2085
2086#ifdef OLD_DD_TEXTURE
2087 /* XXX this will be removed in the future */
2088 if (ctx->Driver.TexSubImage) {
2089 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2090 xoffset, yoffset, width, height,
2091 texImage->IntFormat, texImage);
2092 }
2093 else if (ctx->Driver.TexImage) {
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002094 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
Brian Paul02938782000-03-22 17:38:11 +00002095 level, texImage->IntFormat, texImage );
2096 }
2097#endif
jtgafb833d1999-08-19 00:55:39 +00002098 }
2099}
2100
2101
2102
Brian Paulfbd8f211999-11-11 01:22:25 +00002103void
2104_mesa_TexSubImage3D( GLenum target, GLint level,
2105 GLint xoffset, GLint yoffset, GLint zoffset,
2106 GLsizei width, GLsizei height, GLsizei depth,
2107 GLenum format, GLenum type,
2108 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002109{
Brian Paulfbd8f211999-11-11 01:22:25 +00002110 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002111 struct gl_texture_unit *texUnit;
2112 struct gl_texture_object *texObj;
2113 struct gl_texture_image *texImage;
2114 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002115
Brian Paulc3f0a511999-11-03 17:27:05 +00002116 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2117 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002118 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002119 }
2120
Brian Paul02938782000-03-22 17:38:11 +00002121 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2122 texObj = texUnit->CurrentD[3];
2123 texImage = texObj->Image[level];
2124 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002125
Brian Paulc3f0a511999-11-03 17:27:05 +00002126 if (width == 0 || height == 0 || height == 0 || !pixels)
2127 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002128
Brian Paul02938782000-03-22 17:38:11 +00002129 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
2130 && ctx->Driver.TexSubImage3D) {
2131 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2132 yoffset, zoffset, width, height, depth, format,
2133 type, pixels, &ctx->Unpack, texObj, texImage );
2134 }
2135 if (!success) {
2136 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2137
2138 const GLint texComponents = components_in_intformat(texImage->Format);
2139 const GLenum texFormat = texImage->Format;
2140 const GLint xoffsetb = xoffset + texImage->Border;
2141 const GLint yoffsetb = yoffset + texImage->Border;
2142 const GLint zoffsetb = zoffset + texImage->Border;
2143 const GLint texWidth = texImage->Width;
2144 const GLint dstRectArea = texWidth * texImage->Height;
2145 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
2146 width, format, type);
2147 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
2148 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00002149
Brian Paulc3f0a511999-11-03 17:27:05 +00002150 if (texFormat == GL_COLOR_INDEX) {
2151 /* color index texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00002152 GLint img, row;
2153 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00002154 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2155 width, height, format, type, img, 0, 0);
2156 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2157 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00002158 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002159 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00002160 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2161 src += srcStride;
2162 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00002163 }
jtgafb833d1999-08-19 00:55:39 +00002164 }
2165 }
2166 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00002167 /* color texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00002168 GLint img, row;
2169 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00002170 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2171 width, height, format, type, img, 0, 0);
2172 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2173 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00002174 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002175 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
Brian Paul02938782000-03-22 17:38:11 +00002176 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2177 src += srcStride;
2178 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00002179 }
jtgafb833d1999-08-19 00:55:39 +00002180 }
jtgafb833d1999-08-19 00:55:39 +00002181 }
Brian Paul02938782000-03-22 17:38:11 +00002182
2183 if (ctx->Driver.TexImage3D) {
2184 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2185 GL_UNSIGNED_BYTE, texImage->Data,
2186 &_mesa_native_packing, texObj, texImage,
2187 &retain);
2188 }
2189
2190 if (!retain && texImage->Data) {
2191 FREE(texImage->Data);
2192 texImage->Data = NULL;
2193 }
jtgafb833d1999-08-19 00:55:39 +00002194 }
jtgafb833d1999-08-19 00:55:39 +00002195}
2196
2197
2198
2199/*
2200 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00002201 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00002202 * Input: ctx - the context
2203 * x, y - lower left corner
2204 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00002205 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00002206 */
Brian Paulc3f0a511999-11-03 17:27:05 +00002207static GLubyte *
2208read_color_image( GLcontext *ctx, GLint x, GLint y,
2209 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00002210{
Brian Paulc3f0a511999-11-03 17:27:05 +00002211 GLint stride, i;
2212 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00002213
Brian Paul959f8022000-03-19 01:10:11 +00002214 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00002215 if (!image)
jtgafb833d1999-08-19 00:55:39 +00002216 return NULL;
jtgafb833d1999-08-19 00:55:39 +00002217
2218 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002219 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2220 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002221
Brian Paulc3f0a511999-11-03 17:27:05 +00002222 dst = image;
2223 stride = width * 4 * sizeof(GLubyte);
2224 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00002225 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2226 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00002227 dst += stride;
2228 }
jtgafb833d1999-08-19 00:55:39 +00002229
Brian Paulcea0e8e1999-11-25 17:36:48 +00002230 /* Read from draw buffer (the default) */
2231 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2232 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002233
2234 return image;
2235}
2236
2237
2238
Brian Paulfbd8f211999-11-11 01:22:25 +00002239void
2240_mesa_CopyTexImage1D( GLenum target, GLint level,
2241 GLenum internalFormat,
2242 GLint x, GLint y,
2243 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00002244{
Brian Paulfbd8f211999-11-11 01:22:25 +00002245 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002246 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00002247
Brian Paulf7b57072000-03-20 14:37:52 +00002248 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2249 width, 1, border))
2250 return;
2251
2252 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2253 || !ctx->Driver.CopyTexImage1D
2254 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2255 internalFormat, x, y, width, border))
2256 {
Brian Paulc3f0a511999-11-03 17:27:05 +00002257 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2258 if (!image) {
2259 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2260 return;
2261 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002262 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002263 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00002264 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002265 }
jtgafb833d1999-08-19 00:55:39 +00002266}
2267
2268
2269
Brian Paulfbd8f211999-11-11 01:22:25 +00002270void
2271_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2272 GLint x, GLint y, GLsizei width, GLsizei height,
2273 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002274{
Brian Paulfbd8f211999-11-11 01:22:25 +00002275 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002276 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002277
Brian Paulf7b57072000-03-20 14:37:52 +00002278 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2279 width, height, border))
2280 return;
2281
2282 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2283 || !ctx->Driver.CopyTexImage2D
2284 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2285 internalFormat, x, y, width, height, border))
2286 {
Brian Paulc3f0a511999-11-03 17:27:05 +00002287 GLubyte *image = read_color_image( ctx, x, y, width, height );
2288 if (!image) {
2289 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2290 return;
2291 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002292 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002293 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00002294 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002295 }
jtgafb833d1999-08-19 00:55:39 +00002296}
2297
2298
2299
jtgafb833d1999-08-19 00:55:39 +00002300/*
2301 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00002302 */
Brian Paulc3f0a511999-11-03 17:27:05 +00002303static void
2304copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2305 GLint width, GLint height,
2306 GLint srcx, GLint srcy,
2307 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00002308{
Brian Paulc3f0a511999-11-03 17:27:05 +00002309 GLint i;
jtgafb833d1999-08-19 00:55:39 +00002310 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00002311 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00002312
Brian Paul91baaa31999-10-17 23:24:16 +00002313 /* dst[xyz] may be negative if we have a texture border! */
2314 dstx += dest->Border;
2315 dsty += dest->Border;
2316 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00002317 texwidth = dest->Width;
2318 texheight = dest->Height;
2319 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00002320 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00002321 format = dest->Format;
2322 components = components_in_intformat( format );
2323
2324 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002325 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2326 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002327
Brian Paulc3f0a511999-11-03 17:27:05 +00002328 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00002329 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00002330 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00002331 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00002332 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2333 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2334 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
Brian Paul02938782000-03-22 17:38:11 +00002335 &_mesa_native_packing, GL_TRUE);
Brian Paulc3f0a511999-11-03 17:27:05 +00002336 }
jtgafb833d1999-08-19 00:55:39 +00002337
Brian Paulcea0e8e1999-11-25 17:36:48 +00002338 /* Read from draw buffer (the default) */
2339 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2340 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002341}
2342
2343
2344
2345
Brian Paulfbd8f211999-11-11 01:22:25 +00002346void
2347_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2348 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002349{
Brian Paulfbd8f211999-11-11 01:22:25 +00002350 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002352
Brian Paulf7b57072000-03-20 14:37:52 +00002353 if (copytexsubimage_error_check(ctx, 1, target, level,
2354 xoffset, 0, 0, width, 1))
2355 return;
2356
2357 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2358 || !ctx->Driver.CopyTexSubImage1D
2359 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2360 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002361 struct gl_texture_unit *texUnit;
2362 struct gl_texture_image *teximage;
2363 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2364 teximage = texUnit->CurrentD[1]->Image[level];
2365 assert(teximage);
jtgafb833d1999-08-19 00:55:39 +00002366 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002367 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002368 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002369 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002370 if (ctx->Driver.TexImage) {
2371 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2372 texUnit->CurrentD[1],
2373 level, teximage->IntFormat, teximage );
2374 }
jtgafb833d1999-08-19 00:55:39 +00002375 }
2376 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002377}
2378
2379
2380
Brian Paulfbd8f211999-11-11 01:22:25 +00002381void
2382_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2383 GLint xoffset, GLint yoffset,
2384 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002385{
Brian Paulfbd8f211999-11-11 01:22:25 +00002386 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002387 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2388
Brian Paulf7b57072000-03-20 14:37:52 +00002389 if (copytexsubimage_error_check(ctx, 2, target, level,
2390 xoffset, yoffset, 0, width, height))
2391 return;
2392
2393 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2394 || !ctx->Driver.CopyTexSubImage2D
2395 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2396 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002397 struct gl_texture_unit *texUnit;
2398 struct gl_texture_image *teximage;
2399 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2400 teximage = texUnit->CurrentD[2]->Image[level];
2401 assert(teximage);
2402 if (teximage->Data) {
2403 copy_tex_sub_image(ctx, teximage, width, height,
2404 x, y, xoffset, yoffset, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002405 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002406 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002407 if (ctx->Driver.TexImage) {
2408 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2409 texUnit->CurrentD[2],
2410 level, teximage->IntFormat, teximage );
Brian Paulc3f0a511999-11-03 17:27:05 +00002411 }
2412 }
2413 }
2414}
2415
2416
2417
Brian Paulfbd8f211999-11-11 01:22:25 +00002418void
2419_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2420 GLint xoffset, GLint yoffset, GLint zoffset,
2421 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002422{
Brian Paulfbd8f211999-11-11 01:22:25 +00002423 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002424 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2425
Brian Paulf7b57072000-03-20 14:37:52 +00002426 if (copytexsubimage_error_check(ctx, 3, target, level,
2427 xoffset, yoffset, zoffset, width, height))
2428 return;
2429
Brian Paul02938782000-03-22 17:38:11 +00002430 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
Brian Paulf7b57072000-03-20 14:37:52 +00002431 || !ctx->Driver.CopyTexSubImage3D
2432 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002433 xoffset, yoffset, zoffset, x, y, width, height )) {
2434 struct gl_texture_unit *texUnit;
2435 struct gl_texture_image *teximage;
2436 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2437 teximage = texUnit->CurrentD[3]->Image[level];
2438 assert(teximage);
2439 if (teximage->Data) {
2440 copy_tex_sub_image(ctx, teximage, width, height,
Brian Paulc3f0a511999-11-03 17:27:05 +00002441 x, y, xoffset, yoffset, zoffset);
Brian Paul02938782000-03-22 17:38:11 +00002442 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002443 /* XXX this is obsolete */
Brian Paul02938782000-03-22 17:38:11 +00002444 if (ctx->Driver.TexImage) {
2445 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2446 texUnit->CurrentD[3],
2447 level, teximage->IntFormat, teximage );
Brian Paulf7b57072000-03-20 14:37:52 +00002448 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002449 }
jtgafb833d1999-08-19 00:55:39 +00002450 }
2451}
Brian Paul1207bf02000-05-23 20:10:49 +00002452
2453
2454
2455void
2456_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002457 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002458 GLint border, GLsizei imageSize,
2459 const GLvoid *data)
2460{
Brian Paulaea66b12000-05-24 14:04:06 +00002461 GET_CURRENT_CONTEXT(ctx);
2462 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2463
2464 if (target == GL_TEXTURE_1D) {
2465 struct gl_texture_unit *texUnit;
2466 struct gl_texture_object *texObj;
2467 struct gl_texture_image *texImage;
2468
2469 if (texture_error_check(ctx, target, level, internalFormat,
2470 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2471 return; /* error in texture image was detected */
2472 }
2473
2474 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2475 texObj = texUnit->CurrentD[1];
2476 texImage = texObj->Image[level];
2477
2478 if (!texImage) {
2479 texImage = _mesa_alloc_texture_image();
2480 texObj->Image[level] = texImage;
2481 if (!texImage) {
2482 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2483 return;
2484 }
2485 }
2486 else if (texImage->Data) {
2487 FREE(texImage->Data);
2488 texImage->Data = NULL;
2489 }
2490
2491 /* setup the teximage struct's fields */
2492 init_texture_image(texImage, width, 1, 1, border, internalFormat);
2493
2494 /* process the texture image */
2495 if (data) {
2496 GLboolean retain = GL_TRUE;
2497 GLboolean success = GL_FALSE;
2498 if (ctx->Driver.CompressedTexImage1D) {
2499 success = (*ctx->Driver.CompressedTexImage1D)( ctx, target, level,
2500 data, texObj, texImage, &retain);
2501 }
2502 if (retain || !success) {
2503 /* make internal copy of the texture image */
2504 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2505 width, 1, 1);
2506 texImage->Data = MALLOC(imageSize);
2507 if (texImage->Data) {
2508 MEMCPY(texImage->Data, data, imageSize);
2509 }
2510 }
2511 if (!retain && texImage->Data) {
2512 FREE(texImage->Data);
2513 texImage->Data = NULL;
2514 }
2515 }
2516 else {
2517 make_null_texture(texImage);
2518 if (ctx->Driver.CompressedTexImage1D) {
2519 GLboolean retain;
2520 (*ctx->Driver.CompressedTexImage1D)( ctx, target, level,
2521 texImage->Data, texObj, texImage, &retain);
2522 }
2523 }
2524
2525 /* state update */
2526 gl_put_texobj_on_dirty_list( ctx, texObj );
2527 ctx->NewState |= NEW_TEXTURING;
2528 }
2529 else if (target == GL_PROXY_TEXTURE_1D) {
2530 /* Proxy texture: check for errors and update proxy state */
2531 if (texture_error_check(ctx, target, level, internalFormat,
2532 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2533 /* if error, clear all proxy texture image parameters */
2534 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2535 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
2536 sizeof(struct gl_texture_image) );
2537 }
2538 }
2539 else {
2540 /* if no error, update proxy texture image parameters */
2541 init_texture_image(ctx->Texture.Proxy1D->Image[level],
2542 width, 1, 1, border, internalFormat);
2543 }
2544 }
2545 else {
2546 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2547 return;
2548 }
Brian Paul1207bf02000-05-23 20:10:49 +00002549}
2550
2551
2552void
2553_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002554 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002555 GLsizei height, GLint border, GLsizei imageSize,
2556 const GLvoid *data)
2557{
Brian Paulaea66b12000-05-24 14:04:06 +00002558 GET_CURRENT_CONTEXT(ctx);
2559 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2560
2561 if (target == GL_TEXTURE_2D) {
2562 struct gl_texture_unit *texUnit;
2563 struct gl_texture_object *texObj;
2564 struct gl_texture_image *texImage;
2565
2566 if (texture_error_check(ctx, target, level, internalFormat,
2567 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2568 return; /* error in texture image was detected */
2569 }
2570
2571 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2572 texObj = texUnit->CurrentD[2];
2573 texImage = texObj->Image[level];
2574
2575 if (!texImage) {
2576 texImage = _mesa_alloc_texture_image();
2577 texObj->Image[level] = texImage;
2578 if (!texImage) {
2579 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2580 return;
2581 }
2582 }
2583 else if (texImage->Data) {
2584 FREE(texImage->Data);
2585 texImage->Data = NULL;
2586 }
2587
2588 /* setup the teximage struct's fields */
2589 init_texture_image(texImage, width, height, 1, border, internalFormat);
2590
2591 /* process the texture image */
2592 if (data) {
2593 GLboolean retain = GL_TRUE;
2594 GLboolean success = GL_FALSE;
2595 if (ctx->Driver.CompressedTexImage2D) {
2596 success = (*ctx->Driver.CompressedTexImage2D)( ctx, target, level,
2597 data, texObj, texImage, &retain);
2598 }
2599 if (retain || !success) {
2600 /* make internal copy of the texture image */
2601 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2602 width, height, 1);
2603 texImage->Data = MALLOC(imageSize);
2604 if (texImage->Data) {
2605 MEMCPY(texImage->Data, data, imageSize);
2606 }
2607 }
2608 if (!retain && texImage->Data) {
2609 FREE(texImage->Data);
2610 texImage->Data = NULL;
2611 }
2612 }
2613 else {
2614 make_null_texture(texImage);
2615 if (ctx->Driver.CompressedTexImage2D) {
2616 GLboolean retain;
2617 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level,
2618 texImage->Data, texObj, texImage, &retain);
2619 }
2620 }
2621
2622 /* state update */
2623 gl_put_texobj_on_dirty_list( ctx, texObj );
2624 ctx->NewState |= NEW_TEXTURING;
2625 }
2626 else if (target == GL_PROXY_TEXTURE_2D) {
2627 /* Proxy texture: check for errors and update proxy state */
2628 if (texture_error_check(ctx, target, level, internalFormat,
2629 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2630 /* if error, clear all proxy texture image parameters */
2631 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2632 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
2633 sizeof(struct gl_texture_image) );
2634 }
2635 }
2636 else {
2637 /* if no error, update proxy texture image parameters */
2638 init_texture_image(ctx->Texture.Proxy2D->Image[level],
2639 width, 1, 1, border, internalFormat);
2640 }
2641 }
2642 else {
2643 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
2644 return;
2645 }
Brian Paul1207bf02000-05-23 20:10:49 +00002646}
2647
2648
2649void
2650_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002651 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002652 GLsizei height, GLsizei depth, GLint border,
2653 GLsizei imageSize, const GLvoid *data)
2654{
Brian Paulaea66b12000-05-24 14:04:06 +00002655 GET_CURRENT_CONTEXT(ctx);
2656 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
2657
2658 if (target == GL_TEXTURE_1D) {
2659 struct gl_texture_unit *texUnit;
2660 struct gl_texture_object *texObj;
2661 struct gl_texture_image *texImage;
2662
2663 if (texture_error_check(ctx, target, level, internalFormat,
2664 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2665 return; /* error in texture image was detected */
2666 }
2667
2668 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2669 texObj = texUnit->CurrentD[3];
2670 texImage = texObj->Image[level];
2671
2672 if (!texImage) {
2673 texImage = _mesa_alloc_texture_image();
2674 texObj->Image[level] = texImage;
2675 if (!texImage) {
2676 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2677 return;
2678 }
2679 }
2680 else if (texImage->Data) {
2681 FREE(texImage->Data);
2682 texImage->Data = NULL;
2683 }
2684
2685 /* setup the teximage struct's fields */
2686 init_texture_image(texImage, width, height, depth, border, internalFormat);
2687
2688 /* process the texture image */
2689 if (data) {
2690 GLboolean retain = GL_TRUE;
2691 GLboolean success = GL_FALSE;
2692 if (ctx->Driver.CompressedTexImage3D) {
2693 success = (*ctx->Driver.CompressedTexImage3D)( ctx, target, level,
2694 data, texObj, texImage, &retain);
2695 }
2696 if (retain || !success) {
2697 /* make internal copy of the texture image */
2698 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2699 width, height, depth);
2700 texImage->Data = MALLOC(imageSize);
2701 if (texImage->Data) {
2702 MEMCPY(texImage->Data, data, imageSize);
2703 }
2704 }
2705 if (!retain && texImage->Data) {
2706 FREE(texImage->Data);
2707 texImage->Data = NULL;
2708 }
2709 }
2710 else {
2711 make_null_texture(texImage);
2712 if (ctx->Driver.CompressedTexImage3D) {
2713 GLboolean retain;
2714 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level,
2715 texImage->Data, texObj, texImage, &retain);
2716 }
2717 }
2718
2719 /* state update */
2720 gl_put_texobj_on_dirty_list( ctx, texObj );
2721 ctx->NewState |= NEW_TEXTURING;
2722 }
2723 else if (target == GL_PROXY_TEXTURE_3D) {
2724 /* Proxy texture: check for errors and update proxy state */
2725 if (texture_error_check(ctx, target, level, internalFormat,
2726 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2727 /* if error, clear all proxy texture image parameters */
2728 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2729 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
2730 sizeof(struct gl_texture_image) );
2731 }
2732 }
2733 else {
2734 /* if no error, update proxy texture image parameters */
2735 init_texture_image(ctx->Texture.Proxy3D->Image[level],
2736 width, 1, 1, border, internalFormat);
2737 }
2738 }
2739 else {
2740 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
2741 return;
2742 }
Brian Paul1207bf02000-05-23 20:10:49 +00002743}
2744
2745
2746void
2747_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2748 GLsizei width, GLenum format,
2749 GLsizei imageSize, const GLvoid *data)
2750{
2751}
2752
2753
2754void
2755_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2756 GLint yoffset, GLsizei width, GLsizei height,
2757 GLenum format, GLsizei imageSize,
2758 const GLvoid *data)
2759{
2760}
2761
2762
2763void
2764_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2765 GLint yoffset, GLint zoffset, GLsizei width,
2766 GLsizei height, GLsizei depth, GLenum format,
2767 GLsizei imageSize, const GLvoid *data)
2768{
2769}
2770
2771
2772void
2773_mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img)
2774{
2775}