blob: 6617912c5f1f1739e986e06d12f9e5442edb743f [file] [log] [blame]
Brian Paul37a62112000-09-28 18:30:39 +00001/* $Id: teximage.c,v 1.51 2000/09/28 18:30:39 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paul01e54752000-09-05 15:40:34 +00005 * Version: 3.5
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paul663049a2000-01-31 23:10:16 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000032#include "context.h"
Brian Paulf93b3dd2000-08-30 18:22:28 +000033#include "convolve.h"
jtgafb833d1999-08-19 00:55:39 +000034#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000035#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000036#include "mmath.h"
37#include "span.h"
Brian Paulfa4525e2000-08-21 14:22:24 +000038#include "state.h"
jtgafb833d1999-08-19 00:55:39 +000039#include "teximage.h"
40#include "texstate.h"
41#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000042#endif
43
44
45/*
46 * NOTES:
47 *
Brian Paulc3f0a511999-11-03 17:27:05 +000048 * Mesa's native texture datatype is GLubyte. Native formats are
49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
50 * and GL_COLOR_INDEX.
51 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000052 */
53
54
Brian Paul48271792000-03-29 18:13:59 +000055#ifdef DEBUG
Brian Paule5d68a22000-03-30 18:37:51 +000056static void PrintTexture(const struct gl_texture_image *img)
Brian Paul48271792000-03-29 18:13:59 +000057{
Brian Paule5d68a22000-03-30 18:37:51 +000058 int i, j, c;
59 GLubyte *data = img->Data;
60
61 if (!data) {
62 printf("No texture data\n");
63 return;
64 }
65
66 switch (img->Format) {
67 case GL_ALPHA:
68 case GL_LUMINANCE:
69 case GL_INTENSITY:
70 case GL_COLOR_INDEX:
71 c = 1;
72 break;
73 case GL_LUMINANCE_ALPHA:
74 c = 2;
75 break;
76 case GL_RGB:
77 c = 3;
78 break;
79 case GL_RGBA:
80 c = 4;
81 break;
82 default:
83 gl_problem(NULL, "error in PrintTexture\n");
84 return;
85 }
86
87
88 for (i = 0; i < img->Height; i++) {
89 for (j = 0; j < img->Width; j++) {
Brian Paul48271792000-03-29 18:13:59 +000090 if (c==1)
91 printf("%02x ", data[0]);
92 else if (c==2)
Brian Paule5d68a22000-03-30 18:37:51 +000093 printf("%02x%02x ", data[0], data[1]);
Brian Paul48271792000-03-29 18:13:59 +000094 else if (c==3)
Brian Paule5d68a22000-03-30 18:37:51 +000095 printf("%02x%02x%02x ", data[0], data[1], data[2]);
Brian Paul48271792000-03-29 18:13:59 +000096 else if (c==4)
Brian Paule5d68a22000-03-30 18:37:51 +000097 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
Brian Paul48271792000-03-29 18:13:59 +000098 data += c;
99 }
100 printf("\n");
101 }
102}
103#endif
104
105
106
Brian Paulf7b57072000-03-20 14:37:52 +0000107/*
jtgafb833d1999-08-19 00:55:39 +0000108 * Compute log base 2 of n.
109 * If n isn't an exact power of two return -1.
110 * If n<0 return -1.
111 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000112static int
113logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +0000114{
115 GLint i = 1;
116 GLint log2 = 0;
117
118 if (n<0) {
119 return -1;
120 }
121
122 while ( n > i ) {
123 i *= 2;
124 log2++;
125 }
126 if (i != n) {
127 return -1;
128 }
129 else {
130 return log2;
131 }
132}
133
134
135
136/*
137 * Given an internal texture format enum or 1, 2, 3, 4 return the
138 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +0000139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
140 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +0000141 */
Brian Paulb132e8d2000-03-23 16:23:14 +0000142GLint
Brian Paulaea66b12000-05-24 14:04:06 +0000143_mesa_base_tex_format( GLcontext *ctx, GLint format )
jtgafb833d1999-08-19 00:55:39 +0000144{
Brian Paul289d47e2000-08-29 23:31:23 +0000145 /*
146 * Ask the driver for the base format, if it doesn't
147 * know, it will return -1;
148 */
149 if (ctx->Driver.BaseCompressedTexFormat) {
150 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
151 if (ifmt >= 0) {
152 return ifmt;
153 }
154 }
jtgafb833d1999-08-19 00:55:39 +0000155 switch (format) {
156 case GL_ALPHA:
157 case GL_ALPHA4:
158 case GL_ALPHA8:
159 case GL_ALPHA12:
160 case GL_ALPHA16:
161 return GL_ALPHA;
162 case 1:
163 case GL_LUMINANCE:
164 case GL_LUMINANCE4:
165 case GL_LUMINANCE8:
166 case GL_LUMINANCE12:
167 case GL_LUMINANCE16:
168 return GL_LUMINANCE;
169 case 2:
170 case GL_LUMINANCE_ALPHA:
171 case GL_LUMINANCE4_ALPHA4:
172 case GL_LUMINANCE6_ALPHA2:
173 case GL_LUMINANCE8_ALPHA8:
174 case GL_LUMINANCE12_ALPHA4:
175 case GL_LUMINANCE12_ALPHA12:
176 case GL_LUMINANCE16_ALPHA16:
177 return GL_LUMINANCE_ALPHA;
178 case GL_INTENSITY:
179 case GL_INTENSITY4:
180 case GL_INTENSITY8:
181 case GL_INTENSITY12:
182 case GL_INTENSITY16:
183 return GL_INTENSITY;
184 case 3:
185 case GL_RGB:
186 case GL_R3_G3_B2:
187 case GL_RGB4:
188 case GL_RGB5:
189 case GL_RGB8:
190 case GL_RGB10:
191 case GL_RGB12:
192 case GL_RGB16:
193 return GL_RGB;
194 case 4:
195 case GL_RGBA:
196 case GL_RGBA2:
197 case GL_RGBA4:
198 case GL_RGB5_A1:
199 case GL_RGBA8:
200 case GL_RGB10_A2:
201 case GL_RGBA12:
202 case GL_RGBA16:
203 return GL_RGBA;
204 case GL_COLOR_INDEX:
205 case GL_COLOR_INDEX1_EXT:
206 case GL_COLOR_INDEX2_EXT:
207 case GL_COLOR_INDEX4_EXT:
208 case GL_COLOR_INDEX8_EXT:
209 case GL_COLOR_INDEX12_EXT:
210 case GL_COLOR_INDEX16_EXT:
211 return GL_COLOR_INDEX;
212 default:
213 return -1; /* error */
214 }
215}
216
217
218
219/*
220 * Given an internal texture format enum or 1, 2, 3, 4 return the
221 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
223 * number of components for the format. Return -1 if invalid enum.
224 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000225static GLint
226components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000227{
228 switch (format) {
229 case GL_ALPHA:
230 case GL_ALPHA4:
231 case GL_ALPHA8:
232 case GL_ALPHA12:
233 case GL_ALPHA16:
234 return 1;
235 case 1:
236 case GL_LUMINANCE:
237 case GL_LUMINANCE4:
238 case GL_LUMINANCE8:
239 case GL_LUMINANCE12:
240 case GL_LUMINANCE16:
241 return 1;
242 case 2:
243 case GL_LUMINANCE_ALPHA:
244 case GL_LUMINANCE4_ALPHA4:
245 case GL_LUMINANCE6_ALPHA2:
246 case GL_LUMINANCE8_ALPHA8:
247 case GL_LUMINANCE12_ALPHA4:
248 case GL_LUMINANCE12_ALPHA12:
249 case GL_LUMINANCE16_ALPHA16:
250 return 2;
251 case GL_INTENSITY:
252 case GL_INTENSITY4:
253 case GL_INTENSITY8:
254 case GL_INTENSITY12:
255 case GL_INTENSITY16:
256 return 1;
257 case 3:
258 case GL_RGB:
259 case GL_R3_G3_B2:
260 case GL_RGB4:
261 case GL_RGB5:
262 case GL_RGB8:
263 case GL_RGB10:
264 case GL_RGB12:
265 case GL_RGB16:
266 return 3;
267 case 4:
268 case GL_RGBA:
269 case GL_RGBA2:
270 case GL_RGBA4:
271 case GL_RGB5_A1:
272 case GL_RGBA8:
273 case GL_RGB10_A2:
274 case GL_RGBA12:
275 case GL_RGBA16:
276 return 4;
277 case GL_COLOR_INDEX:
278 case GL_COLOR_INDEX1_EXT:
279 case GL_COLOR_INDEX2_EXT:
280 case GL_COLOR_INDEX4_EXT:
281 case GL_COLOR_INDEX8_EXT:
282 case GL_COLOR_INDEX12_EXT:
283 case GL_COLOR_INDEX16_EXT:
284 return 1;
285 default:
286 return -1; /* error */
287 }
288}
289
290
Brian Paulaea66b12000-05-24 14:04:06 +0000291/*
292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
293 * otherwise.
294 */
295static GLboolean
Brian Paul289d47e2000-08-29 23:31:23 +0000296is_compressed_format(GLcontext *ctx, GLenum internalFormat)
Brian Paulaea66b12000-05-24 14:04:06 +0000297{
Brian Paul289d47e2000-08-29 23:31:23 +0000298 if (ctx->Driver.IsCompressedFormat) {
299 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
300 }
301 return GL_FALSE;
Brian Paulaea66b12000-05-24 14:04:06 +0000302}
303
304
jtgafb833d1999-08-19 00:55:39 +0000305
jtgafb833d1999-08-19 00:55:39 +0000306/*
307 * Examine the texImage->Format field and set the Red, Green, Blue, etc
308 * texel component sizes to default values.
309 * These fields are set only here by core Mesa but device drivers may
310 * overwritting these fields to indicate true texel resolution.
311 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000312static void
313set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000314{
315 switch (texImage->Format) {
316 case GL_ALPHA:
317 texImage->RedBits = 0;
318 texImage->GreenBits = 0;
319 texImage->BlueBits = 0;
320 texImage->AlphaBits = 8;
321 texImage->IntensityBits = 0;
322 texImage->LuminanceBits = 0;
323 texImage->IndexBits = 0;
324 break;
325 case GL_LUMINANCE:
326 texImage->RedBits = 0;
327 texImage->GreenBits = 0;
328 texImage->BlueBits = 0;
329 texImage->AlphaBits = 0;
330 texImage->IntensityBits = 0;
331 texImage->LuminanceBits = 8;
332 texImage->IndexBits = 0;
333 break;
334 case GL_LUMINANCE_ALPHA:
335 texImage->RedBits = 0;
336 texImage->GreenBits = 0;
337 texImage->BlueBits = 0;
338 texImage->AlphaBits = 8;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 8;
341 texImage->IndexBits = 0;
342 break;
343 case GL_INTENSITY:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 0;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 8;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 0;
351 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000352 case GL_RED:
353 texImage->RedBits = 8;
354 texImage->GreenBits = 0;
355 texImage->BlueBits = 0;
356 texImage->AlphaBits = 0;
357 texImage->IntensityBits = 0;
358 texImage->LuminanceBits = 0;
359 texImage->IndexBits = 0;
360 break;
361 case GL_GREEN:
362 texImage->RedBits = 0;
363 texImage->GreenBits = 8;
364 texImage->BlueBits = 0;
365 texImage->AlphaBits = 0;
366 texImage->IntensityBits = 0;
367 texImage->LuminanceBits = 0;
368 texImage->IndexBits = 0;
369 break;
370 case GL_BLUE:
371 texImage->RedBits = 0;
372 texImage->GreenBits = 0;
373 texImage->BlueBits = 8;
374 texImage->AlphaBits = 0;
375 texImage->IntensityBits = 0;
376 texImage->LuminanceBits = 0;
377 texImage->IndexBits = 0;
378 break;
jtgafb833d1999-08-19 00:55:39 +0000379 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000380 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000381 texImage->RedBits = 8;
382 texImage->GreenBits = 8;
383 texImage->BlueBits = 8;
384 texImage->AlphaBits = 0;
385 texImage->IntensityBits = 0;
386 texImage->LuminanceBits = 0;
387 texImage->IndexBits = 0;
388 break;
389 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000390 case GL_BGRA:
391 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000392 texImage->RedBits = 8;
393 texImage->GreenBits = 8;
394 texImage->BlueBits = 8;
395 texImage->AlphaBits = 8;
396 texImage->IntensityBits = 0;
397 texImage->LuminanceBits = 0;
398 texImage->IndexBits = 0;
399 break;
400 case GL_COLOR_INDEX:
401 texImage->RedBits = 0;
402 texImage->GreenBits = 0;
403 texImage->BlueBits = 0;
404 texImage->AlphaBits = 0;
405 texImage->IntensityBits = 0;
406 texImage->LuminanceBits = 0;
407 texImage->IndexBits = 8;
408 break;
409 default:
410 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
411 }
412}
413
414
Brian Paulfc4b4432000-05-23 15:17:12 +0000415static void
416set_tex_image(struct gl_texture_object *tObj,
417 GLenum target, GLint level,
418 struct gl_texture_image *texImage)
419{
420 ASSERT(tObj);
421 ASSERT(texImage);
422 switch (target) {
423 case GL_TEXTURE_2D:
424 tObj->Image[level] = texImage;
425 return;
426 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
Brian Paul413d6a22000-05-26 14:44:59 +0000427 tObj->Image[level] = texImage;
Brian Paulfc4b4432000-05-23 15:17:12 +0000428 return;
429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
430 tObj->NegX[level] = texImage;
431 return;
432 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
433 tObj->PosY[level] = texImage;
434 return;
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
436 tObj->NegY[level] = texImage;
437 return;
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
439 tObj->PosZ[level] = texImage;
440 return;
441 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
442 tObj->NegZ[level] = texImage;
443 return;
444 default:
445 gl_problem(NULL, "bad target in set_tex_image()");
446 return;
447 }
448}
449
450
Brian Paul77ce6da2000-03-20 23:40:12 +0000451/*
452 * Return new gl_texture_image struct with all fields initialized to zero.
453 */
454struct gl_texture_image *
Brian Paul021a5252000-03-27 17:54:17 +0000455_mesa_alloc_texture_image( void )
Brian Paul77ce6da2000-03-20 23:40:12 +0000456{
457 return CALLOC_STRUCT(gl_texture_image);
458}
459
460
461
462/*
Brian Paul02938782000-03-22 17:38:11 +0000463 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000464 */
Brian Paul02938782000-03-22 17:38:11 +0000465static void
Brian Paul289d47e2000-08-29 23:31:23 +0000466init_texture_image( GLcontext *ctx,
467 struct gl_texture_image *img,
Brian Paul02938782000-03-22 17:38:11 +0000468 GLsizei width, GLsizei height, GLsizei depth,
469 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000470{
Brian Paul02938782000-03-22 17:38:11 +0000471 ASSERT(img);
472 ASSERT(!img->Data);
Brian Paul289d47e2000-08-29 23:31:23 +0000473 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000474 set_teximage_component_sizes( img );
475 img->IntFormat = (GLenum) internalFormat;
476 img->Border = border;
477 img->Width = width;
478 img->Height = height;
479 img->Depth = depth;
480 img->WidthLog2 = logbase2(width - 2 * border);
481 if (height == 1) /* 1-D texture */
482 img->HeightLog2 = 0;
483 else
484 img->HeightLog2 = logbase2(height - 2 * border);
485 if (depth == 1) /* 2-D texture */
486 img->DepthLog2 = 0;
487 else
488 img->DepthLog2 = logbase2(depth - 2 * border);
489 img->Width2 = 1 << img->WidthLog2;
490 img->Height2 = 1 << img->HeightLog2;
491 img->Depth2 = 1 << img->DepthLog2;
492 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paul289d47e2000-08-29 23:31:23 +0000493 img->IsCompressed = is_compressed_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000494}
495
496
497
498void
Brian Paul021a5252000-03-27 17:54:17 +0000499_mesa_free_texture_image( struct gl_texture_image *teximage )
Brian Paul77ce6da2000-03-20 23:40:12 +0000500{
501 if (teximage->Data) {
502 FREE( teximage->Data );
503 teximage->Data = NULL;
504 }
505 FREE( teximage );
506}
507
508
509
Brian Paulfc4b4432000-05-23 15:17:12 +0000510/*
Brian Paulaea66b12000-05-24 14:04:06 +0000511 * Return number of bytes of storage needed to store a compressed texture
Brian Paul289d47e2000-08-29 23:31:23 +0000512 * image. Only the driver knows for sure. If the driver can't help us,
513 * we must return 0.
Brian Paulaea66b12000-05-24 14:04:06 +0000514 */
515GLuint
Brian Paul289d47e2000-08-29 23:31:23 +0000516_mesa_compressed_image_size(GLcontext *ctx,
517 GLenum internalFormat,
518 GLint numDimensions,
519 GLint width,
520 GLint height,
521 GLint depth)
Brian Paulaea66b12000-05-24 14:04:06 +0000522{
Brian Paul289d47e2000-08-29 23:31:23 +0000523 if (ctx->Driver.CompressedImageSize) {
524 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
525 numDimensions,
526 width, height, depth);
527 }
528 else {
529 /* Shouldn't this be an internal error of some sort? */
530 return 0;
531 }
Brian Paulaea66b12000-05-24 14:04:06 +0000532}
533
534
535
536/*
Brian Paul35d53012000-05-23 17:14:49 +0000537 * Given a texture unit and a texture target, return the corresponding
538 * texture object.
539 */
540struct gl_texture_object *
Brian Paul01e54752000-09-05 15:40:34 +0000541_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
Brian Paul35d53012000-05-23 17:14:49 +0000542 GLenum target)
543{
544 switch (target) {
545 case GL_TEXTURE_1D:
546 return texUnit->CurrentD[1];
547 case GL_PROXY_TEXTURE_1D:
548 return ctx->Texture.Proxy1D;
549 case GL_TEXTURE_2D:
550 return texUnit->CurrentD[2];
551 case GL_PROXY_TEXTURE_2D:
552 return ctx->Texture.Proxy2D;
553 case GL_TEXTURE_3D:
554 return texUnit->CurrentD[3];
555 case GL_PROXY_TEXTURE_3D:
556 return ctx->Texture.Proxy3D;
557 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
561 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
563 return ctx->Extensions.HaveTextureCubeMap
564 ? texUnit->CurrentCubeMap : NULL;
565 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
566 return ctx->Extensions.HaveTextureCubeMap
567 ? ctx->Texture.ProxyCubeMap : NULL;
568 default:
569 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
570 return NULL;
571 }
572}
573
574
575/*
Brian Paulfc4b4432000-05-23 15:17:12 +0000576 * Return the texture image struct which corresponds to target and level
577 * for the given texture unit.
578 */
579struct gl_texture_image *
580_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
581 GLenum target, GLint level)
582{
583 ASSERT(texUnit);
584 switch (target) {
585 case GL_TEXTURE_1D:
586 return texUnit->CurrentD[1]->Image[level];
587 case GL_PROXY_TEXTURE_1D:
588 return ctx->Texture.Proxy1D->Image[level];
589 case GL_TEXTURE_2D:
590 return texUnit->CurrentD[2]->Image[level];
591 case GL_PROXY_TEXTURE_2D:
592 return ctx->Texture.Proxy2D->Image[level];
593 case GL_TEXTURE_3D:
594 return texUnit->CurrentD[3]->Image[level];
595 case GL_PROXY_TEXTURE_3D:
596 return ctx->Texture.Proxy3D->Image[level];
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
598 if (ctx->Extensions.HaveTextureCubeMap)
Brian Paul413d6a22000-05-26 14:44:59 +0000599 return texUnit->CurrentCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000600 else
601 return NULL;
602 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
603 if (ctx->Extensions.HaveTextureCubeMap)
604 return texUnit->CurrentCubeMap->NegX[level];
605 else
606 return NULL;
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
608 if (ctx->Extensions.HaveTextureCubeMap)
609 return texUnit->CurrentCubeMap->PosY[level];
610 else
611 return NULL;
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
613 if (ctx->Extensions.HaveTextureCubeMap)
614 return texUnit->CurrentCubeMap->NegY[level];
615 else
616 return NULL;
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
618 if (ctx->Extensions.HaveTextureCubeMap)
619 return texUnit->CurrentCubeMap->PosZ[level];
620 else
621 return NULL;
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
623 if (ctx->Extensions.HaveTextureCubeMap)
624 return texUnit->CurrentCubeMap->NegZ[level];
625 else
626 return NULL;
627 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
628 if (ctx->Extensions.HaveTextureCubeMap)
Brian Paul413d6a22000-05-26 14:44:59 +0000629 return ctx->Texture.ProxyCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000630 else
631 return NULL;
632 default:
633 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
634 return NULL;
635 }
636}
637
638
639
Brian Paulf93b3dd2000-08-30 18:22:28 +0000640/*
641 * Calling glTexImage and related functions when convolution is enabled
642 * with GL_REDUCE border mode causes some complications.
643 * The incoming image must be extra large so that the post-convolution
644 * image size is reduced to a power of two size (plus 2 * border).
645 * This function adjusts a texture width and height accordingly if
646 * convolution with GL_REDUCE is enabled.
647 */
648static void
649adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
650 GLsizei *width, GLsizei *height)
651{
652 if (ctx->Pixel.Convolution1DEnabled
653 && dimensions == 1
654 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
655 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
656 }
657 else if (ctx->Pixel.Convolution2DEnabled
658 && dimensions > 1
659 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
660 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
661 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
662 }
663 else if (ctx->Pixel.Separable2DEnabled
664 && dimensions > 1
665 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
666 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
667 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
668 }
669}
670
671
672
Brian Paula805bb92000-09-02 17:52:21 +0000673/*
674 * This function is used to move user image data into a texture image.
675 * We handle full texture images and subtexture images. We also take
676 * care of all image transfer operations here, including convolution.
677 * Input:
678 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
679 * dstRowStride, dstImageStride - strides in bytes
680 */
681static void
682fill_texture_image( GLcontext *ctx, GLuint dimensions,
683 GLenum texFormat, GLubyte *texAddr,
684 GLint srcWidth, GLint srcHeight, GLint srcDepth,
685 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
686 GLint dstRowStride, GLint dstImageStride,
687 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
688 const struct gl_pixelstore_attrib *srcPacking)
689{
690 GLint texComponents;
691
692 ASSERT(ctx);
693 ASSERT(dimensions >= 1 && dimensions <= 3);
694 ASSERT(texAddr);
695 ASSERT(srcWidth >= 1);
696 ASSERT(srcHeight >= 1);
697 ASSERT(srcDepth >= 1);
698 ASSERT(dstXoffset >= 0);
699 ASSERT(dstYoffset >= 0);
700 ASSERT(dstZoffset >= 0);
701 ASSERT(dstRowStride >= 0);
702 ASSERT(dstImageStride >= 0);
703 ASSERT(srcAddr);
704 ASSERT(srcPacking);
705
706 texComponents = components_in_intformat(texFormat);
707
708 /* try common 2D texture cases first */
709 if (!ctx->ImageTransferState && dimensions == 2
710 && srcType == GL_UNSIGNED_BYTE) {
711
712 if (srcFormat == texFormat) {
713 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
714 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
715 */
716 const GLubyte *src = (const GLubyte *) _mesa_image_address(
717 srcPacking, srcAddr, srcWidth, srcHeight,
718 srcFormat, srcType, 0, 0, 0);
719 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
720 srcWidth, srcFormat, srcType);
721 const GLint widthInBytes = srcWidth * texComponents;
722 GLubyte *dst = texAddr + dstYoffset * dstRowStride
723 + dstXoffset * texComponents * sizeof(GLubyte);
724 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
725 MEMCPY(dst, src, srcHeight * widthInBytes);
726 }
727 else {
728 GLint i;
729 for (i = 0; i < srcHeight; i++) {
730 MEMCPY(dst, src, widthInBytes);
731 src += srcRowStride;
732 dst += dstRowStride;
733 }
734 }
735 return; /* all done */
736 }
737 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
738 /* commonly used by Quake */
739 const GLubyte *src = (const GLubyte *) _mesa_image_address(
740 srcPacking, srcAddr, srcWidth, srcHeight,
741 srcFormat, srcType, 0, 0, 0);
742 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
743 srcWidth, srcFormat, srcType);
744 GLubyte *dst = texAddr + dstYoffset * dstRowStride
745 + dstXoffset * texComponents * sizeof(GLubyte);
746 GLint i, j;
747 for (i = 0; i < srcHeight; i++) {
748 const GLubyte *s = src;
749 GLubyte *d = dst;
750 for (j = 0; j < srcWidth; j++) {
751 *d++ = *s++; /*red*/
752 *d++ = *s++; /*green*/
753 *d++ = *s++; /*blue*/
754 s++; /*alpha*/
755 }
756 src += srcRowStride;
757 dst += dstRowStride;
758 }
759 return; /* all done */
760 }
761 }
762
763 /*
764 * General case solutions
765 */
766 if (texFormat == GL_COLOR_INDEX) {
767 /* color index texture */
768 const GLenum texType = GL_UNSIGNED_BYTE;
769 GLint img, row;
770 GLubyte *dest = texAddr + dstZoffset * dstImageStride
771 + dstYoffset * dstRowStride
772 + dstXoffset * texComponents * sizeof(GLubyte);
773 for (img = 0; img < srcDepth; img++) {
774 GLubyte *destRow = dest;
775 for (row = 0; row < srcHeight; row++) {
776 const GLvoid *src = _mesa_image_address(srcPacking,
777 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
778 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
779 srcType, src, srcPacking,
780 ctx->ImageTransferState);
781 destRow += dstRowStride;
782 }
783 dest += dstImageStride;
784 }
785 }
786 else {
787 /* regular, color texture */
788 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
789 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
790 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
791 /*
792 * Fill texture image with convolution
793 */
794 GLint img, row;
795 GLint convWidth = srcWidth, convHeight = srcHeight;
796 GLfloat *tmpImage, *convImage;
797 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
798 if (!tmpImage) {
799 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
800 return;
801 }
802 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
803 if (!convImage) {
804 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
805 FREE(tmpImage);
806 return;
807 }
808
809 for (img = 0; img < srcDepth; img++) {
810 const GLfloat *srcf;
811 GLfloat *dstf = tmpImage;
812 GLubyte *dest;
813
814 /* unpack and do transfer ops up to convolution */
815 for (row = 0; row < srcHeight; row++) {
816 const GLvoid *src = _mesa_image_address(srcPacking,
817 srcAddr, srcWidth, srcHeight,
818 srcFormat, srcType, img, row, 0);
819 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
820 srcFormat, srcType, src, srcPacking,
821 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
822 GL_TRUE);
823 dstf += srcWidth * 4;
824 }
825
826 /* convolve */
827 if (dimensions == 1) {
828 ASSERT(ctx->Pixel.Convolution1DEnabled);
829 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
830 }
831 else {
832 if (ctx->Pixel.Convolution2DEnabled) {
833 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
834 tmpImage, convImage);
835 }
836 else {
837 ASSERT(ctx->Pixel.Separable2DEnabled);
838 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
839 tmpImage, convImage);
840 }
841 }
842
843 /* packing and transfer ops after convolution */
844 srcf = convImage;
845 dest = texAddr + (dstZoffset + img) * dstImageStride
846 + dstYoffset * dstRowStride;
847 for (row = 0; row < convHeight; row++) {
848 _mesa_pack_float_rgba_span(ctx, convWidth,
849 (const GLfloat (*)[4]) srcf,
850 texFormat, GL_UNSIGNED_BYTE,
851 dest, &_mesa_native_packing,
852 ctx->ImageTransferState
853 & IMAGE_POST_CONVOLUTION_BITS);
854 srcf += convWidth * 4;
855 dest += dstRowStride;
856 }
857 }
858
859 FREE(convImage);
860 FREE(tmpImage);
861 }
862 else {
863 /*
864 * no convolution
865 */
866 GLint img, row;
867 GLubyte *dest = texAddr + dstZoffset * dstImageStride
868 + dstYoffset * dstRowStride
869 + dstXoffset * texComponents * sizeof(GLubyte);
870 for (img = 0; img < srcDepth; img++) {
871 GLubyte *destRow = dest;
872 for (row = 0; row < srcHeight; row++) {
Brian Paul01e54752000-09-05 15:40:34 +0000873 const GLvoid *srcRow = _mesa_image_address(srcPacking,
Brian Paula805bb92000-09-02 17:52:21 +0000874 srcAddr, srcWidth, srcHeight,
875 srcFormat, srcType, img, row, 0);
876 _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow,
Brian Paul01e54752000-09-05 15:40:34 +0000877 srcFormat, srcType, srcRow, srcPacking,
Brian Paula805bb92000-09-02 17:52:21 +0000878 ctx->ImageTransferState);
879 destRow += dstRowStride;
880 }
881 dest += dstImageStride;
882 }
883 }
884 }
885}
886
887
888
jtgafb833d1999-08-19 00:55:39 +0000889/* Need this to prevent an out-of-bounds memory access when using
890 * X86 optimized code.
891 */
892#ifdef USE_X86_ASM
893# define EXTRA_BYTE 1
894#else
895# define EXTRA_BYTE 0
896#endif
897
898
Brian Paulc3f0a511999-11-03 17:27:05 +0000899
jtgafb833d1999-08-19 00:55:39 +0000900/*
Brian Paul43911c82000-03-21 00:49:33 +0000901 * Called by glTexImage[123]D. Fill in a texture image with data given
902 * by the client. All pixel transfer and unpack modes are handled here.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000903 * Input: dimensions (1, 2, or 3)
904 * texImage - destination texture image (we'll malloc the memory)
905 * width, height, depth - size of source image
906 * srcFormat, srcType - source image format and type
907 * pixels - source image data
908 * srcPacking - source image packing parameters
909 *
Brian Paul43911c82000-03-21 00:49:33 +0000910 * NOTE: All texture image parameters should have already been error checked.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000911 *
912 * NOTE: the texImage dimensions and source image dimensions must be correct
913 * with respect to convolution with border mode = reduce.
jtgafb833d1999-08-19 00:55:39 +0000914 */
Brian Paul43911c82000-03-21 00:49:33 +0000915static void
Brian Paulf93b3dd2000-08-30 18:22:28 +0000916make_texture_image( GLcontext *ctx, GLuint dimensions,
Brian Paul43911c82000-03-21 00:49:33 +0000917 struct gl_texture_image *texImage,
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000918 GLint width, GLint height, GLint depth,
Brian Paulc3f0a511999-11-03 17:27:05 +0000919 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
Brian Paulf93b3dd2000-08-30 18:22:28 +0000920 const struct gl_pixelstore_attrib *srcPacking)
jtgafb833d1999-08-19 00:55:39 +0000921{
Brian Paula805bb92000-09-02 17:52:21 +0000922 const GLint internalFormat = texImage->IntFormat;
923 const GLint components = components_in_intformat(internalFormat);
924 GLint convWidth = width, convHeight = height;
jtgafb833d1999-08-19 00:55:39 +0000925
Brian Paula805bb92000-09-02 17:52:21 +0000926 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) {
927 _mesa_update_image_transfer_state(ctx);
928 }
jtgafb833d1999-08-19 00:55:39 +0000929
Brian Paula805bb92000-09-02 17:52:21 +0000930 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
931 adjust_texture_size_for_convolution(ctx, dimensions,
932 &convWidth, &convHeight);
933 }
Brian Paul43911c82000-03-21 00:49:33 +0000934
Brian Paula805bb92000-09-02 17:52:21 +0000935 texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth
936 * components + EXTRA_BYTE);
Brian Paul43911c82000-03-21 00:49:33 +0000937 if (!texImage->Data)
938 return; /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000939
Brian Paula805bb92000-09-02 17:52:21 +0000940 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
941 width, height, depth, 0, 0, 0,
942 convWidth * components * sizeof(GLubyte),
943 convWidth * convHeight * components * sizeof(GLubyte),
944 srcFormat, srcType, pixels, srcPacking);
jtgafb833d1999-08-19 00:55:39 +0000945}
946
947
948
949/*
950 * glTexImage[123]D can accept a NULL image pointer. In this case we
951 * create a texture image with unspecified image contents per the OpenGL
Brian Paul43911c82000-03-21 00:49:33 +0000952 * spec. This function creates an empty image for the given texture image.
jtgafb833d1999-08-19 00:55:39 +0000953 */
Brian Paul43911c82000-03-21 00:49:33 +0000954static void
955make_null_texture( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000956{
957 GLint components;
jtgafb833d1999-08-19 00:55:39 +0000958 GLint numPixels;
jtgafb833d1999-08-19 00:55:39 +0000959
Brian Paul43911c82000-03-21 00:49:33 +0000960 ASSERT(texImage);
961 ASSERT(!texImage->Data);
jtgafb833d1999-08-19 00:55:39 +0000962
Brian Paul43911c82000-03-21 00:49:33 +0000963 components = components_in_intformat(texImage->IntFormat);
964 numPixels = texImage->Width * texImage->Height * texImage->Depth;
jtgafb833d1999-08-19 00:55:39 +0000965
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000966 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000967
968 /*
969 * Let's see if anyone finds this. If glTexImage2D() is called with
970 * a NULL image pointer then load the texture image with something
971 * interesting instead of leaving it indeterminate.
972 */
973 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000974 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000975 " X X XXXXX XXX X ",
976 " XX XX X X X X X ",
977 " X X X X X X X ",
978 " X X XXXX XXX XXXXX ",
979 " X X X X X X ",
980 " X X X X X X X ",
981 " X X XXXXX XXX X X ",
982 " "
983 };
984
985 GLubyte *imgPtr = texImage->Data;
986 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000987 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000988 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000989 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000990 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000991 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000992 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000993 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000994 }
995 }
996 }
997 }
jtgafb833d1999-08-19 00:55:39 +0000998}
999
1000
1001
1002/*
Brian Paul9c272782000-09-05 22:04:30 +00001003 * This is called when a proxy texture test fails, we set all the
1004 * image members (except DriverData) to zero.
1005 */
1006static void
1007clear_proxy_teximage(struct gl_texture_image *img)
1008{
1009 ASSERT(img);
1010 img->Format = 0;
1011 img->IntFormat = 0;
1012 img->RedBits = 0;
1013 img->GreenBits = 0;
1014 img->BlueBits = 0;
1015 img->AlphaBits = 0;
1016 img->IntensityBits = 0;
1017 img->LuminanceBits = 0;
1018 img->IndexBits = 0;
1019 img->Border = 0;
1020 img->Width = 0;
1021 img->Height = 0;
1022 img->Depth = 0;
1023 img->Width2 = 0;
1024 img->Height2 = 0;
1025 img->Depth2 = 0;
1026 img->WidthLog2 = 0;
1027 img->HeightLog2 = 0;
1028 img->DepthLog2 = 0;
1029 img->Data = NULL;
1030 img->IsCompressed = 0;
1031 img->CompressedSize = 0;
1032}
1033
1034
1035
1036/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001037 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +00001038 * Input:
1039 * dimensions - must be 1 or 2 or 3
1040 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1041 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001042static GLboolean
1043texture_error_check( GLcontext *ctx, GLenum target,
1044 GLint level, GLint internalFormat,
1045 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +00001046 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001047 GLint width, GLint height,
1048 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001049{
1050 GLboolean isProxy;
1051 GLint iformat;
1052
1053 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +00001054 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +00001055 if (target != GL_TEXTURE_1D && !isProxy) {
1056 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1057 return GL_TRUE;
1058 }
1059 }
1060 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +00001061 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
Brian Paul413d6a22000-05-26 14:44:59 +00001062 if (target != GL_TEXTURE_2D && !isProxy &&
1063 !(ctx->Extensions.HaveTextureCubeMap &&
1064 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1065 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
jtgafb833d1999-08-19 00:55:39 +00001066 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1067 return GL_TRUE;
1068 }
1069 }
1070 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +00001071 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +00001072 if (target != GL_TEXTURE_3D && !isProxy) {
1073 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1074 return GL_TRUE;
1075 }
1076 }
1077 else {
1078 gl_problem( ctx, "bad dims in texture_error_check" );
1079 return GL_TRUE;
1080 }
1081
1082 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001083 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +00001084 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001085 char message[100];
1086 sprintf(message, "glTexImage%dD(border)", dimensions);
1087 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001088 }
1089 return GL_TRUE;
1090 }
1091
1092 /* Width */
1093 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1094 || logbase2( width - 2 * border ) < 0) {
1095 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001096 char message[100];
1097 sprintf(message, "glTexImage%dD(width)", dimensions);
1098 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001099 }
1100 return GL_TRUE;
1101 }
1102
1103 /* Height */
1104 if (dimensions >= 2) {
1105 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1106 || logbase2( height - 2 * border ) < 0) {
1107 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001108 char message[100];
1109 sprintf(message, "glTexImage%dD(height)", dimensions);
1110 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001111 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001112 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00001113 }
1114 }
1115
Brian Paulad817702000-05-30 00:27:24 +00001116 /* For cube map, width must equal height */
1117 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1118 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1119 if (width != height) {
1120 if (!isProxy) {
1121 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1122 }
1123 return GL_TRUE;
1124 }
1125 }
1126
jtgafb833d1999-08-19 00:55:39 +00001127 /* Depth */
1128 if (dimensions >= 3) {
1129 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1130 || logbase2( depth - 2 * border ) < 0) {
1131 if (!isProxy) {
1132 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1133 }
1134 return GL_TRUE;
1135 }
1136 }
1137
1138 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001139 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001140 if (!isProxy) {
1141 char message[100];
1142 sprintf(message, "glTexImage%dD(level)", dimensions);
1143 gl_error(ctx, GL_INVALID_VALUE, message);
1144 }
jtgafb833d1999-08-19 00:55:39 +00001145 return GL_TRUE;
1146 }
1147
Brian Paulaea66b12000-05-24 14:04:06 +00001148 iformat = _mesa_base_tex_format( ctx, internalFormat );
jtgafb833d1999-08-19 00:55:39 +00001149 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001150 if (!isProxy) {
1151 char message[100];
1152 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1153 gl_error(ctx, GL_INVALID_VALUE, message);
1154 }
jtgafb833d1999-08-19 00:55:39 +00001155 return GL_TRUE;
1156 }
1157
Brian Paul289d47e2000-08-29 23:31:23 +00001158 if (!is_compressed_format(ctx, internalFormat)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001159 if (!_mesa_is_legal_format_and_type( format, type )) {
1160 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1161 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1162 */
1163 if (!isProxy) {
1164 char message[100];
1165 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1166 gl_error(ctx, GL_INVALID_OPERATION, message);
1167 }
1168 return GL_TRUE;
Brian Paulc3f0a511999-11-03 17:27:05 +00001169 }
jtgafb833d1999-08-19 00:55:39 +00001170 }
1171
1172 /* if we get here, the parameters are OK */
1173 return GL_FALSE;
1174}
1175
1176
1177
1178/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001179 * Test glTexSubImage[123]D() parameters for errors.
1180 * Input:
1181 * dimensions - must be 1 or 2 or 3
1182 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1183 */
1184static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001185subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001186 GLenum target, GLint level,
1187 GLint xoffset, GLint yoffset, GLint zoffset,
1188 GLint width, GLint height, GLint depth,
1189 GLenum format, GLenum type )
1190{
1191 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1192 struct gl_texture_image *destTex;
1193
1194 if (dimensions == 1) {
1195 if (target != GL_TEXTURE_1D) {
1196 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1197 return GL_TRUE;
1198 }
1199 }
1200 else if (dimensions == 2) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001201 if (ctx->Extensions.HaveTextureCubeMap) {
1202 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1203 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1204 target != GL_TEXTURE_2D) {
1205 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1206 return GL_TRUE;
1207 }
1208 }
1209 else if (target != GL_TEXTURE_2D) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001210 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1211 return GL_TRUE;
1212 }
1213 }
1214 else if (dimensions == 3) {
1215 if (target != GL_TEXTURE_3D) {
1216 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1217 return GL_TRUE;
1218 }
1219 }
1220 else {
1221 gl_problem( ctx, "bad dims in texture_error_check" );
1222 return GL_TRUE;
1223 }
1224
1225 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1226 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1227 return GL_TRUE;
1228 }
1229
1230 if (width < 0) {
1231 char message[100];
1232 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1233 gl_error(ctx, GL_INVALID_VALUE, message);
1234 return GL_TRUE;
1235 }
1236 if (height < 0 && dimensions > 1) {
1237 char message[100];
1238 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1239 gl_error(ctx, GL_INVALID_VALUE, message);
1240 return GL_TRUE;
1241 }
1242 if (depth < 0 && dimensions > 2) {
1243 char message[100];
1244 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1245 gl_error(ctx, GL_INVALID_VALUE, message);
1246 return GL_TRUE;
1247 }
1248
1249 destTex = texUnit->CurrentD[2]->Image[level];
1250 if (!destTex) {
1251 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1252 return GL_TRUE;
1253 }
1254
1255 if (xoffset < -((GLint)destTex->Border)) {
1256 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1257 return GL_TRUE;
1258 }
1259 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1260 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1261 return GL_TRUE;
1262 }
1263 if (dimensions > 1) {
1264 if (yoffset < -((GLint)destTex->Border)) {
1265 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1266 return GL_TRUE;
1267 }
1268 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1269 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1270 return GL_TRUE;
1271 }
1272 }
1273 if (dimensions > 2) {
1274 if (zoffset < -((GLint)destTex->Border)) {
1275 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1276 return GL_TRUE;
1277 }
1278 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1279 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1280 return GL_TRUE;
1281 }
1282 }
1283
Brian Paul289d47e2000-08-29 23:31:23 +00001284 if (!is_compressed_format(ctx, destTex->IntFormat)) {
Brian Paul9540a1d2000-06-06 17:03:38 +00001285 if (!_mesa_is_legal_format_and_type(format, type)) {
1286 char message[100];
1287 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1288 gl_error(ctx, GL_INVALID_ENUM, message);
1289 return GL_TRUE;
1290 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001291 }
1292
1293 return GL_FALSE;
1294}
1295
1296
1297/*
1298 * Test glCopyTexImage[12]D() parameters for errors.
1299 * Input: dimensions - must be 1 or 2 or 3
1300 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1301 */
1302static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001303copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001304 GLenum target, GLint level, GLint internalFormat,
1305 GLint width, GLint height, GLint border )
1306{
1307 GLint iformat;
1308
Brian Paulfc4b4432000-05-23 15:17:12 +00001309 if (dimensions == 1) {
1310 if (target != GL_TEXTURE_1D) {
1311 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1312 return GL_TRUE;
1313 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001314 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001315 else if (dimensions == 2) {
1316 if (ctx->Extensions.HaveTextureCubeMap) {
1317 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1318 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1319 target != GL_TEXTURE_2D) {
1320 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1321 return GL_TRUE;
1322 }
1323 }
1324 else if (target != GL_TEXTURE_2D) {
1325 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1326 return GL_TRUE;
1327 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001328 }
1329
1330 /* Border */
1331 if (border!=0 && border!=1) {
1332 char message[100];
1333 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1334 gl_error(ctx, GL_INVALID_VALUE, message);
1335 return GL_TRUE;
1336 }
1337
1338 /* Width */
1339 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1340 || logbase2( width - 2 * border ) < 0) {
1341 char message[100];
1342 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1343 gl_error(ctx, GL_INVALID_VALUE, message);
1344 return GL_TRUE;
1345 }
1346
1347 /* Height */
1348 if (dimensions >= 2) {
1349 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1350 || logbase2( height - 2 * border ) < 0) {
1351 char message[100];
1352 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1353 gl_error(ctx, GL_INVALID_VALUE, message);
1354 return GL_TRUE;
1355 }
1356 }
1357
Brian Paulad817702000-05-30 00:27:24 +00001358 /* For cube map, width must equal height */
1359 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1360 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1361 if (width != height) {
1362 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1363 return GL_TRUE;
1364 }
1365 }
1366
Brian Paulc3f0a511999-11-03 17:27:05 +00001367 /* Level */
1368 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1369 char message[100];
1370 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1371 gl_error(ctx, GL_INVALID_VALUE, message);
1372 return GL_TRUE;
1373 }
1374
Brian Paulaea66b12000-05-24 14:04:06 +00001375 iformat = _mesa_base_tex_format( ctx, internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +00001376 if (iformat < 0) {
1377 char message[100];
1378 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1379 gl_error(ctx, GL_INVALID_VALUE, message);
1380 return GL_TRUE;
1381 }
1382
1383 /* if we get here, the parameters are OK */
1384 return GL_FALSE;
1385}
1386
1387
1388static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001389copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001390 GLenum target, GLint level,
1391 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +00001392 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001393{
1394 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1395 struct gl_texture_image *teximage;
1396
Brian Paulfc4b4432000-05-23 15:17:12 +00001397 if (dimensions == 1) {
1398 if (target != GL_TEXTURE_1D) {
1399 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1400 return GL_TRUE;
1401 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001402 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001403 else if (dimensions == 2) {
1404 if (ctx->Extensions.HaveTextureCubeMap) {
1405 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1406 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1407 target != GL_TEXTURE_2D) {
1408 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1409 return GL_TRUE;
1410 }
1411 }
1412 else if (target != GL_TEXTURE_2D) {
1413 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1414 return GL_TRUE;
1415 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001416 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001417 else if (dimensions == 3) {
1418 if (target != GL_TEXTURE_3D) {
1419 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1420 return GL_TRUE;
1421 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001422 }
1423
1424 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1425 char message[100];
1426 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1427 gl_error(ctx, GL_INVALID_VALUE, message);
1428 return GL_TRUE;
1429 }
1430
1431 if (width < 0) {
1432 char message[100];
1433 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1434 gl_error(ctx, GL_INVALID_VALUE, message);
1435 return GL_TRUE;
1436 }
1437 if (dimensions > 1 && height < 0) {
1438 char message[100];
1439 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1440 gl_error(ctx, GL_INVALID_VALUE, message);
1441 return GL_TRUE;
1442 }
1443
Brian Pauldf6a28d2000-02-21 16:34:21 +00001444 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001445 if (!teximage) {
1446 char message[100];
1447 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1448 gl_error(ctx, GL_INVALID_OPERATION, message);
1449 return GL_TRUE;
1450 }
1451
1452 if (xoffset < -((GLint)teximage->Border)) {
1453 char message[100];
1454 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1455 gl_error(ctx, GL_INVALID_VALUE, message);
1456 return GL_TRUE;
1457 }
1458 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1459 char message[100];
1460 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1461 gl_error(ctx, GL_INVALID_VALUE, message);
1462 return GL_TRUE;
1463 }
1464 if (dimensions > 1) {
1465 if (yoffset < -((GLint)teximage->Border)) {
1466 char message[100];
1467 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1468 gl_error(ctx, GL_INVALID_VALUE, message);
1469 return GL_TRUE;
1470 }
1471 /* NOTE: we're adding the border here, not subtracting! */
1472 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1473 char message[100];
1474 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1475 gl_error(ctx, GL_INVALID_VALUE, message);
1476 return GL_TRUE;
1477 }
1478 }
1479
1480 if (dimensions > 2) {
1481 if (zoffset < -((GLint)teximage->Border)) {
1482 char message[100];
1483 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1484 gl_error(ctx, GL_INVALID_VALUE, message);
1485 return GL_TRUE;
1486 }
1487 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1488 char message[100];
1489 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1490 gl_error(ctx, GL_INVALID_VALUE, message);
1491 return GL_TRUE;
1492 }
1493 }
1494
1495 /* if we get here, the parameters are OK */
1496 return GL_FALSE;
1497}
1498
1499
1500
1501
1502/*
Brian Paul289d47e2000-08-29 23:31:23 +00001503 * Turn generic compressed formats into specific compressed format.
1504 * Some of the compressed formats we don't support, so we
1505 * fall back to the uncompressed format. (See issue 15 of
1506 * the GL_ARB_texture_compression specification.)
1507 */
1508static GLint
1509get_specific_compressed_tex_format(GLcontext *ctx,
Brian Paul37a62112000-09-28 18:30:39 +00001510 GLint ifmt, GLint numDimensions,
1511 GLint *levelp,
1512 GLsizei *widthp,
1513 GLsizei *heightp,
1514 GLsizei *depthp,
1515 GLint *borderp,
1516 GLenum *formatp,
1517 GLenum *typep)
Brian Paul289d47e2000-08-29 23:31:23 +00001518{
1519 char message[100];
1520 GLint internalFormat = ifmt;
1521
1522 if (ctx->Extensions.HaveTextureCompression
1523 && ctx->Driver.SpecificCompressedTexFormat) {
1524 /*
1525 * First, ask the driver for the specific format.
Brian Paul37a62112000-09-28 18:30:39 +00001526 * We do this for all formats, since we may want to
1527 * fake one compressed format for another.
Brian Paul289d47e2000-08-29 23:31:23 +00001528 */
Brian Paul37a62112000-09-28 18:30:39 +00001529 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1530 (ctx, internalFormat, numDimensions,
1531 levelp,
1532 widthp, heightp, depthp,
1533 borderp, formatp, typep);
Brian Paul289d47e2000-08-29 23:31:23 +00001534 }
1535
1536 /*
1537 * Now, convert any generic format left to an uncompressed
1538 * specific format. If the driver does not support compression
1539 * of the format, we must drop back to the uncompressed format.
1540 * See issue 15 of the GL_ARB_texture_compression specification.
1541 */
1542 switch (internalFormat) {
1543 case GL_COMPRESSED_ALPHA_ARB:
1544 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1545 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1546 gl_error(ctx, GL_INVALID_VALUE, message);
1547 return -1;
1548 }
1549 internalFormat = GL_ALPHA;
1550 break;
1551 case GL_COMPRESSED_LUMINANCE_ARB:
1552 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1553 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1554 gl_error(ctx, GL_INVALID_VALUE, message);
1555 return -1;
1556 }
1557 internalFormat = GL_LUMINANCE;
1558 break;
1559 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1560 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1561 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1562 gl_error(ctx, GL_INVALID_VALUE, message);
1563 return -1;
1564 }
1565 internalFormat = GL_LUMINANCE_ALPHA;
1566 break;
1567 case GL_COMPRESSED_INTENSITY_ARB:
1568 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1569 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1570 gl_error(ctx, GL_INVALID_VALUE, message);
1571 return -1;
1572 }
1573 internalFormat = GL_INTENSITY;
1574 break;
1575 case GL_COMPRESSED_RGB_ARB:
1576 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1577 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1578 gl_error(ctx, GL_INVALID_VALUE, message);
1579 return -1;
1580 }
1581 internalFormat = GL_RGB;
1582 break;
1583 case GL_COMPRESSED_RGBA_ARB:
1584 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1585 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1586 gl_error(ctx, GL_INVALID_VALUE, message);
1587 return -1;
1588 }
1589 internalFormat = GL_RGBA;
1590 break;
1591 default:
Brian Paulf93b3dd2000-08-30 18:22:28 +00001592 /* silence compiler warning */
1593 ;
Brian Paul289d47e2000-08-29 23:31:23 +00001594 }
1595 return internalFormat;
1596}
1597
1598
Brian Paul289d47e2000-08-29 23:31:23 +00001599/*
jtgafb833d1999-08-19 00:55:39 +00001600 * Called from the API. Note that width includes the border.
1601 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001602void
Brian Paul43911c82000-03-21 00:49:33 +00001603_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001604 GLsizei width, GLint border, GLenum format,
1605 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001606{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001607 GLsizei postConvWidth;
Brian Paulfbd8f211999-11-11 01:22:25 +00001608 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001609 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1610
Brian Paulf93b3dd2000-08-30 18:22:28 +00001611 postConvWidth = width;
1612 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1613
jtgafb833d1999-08-19 00:55:39 +00001614 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001615 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001616 struct gl_texture_object *texObj;
1617 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001618 GLint ifmt;
1619
Brian Paul37a62112000-09-28 18:30:39 +00001620 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1621 &level,
1622 &width, 0, 0,
1623 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001624 if (ifmt < 0) {
1625 /*
1626 * The error here is that we were sent a generic compressed
1627 * format, but the extension is not supported.
1628 */
1629 return;
1630 }
1631 else {
1632 internalFormat = ifmt;
1633 }
Brian Paulf7b57072000-03-20 14:37:52 +00001634
Brian Paulaea66b12000-05-24 14:04:06 +00001635 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001636 format, type, 1, postConvWidth, 1, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001637 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001638 }
1639
Brian Paulf7b57072000-03-20 14:37:52 +00001640 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001641 texObj = texUnit->CurrentD[1];
1642 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001643
Brian Paul02938782000-03-22 17:38:11 +00001644 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001645 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001646 texObj->Image[level] = texImage;
1647 if (!texImage) {
1648 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1649 return;
1650 }
1651 }
1652 else if (texImage->Data) {
1653 FREE(texImage->Data);
1654 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001655 }
1656
Brian Paul02938782000-03-22 17:38:11 +00001657 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001658 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001659
Brian Paulfa4525e2000-08-21 14:22:24 +00001660 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1661 _mesa_update_image_transfer_state(ctx);
1662
Brian Paul02938782000-03-22 17:38:11 +00001663 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001664 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001665 GLboolean retain = GL_TRUE;
1666 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001667 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00001668 /* let device driver try to use raw image */
1669 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1670 type, pixels, &ctx->Unpack,
1671 texObj, texImage, &retain);
1672 }
1673 if (retain || !success) {
1674 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001675 make_texture_image(ctx, 1, texImage, width, 1, 1,
1676 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001677 if (!success && ctx->Driver.TexImage1D) {
1678 /* let device driver try to use unpacked image */
1679 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1680 GL_UNSIGNED_BYTE, texImage->Data,
1681 &_mesa_native_packing,
1682 texObj, texImage, &retain);
1683 }
1684 }
1685 if (!retain && texImage->Data) {
1686 FREE(texImage->Data);
1687 texImage->Data = NULL;
1688 }
jtgafb833d1999-08-19 00:55:39 +00001689 }
1690 else {
Brian Paul02938782000-03-22 17:38:11 +00001691 make_null_texture(texImage);
1692 if (ctx->Driver.TexImage1D) {
1693 GLboolean retain;
1694 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1695 GL_UNSIGNED_BYTE, texImage->Data,
1696 &_mesa_native_packing,
1697 texObj, texImage, &retain);
1698 }
jtgafb833d1999-08-19 00:55:39 +00001699 }
1700
Brian Paul02938782000-03-22 17:38:11 +00001701 /* state update */
1702 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001703 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001704 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001705 else if (target == GL_PROXY_TEXTURE_1D) {
jtgafb833d1999-08-19 00:55:39 +00001706 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001707 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1708 format, type, 1, width, 1, 1, border);
1709 if (!error && ctx->Driver.TestProxyTexImage) {
1710 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1711 internalFormat, format, type,
1712 width, 1, 1, border);
1713 }
1714 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001715 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001716 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001717 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001718 }
1719 }
1720 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001721 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001722 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001723 width, 1, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001724 }
jtgafb833d1999-08-19 00:55:39 +00001725 }
1726 else {
1727 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1728 return;
1729 }
1730}
1731
1732
Brian Paulfbd8f211999-11-11 01:22:25 +00001733void
Brian Paul43911c82000-03-21 00:49:33 +00001734_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001735 GLsizei width, GLsizei height, GLint border,
1736 GLenum format, GLenum type,
1737 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001738{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001739 GLsizei postConvWidth, postConvHeight;
Brian Paulfbd8f211999-11-11 01:22:25 +00001740 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001741 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1742
Brian Paulf93b3dd2000-08-30 18:22:28 +00001743 postConvWidth = width;
1744 postConvHeight = height;
1745 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1746
Brian Paulfc4b4432000-05-23 15:17:12 +00001747 if (target==GL_TEXTURE_2D ||
1748 (ctx->Extensions.HaveTextureCubeMap &&
1749 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1750 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001751 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001752 struct gl_texture_object *texObj;
1753 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001754 GLint ifmt;
1755
Brian Paul37a62112000-09-28 18:30:39 +00001756 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1757 &level,
1758 &width, &height, 0,
1759 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001760 if (ifmt < 0) {
1761 /*
1762 * The error here is that we were sent a generic compressed
1763 * format, but the extension is not supported.
1764 */
1765 return;
1766 }
1767 else {
1768 internalFormat = ifmt;
1769 }
Brian Paulf7b57072000-03-20 14:37:52 +00001770
Brian Paulaea66b12000-05-24 14:04:06 +00001771 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001772 format, type, 2, postConvWidth, postConvHeight,
1773 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001774 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001775 }
1776
Brian Paulf7b57072000-03-20 14:37:52 +00001777 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00001778 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paulfc4b4432000-05-23 15:17:12 +00001779 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00001780
Brian Paul02938782000-03-22 17:38:11 +00001781 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001782 texImage = _mesa_alloc_texture_image();
Brian Paulfc4b4432000-05-23 15:17:12 +00001783 set_tex_image(texObj, target, level, texImage);
1784 /*texObj->Image[level] = texImage;*/
Brian Paul02938782000-03-22 17:38:11 +00001785 if (!texImage) {
1786 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1787 return;
1788 }
1789 }
1790 else if (texImage->Data) {
1791 FREE(texImage->Data);
1792 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001793 }
1794
Brian Paul02938782000-03-22 17:38:11 +00001795 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001796 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
Brian Paul289d47e2000-08-29 23:31:23 +00001797 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001798
Brian Paulfa4525e2000-08-21 14:22:24 +00001799 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1800 _mesa_update_image_transfer_state(ctx);
1801
Brian Paul02938782000-03-22 17:38:11 +00001802 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001803 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001804 GLboolean retain = GL_TRUE;
1805 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001806 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00001807 /* let device driver try to use raw image */
1808 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1809 type, pixels, &ctx->Unpack,
1810 texObj, texImage, &retain);
1811 }
1812 if (retain || !success) {
1813 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001814 make_texture_image(ctx, 2, texImage, width, height, 1,
1815 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001816 if (!success && ctx->Driver.TexImage2D) {
1817 /* let device driver try to use unpacked image */
1818 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1819 GL_UNSIGNED_BYTE, texImage->Data,
1820 &_mesa_native_packing,
1821 texObj, texImage, &retain);
1822 }
1823 }
1824 if (!retain && texImage->Data) {
1825 FREE(texImage->Data);
1826 texImage->Data = NULL;
1827 }
jtgafb833d1999-08-19 00:55:39 +00001828 }
1829 else {
Brian Paul02938782000-03-22 17:38:11 +00001830 make_null_texture(texImage);
1831 if (ctx->Driver.TexImage2D) {
1832 GLboolean retain;
1833 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1834 GL_UNSIGNED_BYTE, texImage->Data,
1835 &_mesa_native_packing,
1836 texObj, texImage, &retain);
1837 }
jtgafb833d1999-08-19 00:55:39 +00001838 }
1839
Brian Paul02938782000-03-22 17:38:11 +00001840#define OLD_DD_TEXTURE
1841#ifdef OLD_DD_TEXTURE
1842 /* XXX this will be removed in the future */
jtgafb833d1999-08-19 00:55:39 +00001843 if (ctx->Driver.TexImage) {
Brian Paul02938782000-03-22 17:38:11 +00001844 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1845 texImage );
jtgafb833d1999-08-19 00:55:39 +00001846 }
Brian Paul02938782000-03-22 17:38:11 +00001847#endif
1848
1849 /* state update */
1850 gl_put_texobj_on_dirty_list( ctx, texObj );
1851 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001852 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001853 else if (target == GL_PROXY_TEXTURE_2D) {
jtgafb833d1999-08-19 00:55:39 +00001854 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001855 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1856 format, type, 2, width, height, 1, border);
1857 if (!error && ctx->Driver.TestProxyTexImage) {
1858 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1859 internalFormat, format, type,
1860 width, height, 1, border);
1861 }
1862 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001863 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001864 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001865 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001866 }
1867 }
1868 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001869 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001870 init_texture_image(ctx,
1871 ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001872 width, height, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001873 }
jtgafb833d1999-08-19 00:55:39 +00001874 }
1875 else {
1876 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1877 return;
1878 }
1879}
1880
1881
jtgafb833d1999-08-19 00:55:39 +00001882/*
1883 * Called by the API or display list executor.
1884 * Note that width and height include the border.
1885 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001886void
Brian Paul43911c82000-03-21 00:49:33 +00001887_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001888 GLsizei width, GLsizei height, GLsizei depth,
1889 GLint border, GLenum format, GLenum type,
1890 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001891{
Brian Paulfbd8f211999-11-11 01:22:25 +00001892 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001893 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001894
Brian Paulfbd8f211999-11-11 01:22:25 +00001895 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001896 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001897 struct gl_texture_object *texObj;
1898 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001899 GLint ifmt;
1900
Brian Paul37a62112000-09-28 18:30:39 +00001901 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1902 &level,
1903 &width, &height, &depth,
1904 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001905 if (ifmt < 0) {
1906 /*
1907 * The error here is that we were sent a generic compressed
1908 * format, but the extension is not supported.
1909 */
1910 return;
1911 }
1912 else {
1913 internalFormat = ifmt;
1914 }
1915
Brian Paulaea66b12000-05-24 14:04:06 +00001916 if (texture_error_check(ctx, target, level, internalFormat,
1917 format, type, 3, width, height, depth, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001918 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001919 }
1920
Brian Paulf7b57072000-03-20 14:37:52 +00001921 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001922 texObj = texUnit->CurrentD[3];
1923 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001924
Brian Paul02938782000-03-22 17:38:11 +00001925 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001926 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001927 texObj->Image[level] = texImage;
1928 if (!texImage) {
1929 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1930 return;
1931 }
1932 }
1933 else if (texImage->Data) {
1934 FREE(texImage->Data);
1935 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001936 }
1937
Brian Paul02938782000-03-22 17:38:11 +00001938 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00001939 init_texture_image(ctx, texImage, width, height, depth,
Brian Paul02938782000-03-22 17:38:11 +00001940 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001941
Brian Paulfa4525e2000-08-21 14:22:24 +00001942 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1943 _mesa_update_image_transfer_state(ctx);
1944
Brian Paul02938782000-03-22 17:38:11 +00001945 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001946 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001947 GLboolean retain = GL_TRUE;
1948 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001949 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00001950 /* let device driver try to use raw image */
1951 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1952 type, pixels, &ctx->Unpack,
1953 texObj, texImage, &retain);
1954 }
1955 if (retain || !success) {
1956 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001957 make_texture_image(ctx, 3, texImage, width, height, depth,
1958 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001959 if (!success && ctx->Driver.TexImage3D) {
1960 /* let device driver try to use unpacked image */
1961 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1962 GL_UNSIGNED_BYTE, texImage->Data,
1963 &_mesa_native_packing,
1964 texObj, texImage, &retain);
1965 }
1966 }
1967 if (!retain && texImage->Data) {
1968 FREE(texImage->Data);
1969 texImage->Data = NULL;
1970 }
jtgafb833d1999-08-19 00:55:39 +00001971 }
1972 else {
Brian Paul02938782000-03-22 17:38:11 +00001973 make_null_texture(texImage);
1974 if (ctx->Driver.TexImage3D) {
1975 GLboolean retain;
1976 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1977 GL_UNSIGNED_BYTE, texImage->Data,
1978 &_mesa_native_packing,
1979 texObj, texImage, &retain);
1980 }
jtgafb833d1999-08-19 00:55:39 +00001981 }
1982
Brian Paul02938782000-03-22 17:38:11 +00001983 /* state update */
1984 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001985 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001986 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001987 else if (target == GL_PROXY_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00001988 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001989 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1990 format, type, 3, width, height, depth, border);
1991 if (!error && ctx->Driver.TestProxyTexImage) {
1992 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1993 internalFormat, format, type,
1994 width, height, depth, border);
1995 }
1996 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001997 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001998 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001999 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00002000 }
2001 }
2002 else {
Brian Paulaea66b12000-05-24 14:04:06 +00002003 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002004 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002005 width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00002006 }
jtgafb833d1999-08-19 00:55:39 +00002007 }
2008 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00002009 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00002010 return;
2011 }
2012}
2013
2014
Brian Paul663049a2000-01-31 23:10:16 +00002015void
Brian Paul43911c82000-03-21 00:49:33 +00002016_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00002017 GLsizei width, GLsizei height, GLsizei depth,
2018 GLint border, GLenum format, GLenum type,
2019 const GLvoid *pixels )
2020{
Brian Paul43911c82000-03-21 00:49:33 +00002021 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00002022 depth, border, format, type, pixels);
2023}
2024
2025
Brian Paulf7b57072000-03-20 14:37:52 +00002026/*
2027 * Fetch a texture image from the device driver.
2028 * Store the results in the given texture object at the given mipmap level.
2029 */
Brian Paul021a5252000-03-27 17:54:17 +00002030void
2031_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2032 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00002033{
2034 GLvoid *image;
2035 GLenum imgFormat, imgType;
2036 GLboolean freeImage;
2037 struct gl_texture_image *texImage;
2038 GLint destComponents, numPixels, srcBytesPerTexel;
2039
2040 if (!ctx->Driver.GetTexImage)
2041 return;
2042
Brian Paul48271792000-03-29 18:13:59 +00002043 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00002044 &imgFormat, &imgType, &freeImage);
2045 if (!image)
2046 return;
2047
2048 texImage = texObj->Image[level];
2049 ASSERT(texImage);
2050 if (!texImage)
2051 return;
2052
2053 destComponents = components_in_intformat(texImage->Format);
2054 assert(destComponents > 0);
2055 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2056 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00002057 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00002058 assert(srcBytesPerTexel > 0);
2059
2060 if (!texImage->Data) {
2061 /* Allocate memory for the texture image data */
2062 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
2063 }
2064
2065 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2066 /* We got lucky! The driver's format and type match Mesa's format. */
2067 if (texImage->Data) {
2068 MEMCPY(texImage->Data, image, numPixels * destComponents);
2069 }
2070 }
2071 else {
2072 /* Convert the texture image from the driver's format to Mesa's
2073 * internal format.
2074 */
2075 const GLint width = texImage->Width;
2076 const GLint height = texImage->Height;
2077 const GLint depth = texImage->Depth;
2078 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2079 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2080 const GLenum dstType = GL_UNSIGNED_BYTE;
2081 const GLenum dstFormat = texImage->Format;
2082 const GLubyte *srcPtr = (const GLubyte *) image;
2083 GLubyte *destPtr = texImage->Data;
2084
2085 if (texImage->Format == GL_COLOR_INDEX) {
2086 /* color index texture */
2087 GLint img, row;
2088 assert(imgFormat == GL_COLOR_INDEX);
2089 for (img = 0; img < depth; img++) {
2090 for (row = 0; row < height; row++) {
2091 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002092 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002093 destPtr += destBytesPerRow;
2094 srcPtr += srcBytesPerRow;
2095 }
2096 }
2097 }
2098 else {
2099 /* color texture */
2100 GLint img, row;
2101 for (img = 0; img < depth; img++) {
2102 for (row = 0; row < height; row++) {
2103 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002104 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002105 destPtr += destBytesPerRow;
2106 srcPtr += srcBytesPerRow;
2107 }
2108 }
2109 }
2110 }
2111
2112 if (freeImage)
2113 FREE(image);
2114}
2115
jtgafb833d1999-08-19 00:55:39 +00002116
Brian Paulfbd8f211999-11-11 01:22:25 +00002117void
2118_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2119 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002120{
Brian Paulfbd8f211999-11-11 01:22:25 +00002121 GET_CURRENT_CONTEXT(ctx);
Brian Paul01e54752000-09-05 15:40:34 +00002122 const struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00002123 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00002124 struct gl_texture_image *texImage;
2125 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00002126
2127 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2128
2129 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2130 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2131 return;
2132 }
2133
Brian Paulb7d076f2000-03-21 01:03:40 +00002134 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002135 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2136 return;
2137 }
2138
Brian Paulb7d076f2000-03-21 01:03:40 +00002139 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002140 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2141 return;
2142 }
2143
2144 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00002145 return;
jtgafb833d1999-08-19 00:55:39 +00002146
Brian Paul01e54752000-09-05 15:40:34 +00002147 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2148 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2149 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulc52fc9b2000-09-05 22:11:38 +00002150 if (!texObj || !texImage ||
2151 target == GL_PROXY_TEXTURE_1D ||
2152 target == GL_PROXY_TEXTURE_2D ||
2153 target == GL_PROXY_TEXTURE_3D) {
Brian Paul01e54752000-09-05 15:40:34 +00002154 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2155 return;
jtgafb833d1999-08-19 00:55:39 +00002156 }
2157
Brian Paulf7b57072000-03-20 14:37:52 +00002158 if (!texImage) {
2159 /* invalid mipmap level */
2160 return;
2161 }
2162
2163 if (!texImage->Data) {
2164 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00002165 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00002166 discardImage = GL_TRUE;
2167 }
2168 else {
2169 discardImage = GL_FALSE;
2170 }
2171
2172 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00002173 GLint width = texImage->Width;
2174 GLint height = texImage->Height;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002175 GLint depth = texImage->Depth;
2176 GLint img, row;
jtgafb833d1999-08-19 00:55:39 +00002177
Brian Paulfa4525e2000-08-21 14:22:24 +00002178 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2179 _mesa_update_image_transfer_state(ctx);
2180
Brian Paulf96ce6a2000-09-06 15:15:43 +00002181 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2182 /* convert texture image to GL_RGBA, GL_FLOAT */
2183 GLfloat *tmpImage, *convImage;
2184 const GLint comps = components_in_intformat(texImage->Format);
jtgafb833d1999-08-19 00:55:39 +00002185
Brian Paulf96ce6a2000-09-06 15:15:43 +00002186 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2187 if (!tmpImage) {
2188 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2189 return;
jtgafb833d1999-08-19 00:55:39 +00002190 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002191 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2192 if (!convImage) {
2193 FREE(tmpImage);
2194 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2195 return;
2196 }
2197
2198 for (img = 0; img < depth; img++) {
2199 GLint convWidth, convHeight;
2200
2201 /* convert to GL_RGBA */
2202 for (row = 0; row < height; row++) {
2203 const GLubyte *src = texImage->Data
2204 + (img * height + row ) * width * comps;
2205 GLfloat *dst = tmpImage + row * width * 4;
2206 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2207 texImage->Format, GL_UNSIGNED_BYTE,
2208 src, &_mesa_native_packing,
2209 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2210 GL_FALSE);
jtgafb833d1999-08-19 00:55:39 +00002211 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002212
2213 convWidth = width;
2214 convHeight = height;
2215
2216 /* convolve */
2217 if (target == GL_TEXTURE_1D) {
2218 if (ctx->Pixel.Convolution1DEnabled) {
2219 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2220 }
2221 }
2222 else {
2223 if (ctx->Pixel.Convolution2DEnabled) {
2224 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2225 tmpImage, convImage);
2226 }
2227 else if (ctx->Pixel.Separable2DEnabled) {
2228 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2229 tmpImage, convImage);
2230 }
2231 }
2232
2233 /* pack convolved image */
2234 for (row = 0; row < convHeight; row++) {
2235 const GLfloat *src = convImage + row * convWidth * 4;
2236 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2237 convWidth, convHeight,
2238 format, type, img, row, 0);
2239 _mesa_pack_float_rgba_span(ctx, convWidth,
2240 (const GLfloat(*)[4]) src,
2241 format, type, dest, &ctx->Pack,
2242 ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2243 }
jtgafb833d1999-08-19 00:55:39 +00002244 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002245
2246 FREE(tmpImage);
2247 FREE(convImage);
jtgafb833d1999-08-19 00:55:39 +00002248 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002249 else {
2250 /* no convolution */
2251 for (img = 0; img < depth; img++) {
2252 for (row = 0; row < height; row++) {
2253 /* compute destination address in client memory */
2254 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2255 width, height, format, type, img, row, 0);
2256 assert(dest);
2257 if (texImage->Format == GL_RGBA) {
2258 /* simple case */
2259 const GLubyte *src = texImage->Data
2260 + (img * height + row ) * width * 4;
2261 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
2262 format, type, dest, &ctx->Pack,
2263 ctx->ImageTransferState );
2264 }
2265 else {
2266 /* general case: convert row to RGBA format */
2267 GLubyte rgba[MAX_WIDTH][4];
2268 GLint i;
2269 const GLubyte *src;
2270 switch (texImage->Format) {
2271 case GL_ALPHA:
2272 src = texImage->Data + row * width * sizeof(GLubyte);
2273 for (i = 0; i < width; i++) {
2274 rgba[i][RCOMP] = 255;
2275 rgba[i][GCOMP] = 255;
2276 rgba[i][BCOMP] = 255;
2277 rgba[i][ACOMP] = src[i];
2278 }
2279 break;
2280 case GL_LUMINANCE:
2281 src = texImage->Data + row * width * sizeof(GLubyte);
2282 for (i = 0; i < width; i++) {
2283 rgba[i][RCOMP] = src[i];
2284 rgba[i][GCOMP] = src[i];
2285 rgba[i][BCOMP] = src[i];
2286 rgba[i][ACOMP] = 255;
2287 }
2288 break;
2289 case GL_LUMINANCE_ALPHA:
2290 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2291 for (i = 0; i < width; i++) {
2292 rgba[i][RCOMP] = src[i*2+0];
2293 rgba[i][GCOMP] = src[i*2+0];
2294 rgba[i][BCOMP] = src[i*2+0];
2295 rgba[i][ACOMP] = src[i*2+1];
2296 }
2297 break;
2298 case GL_INTENSITY:
2299 src = texImage->Data + row * width * sizeof(GLubyte);
2300 for (i = 0; i < width; i++) {
2301 rgba[i][RCOMP] = src[i];
2302 rgba[i][GCOMP] = src[i];
2303 rgba[i][BCOMP] = src[i];
2304 rgba[i][ACOMP] = 255;
2305 }
2306 break;
2307 case GL_RGB:
2308 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2309 for (i = 0; i < width; i++) {
2310 rgba[i][RCOMP] = src[i*3+0];
2311 rgba[i][GCOMP] = src[i*3+1];
2312 rgba[i][BCOMP] = src[i*3+2];
2313 rgba[i][ACOMP] = 255;
2314 }
2315 break;
2316 case GL_COLOR_INDEX:
2317 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2318 break;
2319 case GL_RGBA:
2320 default:
2321 gl_problem( ctx, "bad format in gl_GetTexImage" );
2322 }
2323 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
2324 format, type, dest, &ctx->Pack,
2325 ctx->ImageTransferState );
2326 } /* format */
2327 } /* row */
2328 } /* img */
2329 } /* convolution */
Brian Paulf7b57072000-03-20 14:37:52 +00002330
2331 /* if we got the teximage from the device driver we'll discard it now */
2332 if (discardImage) {
2333 FREE(texImage->Data);
2334 texImage->Data = NULL;
2335 }
jtgafb833d1999-08-19 00:55:39 +00002336 }
2337}
2338
2339
2340
Brian Paulfbd8f211999-11-11 01:22:25 +00002341void
2342_mesa_TexSubImage1D( GLenum target, GLint level,
2343 GLint xoffset, GLsizei width,
2344 GLenum format, GLenum type,
2345 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002346{
Brian Paulfbd8f211999-11-11 01:22:25 +00002347 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002348 struct gl_texture_unit *texUnit;
2349 struct gl_texture_object *texObj;
2350 struct gl_texture_image *texImage;
2351 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002352 GLsizei postConvWidth;
2353
2354 postConvWidth = width;
2355 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
jtgafb833d1999-08-19 00:55:39 +00002356
Brian Paulc3f0a511999-11-03 17:27:05 +00002357 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002358 postConvWidth, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002359 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002360 }
2361
Brian Paul02938782000-03-22 17:38:11 +00002362 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2363 texObj = texUnit->CurrentD[1];
2364 texImage = texObj->Image[level];
2365 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002366
Brian Paulc3f0a511999-11-03 17:27:05 +00002367 if (width == 0 || !pixels)
2368 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002369
Brian Paulfa4525e2000-08-21 14:22:24 +00002370 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2371 _mesa_update_image_transfer_state(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002372
Brian Paulfa4525e2000-08-21 14:22:24 +00002373 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00002374 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2375 width, format, type, pixels,
2376 &ctx->Unpack, texObj, texImage );
2377 }
2378 if (!success) {
2379 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
Brian Paul02938782000-03-22 17:38:11 +00002380 GLboolean retain = GL_TRUE;
2381 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002382 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002383 if (!texImage->Data) {
2384 make_null_texture(texImage);
2385 }
2386 if (!texImage->Data)
2387 return; /* we're really out of luck! */
2388 }
2389
Brian Paula805bb92000-09-02 17:52:21 +00002390 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2391 width, 1, 1, xoffset, 0, 0, /* size and offsets */
2392 0, 0, /* strides */
2393 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002394
2395 if (ctx->Driver.TexImage1D) {
2396 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2397 GL_UNSIGNED_BYTE, texImage->Data,
2398 &_mesa_native_packing, texObj, texImage,
2399 &retain );
2400 }
2401
2402 if (!retain && texImage->Data) {
2403 FREE(texImage->Data);
2404 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00002405 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002406 }
jtgafb833d1999-08-19 00:55:39 +00002407}
2408
2409
Brian Paulfbd8f211999-11-11 01:22:25 +00002410void
2411_mesa_TexSubImage2D( GLenum target, GLint level,
2412 GLint xoffset, GLint yoffset,
2413 GLsizei width, GLsizei height,
2414 GLenum format, GLenum type,
2415 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002416{
Brian Paulfbd8f211999-11-11 01:22:25 +00002417 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002418 struct gl_texture_unit *texUnit;
2419 struct gl_texture_object *texObj;
2420 struct gl_texture_image *texImage;
2421 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002422 GLsizei postConvWidth, postConvHeight;
2423
2424 postConvWidth = width;
2425 postConvHeight = height;
2426 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
jtgafb833d1999-08-19 00:55:39 +00002427
Brian Paulc3f0a511999-11-03 17:27:05 +00002428 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002429 postConvWidth, postConvHeight, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002430 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002431 }
2432
Brian Paul02938782000-03-22 17:38:11 +00002433 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00002434 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paul02938782000-03-22 17:38:11 +00002435 texImage = texObj->Image[level];
2436 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002437
Brian Paulc3f0a511999-11-03 17:27:05 +00002438 if (width == 0 || height == 0 || !pixels)
2439 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002440
Brian Paulfa4525e2000-08-21 14:22:24 +00002441 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2442 _mesa_update_image_transfer_state(ctx);
2443
2444 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00002445 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2446 yoffset, width, height, format, type,
2447 pixels, &ctx->Unpack, texObj, texImage );
2448 }
2449 if (!success) {
2450 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002451 const GLint texComps = components_in_intformat(texImage->Format);
2452 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
Brian Paul02938782000-03-22 17:38:11 +00002453 GLboolean retain = GL_TRUE;
2454
2455 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002456 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002457 if (!texImage->Data) {
2458 make_null_texture(texImage);
2459 }
2460 if (!texImage->Data)
2461 return; /* we're really out of luck! */
2462 }
2463
Brian Paula805bb92000-09-02 17:52:21 +00002464 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2465 width, height, 1, xoffset, yoffset, 0,
2466 texRowStride, 0,
2467 format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00002468
Brian Paul02938782000-03-22 17:38:11 +00002469 if (ctx->Driver.TexImage2D) {
2470 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2471 GL_UNSIGNED_BYTE, texImage->Data,
2472 &_mesa_native_packing, texObj, texImage,
2473 &retain);
jtgafb833d1999-08-19 00:55:39 +00002474 }
Brian Paul02938782000-03-22 17:38:11 +00002475
2476 if (!retain && texImage->Data) {
2477 FREE(texImage->Data);
2478 texImage->Data = NULL;
2479 }
2480
2481#ifdef OLD_DD_TEXTURE
2482 /* XXX this will be removed in the future */
2483 if (ctx->Driver.TexSubImage) {
2484 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2485 xoffset, yoffset, width, height,
2486 texImage->IntFormat, texImage);
2487 }
2488 else if (ctx->Driver.TexImage) {
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002489 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
Brian Paul02938782000-03-22 17:38:11 +00002490 level, texImage->IntFormat, texImage );
2491 }
2492#endif
jtgafb833d1999-08-19 00:55:39 +00002493 }
2494}
2495
2496
2497
Brian Paulfbd8f211999-11-11 01:22:25 +00002498void
2499_mesa_TexSubImage3D( GLenum target, GLint level,
2500 GLint xoffset, GLint yoffset, GLint zoffset,
2501 GLsizei width, GLsizei height, GLsizei depth,
2502 GLenum format, GLenum type,
2503 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002504{
Brian Paulfbd8f211999-11-11 01:22:25 +00002505 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002506 struct gl_texture_unit *texUnit;
2507 struct gl_texture_object *texObj;
2508 struct gl_texture_image *texImage;
2509 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002510
Brian Paulc3f0a511999-11-03 17:27:05 +00002511 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2512 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002513 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002514 }
2515
Brian Paul02938782000-03-22 17:38:11 +00002516 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2517 texObj = texUnit->CurrentD[3];
2518 texImage = texObj->Image[level];
2519 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002520
Brian Paulc3f0a511999-11-03 17:27:05 +00002521 if (width == 0 || height == 0 || height == 0 || !pixels)
2522 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002523
Brian Paulfa4525e2000-08-21 14:22:24 +00002524 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2525 _mesa_update_image_transfer_state(ctx);
2526
2527 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00002528 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2529 yoffset, zoffset, width, height, depth, format,
2530 type, pixels, &ctx->Unpack, texObj, texImage );
2531 }
2532 if (!success) {
2533 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002534 const GLint texComps = components_in_intformat(texImage->Format);
2535 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2536 const GLint texImgStride = texRowStride * texImage->Height;
Brian Paul02938782000-03-22 17:38:11 +00002537 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00002538
Brian Paula805bb92000-09-02 17:52:21 +00002539 if (!texImage->Data) {
2540 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2541 if (!texImage->Data) {
2542 make_null_texture(texImage);
jtgafb833d1999-08-19 00:55:39 +00002543 }
Brian Paula805bb92000-09-02 17:52:21 +00002544 if (!texImage->Data)
2545 return; /* we're really out of luck! */
jtgafb833d1999-08-19 00:55:39 +00002546 }
Brian Paula805bb92000-09-02 17:52:21 +00002547
2548 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2549 width, height, depth, xoffset, yoffset, zoffset,
2550 texRowStride, texImgStride,
2551 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002552
2553 if (ctx->Driver.TexImage3D) {
2554 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2555 GL_UNSIGNED_BYTE, texImage->Data,
2556 &_mesa_native_packing, texObj, texImage,
2557 &retain);
2558 }
2559
2560 if (!retain && texImage->Data) {
2561 FREE(texImage->Data);
2562 texImage->Data = NULL;
2563 }
jtgafb833d1999-08-19 00:55:39 +00002564 }
jtgafb833d1999-08-19 00:55:39 +00002565}
2566
2567
2568
2569/*
2570 * Read an RGBA image from the frame buffer.
Brian Paula805bb92000-09-02 17:52:21 +00002571 * This is used by glCopyTex[Sub]Image[12]D().
jtgafb833d1999-08-19 00:55:39 +00002572 * Input: ctx - the context
2573 * x, y - lower left corner
2574 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00002575 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00002576 */
Brian Paulc3f0a511999-11-03 17:27:05 +00002577static GLubyte *
2578read_color_image( GLcontext *ctx, GLint x, GLint y,
2579 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00002580{
Brian Paulc3f0a511999-11-03 17:27:05 +00002581 GLint stride, i;
2582 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00002583
Brian Paul959f8022000-03-19 01:10:11 +00002584 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00002585 if (!image)
jtgafb833d1999-08-19 00:55:39 +00002586 return NULL;
jtgafb833d1999-08-19 00:55:39 +00002587
2588 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002589 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2590 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002591
Brian Paulc3f0a511999-11-03 17:27:05 +00002592 dst = image;
2593 stride = width * 4 * sizeof(GLubyte);
2594 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00002595 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2596 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00002597 dst += stride;
2598 }
jtgafb833d1999-08-19 00:55:39 +00002599
Brian Paulcea0e8e1999-11-25 17:36:48 +00002600 /* Read from draw buffer (the default) */
2601 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2602 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002603
2604 return image;
2605}
2606
2607
2608
Brian Paulfbd8f211999-11-11 01:22:25 +00002609void
2610_mesa_CopyTexImage1D( GLenum target, GLint level,
2611 GLenum internalFormat,
2612 GLint x, GLint y,
2613 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00002614{
Brian Paulfbd8f211999-11-11 01:22:25 +00002615 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002616 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00002617
Brian Paulf7b57072000-03-20 14:37:52 +00002618 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2619 width, 1, border))
2620 return;
2621
Brian Paulfa4525e2000-08-21 14:22:24 +00002622 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2623 _mesa_update_image_transfer_state(ctx);
2624
2625 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002626 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002627 internalFormat, x, y, width, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002628 struct gl_pixelstore_attrib unpackSave;
2629
2630 /* get image from framebuffer */
Brian Paula805bb92000-09-02 17:52:21 +00002631 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
Brian Paulc3f0a511999-11-03 17:27:05 +00002632 if (!image) {
2633 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2634 return;
2635 }
Brian Paul7dac1322000-06-15 19:57:14 +00002636
2637 /* call glTexImage1D to redefine the texture */
2638 unpackSave = ctx->Unpack;
2639 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002640 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002641 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002642 ctx->Unpack = unpackSave;
2643
Brian Paulc3f0a511999-11-03 17:27:05 +00002644 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002645 }
jtgafb833d1999-08-19 00:55:39 +00002646}
2647
2648
2649
Brian Paulfbd8f211999-11-11 01:22:25 +00002650void
2651_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2652 GLint x, GLint y, GLsizei width, GLsizei height,
2653 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002654{
Brian Paulfbd8f211999-11-11 01:22:25 +00002655 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002656 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002657
Brian Paulf7b57072000-03-20 14:37:52 +00002658 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2659 width, height, border))
2660 return;
2661
Brian Paulfa4525e2000-08-21 14:22:24 +00002662 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2663 _mesa_update_image_transfer_state(ctx);
2664
2665 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002666 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002667 internalFormat, x, y, width, height, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002668 struct gl_pixelstore_attrib unpackSave;
2669
2670 /* get image from framebuffer */
Brian Paula805bb92000-09-02 17:52:21 +00002671 GLubyte *image = read_color_image( ctx, x, y, width, height );
Brian Paulc3f0a511999-11-03 17:27:05 +00002672 if (!image) {
2673 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2674 return;
2675 }
Brian Paul7dac1322000-06-15 19:57:14 +00002676
2677 /* call glTexImage2D to redefine the texture */
2678 unpackSave = ctx->Unpack;
2679 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002680 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002681 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002682 ctx->Unpack = unpackSave;
2683
Brian Paulc3f0a511999-11-03 17:27:05 +00002684 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002685 }
jtgafb833d1999-08-19 00:55:39 +00002686}
2687
2688
2689
Brian Paulfbd8f211999-11-11 01:22:25 +00002690void
2691_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2692 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002693{
Brian Paulfbd8f211999-11-11 01:22:25 +00002694 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002695 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002696
Brian Paulf7b57072000-03-20 14:37:52 +00002697 if (copytexsubimage_error_check(ctx, 1, target, level,
2698 xoffset, 0, 0, width, 1))
2699 return;
2700
Brian Paulfa4525e2000-08-21 14:22:24 +00002701 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2702 _mesa_update_image_transfer_state(ctx);
2703
2704 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002705 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2706 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002707 struct gl_texture_unit *texUnit;
2708 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002709 struct gl_pixelstore_attrib unpackSave;
2710 GLubyte *image;
2711
Brian Paulc3f0a511999-11-03 17:27:05 +00002712 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2713 teximage = texUnit->CurrentD[1]->Image[level];
2714 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002715
2716 /* get image from frame buffer */
2717 image = read_color_image(ctx, x, y, width, 1);
2718 if (!image) {
2719 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2720 return;
jtgafb833d1999-08-19 00:55:39 +00002721 }
Brian Paul7dac1322000-06-15 19:57:14 +00002722
2723 /* now call glTexSubImage1D to do the real work */
2724 unpackSave = ctx->Unpack;
2725 ctx->Unpack = _mesa_native_packing;
2726 _mesa_TexSubImage1D(target, level, xoffset, width,
2727 GL_RGBA, GL_UNSIGNED_BYTE, image);
2728 ctx->Unpack = unpackSave;
2729
2730 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002731 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002732}
2733
2734
2735
Brian Paulfbd8f211999-11-11 01:22:25 +00002736void
2737_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2738 GLint xoffset, GLint yoffset,
2739 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002740{
Brian Paulfbd8f211999-11-11 01:22:25 +00002741 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002742 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2743
Brian Paulf7b57072000-03-20 14:37:52 +00002744 if (copytexsubimage_error_check(ctx, 2, target, level,
2745 xoffset, yoffset, 0, width, height))
2746 return;
2747
Brian Paulfa4525e2000-08-21 14:22:24 +00002748 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2749 _mesa_update_image_transfer_state(ctx);
2750
2751 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002752 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2753 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002754 struct gl_texture_unit *texUnit;
2755 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002756 struct gl_pixelstore_attrib unpackSave;
2757 GLubyte *image;
2758
Brian Paulc3f0a511999-11-03 17:27:05 +00002759 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2760 teximage = texUnit->CurrentD[2]->Image[level];
2761 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002762
2763 /* get image from frame buffer */
2764 image = read_color_image(ctx, x, y, width, height);
2765 if (!image) {
2766 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2767 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002768 }
Brian Paul7dac1322000-06-15 19:57:14 +00002769
2770 /* now call glTexSubImage2D to do the real work */
2771 unpackSave = ctx->Unpack;
2772 ctx->Unpack = _mesa_native_packing;
2773 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2774 GL_RGBA, GL_UNSIGNED_BYTE, image);
2775 ctx->Unpack = unpackSave;
2776
2777 FREE(image);
Brian Paulc3f0a511999-11-03 17:27:05 +00002778 }
2779}
2780
2781
2782
Brian Paulfbd8f211999-11-11 01:22:25 +00002783void
2784_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2785 GLint xoffset, GLint yoffset, GLint zoffset,
2786 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002787{
Brian Paulfbd8f211999-11-11 01:22:25 +00002788 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002789 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2790
Brian Paulf7b57072000-03-20 14:37:52 +00002791 if (copytexsubimage_error_check(ctx, 3, target, level,
2792 xoffset, yoffset, zoffset, width, height))
2793 return;
2794
Brian Paulfa4525e2000-08-21 14:22:24 +00002795 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2796 _mesa_update_image_transfer_state(ctx);
2797
2798 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
Brian Paulf7b57072000-03-20 14:37:52 +00002799 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002800 xoffset, yoffset, zoffset, x, y, width, height )) {
2801 struct gl_texture_unit *texUnit;
2802 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002803 struct gl_pixelstore_attrib unpackSave;
2804 GLubyte *image;
2805
Brian Paul02938782000-03-22 17:38:11 +00002806 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2807 teximage = texUnit->CurrentD[3]->Image[level];
2808 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002809
2810 /* get image from frame buffer */
2811 image = read_color_image(ctx, x, y, width, height);
2812 if (!image) {
2813 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2814 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002815 }
Brian Paul7dac1322000-06-15 19:57:14 +00002816
2817 /* now call glTexSubImage2D to do the real work */
2818 unpackSave = ctx->Unpack;
2819 ctx->Unpack = _mesa_native_packing;
2820 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2821 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2822 ctx->Unpack = unpackSave;
2823
2824 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002825 }
2826}
Brian Paul1207bf02000-05-23 20:10:49 +00002827
2828
2829
2830void
2831_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002832 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002833 GLint border, GLsizei imageSize,
2834 const GLvoid *data)
2835{
Brian Paulaea66b12000-05-24 14:04:06 +00002836 GET_CURRENT_CONTEXT(ctx);
2837 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2838
Brian Paul289d47e2000-08-29 23:31:23 +00002839 switch (internalFormat) {
2840 case GL_COMPRESSED_ALPHA_ARB:
2841 case GL_COMPRESSED_LUMINANCE_ARB:
2842 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2843 case GL_COMPRESSED_INTENSITY_ARB:
2844 case GL_COMPRESSED_RGB_ARB:
2845 case GL_COMPRESSED_RGBA_ARB:
2846 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2847 return;
2848 default:
2849 /* silence compiler warning */
2850 ;
2851 }
2852
Brian Paulaea66b12000-05-24 14:04:06 +00002853 if (target == GL_TEXTURE_1D) {
2854 struct gl_texture_unit *texUnit;
2855 struct gl_texture_object *texObj;
2856 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002857 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002858
2859 if (texture_error_check(ctx, target, level, internalFormat,
2860 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2861 return; /* error in texture image was detected */
2862 }
2863
2864 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2865 texObj = texUnit->CurrentD[1];
2866 texImage = texObj->Image[level];
2867
2868 if (!texImage) {
2869 texImage = _mesa_alloc_texture_image();
2870 texObj->Image[level] = texImage;
2871 if (!texImage) {
2872 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2873 return;
2874 }
2875 }
2876 else if (texImage->Data) {
2877 FREE(texImage->Data);
2878 texImage->Data = NULL;
2879 }
2880
2881 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00002882 init_texture_image(ctx, texImage, width, 1, 1,
2883 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00002884
2885 /* process the texture image */
2886 if (data) {
2887 GLboolean retain = GL_TRUE;
2888 GLboolean success = GL_FALSE;
2889 if (ctx->Driver.CompressedTexImage1D) {
Brian Paul289d47e2000-08-29 23:31:23 +00002890 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2891 imageSize, data, texObj, texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002892 }
2893 if (retain || !success) {
2894 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00002895 computedImageSize = _mesa_compressed_image_size(ctx,
2896 internalFormat,
2897 1, /* num dims */
2898 width,
2899 1, /* height */
2900 1); /* depth */
2901 if (computedImageSize != imageSize) {
2902 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2903 return;
2904 }
2905 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002906 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00002907 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002908 }
2909 }
2910 if (!retain && texImage->Data) {
2911 FREE(texImage->Data);
2912 texImage->Data = NULL;
2913 }
2914 }
2915 else {
2916 make_null_texture(texImage);
2917 if (ctx->Driver.CompressedTexImage1D) {
2918 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00002919 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2920 texImage->Data, texObj,
2921 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002922 }
2923 }
2924
2925 /* state update */
2926 gl_put_texobj_on_dirty_list( ctx, texObj );
2927 ctx->NewState |= NEW_TEXTURING;
2928 }
2929 else if (target == GL_PROXY_TEXTURE_1D) {
2930 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00002931 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2932 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2933 if (!error && ctx->Driver.TestProxyTexImage) {
2934 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2935 internalFormat, GL_NONE, GL_NONE,
2936 width, 1, 1, border);
2937 }
2938 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00002939 /* if error, clear all proxy texture image parameters */
2940 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00002941 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00002942 }
2943 }
2944 else {
2945 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002946 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002947 width, 1, 1, border, internalFormat);
2948 }
2949 }
2950 else {
2951 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2952 return;
2953 }
Brian Paul1207bf02000-05-23 20:10:49 +00002954}
2955
2956
2957void
2958_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002959 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002960 GLsizei height, GLint border, GLsizei imageSize,
2961 const GLvoid *data)
2962{
Brian Paulaea66b12000-05-24 14:04:06 +00002963 GET_CURRENT_CONTEXT(ctx);
2964 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2965
Brian Paul289d47e2000-08-29 23:31:23 +00002966 switch (internalFormat) {
2967 case GL_COMPRESSED_ALPHA_ARB:
2968 case GL_COMPRESSED_LUMINANCE_ARB:
2969 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2970 case GL_COMPRESSED_INTENSITY_ARB:
2971 case GL_COMPRESSED_RGB_ARB:
2972 case GL_COMPRESSED_RGBA_ARB:
2973 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2974 return;
2975 default:
2976 /* silence compiler warning */
2977 ;
2978 }
2979
Brian Paul9540a1d2000-06-06 17:03:38 +00002980 if (target==GL_TEXTURE_2D ||
2981 (ctx->Extensions.HaveTextureCubeMap &&
2982 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2983 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulaea66b12000-05-24 14:04:06 +00002984 struct gl_texture_unit *texUnit;
2985 struct gl_texture_object *texObj;
2986 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002987 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002988
2989 if (texture_error_check(ctx, target, level, internalFormat,
2990 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2991 return; /* error in texture image was detected */
2992 }
2993
2994 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2995 texObj = texUnit->CurrentD[2];
2996 texImage = texObj->Image[level];
2997
2998 if (!texImage) {
2999 texImage = _mesa_alloc_texture_image();
3000 texObj->Image[level] = texImage;
3001 if (!texImage) {
3002 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3003 return;
3004 }
3005 }
3006 else if (texImage->Data) {
3007 FREE(texImage->Data);
3008 texImage->Data = NULL;
3009 }
3010
3011 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003012 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003013
3014 /* process the texture image */
3015 if (data) {
3016 GLboolean retain = GL_TRUE;
3017 GLboolean success = GL_FALSE;
3018 if (ctx->Driver.CompressedTexImage2D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003019 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3020 target,
3021 level,
3022 imageSize,
3023 data,
3024 texObj,
3025 texImage,
3026 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003027 }
3028 if (retain || !success) {
3029 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003030 computedImageSize = _mesa_compressed_image_size(ctx,
3031 internalFormat,
3032 2, /* num dims */
3033 width,
3034 height,
3035 1); /* depth */
3036 if (computedImageSize != imageSize) {
3037 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3038 return;
3039 }
3040 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003041 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003042 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003043 }
3044 }
3045 if (!retain && texImage->Data) {
3046 FREE(texImage->Data);
3047 texImage->Data = NULL;
3048 }
3049 }
3050 else {
3051 make_null_texture(texImage);
3052 if (ctx->Driver.CompressedTexImage2D) {
3053 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003054 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3055 texImage->Data, texObj,
3056 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003057 }
3058 }
3059
3060 /* state update */
3061 gl_put_texobj_on_dirty_list( ctx, texObj );
3062 ctx->NewState |= NEW_TEXTURING;
3063 }
3064 else if (target == GL_PROXY_TEXTURE_2D) {
3065 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003066 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3067 GL_NONE, GL_NONE, 2, width, height, 1, border);
3068 if (!error && ctx->Driver.TestProxyTexImage) {
3069 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3070 internalFormat, GL_NONE, GL_NONE,
3071 width, height, 1, border);
3072 }
3073 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003074 /* if error, clear all proxy texture image parameters */
3075 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003076 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003077 }
3078 }
3079 else {
3080 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003081 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003082 width, 1, 1, border, internalFormat);
3083 }
3084 }
3085 else {
3086 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3087 return;
3088 }
Brian Paul1207bf02000-05-23 20:10:49 +00003089}
3090
3091
3092void
3093_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00003094 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00003095 GLsizei height, GLsizei depth, GLint border,
3096 GLsizei imageSize, const GLvoid *data)
3097{
Brian Paulaea66b12000-05-24 14:04:06 +00003098 GET_CURRENT_CONTEXT(ctx);
3099 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3100
Brian Paul289d47e2000-08-29 23:31:23 +00003101 switch (internalFormat) {
3102 case GL_COMPRESSED_ALPHA_ARB:
3103 case GL_COMPRESSED_LUMINANCE_ARB:
3104 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3105 case GL_COMPRESSED_INTENSITY_ARB:
3106 case GL_COMPRESSED_RGB_ARB:
3107 case GL_COMPRESSED_RGBA_ARB:
3108 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3109 return;
3110 default:
3111 /* silence compiler warning */
3112 ;
3113 }
3114
Brian Paul9540a1d2000-06-06 17:03:38 +00003115 if (target == GL_TEXTURE_3D) {
Brian Paulaea66b12000-05-24 14:04:06 +00003116 struct gl_texture_unit *texUnit;
3117 struct gl_texture_object *texObj;
3118 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00003119 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00003120
3121 if (texture_error_check(ctx, target, level, internalFormat,
3122 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3123 return; /* error in texture image was detected */
3124 }
3125
3126 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3127 texObj = texUnit->CurrentD[3];
3128 texImage = texObj->Image[level];
3129
3130 if (!texImage) {
3131 texImage = _mesa_alloc_texture_image();
3132 texObj->Image[level] = texImage;
3133 if (!texImage) {
3134 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3135 return;
3136 }
3137 }
3138 else if (texImage->Data) {
3139 FREE(texImage->Data);
3140 texImage->Data = NULL;
3141 }
3142
3143 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003144 init_texture_image(ctx, texImage, width, height, depth,
3145 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003146
3147 /* process the texture image */
3148 if (data) {
3149 GLboolean retain = GL_TRUE;
3150 GLboolean success = GL_FALSE;
3151 if (ctx->Driver.CompressedTexImage3D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003152 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3153 imageSize, data,
3154 texObj, texImage,
3155 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003156 }
3157 if (retain || !success) {
3158 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003159 computedImageSize = _mesa_compressed_image_size(ctx,
3160 internalFormat,
3161 3, /* num dims */
3162 width,
3163 height,
3164 depth);
3165 if (computedImageSize != imageSize) {
3166 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3167 return;
3168 }
3169 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003170 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003171 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003172 }
3173 }
3174 if (!retain && texImage->Data) {
3175 FREE(texImage->Data);
3176 texImage->Data = NULL;
3177 }
3178 }
3179 else {
3180 make_null_texture(texImage);
3181 if (ctx->Driver.CompressedTexImage3D) {
3182 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003183 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3184 texImage->Data, texObj,
3185 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003186 }
3187 }
3188
3189 /* state update */
3190 gl_put_texobj_on_dirty_list( ctx, texObj );
3191 ctx->NewState |= NEW_TEXTURING;
3192 }
3193 else if (target == GL_PROXY_TEXTURE_3D) {
3194 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003195 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3196 GL_NONE, GL_NONE, 1, width, height, depth, border);
3197 if (!error && ctx->Driver.TestProxyTexImage) {
3198 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3199 internalFormat, GL_NONE, GL_NONE,
3200 width, height, depth, border);
3201 }
3202 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003203 /* if error, clear all proxy texture image parameters */
3204 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003205 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003206 }
3207 }
3208 else {
3209 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003210 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003211 width, 1, 1, border, internalFormat);
3212 }
3213 }
3214 else {
3215 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3216 return;
3217 }
Brian Paul1207bf02000-05-23 20:10:49 +00003218}
3219
3220
3221void
3222_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3223 GLsizei width, GLenum format,
3224 GLsizei imageSize, const GLvoid *data)
3225{
Brian Paul9540a1d2000-06-06 17:03:38 +00003226 GET_CURRENT_CONTEXT(ctx);
3227 struct gl_texture_unit *texUnit;
3228 struct gl_texture_object *texObj;
3229 struct gl_texture_image *texImage;
3230 GLboolean success = GL_FALSE;
3231
3232 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3233 width, 1, 1, format, GL_NONE)) {
3234 return; /* error was detected */
3235 }
3236
3237 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3238 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3239 texImage = texObj->Image[level];
3240 assert(texImage);
3241
3242 if (width == 0 || !data)
3243 return; /* no-op, not an error */
3244
3245 if (ctx->Driver.CompressedTexSubImage1D) {
3246 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3247 xoffset, width, format, imageSize, data, texObj, texImage);
3248 }
3249 if (!success) {
3250 /* XXX what else can we do? */
3251 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3252 return;
3253 }
Brian Paul1207bf02000-05-23 20:10:49 +00003254}
3255
3256
3257void
3258_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3259 GLint yoffset, GLsizei width, GLsizei height,
3260 GLenum format, GLsizei imageSize,
3261 const GLvoid *data)
3262{
Brian Paul9540a1d2000-06-06 17:03:38 +00003263 GET_CURRENT_CONTEXT(ctx);
3264 struct gl_texture_unit *texUnit;
3265 struct gl_texture_object *texObj;
3266 struct gl_texture_image *texImage;
3267 GLboolean success = GL_FALSE;
3268
3269 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3270 width, height, 1, format, GL_NONE)) {
3271 return; /* error was detected */
3272 }
3273
3274 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3275 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3276 texImage = texObj->Image[level];
3277 assert(texImage);
3278
3279 if (width == 0 || height == 0 || !data)
3280 return; /* no-op, not an error */
3281
3282 if (ctx->Driver.CompressedTexSubImage2D) {
3283 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3284 xoffset, yoffset, width, height, format,
3285 imageSize, data, texObj, texImage);
3286 }
3287 if (!success) {
3288 /* XXX what else can we do? */
3289 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3290 return;
3291 }
Brian Paul1207bf02000-05-23 20:10:49 +00003292}
3293
3294
3295void
3296_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3297 GLint yoffset, GLint zoffset, GLsizei width,
3298 GLsizei height, GLsizei depth, GLenum format,
3299 GLsizei imageSize, const GLvoid *data)
3300{
Brian Paul9540a1d2000-06-06 17:03:38 +00003301 GET_CURRENT_CONTEXT(ctx);
3302 struct gl_texture_unit *texUnit;
3303 struct gl_texture_object *texObj;
3304 struct gl_texture_image *texImage;
3305 GLboolean success = GL_FALSE;
3306
3307 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3308 width, height, depth, format, GL_NONE)) {
3309 return; /* error was detected */
3310 }
3311
3312 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3313 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3314 texImage = texObj->Image[level];
3315 assert(texImage);
3316
3317 if (width == 0 || height == 0 || depth == 0 || !data)
3318 return; /* no-op, not an error */
3319
3320 if (ctx->Driver.CompressedTexSubImage3D) {
3321 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3322 xoffset, yoffset, zoffset, width, height, depth,
3323 format, imageSize, data, texObj, texImage);
3324 }
3325 if (!success) {
3326 /* XXX what else can we do? */
3327 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3328 return;
3329 }
Brian Paul1207bf02000-05-23 20:10:49 +00003330}
3331
3332
3333void
Brian Paul9540a1d2000-06-06 17:03:38 +00003334_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
Brian Paul1207bf02000-05-23 20:10:49 +00003335{
Brian Paul9540a1d2000-06-06 17:03:38 +00003336 GET_CURRENT_CONTEXT(ctx);
3337 const struct gl_texture_object *texObj;
3338 struct gl_texture_image *texImage;
3339
3340 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3341
3342 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3343 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3344 return;
3345 }
3346
3347 switch (target) {
3348 case GL_TEXTURE_1D:
3349 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3350 texImage = texObj->Image[level];
3351 break;
3352 case GL_TEXTURE_2D:
3353 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3354 texImage = texObj->Image[level];
3355 break;
3356 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3357 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3358 texImage = texObj->Image[level];
3359 break;
3360 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3361 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3362 texImage = texObj->NegX[level];
3363 break;
3364 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3365 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3366 texImage = texObj->PosY[level];
3367 break;
3368 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3369 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3370 texImage = texObj->NegY[level];
3371 break;
3372 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3373 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3374 texImage = texObj->PosZ[level];
3375 break;
3376 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3377 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3378 texImage = texObj->NegZ[level];
3379 break;
3380 case GL_TEXTURE_3D:
3381 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3382 texImage = texObj->Image[level];
3383 break;
3384 default:
3385 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3386 return;
3387 }
3388
3389 if (!texImage) {
3390 /* invalid mipmap level */
3391 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3392 return;
3393 }
3394
3395 if (!texImage->IsCompressed) {
3396 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3397 return;
3398 }
3399
3400 if (!img)
3401 return;
3402
3403 if (ctx->Driver.GetCompressedTexImage) {
3404 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3405 texImage);
3406 }
3407 else {
3408 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3409 }
Brian Paul1207bf02000-05-23 20:10:49 +00003410}