blob: 0eab5dfa50c9c638de8334b14fffefe16597fd97 [file] [log] [blame]
Brian Pauld45fdea2000-11-13 15:25:26 +00001/* $Id: teximage.c,v 1.62 2000/11/13 15:25:26 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 Paulebb248a2000-10-29 18:23:16 +000035#include "macros.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000036#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000037#include "mmath.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"
Brian Paul7298e712000-11-07 16:40:37 +000042#include "swrast/s_span.h" /* XXX SWRAST hack */
jtgafb833d1999-08-19 00:55:39 +000043#endif
44
45
46/*
47 * NOTES:
48 *
Brian Paul699bc7b2000-10-29 18:12:14 +000049 * Mesa's native texture datatype is GLchan. Native formats are
Brian Paulc3f0a511999-11-03 17:27:05 +000050 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
51 * and GL_COLOR_INDEX.
52 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000053 */
54
55
Brian Paul48271792000-03-29 18:13:59 +000056#ifdef DEBUG
Brian Paule5d68a22000-03-30 18:37:51 +000057static void PrintTexture(const struct gl_texture_image *img)
Brian Paul48271792000-03-29 18:13:59 +000058{
Brian Paule5d68a22000-03-30 18:37:51 +000059 int i, j, c;
Brian Paul699bc7b2000-10-29 18:12:14 +000060 GLchan *data = img->Data;
Brian Paule5d68a22000-03-30 18:37:51 +000061
62 if (!data) {
63 printf("No texture data\n");
64 return;
65 }
66
67 switch (img->Format) {
68 case GL_ALPHA:
69 case GL_LUMINANCE:
70 case GL_INTENSITY:
71 case GL_COLOR_INDEX:
72 c = 1;
73 break;
74 case GL_LUMINANCE_ALPHA:
75 c = 2;
76 break;
77 case GL_RGB:
78 c = 3;
79 break;
80 case GL_RGBA:
81 c = 4;
82 break;
83 default:
84 gl_problem(NULL, "error in PrintTexture\n");
85 return;
86 }
87
88
89 for (i = 0; i < img->Height; i++) {
90 for (j = 0; j < img->Width; j++) {
Brian Paul48271792000-03-29 18:13:59 +000091 if (c==1)
92 printf("%02x ", data[0]);
93 else if (c==2)
Brian Paule5d68a22000-03-30 18:37:51 +000094 printf("%02x%02x ", data[0], data[1]);
Brian Paul48271792000-03-29 18:13:59 +000095 else if (c==3)
Brian Paule5d68a22000-03-30 18:37:51 +000096 printf("%02x%02x%02x ", data[0], data[1], data[2]);
Brian Paul48271792000-03-29 18:13:59 +000097 else if (c==4)
Brian Paule5d68a22000-03-30 18:37:51 +000098 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
Brian Paul48271792000-03-29 18:13:59 +000099 data += c;
100 }
101 printf("\n");
102 }
103}
104#endif
105
106
107
Brian Paulf7b57072000-03-20 14:37:52 +0000108/*
jtgafb833d1999-08-19 00:55:39 +0000109 * Compute log base 2 of n.
110 * If n isn't an exact power of two return -1.
111 * If n<0 return -1.
112 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000113static int
114logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +0000115{
116 GLint i = 1;
117 GLint log2 = 0;
118
119 if (n<0) {
120 return -1;
121 }
122
123 while ( n > i ) {
124 i *= 2;
125 log2++;
126 }
127 if (i != n) {
128 return -1;
129 }
130 else {
131 return log2;
132 }
133}
134
135
136
137/*
138 * Given an internal texture format enum or 1, 2, 3, 4 return the
139 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +0000140 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
141 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +0000142 */
Brian Paulb132e8d2000-03-23 16:23:14 +0000143GLint
Brian Paulaea66b12000-05-24 14:04:06 +0000144_mesa_base_tex_format( GLcontext *ctx, GLint format )
jtgafb833d1999-08-19 00:55:39 +0000145{
Brian Paul289d47e2000-08-29 23:31:23 +0000146 /*
147 * Ask the driver for the base format, if it doesn't
148 * know, it will return -1;
149 */
150 if (ctx->Driver.BaseCompressedTexFormat) {
151 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
152 if (ifmt >= 0) {
153 return ifmt;
154 }
155 }
jtgafb833d1999-08-19 00:55:39 +0000156 switch (format) {
157 case GL_ALPHA:
158 case GL_ALPHA4:
159 case GL_ALPHA8:
160 case GL_ALPHA12:
161 case GL_ALPHA16:
162 return GL_ALPHA;
163 case 1:
164 case GL_LUMINANCE:
165 case GL_LUMINANCE4:
166 case GL_LUMINANCE8:
167 case GL_LUMINANCE12:
168 case GL_LUMINANCE16:
169 return GL_LUMINANCE;
170 case 2:
171 case GL_LUMINANCE_ALPHA:
172 case GL_LUMINANCE4_ALPHA4:
173 case GL_LUMINANCE6_ALPHA2:
174 case GL_LUMINANCE8_ALPHA8:
175 case GL_LUMINANCE12_ALPHA4:
176 case GL_LUMINANCE12_ALPHA12:
177 case GL_LUMINANCE16_ALPHA16:
178 return GL_LUMINANCE_ALPHA;
179 case GL_INTENSITY:
180 case GL_INTENSITY4:
181 case GL_INTENSITY8:
182 case GL_INTENSITY12:
183 case GL_INTENSITY16:
184 return GL_INTENSITY;
185 case 3:
186 case GL_RGB:
187 case GL_R3_G3_B2:
188 case GL_RGB4:
189 case GL_RGB5:
190 case GL_RGB8:
191 case GL_RGB10:
192 case GL_RGB12:
193 case GL_RGB16:
194 return GL_RGB;
195 case 4:
196 case GL_RGBA:
197 case GL_RGBA2:
198 case GL_RGBA4:
199 case GL_RGB5_A1:
200 case GL_RGBA8:
201 case GL_RGB10_A2:
202 case GL_RGBA12:
203 case GL_RGBA16:
204 return GL_RGBA;
205 case GL_COLOR_INDEX:
206 case GL_COLOR_INDEX1_EXT:
207 case GL_COLOR_INDEX2_EXT:
208 case GL_COLOR_INDEX4_EXT:
209 case GL_COLOR_INDEX8_EXT:
210 case GL_COLOR_INDEX12_EXT:
211 case GL_COLOR_INDEX16_EXT:
212 return GL_COLOR_INDEX;
213 default:
214 return -1; /* error */
215 }
216}
217
218
219
220/*
221 * Given an internal texture format enum or 1, 2, 3, 4 return the
222 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
223 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
224 * number of components for the format. Return -1 if invalid enum.
225 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000226static GLint
227components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000228{
229 switch (format) {
230 case GL_ALPHA:
231 case GL_ALPHA4:
232 case GL_ALPHA8:
233 case GL_ALPHA12:
234 case GL_ALPHA16:
235 return 1;
236 case 1:
237 case GL_LUMINANCE:
238 case GL_LUMINANCE4:
239 case GL_LUMINANCE8:
240 case GL_LUMINANCE12:
241 case GL_LUMINANCE16:
242 return 1;
243 case 2:
244 case GL_LUMINANCE_ALPHA:
245 case GL_LUMINANCE4_ALPHA4:
246 case GL_LUMINANCE6_ALPHA2:
247 case GL_LUMINANCE8_ALPHA8:
248 case GL_LUMINANCE12_ALPHA4:
249 case GL_LUMINANCE12_ALPHA12:
250 case GL_LUMINANCE16_ALPHA16:
251 return 2;
252 case GL_INTENSITY:
253 case GL_INTENSITY4:
254 case GL_INTENSITY8:
255 case GL_INTENSITY12:
256 case GL_INTENSITY16:
257 return 1;
258 case 3:
259 case GL_RGB:
260 case GL_R3_G3_B2:
261 case GL_RGB4:
262 case GL_RGB5:
263 case GL_RGB8:
264 case GL_RGB10:
265 case GL_RGB12:
266 case GL_RGB16:
267 return 3;
268 case 4:
269 case GL_RGBA:
270 case GL_RGBA2:
271 case GL_RGBA4:
272 case GL_RGB5_A1:
273 case GL_RGBA8:
274 case GL_RGB10_A2:
275 case GL_RGBA12:
276 case GL_RGBA16:
277 return 4;
278 case GL_COLOR_INDEX:
279 case GL_COLOR_INDEX1_EXT:
280 case GL_COLOR_INDEX2_EXT:
281 case GL_COLOR_INDEX4_EXT:
282 case GL_COLOR_INDEX8_EXT:
283 case GL_COLOR_INDEX12_EXT:
284 case GL_COLOR_INDEX16_EXT:
285 return 1;
286 default:
287 return -1; /* error */
288 }
289}
290
291
Brian Paulaea66b12000-05-24 14:04:06 +0000292/*
293 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
294 * otherwise.
295 */
296static GLboolean
Brian Paul289d47e2000-08-29 23:31:23 +0000297is_compressed_format(GLcontext *ctx, GLenum internalFormat)
Brian Paulaea66b12000-05-24 14:04:06 +0000298{
Brian Paul289d47e2000-08-29 23:31:23 +0000299 if (ctx->Driver.IsCompressedFormat) {
300 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
301 }
302 return GL_FALSE;
Brian Paulaea66b12000-05-24 14:04:06 +0000303}
304
305
jtgafb833d1999-08-19 00:55:39 +0000306
jtgafb833d1999-08-19 00:55:39 +0000307/*
308 * Examine the texImage->Format field and set the Red, Green, Blue, etc
309 * texel component sizes to default values.
310 * These fields are set only here by core Mesa but device drivers may
311 * overwritting these fields to indicate true texel resolution.
312 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000313static void
314set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000315{
316 switch (texImage->Format) {
317 case GL_ALPHA:
318 texImage->RedBits = 0;
319 texImage->GreenBits = 0;
320 texImage->BlueBits = 0;
321 texImage->AlphaBits = 8;
322 texImage->IntensityBits = 0;
323 texImage->LuminanceBits = 0;
324 texImage->IndexBits = 0;
325 break;
326 case GL_LUMINANCE:
327 texImage->RedBits = 0;
328 texImage->GreenBits = 0;
329 texImage->BlueBits = 0;
330 texImage->AlphaBits = 0;
331 texImage->IntensityBits = 0;
332 texImage->LuminanceBits = 8;
333 texImage->IndexBits = 0;
334 break;
335 case GL_LUMINANCE_ALPHA:
336 texImage->RedBits = 0;
337 texImage->GreenBits = 0;
338 texImage->BlueBits = 0;
339 texImage->AlphaBits = 8;
340 texImage->IntensityBits = 0;
341 texImage->LuminanceBits = 8;
342 texImage->IndexBits = 0;
343 break;
344 case GL_INTENSITY:
345 texImage->RedBits = 0;
346 texImage->GreenBits = 0;
347 texImage->BlueBits = 0;
348 texImage->AlphaBits = 0;
349 texImage->IntensityBits = 8;
350 texImage->LuminanceBits = 0;
351 texImage->IndexBits = 0;
352 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000353 case GL_RED:
354 texImage->RedBits = 8;
355 texImage->GreenBits = 0;
356 texImage->BlueBits = 0;
357 texImage->AlphaBits = 0;
358 texImage->IntensityBits = 0;
359 texImage->LuminanceBits = 0;
360 texImage->IndexBits = 0;
361 break;
362 case GL_GREEN:
363 texImage->RedBits = 0;
364 texImage->GreenBits = 8;
365 texImage->BlueBits = 0;
366 texImage->AlphaBits = 0;
367 texImage->IntensityBits = 0;
368 texImage->LuminanceBits = 0;
369 texImage->IndexBits = 0;
370 break;
371 case GL_BLUE:
372 texImage->RedBits = 0;
373 texImage->GreenBits = 0;
374 texImage->BlueBits = 8;
375 texImage->AlphaBits = 0;
376 texImage->IntensityBits = 0;
377 texImage->LuminanceBits = 0;
378 texImage->IndexBits = 0;
379 break;
jtgafb833d1999-08-19 00:55:39 +0000380 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000381 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000382 texImage->RedBits = 8;
383 texImage->GreenBits = 8;
384 texImage->BlueBits = 8;
385 texImage->AlphaBits = 0;
386 texImage->IntensityBits = 0;
387 texImage->LuminanceBits = 0;
388 texImage->IndexBits = 0;
389 break;
390 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000391 case GL_BGRA:
392 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000393 texImage->RedBits = 8;
394 texImage->GreenBits = 8;
395 texImage->BlueBits = 8;
396 texImage->AlphaBits = 8;
397 texImage->IntensityBits = 0;
398 texImage->LuminanceBits = 0;
399 texImage->IndexBits = 0;
400 break;
401 case GL_COLOR_INDEX:
402 texImage->RedBits = 0;
403 texImage->GreenBits = 0;
404 texImage->BlueBits = 0;
405 texImage->AlphaBits = 0;
406 texImage->IntensityBits = 0;
407 texImage->LuminanceBits = 0;
408 texImage->IndexBits = 8;
409 break;
410 default:
411 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
412 }
413}
414
415
Brian Paulfc4b4432000-05-23 15:17:12 +0000416static void
417set_tex_image(struct gl_texture_object *tObj,
418 GLenum target, GLint level,
419 struct gl_texture_image *texImage)
420{
421 ASSERT(tObj);
422 ASSERT(texImage);
423 switch (target) {
424 case GL_TEXTURE_2D:
425 tObj->Image[level] = texImage;
426 return;
427 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
Brian Paul413d6a22000-05-26 14:44:59 +0000428 tObj->Image[level] = texImage;
Brian Paulfc4b4432000-05-23 15:17:12 +0000429 return;
430 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
431 tObj->NegX[level] = texImage;
432 return;
433 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
434 tObj->PosY[level] = texImage;
435 return;
436 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
437 tObj->NegY[level] = texImage;
438 return;
439 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
440 tObj->PosZ[level] = texImage;
441 return;
442 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
443 tObj->NegZ[level] = texImage;
444 return;
445 default:
446 gl_problem(NULL, "bad target in set_tex_image()");
447 return;
448 }
449}
450
451
Brian Paul77ce6da2000-03-20 23:40:12 +0000452/*
453 * Return new gl_texture_image struct with all fields initialized to zero.
454 */
455struct gl_texture_image *
Brian Paul021a5252000-03-27 17:54:17 +0000456_mesa_alloc_texture_image( void )
Brian Paul77ce6da2000-03-20 23:40:12 +0000457{
458 return CALLOC_STRUCT(gl_texture_image);
459}
460
461
462
463/*
Brian Paul02938782000-03-22 17:38:11 +0000464 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000465 */
Brian Paul02938782000-03-22 17:38:11 +0000466static void
Brian Paul289d47e2000-08-29 23:31:23 +0000467init_texture_image( GLcontext *ctx,
468 struct gl_texture_image *img,
Brian Paul02938782000-03-22 17:38:11 +0000469 GLsizei width, GLsizei height, GLsizei depth,
470 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000471{
Brian Paul02938782000-03-22 17:38:11 +0000472 ASSERT(img);
473 ASSERT(!img->Data);
Brian Paul289d47e2000-08-29 23:31:23 +0000474 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000475 set_teximage_component_sizes( img );
476 img->IntFormat = (GLenum) internalFormat;
477 img->Border = border;
478 img->Width = width;
479 img->Height = height;
480 img->Depth = depth;
481 img->WidthLog2 = logbase2(width - 2 * border);
482 if (height == 1) /* 1-D texture */
483 img->HeightLog2 = 0;
484 else
485 img->HeightLog2 = logbase2(height - 2 * border);
486 if (depth == 1) /* 2-D texture */
487 img->DepthLog2 = 0;
488 else
489 img->DepthLog2 = logbase2(depth - 2 * border);
490 img->Width2 = 1 << img->WidthLog2;
491 img->Height2 = 1 << img->HeightLog2;
492 img->Depth2 = 1 << img->DepthLog2;
493 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paul289d47e2000-08-29 23:31:23 +0000494 img->IsCompressed = is_compressed_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000495}
496
497
498
499void
Brian Paul021a5252000-03-27 17:54:17 +0000500_mesa_free_texture_image( struct gl_texture_image *teximage )
Brian Paul77ce6da2000-03-20 23:40:12 +0000501{
502 if (teximage->Data) {
503 FREE( teximage->Data );
504 teximage->Data = NULL;
505 }
506 FREE( teximage );
507}
508
509
510
Brian Paulfc4b4432000-05-23 15:17:12 +0000511/*
Brian Paulaea66b12000-05-24 14:04:06 +0000512 * Return number of bytes of storage needed to store a compressed texture
Brian Paul289d47e2000-08-29 23:31:23 +0000513 * image. Only the driver knows for sure. If the driver can't help us,
514 * we must return 0.
Brian Paulaea66b12000-05-24 14:04:06 +0000515 */
516GLuint
Brian Paul289d47e2000-08-29 23:31:23 +0000517_mesa_compressed_image_size(GLcontext *ctx,
518 GLenum internalFormat,
519 GLint numDimensions,
520 GLint width,
521 GLint height,
522 GLint depth)
Brian Paulaea66b12000-05-24 14:04:06 +0000523{
Brian Paul289d47e2000-08-29 23:31:23 +0000524 if (ctx->Driver.CompressedImageSize) {
525 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
526 numDimensions,
527 width, height, depth);
528 }
529 else {
530 /* Shouldn't this be an internal error of some sort? */
531 return 0;
532 }
Brian Paulaea66b12000-05-24 14:04:06 +0000533}
534
535
536
537/*
Brian Paul35d53012000-05-23 17:14:49 +0000538 * Given a texture unit and a texture target, return the corresponding
539 * texture object.
540 */
541struct gl_texture_object *
Brian Paul01e54752000-09-05 15:40:34 +0000542_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
Brian Paul35d53012000-05-23 17:14:49 +0000543 GLenum target)
544{
545 switch (target) {
546 case GL_TEXTURE_1D:
547 return texUnit->CurrentD[1];
548 case GL_PROXY_TEXTURE_1D:
549 return ctx->Texture.Proxy1D;
550 case GL_TEXTURE_2D:
551 return texUnit->CurrentD[2];
552 case GL_PROXY_TEXTURE_2D:
553 return ctx->Texture.Proxy2D;
554 case GL_TEXTURE_3D:
555 return texUnit->CurrentD[3];
556 case GL_PROXY_TEXTURE_3D:
557 return ctx->Texture.Proxy3D;
558 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
559 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
560 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
561 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
562 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000564 return ctx->Extensions.ARB_texture_cube_map
Brian Paul35d53012000-05-23 17:14:49 +0000565 ? texUnit->CurrentCubeMap : NULL;
566 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000567 return ctx->Extensions.ARB_texture_cube_map
Brian Paul35d53012000-05-23 17:14:49 +0000568 ? ctx->Texture.ProxyCubeMap : NULL;
569 default:
570 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
571 return NULL;
572 }
573}
574
575
576/*
Brian Paulfc4b4432000-05-23 15:17:12 +0000577 * Return the texture image struct which corresponds to target and level
578 * for the given texture unit.
579 */
580struct gl_texture_image *
581_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
582 GLenum target, GLint level)
583{
584 ASSERT(texUnit);
585 switch (target) {
586 case GL_TEXTURE_1D:
587 return texUnit->CurrentD[1]->Image[level];
588 case GL_PROXY_TEXTURE_1D:
589 return ctx->Texture.Proxy1D->Image[level];
590 case GL_TEXTURE_2D:
591 return texUnit->CurrentD[2]->Image[level];
592 case GL_PROXY_TEXTURE_2D:
593 return ctx->Texture.Proxy2D->Image[level];
594 case GL_TEXTURE_3D:
595 return texUnit->CurrentD[3]->Image[level];
596 case GL_PROXY_TEXTURE_3D:
597 return ctx->Texture.Proxy3D->Image[level];
598 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000599 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paul413d6a22000-05-26 14:44:59 +0000600 return texUnit->CurrentCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000601 else
602 return NULL;
603 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000604 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paulfc4b4432000-05-23 15:17:12 +0000605 return texUnit->CurrentCubeMap->NegX[level];
606 else
607 return NULL;
608 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000609 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paulfc4b4432000-05-23 15:17:12 +0000610 return texUnit->CurrentCubeMap->PosY[level];
611 else
612 return NULL;
613 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000614 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paulfc4b4432000-05-23 15:17:12 +0000615 return texUnit->CurrentCubeMap->NegY[level];
616 else
617 return NULL;
618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000619 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paulfc4b4432000-05-23 15:17:12 +0000620 return texUnit->CurrentCubeMap->PosZ[level];
621 else
622 return NULL;
623 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000624 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paulfc4b4432000-05-23 15:17:12 +0000625 return texUnit->CurrentCubeMap->NegZ[level];
626 else
627 return NULL;
628 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +0000629 if (ctx->Extensions.ARB_texture_cube_map)
Brian Paul413d6a22000-05-26 14:44:59 +0000630 return ctx->Texture.ProxyCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000631 else
632 return NULL;
633 default:
634 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
635 return NULL;
636 }
637}
638
639
640
Brian Paulf93b3dd2000-08-30 18:22:28 +0000641/*
642 * Calling glTexImage and related functions when convolution is enabled
643 * with GL_REDUCE border mode causes some complications.
644 * The incoming image must be extra large so that the post-convolution
645 * image size is reduced to a power of two size (plus 2 * border).
646 * This function adjusts a texture width and height accordingly if
647 * convolution with GL_REDUCE is enabled.
648 */
649static void
650adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
651 GLsizei *width, GLsizei *height)
652{
653 if (ctx->Pixel.Convolution1DEnabled
654 && dimensions == 1
655 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
656 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
657 }
658 else if (ctx->Pixel.Convolution2DEnabled
659 && dimensions > 1
660 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
661 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
662 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
663 }
664 else if (ctx->Pixel.Separable2DEnabled
665 && dimensions > 1
666 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
667 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
668 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
669 }
670}
671
672
673
Brian Paula805bb92000-09-02 17:52:21 +0000674/*
675 * This function is used to move user image data into a texture image.
676 * We handle full texture images and subtexture images. We also take
677 * care of all image transfer operations here, including convolution.
678 * Input:
679 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
Brian Paul699bc7b2000-10-29 18:12:14 +0000680 * dstRowStride, dstImageStride - strides in GLchan's
Brian Paula805bb92000-09-02 17:52:21 +0000681 */
682static void
683fill_texture_image( GLcontext *ctx, GLuint dimensions,
Brian Paul699bc7b2000-10-29 18:12:14 +0000684 GLenum texFormat, GLchan *texAddr,
Brian Paula805bb92000-09-02 17:52:21 +0000685 GLint srcWidth, GLint srcHeight, GLint srcDepth,
686 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
687 GLint dstRowStride, GLint dstImageStride,
688 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
689 const struct gl_pixelstore_attrib *srcPacking)
690{
691 GLint texComponents;
692
693 ASSERT(ctx);
694 ASSERT(dimensions >= 1 && dimensions <= 3);
695 ASSERT(texAddr);
696 ASSERT(srcWidth >= 1);
697 ASSERT(srcHeight >= 1);
698 ASSERT(srcDepth >= 1);
699 ASSERT(dstXoffset >= 0);
700 ASSERT(dstYoffset >= 0);
701 ASSERT(dstZoffset >= 0);
702 ASSERT(dstRowStride >= 0);
703 ASSERT(dstImageStride >= 0);
704 ASSERT(srcAddr);
705 ASSERT(srcPacking);
706
707 texComponents = components_in_intformat(texFormat);
708
709 /* try common 2D texture cases first */
Keith Whitwell14940c42000-11-05 18:40:57 +0000710 if (!ctx->_ImageTransferState && dimensions == 2
Brian Paula805bb92000-09-02 17:52:21 +0000711 && srcType == GL_UNSIGNED_BYTE) {
712
713 if (srcFormat == texFormat) {
714 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
715 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
716 */
Brian Paul699bc7b2000-10-29 18:12:14 +0000717 const GLchan *src = (const GLchan *) _mesa_image_address(
Brian Paula805bb92000-09-02 17:52:21 +0000718 srcPacking, srcAddr, srcWidth, srcHeight,
719 srcFormat, srcType, 0, 0, 0);
720 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
721 srcWidth, srcFormat, srcType);
Brian Paul699bc7b2000-10-29 18:12:14 +0000722 const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
723 GLchan *dst = texAddr + dstYoffset * dstRowStride
724 + dstXoffset * texComponents;
Brian Paula805bb92000-09-02 17:52:21 +0000725 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
726 MEMCPY(dst, src, srcHeight * widthInBytes);
727 }
728 else {
729 GLint i;
730 for (i = 0; i < srcHeight; i++) {
731 MEMCPY(dst, src, widthInBytes);
732 src += srcRowStride;
733 dst += dstRowStride;
734 }
735 }
736 return; /* all done */
737 }
738 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
739 /* commonly used by Quake */
Brian Paul699bc7b2000-10-29 18:12:14 +0000740 const GLchan *src = (const GLchan *) _mesa_image_address(
Brian Paula805bb92000-09-02 17:52:21 +0000741 srcPacking, srcAddr, srcWidth, srcHeight,
742 srcFormat, srcType, 0, 0, 0);
743 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
744 srcWidth, srcFormat, srcType);
Brian Paul699bc7b2000-10-29 18:12:14 +0000745 GLchan *dst = texAddr + dstYoffset * dstRowStride
746 + dstXoffset * texComponents;
Brian Paula805bb92000-09-02 17:52:21 +0000747 GLint i, j;
748 for (i = 0; i < srcHeight; i++) {
Brian Paul699bc7b2000-10-29 18:12:14 +0000749 const GLchan *s = src;
750 GLchan *d = dst;
Brian Paula805bb92000-09-02 17:52:21 +0000751 for (j = 0; j < srcWidth; j++) {
752 *d++ = *s++; /*red*/
753 *d++ = *s++; /*green*/
754 *d++ = *s++; /*blue*/
755 s++; /*alpha*/
756 }
757 src += srcRowStride;
758 dst += dstRowStride;
759 }
760 return; /* all done */
761 }
762 }
763
764 /*
765 * General case solutions
766 */
767 if (texFormat == GL_COLOR_INDEX) {
768 /* color index texture */
769 const GLenum texType = GL_UNSIGNED_BYTE;
770 GLint img, row;
Brian Paul699bc7b2000-10-29 18:12:14 +0000771 GLchan *dest = texAddr + dstZoffset * dstImageStride
Brian Paula805bb92000-09-02 17:52:21 +0000772 + dstYoffset * dstRowStride
Brian Paul699bc7b2000-10-29 18:12:14 +0000773 + dstXoffset * texComponents;
Brian Paula805bb92000-09-02 17:52:21 +0000774 for (img = 0; img < srcDepth; img++) {
Brian Paul699bc7b2000-10-29 18:12:14 +0000775 GLchan *destRow = dest;
Brian Paula805bb92000-09-02 17:52:21 +0000776 for (row = 0; row < srcHeight; row++) {
777 const GLvoid *src = _mesa_image_address(srcPacking,
778 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
779 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
780 srcType, src, srcPacking,
Keith Whitwell14940c42000-11-05 18:40:57 +0000781 ctx->_ImageTransferState);
Brian Paula805bb92000-09-02 17:52:21 +0000782 destRow += dstRowStride;
783 }
784 dest += dstImageStride;
785 }
786 }
787 else {
788 /* regular, color texture */
789 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
790 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
791 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
792 /*
793 * Fill texture image with convolution
794 */
795 GLint img, row;
796 GLint convWidth = srcWidth, convHeight = srcHeight;
797 GLfloat *tmpImage, *convImage;
798 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
799 if (!tmpImage) {
800 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
801 return;
802 }
803 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
804 if (!convImage) {
805 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
806 FREE(tmpImage);
807 return;
808 }
809
810 for (img = 0; img < srcDepth; img++) {
811 const GLfloat *srcf;
812 GLfloat *dstf = tmpImage;
Brian Paul699bc7b2000-10-29 18:12:14 +0000813 GLchan *dest;
Brian Paula805bb92000-09-02 17:52:21 +0000814
815 /* unpack and do transfer ops up to convolution */
816 for (row = 0; row < srcHeight; row++) {
817 const GLvoid *src = _mesa_image_address(srcPacking,
818 srcAddr, srcWidth, srcHeight,
819 srcFormat, srcType, img, row, 0);
820 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
821 srcFormat, srcType, src, srcPacking,
Keith Whitwell14940c42000-11-05 18:40:57 +0000822 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
Brian Paula805bb92000-09-02 17:52:21 +0000823 GL_TRUE);
824 dstf += srcWidth * 4;
825 }
826
827 /* convolve */
828 if (dimensions == 1) {
829 ASSERT(ctx->Pixel.Convolution1DEnabled);
830 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
831 }
832 else {
833 if (ctx->Pixel.Convolution2DEnabled) {
834 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
835 tmpImage, convImage);
836 }
837 else {
838 ASSERT(ctx->Pixel.Separable2DEnabled);
839 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
840 tmpImage, convImage);
841 }
842 }
843
844 /* packing and transfer ops after convolution */
845 srcf = convImage;
846 dest = texAddr + (dstZoffset + img) * dstImageStride
847 + dstYoffset * dstRowStride;
848 for (row = 0; row < convHeight; row++) {
849 _mesa_pack_float_rgba_span(ctx, convWidth,
850 (const GLfloat (*)[4]) srcf,
851 texFormat, GL_UNSIGNED_BYTE,
852 dest, &_mesa_native_packing,
Keith Whitwell14940c42000-11-05 18:40:57 +0000853 ctx->_ImageTransferState
Brian Paula805bb92000-09-02 17:52:21 +0000854 & IMAGE_POST_CONVOLUTION_BITS);
855 srcf += convWidth * 4;
856 dest += dstRowStride;
857 }
858 }
859
860 FREE(convImage);
861 FREE(tmpImage);
862 }
863 else {
864 /*
865 * no convolution
866 */
867 GLint img, row;
Brian Paul699bc7b2000-10-29 18:12:14 +0000868 GLchan *dest = texAddr + dstZoffset * dstImageStride
Brian Paula805bb92000-09-02 17:52:21 +0000869 + dstYoffset * dstRowStride
Brian Paul699bc7b2000-10-29 18:12:14 +0000870 + dstXoffset * texComponents;
Brian Paula805bb92000-09-02 17:52:21 +0000871 for (img = 0; img < srcDepth; img++) {
Brian Paul699bc7b2000-10-29 18:12:14 +0000872 GLchan *destRow = dest;
Brian Paula805bb92000-09-02 17:52:21 +0000873 for (row = 0; row < srcHeight; row++) {
Brian Paul01e54752000-09-05 15:40:34 +0000874 const GLvoid *srcRow = _mesa_image_address(srcPacking,
Brian Paula805bb92000-09-02 17:52:21 +0000875 srcAddr, srcWidth, srcHeight,
876 srcFormat, srcType, img, row, 0);
Brian Paul699bc7b2000-10-29 18:12:14 +0000877 _mesa_unpack_chan_color_span(ctx, srcWidth, texFormat, destRow,
Brian Paul01e54752000-09-05 15:40:34 +0000878 srcFormat, srcType, srcRow, srcPacking,
Keith Whitwell14940c42000-11-05 18:40:57 +0000879 ctx->_ImageTransferState);
Brian Paula805bb92000-09-02 17:52:21 +0000880 destRow += dstRowStride;
881 }
882 dest += dstImageStride;
883 }
884 }
885 }
886}
887
888
889
jtgafb833d1999-08-19 00:55:39 +0000890/* Need this to prevent an out-of-bounds memory access when using
891 * X86 optimized code.
892 */
893#ifdef USE_X86_ASM
Brian Paul699bc7b2000-10-29 18:12:14 +0000894# define EXTRA_BYTE sizeof(GLchan)
jtgafb833d1999-08-19 00:55:39 +0000895#else
896# define EXTRA_BYTE 0
897#endif
898
899
Brian Paulc3f0a511999-11-03 17:27:05 +0000900
jtgafb833d1999-08-19 00:55:39 +0000901/*
Brian Paul43911c82000-03-21 00:49:33 +0000902 * Called by glTexImage[123]D. Fill in a texture image with data given
903 * by the client. All pixel transfer and unpack modes are handled here.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000904 * Input: dimensions (1, 2, or 3)
905 * texImage - destination texture image (we'll malloc the memory)
906 * width, height, depth - size of source image
907 * srcFormat, srcType - source image format and type
908 * pixels - source image data
909 * srcPacking - source image packing parameters
910 *
Brian Paul43911c82000-03-21 00:49:33 +0000911 * NOTE: All texture image parameters should have already been error checked.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000912 *
913 * NOTE: the texImage dimensions and source image dimensions must be correct
914 * with respect to convolution with border mode = reduce.
jtgafb833d1999-08-19 00:55:39 +0000915 */
Brian Paul43911c82000-03-21 00:49:33 +0000916static void
Brian Paulf93b3dd2000-08-30 18:22:28 +0000917make_texture_image( GLcontext *ctx, GLuint dimensions,
Brian Paul43911c82000-03-21 00:49:33 +0000918 struct gl_texture_image *texImage,
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000919 GLint width, GLint height, GLint depth,
Brian Paulc3f0a511999-11-03 17:27:05 +0000920 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
Brian Paulf93b3dd2000-08-30 18:22:28 +0000921 const struct gl_pixelstore_attrib *srcPacking)
jtgafb833d1999-08-19 00:55:39 +0000922{
Brian Paula805bb92000-09-02 17:52:21 +0000923 const GLint internalFormat = texImage->IntFormat;
924 const GLint components = components_in_intformat(internalFormat);
925 GLint convWidth = width, convHeight = height;
jtgafb833d1999-08-19 00:55:39 +0000926
Brian Paul9499e012000-10-30 16:32:42 +0000927 if (ctx->NewState & _NEW_PIXEL)
928 gl_update_state(ctx);
jtgafb833d1999-08-19 00:55:39 +0000929
Keith Whitwell14940c42000-11-05 18:40:57 +0000930 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
Brian Paula805bb92000-09-02 17:52:21 +0000931 adjust_texture_size_for_convolution(ctx, dimensions,
932 &convWidth, &convHeight);
933 }
Brian Paul43911c82000-03-21 00:49:33 +0000934
Brian Paul699bc7b2000-10-29 18:12:14 +0000935 texImage->Data = (GLchan *) MALLOC(convWidth * convHeight * depth
936 * components * sizeof(GLchan) + 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,
Brian Paul699bc7b2000-10-29 18:12:14 +0000942 convWidth * components * sizeof(GLchan),
943 convWidth * convHeight * components * sizeof(GLchan),
Brian Paula805bb92000-09-02 17:52:21 +0000944 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 Paul699bc7b2000-10-29 18:12:14 +0000966 texImage->Data = (GLchan *) MALLOC( numPixels * components * sizeof(GLchan)
967 + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000968
969 /*
970 * Let's see if anyone finds this. If glTexImage2D() is called with
971 * a NULL image pointer then load the texture image with something
972 * interesting instead of leaving it indeterminate.
973 */
974 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000975 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000976 " X X XXXXX XXX X ",
977 " XX XX X X X X X ",
978 " X X X X X X X ",
979 " X X XXXX XXX XXXXX ",
980 " X X X X X X ",
981 " X X X X X X X ",
982 " X X XXXXX XXX X X ",
983 " "
984 };
985
Brian Paul699bc7b2000-10-29 18:12:14 +0000986 GLchan *imgPtr = texImage->Data;
jtgafb833d1999-08-19 00:55:39 +0000987 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000988 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000989 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000990 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000991 GLint srcCol = j % 32;
Brian Paulba643a22000-10-28 18:34:48 +0000992 GLint texel = (message[srcRow][srcCol]=='X') ? CHAN_MAX : 70;
jtgafb833d1999-08-19 00:55:39 +0000993 for (k=0;k<components;k++) {
Brian Paul699bc7b2000-10-29 18:12:14 +0000994 *imgPtr++ = (GLchan) texel;
jtgafb833d1999-08-19 00:55:39 +0000995 }
996 }
997 }
998 }
jtgafb833d1999-08-19 00:55:39 +0000999}
1000
1001
1002
1003/*
Brian Paul9c272782000-09-05 22:04:30 +00001004 * This is called when a proxy texture test fails, we set all the
1005 * image members (except DriverData) to zero.
1006 */
1007static void
1008clear_proxy_teximage(struct gl_texture_image *img)
1009{
1010 ASSERT(img);
1011 img->Format = 0;
1012 img->IntFormat = 0;
1013 img->RedBits = 0;
1014 img->GreenBits = 0;
1015 img->BlueBits = 0;
1016 img->AlphaBits = 0;
1017 img->IntensityBits = 0;
1018 img->LuminanceBits = 0;
1019 img->IndexBits = 0;
1020 img->Border = 0;
1021 img->Width = 0;
1022 img->Height = 0;
1023 img->Depth = 0;
1024 img->Width2 = 0;
1025 img->Height2 = 0;
1026 img->Depth2 = 0;
1027 img->WidthLog2 = 0;
1028 img->HeightLog2 = 0;
1029 img->DepthLog2 = 0;
1030 img->Data = NULL;
1031 img->IsCompressed = 0;
1032 img->CompressedSize = 0;
1033}
1034
1035
1036
1037/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001038 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +00001039 * Input:
1040 * dimensions - must be 1 or 2 or 3
1041 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1042 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001043static GLboolean
1044texture_error_check( GLcontext *ctx, GLenum target,
1045 GLint level, GLint internalFormat,
1046 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +00001047 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001048 GLint width, GLint height,
1049 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001050{
1051 GLboolean isProxy;
1052 GLint iformat;
1053
1054 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +00001055 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +00001056 if (target != GL_TEXTURE_1D && !isProxy) {
1057 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1058 return GL_TRUE;
1059 }
1060 }
1061 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +00001062 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
Brian Paul413d6a22000-05-26 14:44:59 +00001063 if (target != GL_TEXTURE_2D && !isProxy &&
Keith Whitwella96308c2000-10-30 13:31:59 +00001064 !(ctx->Extensions.ARB_texture_cube_map &&
Brian Paul413d6a22000-05-26 14:44:59 +00001065 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1066 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
jtgafb833d1999-08-19 00:55:39 +00001067 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1068 return GL_TRUE;
1069 }
1070 }
1071 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +00001072 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +00001073 if (target != GL_TEXTURE_3D && !isProxy) {
1074 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1075 return GL_TRUE;
1076 }
1077 }
1078 else {
1079 gl_problem( ctx, "bad dims in texture_error_check" );
1080 return GL_TRUE;
1081 }
1082
1083 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001084 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +00001085 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001086 char message[100];
1087 sprintf(message, "glTexImage%dD(border)", dimensions);
1088 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001089 }
1090 return GL_TRUE;
1091 }
1092
1093 /* Width */
1094 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1095 || logbase2( width - 2 * border ) < 0) {
1096 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001097 char message[100];
1098 sprintf(message, "glTexImage%dD(width)", dimensions);
1099 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001100 }
1101 return GL_TRUE;
1102 }
1103
1104 /* Height */
1105 if (dimensions >= 2) {
1106 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1107 || logbase2( height - 2 * border ) < 0) {
1108 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001109 char message[100];
1110 sprintf(message, "glTexImage%dD(height)", dimensions);
1111 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001112 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001113 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00001114 }
1115 }
1116
Brian Paulad817702000-05-30 00:27:24 +00001117 /* For cube map, width must equal height */
1118 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1119 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1120 if (width != height) {
1121 if (!isProxy) {
1122 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1123 }
1124 return GL_TRUE;
1125 }
1126 }
1127
jtgafb833d1999-08-19 00:55:39 +00001128 /* Depth */
1129 if (dimensions >= 3) {
1130 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1131 || logbase2( depth - 2 * border ) < 0) {
1132 if (!isProxy) {
1133 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1134 }
1135 return GL_TRUE;
1136 }
1137 }
1138
1139 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001140 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001141 if (!isProxy) {
1142 char message[100];
1143 sprintf(message, "glTexImage%dD(level)", dimensions);
1144 gl_error(ctx, GL_INVALID_VALUE, message);
1145 }
jtgafb833d1999-08-19 00:55:39 +00001146 return GL_TRUE;
1147 }
1148
Brian Paulaea66b12000-05-24 14:04:06 +00001149 iformat = _mesa_base_tex_format( ctx, internalFormat );
jtgafb833d1999-08-19 00:55:39 +00001150 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001151 if (!isProxy) {
1152 char message[100];
1153 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1154 gl_error(ctx, GL_INVALID_VALUE, message);
1155 }
jtgafb833d1999-08-19 00:55:39 +00001156 return GL_TRUE;
1157 }
1158
Brian Paul289d47e2000-08-29 23:31:23 +00001159 if (!is_compressed_format(ctx, internalFormat)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001160 if (!_mesa_is_legal_format_and_type( format, type )) {
1161 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1162 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1163 */
1164 if (!isProxy) {
1165 char message[100];
1166 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1167 gl_error(ctx, GL_INVALID_OPERATION, message);
1168 }
1169 return GL_TRUE;
Brian Paulc3f0a511999-11-03 17:27:05 +00001170 }
jtgafb833d1999-08-19 00:55:39 +00001171 }
1172
1173 /* if we get here, the parameters are OK */
1174 return GL_FALSE;
1175}
1176
1177
1178
1179/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001180 * Test glTexSubImage[123]D() parameters for errors.
1181 * Input:
1182 * dimensions - must be 1 or 2 or 3
1183 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1184 */
1185static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001186subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001187 GLenum target, GLint level,
1188 GLint xoffset, GLint yoffset, GLint zoffset,
1189 GLint width, GLint height, GLint depth,
1190 GLenum format, GLenum type )
1191{
1192 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1193 struct gl_texture_image *destTex;
1194
1195 if (dimensions == 1) {
1196 if (target != GL_TEXTURE_1D) {
1197 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1198 return GL_TRUE;
1199 }
1200 }
1201 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001202 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001203 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1204 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1205 target != GL_TEXTURE_2D) {
1206 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1207 return GL_TRUE;
1208 }
1209 }
1210 else if (target != GL_TEXTURE_2D) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001211 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1212 return GL_TRUE;
1213 }
1214 }
1215 else if (dimensions == 3) {
1216 if (target != GL_TEXTURE_3D) {
1217 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1218 return GL_TRUE;
1219 }
1220 }
1221 else {
1222 gl_problem( ctx, "bad dims in texture_error_check" );
1223 return GL_TRUE;
1224 }
1225
1226 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1227 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1228 return GL_TRUE;
1229 }
1230
1231 if (width < 0) {
1232 char message[100];
1233 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1234 gl_error(ctx, GL_INVALID_VALUE, message);
1235 return GL_TRUE;
1236 }
1237 if (height < 0 && dimensions > 1) {
1238 char message[100];
1239 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1240 gl_error(ctx, GL_INVALID_VALUE, message);
1241 return GL_TRUE;
1242 }
1243 if (depth < 0 && dimensions > 2) {
1244 char message[100];
1245 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1246 gl_error(ctx, GL_INVALID_VALUE, message);
1247 return GL_TRUE;
1248 }
1249
1250 destTex = texUnit->CurrentD[2]->Image[level];
1251 if (!destTex) {
1252 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1253 return GL_TRUE;
1254 }
1255
1256 if (xoffset < -((GLint)destTex->Border)) {
1257 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1258 return GL_TRUE;
1259 }
1260 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1261 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1262 return GL_TRUE;
1263 }
1264 if (dimensions > 1) {
1265 if (yoffset < -((GLint)destTex->Border)) {
1266 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1267 return GL_TRUE;
1268 }
1269 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1270 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1271 return GL_TRUE;
1272 }
1273 }
1274 if (dimensions > 2) {
1275 if (zoffset < -((GLint)destTex->Border)) {
1276 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1277 return GL_TRUE;
1278 }
1279 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1280 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1281 return GL_TRUE;
1282 }
1283 }
1284
Brian Paul289d47e2000-08-29 23:31:23 +00001285 if (!is_compressed_format(ctx, destTex->IntFormat)) {
Brian Paul9540a1d2000-06-06 17:03:38 +00001286 if (!_mesa_is_legal_format_and_type(format, type)) {
1287 char message[100];
1288 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1289 gl_error(ctx, GL_INVALID_ENUM, message);
1290 return GL_TRUE;
1291 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001292 }
1293
1294 return GL_FALSE;
1295}
1296
1297
1298/*
1299 * Test glCopyTexImage[12]D() parameters for errors.
1300 * Input: dimensions - must be 1 or 2 or 3
1301 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1302 */
1303static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001304copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001305 GLenum target, GLint level, GLint internalFormat,
1306 GLint width, GLint height, GLint border )
1307{
1308 GLint iformat;
1309
Brian Paulfc4b4432000-05-23 15:17:12 +00001310 if (dimensions == 1) {
1311 if (target != GL_TEXTURE_1D) {
1312 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1313 return GL_TRUE;
1314 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001315 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001316 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001317 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001318 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1319 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1320 target != GL_TEXTURE_2D) {
1321 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1322 return GL_TRUE;
1323 }
1324 }
1325 else if (target != GL_TEXTURE_2D) {
1326 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1327 return GL_TRUE;
1328 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001329 }
1330
1331 /* Border */
1332 if (border!=0 && border!=1) {
1333 char message[100];
1334 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1335 gl_error(ctx, GL_INVALID_VALUE, message);
1336 return GL_TRUE;
1337 }
1338
1339 /* Width */
1340 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1341 || logbase2( width - 2 * border ) < 0) {
1342 char message[100];
1343 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1344 gl_error(ctx, GL_INVALID_VALUE, message);
1345 return GL_TRUE;
1346 }
1347
1348 /* Height */
1349 if (dimensions >= 2) {
1350 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1351 || logbase2( height - 2 * border ) < 0) {
1352 char message[100];
1353 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1354 gl_error(ctx, GL_INVALID_VALUE, message);
1355 return GL_TRUE;
1356 }
1357 }
1358
Brian Paulad817702000-05-30 00:27:24 +00001359 /* For cube map, width must equal height */
1360 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1361 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1362 if (width != height) {
1363 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1364 return GL_TRUE;
1365 }
1366 }
1367
Brian Paulc3f0a511999-11-03 17:27:05 +00001368 /* Level */
1369 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1370 char message[100];
1371 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1372 gl_error(ctx, GL_INVALID_VALUE, message);
1373 return GL_TRUE;
1374 }
1375
Brian Paulaea66b12000-05-24 14:04:06 +00001376 iformat = _mesa_base_tex_format( ctx, internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +00001377 if (iformat < 0) {
1378 char message[100];
1379 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1380 gl_error(ctx, GL_INVALID_VALUE, message);
1381 return GL_TRUE;
1382 }
1383
1384 /* if we get here, the parameters are OK */
1385 return GL_FALSE;
1386}
1387
1388
1389static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001390copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001391 GLenum target, GLint level,
1392 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +00001393 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001394{
1395 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1396 struct gl_texture_image *teximage;
1397
Brian Paulfc4b4432000-05-23 15:17:12 +00001398 if (dimensions == 1) {
1399 if (target != GL_TEXTURE_1D) {
1400 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1401 return GL_TRUE;
1402 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001403 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001404 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001405 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001406 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1407 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1408 target != GL_TEXTURE_2D) {
1409 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1410 return GL_TRUE;
1411 }
1412 }
1413 else if (target != GL_TEXTURE_2D) {
1414 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1415 return GL_TRUE;
1416 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001417 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001418 else if (dimensions == 3) {
1419 if (target != GL_TEXTURE_3D) {
1420 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1421 return GL_TRUE;
1422 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001423 }
1424
1425 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1426 char message[100];
1427 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1428 gl_error(ctx, GL_INVALID_VALUE, message);
1429 return GL_TRUE;
1430 }
1431
1432 if (width < 0) {
1433 char message[100];
1434 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1435 gl_error(ctx, GL_INVALID_VALUE, message);
1436 return GL_TRUE;
1437 }
1438 if (dimensions > 1 && height < 0) {
1439 char message[100];
1440 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1441 gl_error(ctx, GL_INVALID_VALUE, message);
1442 return GL_TRUE;
1443 }
1444
Brian Pauldf6a28d2000-02-21 16:34:21 +00001445 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001446 if (!teximage) {
1447 char message[100];
1448 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1449 gl_error(ctx, GL_INVALID_OPERATION, message);
1450 return GL_TRUE;
1451 }
1452
1453 if (xoffset < -((GLint)teximage->Border)) {
1454 char message[100];
1455 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1456 gl_error(ctx, GL_INVALID_VALUE, message);
1457 return GL_TRUE;
1458 }
1459 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1460 char message[100];
1461 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1462 gl_error(ctx, GL_INVALID_VALUE, message);
1463 return GL_TRUE;
1464 }
1465 if (dimensions > 1) {
1466 if (yoffset < -((GLint)teximage->Border)) {
1467 char message[100];
1468 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1469 gl_error(ctx, GL_INVALID_VALUE, message);
1470 return GL_TRUE;
1471 }
1472 /* NOTE: we're adding the border here, not subtracting! */
1473 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1474 char message[100];
1475 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1476 gl_error(ctx, GL_INVALID_VALUE, message);
1477 return GL_TRUE;
1478 }
1479 }
1480
1481 if (dimensions > 2) {
1482 if (zoffset < -((GLint)teximage->Border)) {
1483 char message[100];
1484 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1485 gl_error(ctx, GL_INVALID_VALUE, message);
1486 return GL_TRUE;
1487 }
1488 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1489 char message[100];
1490 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1491 gl_error(ctx, GL_INVALID_VALUE, message);
1492 return GL_TRUE;
1493 }
1494 }
1495
1496 /* if we get here, the parameters are OK */
1497 return GL_FALSE;
1498}
1499
1500
1501
1502
1503/*
Brian Paul289d47e2000-08-29 23:31:23 +00001504 * Turn generic compressed formats into specific compressed format.
1505 * Some of the compressed formats we don't support, so we
1506 * fall back to the uncompressed format. (See issue 15 of
1507 * the GL_ARB_texture_compression specification.)
1508 */
1509static GLint
1510get_specific_compressed_tex_format(GLcontext *ctx,
Brian Paul37a62112000-09-28 18:30:39 +00001511 GLint ifmt, GLint numDimensions,
1512 GLint *levelp,
1513 GLsizei *widthp,
1514 GLsizei *heightp,
1515 GLsizei *depthp,
1516 GLint *borderp,
1517 GLenum *formatp,
1518 GLenum *typep)
Brian Paul289d47e2000-08-29 23:31:23 +00001519{
1520 char message[100];
1521 GLint internalFormat = ifmt;
1522
Keith Whitwella96308c2000-10-30 13:31:59 +00001523 if (ctx->Extensions.ARB_texture_compression
Brian Paul289d47e2000-08-29 23:31:23 +00001524 && ctx->Driver.SpecificCompressedTexFormat) {
1525 /*
1526 * First, ask the driver for the specific format.
Brian Paul37a62112000-09-28 18:30:39 +00001527 * We do this for all formats, since we may want to
1528 * fake one compressed format for another.
Brian Paul289d47e2000-08-29 23:31:23 +00001529 */
Brian Paul37a62112000-09-28 18:30:39 +00001530 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1531 (ctx, internalFormat, numDimensions,
1532 levelp,
1533 widthp, heightp, depthp,
1534 borderp, formatp, typep);
Brian Paul289d47e2000-08-29 23:31:23 +00001535 }
1536
1537 /*
1538 * Now, convert any generic format left to an uncompressed
1539 * specific format. If the driver does not support compression
1540 * of the format, we must drop back to the uncompressed format.
1541 * See issue 15 of the GL_ARB_texture_compression specification.
1542 */
1543 switch (internalFormat) {
1544 case GL_COMPRESSED_ALPHA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001545 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001546 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1547 gl_error(ctx, GL_INVALID_VALUE, message);
1548 return -1;
1549 }
1550 internalFormat = GL_ALPHA;
1551 break;
1552 case GL_COMPRESSED_LUMINANCE_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001553 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001554 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1555 gl_error(ctx, GL_INVALID_VALUE, message);
1556 return -1;
1557 }
1558 internalFormat = GL_LUMINANCE;
1559 break;
1560 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001561 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001562 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1563 gl_error(ctx, GL_INVALID_VALUE, message);
1564 return -1;
1565 }
1566 internalFormat = GL_LUMINANCE_ALPHA;
1567 break;
1568 case GL_COMPRESSED_INTENSITY_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001569 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001570 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1571 gl_error(ctx, GL_INVALID_VALUE, message);
1572 return -1;
1573 }
1574 internalFormat = GL_INTENSITY;
1575 break;
1576 case GL_COMPRESSED_RGB_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001577 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001578 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1579 gl_error(ctx, GL_INVALID_VALUE, message);
1580 return -1;
1581 }
1582 internalFormat = GL_RGB;
1583 break;
1584 case GL_COMPRESSED_RGBA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001585 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001586 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1587 gl_error(ctx, GL_INVALID_VALUE, message);
1588 return -1;
1589 }
1590 internalFormat = GL_RGBA;
1591 break;
1592 default:
Brian Paulf93b3dd2000-08-30 18:22:28 +00001593 /* silence compiler warning */
1594 ;
Brian Paul289d47e2000-08-29 23:31:23 +00001595 }
1596 return internalFormat;
1597}
1598
1599
Brian Paul289d47e2000-08-29 23:31:23 +00001600/*
jtgafb833d1999-08-19 00:55:39 +00001601 * Called from the API. Note that width includes the border.
1602 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001603void
Brian Paul43911c82000-03-21 00:49:33 +00001604_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001605 GLsizei width, GLint border, GLenum format,
1606 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001607{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001608 GLsizei postConvWidth;
Brian Paulfbd8f211999-11-11 01:22:25 +00001609 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001610 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1611
Brian Paulf93b3dd2000-08-30 18:22:28 +00001612 postConvWidth = width;
1613 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1614
jtgafb833d1999-08-19 00:55:39 +00001615 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001616 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001617 struct gl_texture_object *texObj;
1618 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001619 GLint ifmt;
1620
Brian Paul37a62112000-09-28 18:30:39 +00001621 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1622 &level,
1623 &width, 0, 0,
1624 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001625 if (ifmt < 0) {
1626 /*
1627 * The error here is that we were sent a generic compressed
1628 * format, but the extension is not supported.
1629 */
1630 return;
1631 }
1632 else {
1633 internalFormat = ifmt;
1634 }
Brian Paulf7b57072000-03-20 14:37:52 +00001635
Brian Paulaea66b12000-05-24 14:04:06 +00001636 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001637 format, type, 1, postConvWidth, 1, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001638 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001639 }
1640
Brian Paulf7b57072000-03-20 14:37:52 +00001641 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001642 texObj = texUnit->CurrentD[1];
1643 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001644
Brian Paul02938782000-03-22 17:38:11 +00001645 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001646 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001647 texObj->Image[level] = texImage;
1648 if (!texImage) {
1649 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1650 return;
1651 }
1652 }
1653 else if (texImage->Data) {
1654 FREE(texImage->Data);
1655 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001656 }
1657
Brian Paul02938782000-03-22 17:38:11 +00001658 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001659 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001660
Brian Paul9499e012000-10-30 16:32:42 +00001661 if (ctx->NewState & _NEW_PIXEL)
1662 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001663
Brian Paul02938782000-03-22 17:38:11 +00001664 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001665 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001666 GLboolean retain = GL_TRUE;
1667 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001668 if (!ctx->_ImageTransferState && ctx->Driver.TexImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00001669 /* let device driver try to use raw image */
1670 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1671 type, pixels, &ctx->Unpack,
1672 texObj, texImage, &retain);
1673 }
1674 if (retain || !success) {
1675 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001676 make_texture_image(ctx, 1, texImage, width, 1, 1,
1677 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001678 if (!success && ctx->Driver.TexImage1D) {
1679 /* let device driver try to use unpacked image */
1680 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1681 GL_UNSIGNED_BYTE, texImage->Data,
1682 &_mesa_native_packing,
1683 texObj, texImage, &retain);
1684 }
1685 }
1686 if (!retain && texImage->Data) {
1687 FREE(texImage->Data);
1688 texImage->Data = NULL;
1689 }
jtgafb833d1999-08-19 00:55:39 +00001690 }
1691 else {
Brian Paul02938782000-03-22 17:38:11 +00001692 make_null_texture(texImage);
1693 if (ctx->Driver.TexImage1D) {
1694 GLboolean retain;
1695 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1696 GL_UNSIGNED_BYTE, texImage->Data,
1697 &_mesa_native_packing,
1698 texObj, texImage, &retain);
1699 }
jtgafb833d1999-08-19 00:55:39 +00001700 }
1701
Brian Paul02938782000-03-22 17:38:11 +00001702 /* state update */
1703 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00001704 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001705 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001706 else if (target == GL_PROXY_TEXTURE_1D) {
jtgafb833d1999-08-19 00:55:39 +00001707 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001708 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1709 format, type, 1, width, 1, 1, border);
1710 if (!error && ctx->Driver.TestProxyTexImage) {
1711 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1712 internalFormat, format, type,
1713 width, 1, 1, border);
1714 }
1715 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001716 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001717 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001718 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001719 }
1720 }
1721 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001722 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001723 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001724 width, 1, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001725 }
jtgafb833d1999-08-19 00:55:39 +00001726 }
1727 else {
1728 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1729 return;
1730 }
1731}
1732
1733
Brian Paulfbd8f211999-11-11 01:22:25 +00001734void
Brian Paul43911c82000-03-21 00:49:33 +00001735_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001736 GLsizei width, GLsizei height, GLint border,
1737 GLenum format, GLenum type,
1738 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001739{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001740 GLsizei postConvWidth, postConvHeight;
Brian Paulfbd8f211999-11-11 01:22:25 +00001741 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001742 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1743
Brian Paulf93b3dd2000-08-30 18:22:28 +00001744 postConvWidth = width;
1745 postConvHeight = height;
1746 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1747
Brian Paulfc4b4432000-05-23 15:17:12 +00001748 if (target==GL_TEXTURE_2D ||
Keith Whitwella96308c2000-10-30 13:31:59 +00001749 (ctx->Extensions.ARB_texture_cube_map &&
Brian Paulfc4b4432000-05-23 15:17:12 +00001750 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1751 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001752 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001753 struct gl_texture_object *texObj;
1754 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001755 GLint ifmt;
1756
Brian Paul37a62112000-09-28 18:30:39 +00001757 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1758 &level,
1759 &width, &height, 0,
1760 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001761 if (ifmt < 0) {
1762 /*
1763 * The error here is that we were sent a generic compressed
1764 * format, but the extension is not supported.
1765 */
1766 return;
1767 }
1768 else {
1769 internalFormat = ifmt;
1770 }
Brian Paulf7b57072000-03-20 14:37:52 +00001771
Brian Paulaea66b12000-05-24 14:04:06 +00001772 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001773 format, type, 2, postConvWidth, postConvHeight,
1774 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001775 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001776 }
1777
Brian Paulf7b57072000-03-20 14:37:52 +00001778 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00001779 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paulfc4b4432000-05-23 15:17:12 +00001780 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00001781
Brian Paul02938782000-03-22 17:38:11 +00001782 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001783 texImage = _mesa_alloc_texture_image();
Brian Paulfc4b4432000-05-23 15:17:12 +00001784 set_tex_image(texObj, target, level, texImage);
1785 /*texObj->Image[level] = texImage;*/
Brian Paul02938782000-03-22 17:38:11 +00001786 if (!texImage) {
1787 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1788 return;
1789 }
1790 }
1791 else if (texImage->Data) {
1792 FREE(texImage->Data);
1793 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001794 }
1795
Brian Paul02938782000-03-22 17:38:11 +00001796 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001797 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
Brian Paul289d47e2000-08-29 23:31:23 +00001798 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001799
Brian Paul9499e012000-10-30 16:32:42 +00001800 if (ctx->NewState & _NEW_PIXEL)
1801 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001802
Brian Paul02938782000-03-22 17:38:11 +00001803 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001804 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001805 GLboolean retain = GL_TRUE;
1806 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001807 if (!ctx->_ImageTransferState && ctx->Driver.TexImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00001808 /* let device driver try to use raw image */
1809 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1810 type, pixels, &ctx->Unpack,
1811 texObj, texImage, &retain);
1812 }
1813 if (retain || !success) {
1814 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001815 make_texture_image(ctx, 2, texImage, width, height, 1,
1816 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001817 if (!success && ctx->Driver.TexImage2D) {
1818 /* let device driver try to use unpacked image */
1819 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1820 GL_UNSIGNED_BYTE, texImage->Data,
1821 &_mesa_native_packing,
1822 texObj, texImage, &retain);
1823 }
1824 }
1825 if (!retain && texImage->Data) {
1826 FREE(texImage->Data);
1827 texImage->Data = NULL;
1828 }
jtgafb833d1999-08-19 00:55:39 +00001829 }
1830 else {
Brian Paul02938782000-03-22 17:38:11 +00001831 make_null_texture(texImage);
1832 if (ctx->Driver.TexImage2D) {
1833 GLboolean retain;
1834 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1835 GL_UNSIGNED_BYTE, texImage->Data,
1836 &_mesa_native_packing,
1837 texObj, texImage, &retain);
1838 }
jtgafb833d1999-08-19 00:55:39 +00001839 }
1840
Brian Paul02938782000-03-22 17:38:11 +00001841 /* state update */
1842 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00001843 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001844 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001845 else if (target == GL_PROXY_TEXTURE_2D) {
jtgafb833d1999-08-19 00:55:39 +00001846 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001847 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1848 format, type, 2, width, height, 1, border);
1849 if (!error && ctx->Driver.TestProxyTexImage) {
1850 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1851 internalFormat, format, type,
1852 width, height, 1, border);
1853 }
1854 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001855 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001856 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001857 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001858 }
1859 }
1860 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001861 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001862 init_texture_image(ctx,
1863 ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001864 width, height, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001865 }
jtgafb833d1999-08-19 00:55:39 +00001866 }
1867 else {
1868 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1869 return;
1870 }
1871}
1872
1873
jtgafb833d1999-08-19 00:55:39 +00001874/*
1875 * Called by the API or display list executor.
1876 * Note that width and height include the border.
1877 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001878void
Brian Paul43911c82000-03-21 00:49:33 +00001879_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001880 GLsizei width, GLsizei height, GLsizei depth,
1881 GLint border, GLenum format, GLenum type,
1882 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001883{
Brian Paulfbd8f211999-11-11 01:22:25 +00001884 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001885 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001886
Brian Paulfbd8f211999-11-11 01:22:25 +00001887 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001888 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001889 struct gl_texture_object *texObj;
1890 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001891 GLint ifmt;
1892
Brian Paul37a62112000-09-28 18:30:39 +00001893 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1894 &level,
1895 &width, &height, &depth,
1896 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001897 if (ifmt < 0) {
1898 /*
1899 * The error here is that we were sent a generic compressed
1900 * format, but the extension is not supported.
1901 */
1902 return;
1903 }
1904 else {
1905 internalFormat = ifmt;
1906 }
1907
Brian Paulaea66b12000-05-24 14:04:06 +00001908 if (texture_error_check(ctx, target, level, internalFormat,
1909 format, type, 3, width, height, depth, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001910 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001911 }
1912
Brian Paulf7b57072000-03-20 14:37:52 +00001913 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001914 texObj = texUnit->CurrentD[3];
1915 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001916
Brian Paul02938782000-03-22 17:38:11 +00001917 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001918 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001919 texObj->Image[level] = texImage;
1920 if (!texImage) {
1921 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1922 return;
1923 }
1924 }
1925 else if (texImage->Data) {
1926 FREE(texImage->Data);
1927 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001928 }
1929
Brian Paul02938782000-03-22 17:38:11 +00001930 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00001931 init_texture_image(ctx, texImage, width, height, depth,
Brian Paul02938782000-03-22 17:38:11 +00001932 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001933
Brian Paul9499e012000-10-30 16:32:42 +00001934 if (ctx->NewState & _NEW_PIXEL)
1935 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001936
Brian Paul02938782000-03-22 17:38:11 +00001937 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001938 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001939 GLboolean retain = GL_TRUE;
1940 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001941 if (!ctx->_ImageTransferState && ctx->Driver.TexImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00001942 /* let device driver try to use raw image */
1943 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1944 type, pixels, &ctx->Unpack,
1945 texObj, texImage, &retain);
1946 }
1947 if (retain || !success) {
1948 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001949 make_texture_image(ctx, 3, texImage, width, height, depth,
1950 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001951 if (!success && ctx->Driver.TexImage3D) {
1952 /* let device driver try to use unpacked image */
1953 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1954 GL_UNSIGNED_BYTE, texImage->Data,
1955 &_mesa_native_packing,
1956 texObj, texImage, &retain);
1957 }
1958 }
1959 if (!retain && texImage->Data) {
1960 FREE(texImage->Data);
1961 texImage->Data = NULL;
1962 }
jtgafb833d1999-08-19 00:55:39 +00001963 }
1964 else {
Brian Paul02938782000-03-22 17:38:11 +00001965 make_null_texture(texImage);
1966 if (ctx->Driver.TexImage3D) {
1967 GLboolean retain;
1968 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1969 GL_UNSIGNED_BYTE, texImage->Data,
1970 &_mesa_native_packing,
1971 texObj, texImage, &retain);
1972 }
jtgafb833d1999-08-19 00:55:39 +00001973 }
1974
Brian Paul02938782000-03-22 17:38:11 +00001975 /* state update */
1976 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00001977 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001978 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001979 else if (target == GL_PROXY_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00001980 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001981 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1982 format, type, 3, width, height, depth, border);
1983 if (!error && ctx->Driver.TestProxyTexImage) {
1984 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1985 internalFormat, format, type,
1986 width, height, depth, border);
1987 }
1988 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001989 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001990 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001991 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001992 }
1993 }
1994 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001995 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001996 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001997 width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001998 }
jtgafb833d1999-08-19 00:55:39 +00001999 }
2000 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00002001 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00002002 return;
2003 }
2004}
2005
2006
Brian Paul663049a2000-01-31 23:10:16 +00002007void
Brian Paul43911c82000-03-21 00:49:33 +00002008_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00002009 GLsizei width, GLsizei height, GLsizei depth,
2010 GLint border, GLenum format, GLenum type,
2011 const GLvoid *pixels )
2012{
Brian Paul43911c82000-03-21 00:49:33 +00002013 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00002014 depth, border, format, type, pixels);
2015}
2016
2017
Brian Paulf7b57072000-03-20 14:37:52 +00002018/*
2019 * Fetch a texture image from the device driver.
2020 * Store the results in the given texture object at the given mipmap level.
2021 */
Brian Paul021a5252000-03-27 17:54:17 +00002022void
2023_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2024 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00002025{
2026 GLvoid *image;
2027 GLenum imgFormat, imgType;
2028 GLboolean freeImage;
2029 struct gl_texture_image *texImage;
2030 GLint destComponents, numPixels, srcBytesPerTexel;
2031
2032 if (!ctx->Driver.GetTexImage)
2033 return;
2034
Brian Paul48271792000-03-29 18:13:59 +00002035 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00002036 &imgFormat, &imgType, &freeImage);
2037 if (!image)
2038 return;
2039
2040 texImage = texObj->Image[level];
2041 ASSERT(texImage);
2042 if (!texImage)
2043 return;
2044
2045 destComponents = components_in_intformat(texImage->Format);
2046 assert(destComponents > 0);
2047 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2048 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00002049 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00002050 assert(srcBytesPerTexel > 0);
2051
2052 if (!texImage->Data) {
2053 /* Allocate memory for the texture image data */
Brian Paul699bc7b2000-10-29 18:12:14 +00002054 texImage->Data = (GLchan *) MALLOC(numPixels * destComponents
2055 * sizeof(GLchan) + EXTRA_BYTE);
Brian Paulf7b57072000-03-20 14:37:52 +00002056 }
2057
2058 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2059 /* We got lucky! The driver's format and type match Mesa's format. */
2060 if (texImage->Data) {
2061 MEMCPY(texImage->Data, image, numPixels * destComponents);
2062 }
2063 }
2064 else {
2065 /* Convert the texture image from the driver's format to Mesa's
2066 * internal format.
2067 */
2068 const GLint width = texImage->Width;
2069 const GLint height = texImage->Height;
2070 const GLint depth = texImage->Depth;
2071 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2072 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2073 const GLenum dstType = GL_UNSIGNED_BYTE;
2074 const GLenum dstFormat = texImage->Format;
Brian Paul699bc7b2000-10-29 18:12:14 +00002075 const GLchan *srcPtr = (const GLchan *) image;
2076 GLchan *destPtr = texImage->Data;
Brian Paulf7b57072000-03-20 14:37:52 +00002077
2078 if (texImage->Format == GL_COLOR_INDEX) {
2079 /* color index texture */
2080 GLint img, row;
2081 assert(imgFormat == GL_COLOR_INDEX);
2082 for (img = 0; img < depth; img++) {
2083 for (row = 0; row < height; row++) {
2084 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002085 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002086 destPtr += destBytesPerRow;
2087 srcPtr += srcBytesPerRow;
2088 }
2089 }
2090 }
2091 else {
2092 /* color texture */
2093 GLint img, row;
2094 for (img = 0; img < depth; img++) {
2095 for (row = 0; row < height; row++) {
Brian Paul699bc7b2000-10-29 18:12:14 +00002096 _mesa_unpack_chan_color_span(ctx, width, dstFormat, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002097 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002098 destPtr += destBytesPerRow;
2099 srcPtr += srcBytesPerRow;
2100 }
2101 }
2102 }
2103 }
2104
2105 if (freeImage)
2106 FREE(image);
2107}
2108
jtgafb833d1999-08-19 00:55:39 +00002109
Brian Paul1873b562000-10-16 23:43:12 +00002110/*
2111 * Get all the mipmap images for a texture object from the device driver.
2112 * Actually, only get mipmap images if we're using a mipmap filter.
2113 */
2114GLboolean
2115_mesa_get_teximages_from_driver(GLcontext *ctx,
2116 struct gl_texture_object *texObj)
2117{
2118 if (ctx->Driver.GetTexImage) {
2119 static const GLenum targets[] = {
2120 GL_TEXTURE_1D,
2121 GL_TEXTURE_2D,
2122 GL_TEXTURE_3D,
2123 GL_TEXTURE_CUBE_MAP_ARB,
2124 GL_TEXTURE_CUBE_MAP_ARB,
2125 GL_TEXTURE_CUBE_MAP_ARB
2126 };
2127 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2128 GLenum target = targets[texObj->Dimensions - 1];
2129 if (needLambda) {
2130 GLint level;
2131 /* Get images for all mipmap levels. We might not need them
2132 * all but this is easier. We're on a (slow) software path
2133 * anyway.
2134 */
Keith Whitwell14940c42000-11-05 18:40:57 +00002135 for (level = 0; level <= texObj->_P; level++) {
Brian Paul1873b562000-10-16 23:43:12 +00002136 struct gl_texture_image *texImg = texObj->Image[level];
2137 if (texImg && !texImg->Data) {
2138 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2139 if (!texImg->Data)
2140 return GL_FALSE; /* out of memory */
2141 }
2142 }
2143 }
2144 else {
2145 GLint level = texObj->BaseLevel;
2146 struct gl_texture_image *texImg = texObj->Image[level];
2147 if (texImg && !texImg->Data) {
2148 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2149 if (!texImg->Data)
2150 return GL_FALSE; /* out of memory */
2151 }
2152 }
2153 return GL_TRUE;
2154 }
2155 return GL_FALSE;
2156}
2157
2158
2159
Brian Paulfbd8f211999-11-11 01:22:25 +00002160void
2161_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2162 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002163{
Brian Paulfbd8f211999-11-11 01:22:25 +00002164 GET_CURRENT_CONTEXT(ctx);
Brian Paul01e54752000-09-05 15:40:34 +00002165 const struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00002166 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00002167 struct gl_texture_image *texImage;
2168 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00002169
2170 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2171
2172 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2173 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2174 return;
2175 }
2176
Brian Paulb7d076f2000-03-21 01:03:40 +00002177 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002178 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2179 return;
2180 }
2181
Brian Paulb7d076f2000-03-21 01:03:40 +00002182 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002183 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2184 return;
2185 }
2186
2187 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00002188 return;
jtgafb833d1999-08-19 00:55:39 +00002189
Brian Paul01e54752000-09-05 15:40:34 +00002190 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2191 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Pauld45fdea2000-11-13 15:25:26 +00002192 if (!texObj ||
Brian Paulc52fc9b2000-09-05 22:11:38 +00002193 target == GL_PROXY_TEXTURE_1D ||
2194 target == GL_PROXY_TEXTURE_2D ||
2195 target == GL_PROXY_TEXTURE_3D) {
Brian Paul01e54752000-09-05 15:40:34 +00002196 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2197 return;
jtgafb833d1999-08-19 00:55:39 +00002198 }
2199
Brian Paul8e3366f2000-11-10 15:32:07 +00002200 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00002201 if (!texImage) {
Brian Paul7298e712000-11-07 16:40:37 +00002202 /* invalid mipmap level, not an error */
Brian Paulf7b57072000-03-20 14:37:52 +00002203 return;
2204 }
2205
2206 if (!texImage->Data) {
2207 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00002208 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00002209 discardImage = GL_TRUE;
2210 }
2211 else {
2212 discardImage = GL_FALSE;
2213 }
2214
2215 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00002216 GLint width = texImage->Width;
2217 GLint height = texImage->Height;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002218 GLint depth = texImage->Depth;
2219 GLint img, row;
jtgafb833d1999-08-19 00:55:39 +00002220
Brian Paul9499e012000-10-30 16:32:42 +00002221 if (ctx->NewState & _NEW_PIXEL)
2222 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002223
Keith Whitwell14940c42000-11-05 18:40:57 +00002224 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
Brian Paulf96ce6a2000-09-06 15:15:43 +00002225 /* convert texture image to GL_RGBA, GL_FLOAT */
2226 GLfloat *tmpImage, *convImage;
2227 const GLint comps = components_in_intformat(texImage->Format);
jtgafb833d1999-08-19 00:55:39 +00002228
Brian Paulf96ce6a2000-09-06 15:15:43 +00002229 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2230 if (!tmpImage) {
2231 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2232 return;
jtgafb833d1999-08-19 00:55:39 +00002233 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002234 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2235 if (!convImage) {
2236 FREE(tmpImage);
2237 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2238 return;
2239 }
2240
2241 for (img = 0; img < depth; img++) {
2242 GLint convWidth, convHeight;
2243
2244 /* convert to GL_RGBA */
2245 for (row = 0; row < height; row++) {
Brian Paul699bc7b2000-10-29 18:12:14 +00002246 const GLchan *src = texImage->Data
Brian Paulf96ce6a2000-09-06 15:15:43 +00002247 + (img * height + row ) * width * comps;
2248 GLfloat *dst = tmpImage + row * width * 4;
2249 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2250 texImage->Format, GL_UNSIGNED_BYTE,
2251 src, &_mesa_native_packing,
Keith Whitwell14940c42000-11-05 18:40:57 +00002252 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002253 GL_FALSE);
jtgafb833d1999-08-19 00:55:39 +00002254 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002255
2256 convWidth = width;
2257 convHeight = height;
2258
2259 /* convolve */
2260 if (target == GL_TEXTURE_1D) {
2261 if (ctx->Pixel.Convolution1DEnabled) {
2262 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2263 }
2264 }
2265 else {
2266 if (ctx->Pixel.Convolution2DEnabled) {
2267 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2268 tmpImage, convImage);
2269 }
2270 else if (ctx->Pixel.Separable2DEnabled) {
2271 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2272 tmpImage, convImage);
2273 }
2274 }
2275
2276 /* pack convolved image */
2277 for (row = 0; row < convHeight; row++) {
2278 const GLfloat *src = convImage + row * convWidth * 4;
2279 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2280 convWidth, convHeight,
2281 format, type, img, row, 0);
2282 _mesa_pack_float_rgba_span(ctx, convWidth,
2283 (const GLfloat(*)[4]) src,
2284 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002285 ctx->_ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
Brian Paulf96ce6a2000-09-06 15:15:43 +00002286 }
jtgafb833d1999-08-19 00:55:39 +00002287 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002288
2289 FREE(tmpImage);
2290 FREE(convImage);
jtgafb833d1999-08-19 00:55:39 +00002291 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002292 else {
2293 /* no convolution */
2294 for (img = 0; img < depth; img++) {
2295 for (row = 0; row < height; row++) {
2296 /* compute destination address in client memory */
2297 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2298 width, height, format, type, img, row, 0);
2299 assert(dest);
2300 if (texImage->Format == GL_RGBA) {
2301 /* simple case */
Brian Paul699bc7b2000-10-29 18:12:14 +00002302 const GLchan *src = texImage->Data
Brian Paulf96ce6a2000-09-06 15:15:43 +00002303 + (img * height + row ) * width * 4;
Brian Paul699bc7b2000-10-29 18:12:14 +00002304 _mesa_pack_rgba_span( ctx, width, (CONST GLchan (*)[4]) src,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002305 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002306 ctx->_ImageTransferState );
Brian Paulf96ce6a2000-09-06 15:15:43 +00002307 }
2308 else {
2309 /* general case: convert row to RGBA format */
Brian Paul699bc7b2000-10-29 18:12:14 +00002310 GLchan rgba[MAX_WIDTH][4];
Brian Paulf96ce6a2000-09-06 15:15:43 +00002311 GLint i;
Brian Paul699bc7b2000-10-29 18:12:14 +00002312 const GLchan *src;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002313 switch (texImage->Format) {
2314 case GL_ALPHA:
Brian Paul699bc7b2000-10-29 18:12:14 +00002315 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002316 for (i = 0; i < width; i++) {
Brian Paulba643a22000-10-28 18:34:48 +00002317 rgba[i][RCOMP] = CHAN_MAX;
2318 rgba[i][GCOMP] = CHAN_MAX;
2319 rgba[i][BCOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002320 rgba[i][ACOMP] = src[i];
2321 }
2322 break;
2323 case GL_LUMINANCE:
Brian Paul699bc7b2000-10-29 18:12:14 +00002324 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002325 for (i = 0; i < width; i++) {
2326 rgba[i][RCOMP] = src[i];
2327 rgba[i][GCOMP] = src[i];
2328 rgba[i][BCOMP] = src[i];
Brian Paulba643a22000-10-28 18:34:48 +00002329 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002330 }
2331 break;
2332 case GL_LUMINANCE_ALPHA:
Brian Paul699bc7b2000-10-29 18:12:14 +00002333 src = texImage->Data + row * 2 * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002334 for (i = 0; i < width; i++) {
2335 rgba[i][RCOMP] = src[i*2+0];
2336 rgba[i][GCOMP] = src[i*2+0];
2337 rgba[i][BCOMP] = src[i*2+0];
2338 rgba[i][ACOMP] = src[i*2+1];
2339 }
2340 break;
2341 case GL_INTENSITY:
Brian Paul699bc7b2000-10-29 18:12:14 +00002342 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002343 for (i = 0; i < width; i++) {
2344 rgba[i][RCOMP] = src[i];
2345 rgba[i][GCOMP] = src[i];
2346 rgba[i][BCOMP] = src[i];
Brian Paulba643a22000-10-28 18:34:48 +00002347 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002348 }
2349 break;
2350 case GL_RGB:
Brian Paul699bc7b2000-10-29 18:12:14 +00002351 src = texImage->Data + row * 3 * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002352 for (i = 0; i < width; i++) {
2353 rgba[i][RCOMP] = src[i*3+0];
2354 rgba[i][GCOMP] = src[i*3+1];
2355 rgba[i][BCOMP] = src[i*3+2];
Brian Paulba643a22000-10-28 18:34:48 +00002356 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002357 }
2358 break;
2359 case GL_COLOR_INDEX:
2360 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2361 break;
2362 case GL_RGBA:
2363 default:
2364 gl_problem( ctx, "bad format in gl_GetTexImage" );
2365 }
Brian Paul699bc7b2000-10-29 18:12:14 +00002366 _mesa_pack_rgba_span( ctx, width, (const GLchan (*)[4])rgba,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002367 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002368 ctx->_ImageTransferState );
Brian Paulf96ce6a2000-09-06 15:15:43 +00002369 } /* format */
2370 } /* row */
2371 } /* img */
2372 } /* convolution */
Brian Paulf7b57072000-03-20 14:37:52 +00002373
2374 /* if we got the teximage from the device driver we'll discard it now */
2375 if (discardImage) {
2376 FREE(texImage->Data);
2377 texImage->Data = NULL;
2378 }
jtgafb833d1999-08-19 00:55:39 +00002379 }
2380}
2381
2382
2383
Brian Paulfbd8f211999-11-11 01:22:25 +00002384void
2385_mesa_TexSubImage1D( GLenum target, GLint level,
2386 GLint xoffset, GLsizei width,
2387 GLenum format, GLenum type,
2388 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002389{
Brian Paulfbd8f211999-11-11 01:22:25 +00002390 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002391 struct gl_texture_unit *texUnit;
2392 struct gl_texture_object *texObj;
2393 struct gl_texture_image *texImage;
2394 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002395 GLsizei postConvWidth;
2396
2397 postConvWidth = width;
2398 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
jtgafb833d1999-08-19 00:55:39 +00002399
Brian Paulc3f0a511999-11-03 17:27:05 +00002400 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002401 postConvWidth, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002402 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002403 }
2404
Brian Paul02938782000-03-22 17:38:11 +00002405 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2406 texObj = texUnit->CurrentD[1];
2407 texImage = texObj->Image[level];
2408 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002409
Brian Paulc3f0a511999-11-03 17:27:05 +00002410 if (width == 0 || !pixels)
2411 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002412
Brian Paul9499e012000-10-30 16:32:42 +00002413 if (ctx->NewState & _NEW_PIXEL)
2414 gl_update_state(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002415
Keith Whitwell14940c42000-11-05 18:40:57 +00002416 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00002417 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2418 width, format, type, pixels,
2419 &ctx->Unpack, texObj, texImage );
2420 }
2421 if (!success) {
2422 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
Brian Paul02938782000-03-22 17:38:11 +00002423 GLboolean retain = GL_TRUE;
2424 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002425 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002426 if (!texImage->Data) {
2427 make_null_texture(texImage);
2428 }
2429 if (!texImage->Data)
2430 return; /* we're really out of luck! */
2431 }
2432
Brian Paula805bb92000-09-02 17:52:21 +00002433 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002434 width, 1, 1, xoffset + texImage->Border, 0, 0, /* size and offsets */
Brian Paula805bb92000-09-02 17:52:21 +00002435 0, 0, /* strides */
2436 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002437
2438 if (ctx->Driver.TexImage1D) {
2439 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2440 GL_UNSIGNED_BYTE, texImage->Data,
2441 &_mesa_native_packing, texObj, texImage,
2442 &retain );
2443 }
2444
2445 if (!retain && texImage->Data) {
2446 FREE(texImage->Data);
2447 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00002448 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002449 }
jtgafb833d1999-08-19 00:55:39 +00002450}
2451
2452
Brian Paulfbd8f211999-11-11 01:22:25 +00002453void
2454_mesa_TexSubImage2D( GLenum target, GLint level,
2455 GLint xoffset, GLint yoffset,
2456 GLsizei width, GLsizei height,
2457 GLenum format, GLenum type,
2458 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002459{
Brian Paulfbd8f211999-11-11 01:22:25 +00002460 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002461 struct gl_texture_unit *texUnit;
2462 struct gl_texture_object *texObj;
2463 struct gl_texture_image *texImage;
2464 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002465 GLsizei postConvWidth, postConvHeight;
2466
2467 postConvWidth = width;
2468 postConvHeight = height;
2469 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
jtgafb833d1999-08-19 00:55:39 +00002470
Brian Paulc3f0a511999-11-03 17:27:05 +00002471 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002472 postConvWidth, postConvHeight, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002473 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002474 }
2475
Brian Paul02938782000-03-22 17:38:11 +00002476 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00002477 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paul02938782000-03-22 17:38:11 +00002478 texImage = texObj->Image[level];
2479 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002480
Brian Paulc3f0a511999-11-03 17:27:05 +00002481 if (width == 0 || height == 0 || !pixels)
2482 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002483
Brian Paul9499e012000-10-30 16:32:42 +00002484 if (ctx->NewState & _NEW_PIXEL)
2485 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002486
Keith Whitwell14940c42000-11-05 18:40:57 +00002487 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00002488 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2489 yoffset, width, height, format, type,
2490 pixels, &ctx->Unpack, texObj, texImage );
2491 }
2492 if (!success) {
2493 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002494 const GLint texComps = components_in_intformat(texImage->Format);
Brian Paul699bc7b2000-10-29 18:12:14 +00002495 const GLint texRowStride = texImage->Width * texComps;
Brian Paul02938782000-03-22 17:38:11 +00002496 GLboolean retain = GL_TRUE;
2497
2498 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002499 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002500 if (!texImage->Data) {
2501 make_null_texture(texImage);
2502 }
2503 if (!texImage->Data)
2504 return; /* we're really out of luck! */
2505 }
2506
Brian Paula805bb92000-09-02 17:52:21 +00002507 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002508 width, height, 1, xoffset + texImage->Border,
2509 yoffset + texImage->Border, 0, texRowStride, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002510 format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00002511
Brian Paul02938782000-03-22 17:38:11 +00002512 if (ctx->Driver.TexImage2D) {
2513 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2514 GL_UNSIGNED_BYTE, texImage->Data,
2515 &_mesa_native_packing, texObj, texImage,
2516 &retain);
jtgafb833d1999-08-19 00:55:39 +00002517 }
Brian Paul02938782000-03-22 17:38:11 +00002518
2519 if (!retain && texImage->Data) {
2520 FREE(texImage->Data);
2521 texImage->Data = NULL;
2522 }
jtgafb833d1999-08-19 00:55:39 +00002523 }
2524}
2525
2526
2527
Brian Paulfbd8f211999-11-11 01:22:25 +00002528void
2529_mesa_TexSubImage3D( GLenum target, GLint level,
2530 GLint xoffset, GLint yoffset, GLint zoffset,
2531 GLsizei width, GLsizei height, GLsizei depth,
2532 GLenum format, GLenum type,
2533 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002534{
Brian Paulfbd8f211999-11-11 01:22:25 +00002535 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002536 struct gl_texture_unit *texUnit;
2537 struct gl_texture_object *texObj;
2538 struct gl_texture_image *texImage;
2539 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002540
Brian Paulc3f0a511999-11-03 17:27:05 +00002541 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2542 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002543 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002544 }
2545
Brian Paul02938782000-03-22 17:38:11 +00002546 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2547 texObj = texUnit->CurrentD[3];
2548 texImage = texObj->Image[level];
2549 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002550
Brian Paulc3f0a511999-11-03 17:27:05 +00002551 if (width == 0 || height == 0 || height == 0 || !pixels)
2552 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002553
Brian Paul9499e012000-10-30 16:32:42 +00002554 if (ctx->NewState & _NEW_PIXEL)
2555 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002556
Keith Whitwell14940c42000-11-05 18:40:57 +00002557 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00002558 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2559 yoffset, zoffset, width, height, depth, format,
2560 type, pixels, &ctx->Unpack, texObj, texImage );
2561 }
2562 if (!success) {
2563 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002564 const GLint texComps = components_in_intformat(texImage->Format);
Brian Paul699bc7b2000-10-29 18:12:14 +00002565 const GLint texRowStride = texImage->Width * texComps;
Brian Paula805bb92000-09-02 17:52:21 +00002566 const GLint texImgStride = texRowStride * texImage->Height;
Brian Paul02938782000-03-22 17:38:11 +00002567 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00002568
Brian Paula805bb92000-09-02 17:52:21 +00002569 if (!texImage->Data) {
2570 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2571 if (!texImage->Data) {
2572 make_null_texture(texImage);
jtgafb833d1999-08-19 00:55:39 +00002573 }
Brian Paula805bb92000-09-02 17:52:21 +00002574 if (!texImage->Data)
2575 return; /* we're really out of luck! */
jtgafb833d1999-08-19 00:55:39 +00002576 }
Brian Paula805bb92000-09-02 17:52:21 +00002577
2578 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002579 width, height, depth, xoffset + texImage->Border,
2580 yoffset + texImage->Border,
2581 zoffset + texImage->Border, texRowStride,
2582 texImgStride, format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002583
2584 if (ctx->Driver.TexImage3D) {
2585 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2586 GL_UNSIGNED_BYTE, texImage->Data,
2587 &_mesa_native_packing, texObj, texImage,
2588 &retain);
2589 }
2590
2591 if (!retain && texImage->Data) {
2592 FREE(texImage->Data);
2593 texImage->Data = NULL;
2594 }
jtgafb833d1999-08-19 00:55:39 +00002595 }
jtgafb833d1999-08-19 00:55:39 +00002596}
2597
2598
2599
2600/*
2601 * Read an RGBA image from the frame buffer.
Brian Paula805bb92000-09-02 17:52:21 +00002602 * This is used by glCopyTex[Sub]Image[12]D().
jtgafb833d1999-08-19 00:55:39 +00002603 * Input: ctx - the context
2604 * x, y - lower left corner
2605 * width, height - size of region to read
Brian Paul699bc7b2000-10-29 18:12:14 +00002606 * Return: pointer to block of GL_RGBA, GLchan data.
jtgafb833d1999-08-19 00:55:39 +00002607 */
Brian Paul699bc7b2000-10-29 18:12:14 +00002608static GLchan *
Brian Paulc3f0a511999-11-03 17:27:05 +00002609read_color_image( GLcontext *ctx, GLint x, GLint y,
2610 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00002611{
Brian Paulc3f0a511999-11-03 17:27:05 +00002612 GLint stride, i;
Brian Paul699bc7b2000-10-29 18:12:14 +00002613 GLchan *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00002614
Brian Paul699bc7b2000-10-29 18:12:14 +00002615 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
Brian Paulc3f0a511999-11-03 17:27:05 +00002616 if (!image)
jtgafb833d1999-08-19 00:55:39 +00002617 return NULL;
jtgafb833d1999-08-19 00:55:39 +00002618
2619 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002620 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2621 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002622
Brian Paulc3f0a511999-11-03 17:27:05 +00002623 dst = image;
Brian Paul699bc7b2000-10-29 18:12:14 +00002624 stride = width * 4;
Brian Paulc3f0a511999-11-03 17:27:05 +00002625 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00002626 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
Brian Paul699bc7b2000-10-29 18:12:14 +00002627 (GLchan (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00002628 dst += stride;
2629 }
jtgafb833d1999-08-19 00:55:39 +00002630
Brian Paulcea0e8e1999-11-25 17:36:48 +00002631 /* Read from draw buffer (the default) */
2632 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2633 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002634
2635 return image;
2636}
2637
2638
2639
Brian Paulfbd8f211999-11-11 01:22:25 +00002640void
2641_mesa_CopyTexImage1D( GLenum target, GLint level,
2642 GLenum internalFormat,
2643 GLint x, GLint y,
2644 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00002645{
Brian Paulfbd8f211999-11-11 01:22:25 +00002646 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002647 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00002648
Brian Paulf7b57072000-03-20 14:37:52 +00002649 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2650 width, 1, border))
2651 return;
2652
Brian Paul9499e012000-10-30 16:32:42 +00002653 if (ctx->NewState & _NEW_PIXEL)
2654 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002655
Keith Whitwell14940c42000-11-05 18:40:57 +00002656 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002657 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002658 internalFormat, x, y, width, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002659 struct gl_pixelstore_attrib unpackSave;
2660
2661 /* get image from framebuffer */
Brian Paul699bc7b2000-10-29 18:12:14 +00002662 GLchan *image = read_color_image( ctx, x, y, width, 1 );
Brian Paulc3f0a511999-11-03 17:27:05 +00002663 if (!image) {
2664 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2665 return;
2666 }
Brian Paul7dac1322000-06-15 19:57:14 +00002667
2668 /* call glTexImage1D to redefine the texture */
2669 unpackSave = ctx->Unpack;
2670 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002671 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002672 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002673 ctx->Unpack = unpackSave;
2674
Brian Paulc3f0a511999-11-03 17:27:05 +00002675 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002676 }
jtgafb833d1999-08-19 00:55:39 +00002677}
2678
2679
2680
Brian Paulfbd8f211999-11-11 01:22:25 +00002681void
2682_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2683 GLint x, GLint y, GLsizei width, GLsizei height,
2684 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002685{
Brian Paulfbd8f211999-11-11 01:22:25 +00002686 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002687 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002688
Brian Paulf7b57072000-03-20 14:37:52 +00002689 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2690 width, height, border))
2691 return;
2692
Brian Paul9499e012000-10-30 16:32:42 +00002693 if (ctx->NewState & _NEW_PIXEL)
2694 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002695
Keith Whitwell14940c42000-11-05 18:40:57 +00002696 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002697 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002698 internalFormat, x, y, width, height, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002699 struct gl_pixelstore_attrib unpackSave;
2700
2701 /* get image from framebuffer */
Brian Paul699bc7b2000-10-29 18:12:14 +00002702 GLchan *image = read_color_image( ctx, x, y, width, height );
Brian Paulc3f0a511999-11-03 17:27:05 +00002703 if (!image) {
2704 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2705 return;
2706 }
Brian Paul7dac1322000-06-15 19:57:14 +00002707
2708 /* call glTexImage2D to redefine the texture */
2709 unpackSave = ctx->Unpack;
2710 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002711 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002712 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002713 ctx->Unpack = unpackSave;
2714
Brian Paulc3f0a511999-11-03 17:27:05 +00002715 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002716 }
jtgafb833d1999-08-19 00:55:39 +00002717}
2718
2719
2720
Brian Paulfbd8f211999-11-11 01:22:25 +00002721void
2722_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2723 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002724{
Brian Paulfbd8f211999-11-11 01:22:25 +00002725 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002726 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002727
Brian Paulf7b57072000-03-20 14:37:52 +00002728 if (copytexsubimage_error_check(ctx, 1, target, level,
2729 xoffset, 0, 0, width, 1))
2730 return;
2731
Brian Paul9499e012000-10-30 16:32:42 +00002732 if (ctx->NewState & _NEW_PIXEL)
2733 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002734
Keith Whitwell14940c42000-11-05 18:40:57 +00002735 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002736 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2737 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002738 struct gl_texture_unit *texUnit;
2739 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002740 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002741 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002742
Brian Paulc3f0a511999-11-03 17:27:05 +00002743 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2744 teximage = texUnit->CurrentD[1]->Image[level];
2745 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002746
2747 /* get image from frame buffer */
2748 image = read_color_image(ctx, x, y, width, 1);
2749 if (!image) {
2750 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2751 return;
jtgafb833d1999-08-19 00:55:39 +00002752 }
Brian Paul7dac1322000-06-15 19:57:14 +00002753
2754 /* now call glTexSubImage1D to do the real work */
2755 unpackSave = ctx->Unpack;
2756 ctx->Unpack = _mesa_native_packing;
2757 _mesa_TexSubImage1D(target, level, xoffset, width,
2758 GL_RGBA, GL_UNSIGNED_BYTE, image);
2759 ctx->Unpack = unpackSave;
2760
2761 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002762 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002763}
2764
2765
2766
Brian Paulfbd8f211999-11-11 01:22:25 +00002767void
2768_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2769 GLint xoffset, GLint yoffset,
2770 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002771{
Brian Paulfbd8f211999-11-11 01:22:25 +00002772 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002773 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2774
Brian Paulf7b57072000-03-20 14:37:52 +00002775 if (copytexsubimage_error_check(ctx, 2, target, level,
2776 xoffset, yoffset, 0, width, height))
2777 return;
2778
Brian Paul9499e012000-10-30 16:32:42 +00002779 if (ctx->NewState & _NEW_PIXEL)
2780 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002781
Keith Whitwell14940c42000-11-05 18:40:57 +00002782 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002783 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2784 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002785 struct gl_texture_unit *texUnit;
2786 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002787 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002788 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002789
Brian Paulc3f0a511999-11-03 17:27:05 +00002790 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2791 teximage = texUnit->CurrentD[2]->Image[level];
2792 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002793
2794 /* get image from frame buffer */
2795 image = read_color_image(ctx, x, y, width, height);
2796 if (!image) {
2797 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2798 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002799 }
Brian Paul7dac1322000-06-15 19:57:14 +00002800
2801 /* now call glTexSubImage2D to do the real work */
2802 unpackSave = ctx->Unpack;
2803 ctx->Unpack = _mesa_native_packing;
2804 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2805 GL_RGBA, GL_UNSIGNED_BYTE, image);
2806 ctx->Unpack = unpackSave;
2807
2808 FREE(image);
Brian Paulc3f0a511999-11-03 17:27:05 +00002809 }
2810}
2811
2812
2813
Brian Paulfbd8f211999-11-11 01:22:25 +00002814void
2815_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2816 GLint xoffset, GLint yoffset, GLint zoffset,
2817 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002818{
Brian Paulfbd8f211999-11-11 01:22:25 +00002819 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002820 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2821
Brian Paulf7b57072000-03-20 14:37:52 +00002822 if (copytexsubimage_error_check(ctx, 3, target, level,
2823 xoffset, yoffset, zoffset, width, height))
2824 return;
2825
Brian Paul9499e012000-10-30 16:32:42 +00002826 if (ctx->NewState & _NEW_PIXEL)
2827 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002828
Keith Whitwell14940c42000-11-05 18:40:57 +00002829 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage3D
Brian Paulf7b57072000-03-20 14:37:52 +00002830 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002831 xoffset, yoffset, zoffset, x, y, width, height )) {
2832 struct gl_texture_unit *texUnit;
2833 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002834 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002835 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002836
Brian Paul02938782000-03-22 17:38:11 +00002837 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2838 teximage = texUnit->CurrentD[3]->Image[level];
2839 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002840
2841 /* get image from frame buffer */
2842 image = read_color_image(ctx, x, y, width, height);
2843 if (!image) {
2844 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2845 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002846 }
Brian Paul7dac1322000-06-15 19:57:14 +00002847
2848 /* now call glTexSubImage2D to do the real work */
2849 unpackSave = ctx->Unpack;
2850 ctx->Unpack = _mesa_native_packing;
2851 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2852 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2853 ctx->Unpack = unpackSave;
2854
2855 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002856 }
2857}
Brian Paul1207bf02000-05-23 20:10:49 +00002858
2859
2860
2861void
2862_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002863 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002864 GLint border, GLsizei imageSize,
2865 const GLvoid *data)
2866{
Brian Paulaea66b12000-05-24 14:04:06 +00002867 GET_CURRENT_CONTEXT(ctx);
2868 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2869
Brian Paul289d47e2000-08-29 23:31:23 +00002870 switch (internalFormat) {
2871 case GL_COMPRESSED_ALPHA_ARB:
2872 case GL_COMPRESSED_LUMINANCE_ARB:
2873 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2874 case GL_COMPRESSED_INTENSITY_ARB:
2875 case GL_COMPRESSED_RGB_ARB:
2876 case GL_COMPRESSED_RGBA_ARB:
2877 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2878 return;
2879 default:
2880 /* silence compiler warning */
2881 ;
2882 }
2883
Brian Paulaea66b12000-05-24 14:04:06 +00002884 if (target == GL_TEXTURE_1D) {
2885 struct gl_texture_unit *texUnit;
2886 struct gl_texture_object *texObj;
2887 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002888 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002889
2890 if (texture_error_check(ctx, target, level, internalFormat,
2891 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2892 return; /* error in texture image was detected */
2893 }
2894
2895 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2896 texObj = texUnit->CurrentD[1];
2897 texImage = texObj->Image[level];
2898
2899 if (!texImage) {
2900 texImage = _mesa_alloc_texture_image();
2901 texObj->Image[level] = texImage;
2902 if (!texImage) {
2903 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2904 return;
2905 }
2906 }
2907 else if (texImage->Data) {
2908 FREE(texImage->Data);
2909 texImage->Data = NULL;
2910 }
2911
2912 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00002913 init_texture_image(ctx, texImage, width, 1, 1,
2914 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00002915
2916 /* process the texture image */
2917 if (data) {
2918 GLboolean retain = GL_TRUE;
2919 GLboolean success = GL_FALSE;
2920 if (ctx->Driver.CompressedTexImage1D) {
Brian Paul289d47e2000-08-29 23:31:23 +00002921 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2922 imageSize, data, texObj, texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002923 }
2924 if (retain || !success) {
2925 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00002926 computedImageSize = _mesa_compressed_image_size(ctx,
2927 internalFormat,
2928 1, /* num dims */
2929 width,
2930 1, /* height */
2931 1); /* depth */
2932 if (computedImageSize != imageSize) {
2933 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2934 return;
2935 }
2936 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002937 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00002938 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002939 }
2940 }
2941 if (!retain && texImage->Data) {
2942 FREE(texImage->Data);
2943 texImage->Data = NULL;
2944 }
2945 }
2946 else {
2947 make_null_texture(texImage);
2948 if (ctx->Driver.CompressedTexImage1D) {
2949 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00002950 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2951 texImage->Data, texObj,
2952 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002953 }
2954 }
2955
2956 /* state update */
2957 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00002958 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00002959 }
2960 else if (target == GL_PROXY_TEXTURE_1D) {
2961 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00002962 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2963 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2964 if (!error && ctx->Driver.TestProxyTexImage) {
2965 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2966 internalFormat, GL_NONE, GL_NONE,
2967 width, 1, 1, border);
2968 }
2969 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00002970 /* if error, clear all proxy texture image parameters */
2971 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00002972 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00002973 }
2974 }
2975 else {
2976 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002977 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002978 width, 1, 1, border, internalFormat);
2979 }
2980 }
2981 else {
2982 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2983 return;
2984 }
Brian Paul1207bf02000-05-23 20:10:49 +00002985}
2986
2987
2988void
2989_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002990 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002991 GLsizei height, GLint border, GLsizei imageSize,
2992 const GLvoid *data)
2993{
Brian Paulaea66b12000-05-24 14:04:06 +00002994 GET_CURRENT_CONTEXT(ctx);
2995 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2996
Brian Paul289d47e2000-08-29 23:31:23 +00002997 switch (internalFormat) {
2998 case GL_COMPRESSED_ALPHA_ARB:
2999 case GL_COMPRESSED_LUMINANCE_ARB:
3000 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3001 case GL_COMPRESSED_INTENSITY_ARB:
3002 case GL_COMPRESSED_RGB_ARB:
3003 case GL_COMPRESSED_RGBA_ARB:
3004 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3005 return;
3006 default:
3007 /* silence compiler warning */
3008 ;
3009 }
3010
Brian Paul9540a1d2000-06-06 17:03:38 +00003011 if (target==GL_TEXTURE_2D ||
Keith Whitwella96308c2000-10-30 13:31:59 +00003012 (ctx->Extensions.ARB_texture_cube_map &&
Brian Paul9540a1d2000-06-06 17:03:38 +00003013 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3014 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulaea66b12000-05-24 14:04:06 +00003015 struct gl_texture_unit *texUnit;
3016 struct gl_texture_object *texObj;
3017 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00003018 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00003019
3020 if (texture_error_check(ctx, target, level, internalFormat,
3021 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3022 return; /* error in texture image was detected */
3023 }
3024
3025 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3026 texObj = texUnit->CurrentD[2];
3027 texImage = texObj->Image[level];
3028
3029 if (!texImage) {
3030 texImage = _mesa_alloc_texture_image();
3031 texObj->Image[level] = texImage;
3032 if (!texImage) {
3033 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3034 return;
3035 }
3036 }
3037 else if (texImage->Data) {
3038 FREE(texImage->Data);
3039 texImage->Data = NULL;
3040 }
3041
3042 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003043 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003044
3045 /* process the texture image */
3046 if (data) {
3047 GLboolean retain = GL_TRUE;
3048 GLboolean success = GL_FALSE;
3049 if (ctx->Driver.CompressedTexImage2D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003050 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3051 target,
3052 level,
3053 imageSize,
3054 data,
3055 texObj,
3056 texImage,
3057 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003058 }
3059 if (retain || !success) {
3060 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003061 computedImageSize = _mesa_compressed_image_size(ctx,
3062 internalFormat,
3063 2, /* num dims */
3064 width,
3065 height,
3066 1); /* depth */
3067 if (computedImageSize != imageSize) {
3068 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3069 return;
3070 }
3071 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003072 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003073 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003074 }
3075 }
3076 if (!retain && texImage->Data) {
3077 FREE(texImage->Data);
3078 texImage->Data = NULL;
3079 }
3080 }
3081 else {
3082 make_null_texture(texImage);
3083 if (ctx->Driver.CompressedTexImage2D) {
3084 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003085 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3086 texImage->Data, texObj,
3087 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003088 }
3089 }
3090
3091 /* state update */
3092 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00003093 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00003094 }
3095 else if (target == GL_PROXY_TEXTURE_2D) {
3096 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003097 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3098 GL_NONE, GL_NONE, 2, width, height, 1, border);
3099 if (!error && ctx->Driver.TestProxyTexImage) {
3100 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3101 internalFormat, GL_NONE, GL_NONE,
3102 width, height, 1, border);
3103 }
3104 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003105 /* if error, clear all proxy texture image parameters */
3106 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003107 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003108 }
3109 }
3110 else {
3111 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003112 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003113 width, 1, 1, border, internalFormat);
3114 }
3115 }
3116 else {
3117 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3118 return;
3119 }
Brian Paul1207bf02000-05-23 20:10:49 +00003120}
3121
3122
3123void
3124_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00003125 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00003126 GLsizei height, GLsizei depth, GLint border,
3127 GLsizei imageSize, const GLvoid *data)
3128{
Brian Paulaea66b12000-05-24 14:04:06 +00003129 GET_CURRENT_CONTEXT(ctx);
3130 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3131
Brian Paul289d47e2000-08-29 23:31:23 +00003132 switch (internalFormat) {
3133 case GL_COMPRESSED_ALPHA_ARB:
3134 case GL_COMPRESSED_LUMINANCE_ARB:
3135 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3136 case GL_COMPRESSED_INTENSITY_ARB:
3137 case GL_COMPRESSED_RGB_ARB:
3138 case GL_COMPRESSED_RGBA_ARB:
3139 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3140 return;
3141 default:
3142 /* silence compiler warning */
3143 ;
3144 }
3145
Brian Paul9540a1d2000-06-06 17:03:38 +00003146 if (target == GL_TEXTURE_3D) {
Brian Paulaea66b12000-05-24 14:04:06 +00003147 struct gl_texture_unit *texUnit;
3148 struct gl_texture_object *texObj;
3149 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00003150 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00003151
3152 if (texture_error_check(ctx, target, level, internalFormat,
3153 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3154 return; /* error in texture image was detected */
3155 }
3156
3157 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3158 texObj = texUnit->CurrentD[3];
3159 texImage = texObj->Image[level];
3160
3161 if (!texImage) {
3162 texImage = _mesa_alloc_texture_image();
3163 texObj->Image[level] = texImage;
3164 if (!texImage) {
3165 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3166 return;
3167 }
3168 }
3169 else if (texImage->Data) {
3170 FREE(texImage->Data);
3171 texImage->Data = NULL;
3172 }
3173
3174 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003175 init_texture_image(ctx, texImage, width, height, depth,
3176 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003177
3178 /* process the texture image */
3179 if (data) {
3180 GLboolean retain = GL_TRUE;
3181 GLboolean success = GL_FALSE;
3182 if (ctx->Driver.CompressedTexImage3D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003183 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3184 imageSize, data,
3185 texObj, texImage,
3186 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003187 }
3188 if (retain || !success) {
3189 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003190 computedImageSize = _mesa_compressed_image_size(ctx,
3191 internalFormat,
3192 3, /* num dims */
3193 width,
3194 height,
3195 depth);
3196 if (computedImageSize != imageSize) {
3197 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3198 return;
3199 }
3200 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003201 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003202 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003203 }
3204 }
3205 if (!retain && texImage->Data) {
3206 FREE(texImage->Data);
3207 texImage->Data = NULL;
3208 }
3209 }
3210 else {
3211 make_null_texture(texImage);
3212 if (ctx->Driver.CompressedTexImage3D) {
3213 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003214 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3215 texImage->Data, texObj,
3216 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003217 }
3218 }
3219
3220 /* state update */
3221 gl_put_texobj_on_dirty_list( ctx, texObj );
Keith Whitwella96308c2000-10-30 13:31:59 +00003222 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00003223 }
3224 else if (target == GL_PROXY_TEXTURE_3D) {
3225 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003226 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3227 GL_NONE, GL_NONE, 1, width, height, depth, border);
3228 if (!error && ctx->Driver.TestProxyTexImage) {
3229 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3230 internalFormat, GL_NONE, GL_NONE,
3231 width, height, depth, border);
3232 }
3233 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003234 /* if error, clear all proxy texture image parameters */
3235 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003236 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003237 }
3238 }
3239 else {
3240 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003241 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003242 width, 1, 1, border, internalFormat);
3243 }
3244 }
3245 else {
3246 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3247 return;
3248 }
Brian Paul1207bf02000-05-23 20:10:49 +00003249}
3250
3251
3252void
3253_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3254 GLsizei width, GLenum format,
3255 GLsizei imageSize, const GLvoid *data)
3256{
Brian Paul9540a1d2000-06-06 17:03:38 +00003257 GET_CURRENT_CONTEXT(ctx);
3258 struct gl_texture_unit *texUnit;
3259 struct gl_texture_object *texObj;
3260 struct gl_texture_image *texImage;
3261 GLboolean success = GL_FALSE;
3262
3263 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3264 width, 1, 1, format, GL_NONE)) {
3265 return; /* error was detected */
3266 }
3267
3268 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3269 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3270 texImage = texObj->Image[level];
3271 assert(texImage);
3272
3273 if (width == 0 || !data)
3274 return; /* no-op, not an error */
3275
3276 if (ctx->Driver.CompressedTexSubImage1D) {
3277 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3278 xoffset, width, format, imageSize, data, texObj, texImage);
3279 }
3280 if (!success) {
3281 /* XXX what else can we do? */
3282 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3283 return;
3284 }
Brian Paul1207bf02000-05-23 20:10:49 +00003285}
3286
3287
3288void
3289_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3290 GLint yoffset, GLsizei width, GLsizei height,
3291 GLenum format, GLsizei imageSize,
3292 const GLvoid *data)
3293{
Brian Paul9540a1d2000-06-06 17:03:38 +00003294 GET_CURRENT_CONTEXT(ctx);
3295 struct gl_texture_unit *texUnit;
3296 struct gl_texture_object *texObj;
3297 struct gl_texture_image *texImage;
3298 GLboolean success = GL_FALSE;
3299
3300 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3301 width, height, 1, format, GL_NONE)) {
3302 return; /* error was detected */
3303 }
3304
3305 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3306 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3307 texImage = texObj->Image[level];
3308 assert(texImage);
3309
3310 if (width == 0 || height == 0 || !data)
3311 return; /* no-op, not an error */
3312
3313 if (ctx->Driver.CompressedTexSubImage2D) {
3314 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3315 xoffset, yoffset, width, height, format,
3316 imageSize, data, texObj, texImage);
3317 }
3318 if (!success) {
3319 /* XXX what else can we do? */
3320 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3321 return;
3322 }
Brian Paul1207bf02000-05-23 20:10:49 +00003323}
3324
3325
3326void
3327_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3328 GLint yoffset, GLint zoffset, GLsizei width,
3329 GLsizei height, GLsizei depth, GLenum format,
3330 GLsizei imageSize, const GLvoid *data)
3331{
Brian Paul9540a1d2000-06-06 17:03:38 +00003332 GET_CURRENT_CONTEXT(ctx);
3333 struct gl_texture_unit *texUnit;
3334 struct gl_texture_object *texObj;
3335 struct gl_texture_image *texImage;
3336 GLboolean success = GL_FALSE;
3337
3338 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3339 width, height, depth, format, GL_NONE)) {
3340 return; /* error was detected */
3341 }
3342
3343 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3344 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3345 texImage = texObj->Image[level];
3346 assert(texImage);
3347
3348 if (width == 0 || height == 0 || depth == 0 || !data)
3349 return; /* no-op, not an error */
3350
3351 if (ctx->Driver.CompressedTexSubImage3D) {
3352 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3353 xoffset, yoffset, zoffset, width, height, depth,
3354 format, imageSize, data, texObj, texImage);
3355 }
3356 if (!success) {
3357 /* XXX what else can we do? */
3358 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3359 return;
3360 }
Brian Paul1207bf02000-05-23 20:10:49 +00003361}
3362
3363
3364void
Brian Paul9540a1d2000-06-06 17:03:38 +00003365_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
Brian Paul1207bf02000-05-23 20:10:49 +00003366{
Brian Paul9540a1d2000-06-06 17:03:38 +00003367 GET_CURRENT_CONTEXT(ctx);
3368 const struct gl_texture_object *texObj;
3369 struct gl_texture_image *texImage;
3370
3371 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3372
3373 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3374 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3375 return;
3376 }
3377
3378 switch (target) {
3379 case GL_TEXTURE_1D:
3380 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3381 texImage = texObj->Image[level];
3382 break;
3383 case GL_TEXTURE_2D:
3384 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3385 texImage = texObj->Image[level];
3386 break;
3387 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3388 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3389 texImage = texObj->Image[level];
3390 break;
3391 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3392 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3393 texImage = texObj->NegX[level];
3394 break;
3395 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3396 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3397 texImage = texObj->PosY[level];
3398 break;
3399 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3400 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3401 texImage = texObj->NegY[level];
3402 break;
3403 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3404 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3405 texImage = texObj->PosZ[level];
3406 break;
3407 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3408 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3409 texImage = texObj->NegZ[level];
3410 break;
3411 case GL_TEXTURE_3D:
3412 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3413 texImage = texObj->Image[level];
3414 break;
3415 default:
3416 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3417 return;
3418 }
3419
3420 if (!texImage) {
3421 /* invalid mipmap level */
3422 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3423 return;
3424 }
3425
3426 if (!texImage->IsCompressed) {
3427 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3428 return;
3429 }
3430
3431 if (!img)
3432 return;
3433
3434 if (ctx->Driver.GetCompressedTexImage) {
3435 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3436 texImage);
3437 }
3438 else {
3439 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3440 }
Brian Paul1207bf02000-05-23 20:10:49 +00003441}