blob: cb91c379f88ef1168eb82f2fde7b73f72784da47 [file] [log] [blame]
Brian Paulec153982000-12-08 18:09:33 +00001/* $Id: teximage.c,v 1.66 2000/12/08 18:09:33 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
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00006 *
Brian Paul663049a2000-01-31 23:10:16 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00008 *
jtgafb833d1999-08-19 00:55:39 +00009 * 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:
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000015 *
jtgafb833d1999-08-19 00:55:39 +000016 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000018 *
jtgafb833d1999-08-19 00:55:39 +000019 * 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"
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +000041#include "mtypes.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:
Brian Paula8523782000-11-19 23:10:25 +0000547 return texUnit->Current1D;
Brian Paul35d53012000-05-23 17:14:49 +0000548 case GL_PROXY_TEXTURE_1D:
549 return ctx->Texture.Proxy1D;
550 case GL_TEXTURE_2D:
Brian Paula8523782000-11-19 23:10:25 +0000551 return texUnit->Current2D;
Brian Paul35d53012000-05-23 17:14:49 +0000552 case GL_PROXY_TEXTURE_2D:
553 return ctx->Texture.Proxy2D;
554 case GL_TEXTURE_3D:
Brian Paula8523782000-11-19 23:10:25 +0000555 return texUnit->Current3D;
Brian Paul35d53012000-05-23 17:14:49 +0000556 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:
Brian Paula8523782000-11-19 23:10:25 +0000587 return texUnit->Current1D->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000588 case GL_PROXY_TEXTURE_1D:
589 return ctx->Texture.Proxy1D->Image[level];
590 case GL_TEXTURE_2D:
Brian Paula8523782000-11-19 23:10:25 +0000591 return texUnit->Current2D->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000592 case GL_PROXY_TEXTURE_2D:
593 return ctx->Texture.Proxy2D->Image[level];
594 case GL_TEXTURE_3D:
Brian Paula8523782000-11-19 23:10:25 +0000595 return texUnit->Current3D->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000596 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 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000762 }
Brian Paula805bb92000-09-02 17:52:21 +0000763
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 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +0000832 else {
Brian Paula805bb92000-09-02 17:52:21 +0000833 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];
Brian Paulec153982000-12-08 18:09:33 +00001087 sprintf(message, "glTexImage%dD(border=%d)", dimensions, border);
Brian Paulc3f0a511999-11-03 17:27:05 +00001088 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];
Brian Paulec153982000-12-08 18:09:33 +00001098 sprintf(message, "glTexImage%dD(width=%d)", dimensions, width);
Brian Paulc3f0a511999-11-03 17:27:05 +00001099 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];
Brian Paulec153982000-12-08 18:09:33 +00001110 sprintf(message, "glTexImage%dD(height=%d)", dimensions, height);
Brian Paulc3f0a511999-11-03 17:27:05 +00001111 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) {
Brian Paulec153982000-12-08 18:09:33 +00001133 char message[100];
1134 sprintf(message, "glTexImage3D(depth=%d)", depth );
1135 gl_error( ctx, GL_INVALID_VALUE, message );
jtgafb833d1999-08-19 00:55:39 +00001136 }
1137 return GL_TRUE;
1138 }
1139 }
1140
1141 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001142 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001143 if (!isProxy) {
1144 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001145 sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
Brian Paulc3f0a511999-11-03 17:27:05 +00001146 gl_error(ctx, GL_INVALID_VALUE, message);
1147 }
jtgafb833d1999-08-19 00:55:39 +00001148 return GL_TRUE;
1149 }
1150
Brian Paulaea66b12000-05-24 14:04:06 +00001151 iformat = _mesa_base_tex_format( ctx, internalFormat );
jtgafb833d1999-08-19 00:55:39 +00001152 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001153 if (!isProxy) {
1154 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001155 sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions,
1156 internalFormat);
Brian Paulc3f0a511999-11-03 17:27:05 +00001157 gl_error(ctx, GL_INVALID_VALUE, message);
1158 }
jtgafb833d1999-08-19 00:55:39 +00001159 return GL_TRUE;
1160 }
1161
Brian Paul289d47e2000-08-29 23:31:23 +00001162 if (!is_compressed_format(ctx, internalFormat)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001163 if (!_mesa_is_legal_format_and_type( format, type )) {
1164 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1165 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1166 */
1167 if (!isProxy) {
1168 char message[100];
1169 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1170 gl_error(ctx, GL_INVALID_OPERATION, message);
1171 }
1172 return GL_TRUE;
Brian Paulc3f0a511999-11-03 17:27:05 +00001173 }
jtgafb833d1999-08-19 00:55:39 +00001174 }
1175
1176 /* if we get here, the parameters are OK */
1177 return GL_FALSE;
1178}
1179
1180
1181
1182/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001183 * Test glTexSubImage[123]D() parameters for errors.
1184 * Input:
1185 * dimensions - must be 1 or 2 or 3
1186 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1187 */
1188static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001189subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001190 GLenum target, GLint level,
1191 GLint xoffset, GLint yoffset, GLint zoffset,
1192 GLint width, GLint height, GLint depth,
1193 GLenum format, GLenum type )
1194{
1195 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1196 struct gl_texture_image *destTex;
1197
1198 if (dimensions == 1) {
1199 if (target != GL_TEXTURE_1D) {
1200 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1201 return GL_TRUE;
1202 }
1203 }
1204 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001205 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001206 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1207 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1208 target != GL_TEXTURE_2D) {
1209 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1210 return GL_TRUE;
1211 }
1212 }
1213 else if (target != GL_TEXTURE_2D) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001214 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1215 return GL_TRUE;
1216 }
1217 }
1218 else if (dimensions == 3) {
1219 if (target != GL_TEXTURE_3D) {
1220 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1221 return GL_TRUE;
1222 }
1223 }
1224 else {
1225 gl_problem( ctx, "bad dims in texture_error_check" );
1226 return GL_TRUE;
1227 }
1228
1229 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulec153982000-12-08 18:09:33 +00001230 char message[100];
1231 sprintf(message, "glTexSubImage2D(level=%d)", level);
1232 gl_error(ctx, GL_INVALID_ENUM, message);
Brian Paulc3f0a511999-11-03 17:27:05 +00001233 return GL_TRUE;
1234 }
1235
1236 if (width < 0) {
1237 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001238 sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width);
Brian Paulc3f0a511999-11-03 17:27:05 +00001239 gl_error(ctx, GL_INVALID_VALUE, message);
1240 return GL_TRUE;
1241 }
1242 if (height < 0 && dimensions > 1) {
1243 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001244 sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height);
Brian Paulc3f0a511999-11-03 17:27:05 +00001245 gl_error(ctx, GL_INVALID_VALUE, message);
1246 return GL_TRUE;
1247 }
1248 if (depth < 0 && dimensions > 2) {
1249 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001250 sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth);
Brian Paulc3f0a511999-11-03 17:27:05 +00001251 gl_error(ctx, GL_INVALID_VALUE, message);
1252 return GL_TRUE;
1253 }
1254
Brian Paula8523782000-11-19 23:10:25 +00001255 destTex = texUnit->Current2D->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001256 if (!destTex) {
1257 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1258 return GL_TRUE;
1259 }
1260
1261 if (xoffset < -((GLint)destTex->Border)) {
1262 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1263 return GL_TRUE;
1264 }
1265 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1266 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1267 return GL_TRUE;
1268 }
1269 if (dimensions > 1) {
1270 if (yoffset < -((GLint)destTex->Border)) {
1271 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1272 return GL_TRUE;
1273 }
1274 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1275 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1276 return GL_TRUE;
1277 }
1278 }
1279 if (dimensions > 2) {
1280 if (zoffset < -((GLint)destTex->Border)) {
1281 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1282 return GL_TRUE;
1283 }
1284 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1285 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1286 return GL_TRUE;
1287 }
1288 }
1289
Brian Paul289d47e2000-08-29 23:31:23 +00001290 if (!is_compressed_format(ctx, destTex->IntFormat)) {
Brian Paul9540a1d2000-06-06 17:03:38 +00001291 if (!_mesa_is_legal_format_and_type(format, type)) {
1292 char message[100];
1293 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1294 gl_error(ctx, GL_INVALID_ENUM, message);
1295 return GL_TRUE;
1296 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001297 }
1298
1299 return GL_FALSE;
1300}
1301
1302
1303/*
1304 * Test glCopyTexImage[12]D() parameters for errors.
1305 * Input: dimensions - must be 1 or 2 or 3
1306 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1307 */
1308static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001309copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001310 GLenum target, GLint level, GLint internalFormat,
1311 GLint width, GLint height, GLint border )
1312{
1313 GLint iformat;
1314
Brian Paulfc4b4432000-05-23 15:17:12 +00001315 if (dimensions == 1) {
1316 if (target != GL_TEXTURE_1D) {
1317 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1318 return GL_TRUE;
1319 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001320 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001321 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001322 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001323 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1324 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1325 target != GL_TEXTURE_2D) {
1326 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1327 return GL_TRUE;
1328 }
1329 }
1330 else if (target != GL_TEXTURE_2D) {
1331 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1332 return GL_TRUE;
1333 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001334 }
1335
1336 /* Border */
1337 if (border!=0 && border!=1) {
1338 char message[100];
1339 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1340 gl_error(ctx, GL_INVALID_VALUE, message);
1341 return GL_TRUE;
1342 }
1343
1344 /* Width */
1345 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1346 || logbase2( width - 2 * border ) < 0) {
1347 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001348 sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
Brian Paulc3f0a511999-11-03 17:27:05 +00001349 gl_error(ctx, GL_INVALID_VALUE, message);
1350 return GL_TRUE;
1351 }
1352
1353 /* Height */
1354 if (dimensions >= 2) {
1355 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1356 || logbase2( height - 2 * border ) < 0) {
1357 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001358 sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
Brian Paulc3f0a511999-11-03 17:27:05 +00001359 gl_error(ctx, GL_INVALID_VALUE, message);
1360 return GL_TRUE;
1361 }
1362 }
1363
Brian Paulad817702000-05-30 00:27:24 +00001364 /* For cube map, width must equal height */
1365 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1366 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1367 if (width != height) {
1368 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1369 return GL_TRUE;
1370 }
1371 }
1372
Brian Paulc3f0a511999-11-03 17:27:05 +00001373 /* Level */
1374 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1375 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001376 sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
Brian Paulc3f0a511999-11-03 17:27:05 +00001377 gl_error(ctx, GL_INVALID_VALUE, message);
1378 return GL_TRUE;
1379 }
1380
Brian Paulaea66b12000-05-24 14:04:06 +00001381 iformat = _mesa_base_tex_format( ctx, internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +00001382 if (iformat < 0) {
1383 char message[100];
1384 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1385 gl_error(ctx, GL_INVALID_VALUE, message);
1386 return GL_TRUE;
1387 }
1388
1389 /* if we get here, the parameters are OK */
1390 return GL_FALSE;
1391}
1392
1393
1394static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001395copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001396 GLenum target, GLint level,
1397 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +00001398 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001399{
1400 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1401 struct gl_texture_image *teximage;
1402
Brian Paulfc4b4432000-05-23 15:17:12 +00001403 if (dimensions == 1) {
1404 if (target != GL_TEXTURE_1D) {
1405 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1406 return GL_TRUE;
1407 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001408 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001409 else if (dimensions == 2) {
Keith Whitwella96308c2000-10-30 13:31:59 +00001410 if (ctx->Extensions.ARB_texture_cube_map) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001411 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1412 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1413 target != GL_TEXTURE_2D) {
1414 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1415 return GL_TRUE;
1416 }
1417 }
1418 else if (target != GL_TEXTURE_2D) {
1419 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1420 return GL_TRUE;
1421 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001422 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001423 else if (dimensions == 3) {
1424 if (target != GL_TEXTURE_3D) {
1425 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1426 return GL_TRUE;
1427 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001428 }
1429
1430 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1431 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001432 sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
Brian Paulc3f0a511999-11-03 17:27:05 +00001433 gl_error(ctx, GL_INVALID_VALUE, message);
1434 return GL_TRUE;
1435 }
1436
1437 if (width < 0) {
1438 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001439 sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width);
Brian Paulc3f0a511999-11-03 17:27:05 +00001440 gl_error(ctx, GL_INVALID_VALUE, message);
1441 return GL_TRUE;
1442 }
1443 if (dimensions > 1 && height < 0) {
1444 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001445 sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height);
Brian Paulc3f0a511999-11-03 17:27:05 +00001446 gl_error(ctx, GL_INVALID_VALUE, message);
1447 return GL_TRUE;
1448 }
1449
Brian Paula8523782000-11-19 23:10:25 +00001450 teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulc3f0a511999-11-03 17:27:05 +00001451 if (!teximage) {
1452 char message[100];
1453 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1454 gl_error(ctx, GL_INVALID_OPERATION, message);
1455 return GL_TRUE;
1456 }
1457
1458 if (xoffset < -((GLint)teximage->Border)) {
1459 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001460 sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
Brian Paulc3f0a511999-11-03 17:27:05 +00001461 gl_error(ctx, GL_INVALID_VALUE, message);
1462 return GL_TRUE;
1463 }
1464 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1465 char message[100];
1466 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1467 gl_error(ctx, GL_INVALID_VALUE, message);
1468 return GL_TRUE;
1469 }
1470 if (dimensions > 1) {
1471 if (yoffset < -((GLint)teximage->Border)) {
1472 char message[100];
Brian Paulec153982000-12-08 18:09:33 +00001473 sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
Brian Paulc3f0a511999-11-03 17:27:05 +00001474 gl_error(ctx, GL_INVALID_VALUE, message);
1475 return GL_TRUE;
1476 }
1477 /* NOTE: we're adding the border here, not subtracting! */
1478 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1479 char message[100];
1480 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1481 gl_error(ctx, GL_INVALID_VALUE, message);
1482 return GL_TRUE;
1483 }
1484 }
1485
1486 if (dimensions > 2) {
1487 if (zoffset < -((GLint)teximage->Border)) {
1488 char message[100];
1489 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1490 gl_error(ctx, GL_INVALID_VALUE, message);
1491 return GL_TRUE;
1492 }
1493 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1494 char message[100];
1495 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1496 gl_error(ctx, GL_INVALID_VALUE, message);
1497 return GL_TRUE;
1498 }
1499 }
1500
1501 /* if we get here, the parameters are OK */
1502 return GL_FALSE;
1503}
1504
1505
1506
1507
1508/*
Brian Paul289d47e2000-08-29 23:31:23 +00001509 * Turn generic compressed formats into specific compressed format.
1510 * Some of the compressed formats we don't support, so we
1511 * fall back to the uncompressed format. (See issue 15 of
1512 * the GL_ARB_texture_compression specification.)
1513 */
1514static GLint
1515get_specific_compressed_tex_format(GLcontext *ctx,
Brian Paul37a62112000-09-28 18:30:39 +00001516 GLint ifmt, GLint numDimensions,
1517 GLint *levelp,
1518 GLsizei *widthp,
1519 GLsizei *heightp,
1520 GLsizei *depthp,
1521 GLint *borderp,
1522 GLenum *formatp,
1523 GLenum *typep)
Brian Paul289d47e2000-08-29 23:31:23 +00001524{
1525 char message[100];
1526 GLint internalFormat = ifmt;
1527
Keith Whitwella96308c2000-10-30 13:31:59 +00001528 if (ctx->Extensions.ARB_texture_compression
Brian Paul289d47e2000-08-29 23:31:23 +00001529 && ctx->Driver.SpecificCompressedTexFormat) {
1530 /*
1531 * First, ask the driver for the specific format.
Brian Paul37a62112000-09-28 18:30:39 +00001532 * We do this for all formats, since we may want to
1533 * fake one compressed format for another.
Brian Paul289d47e2000-08-29 23:31:23 +00001534 */
Brian Paul37a62112000-09-28 18:30:39 +00001535 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1536 (ctx, internalFormat, numDimensions,
1537 levelp,
1538 widthp, heightp, depthp,
1539 borderp, formatp, typep);
Brian Paul289d47e2000-08-29 23:31:23 +00001540 }
1541
1542 /*
1543 * Now, convert any generic format left to an uncompressed
1544 * specific format. If the driver does not support compression
1545 * of the format, we must drop back to the uncompressed format.
1546 * See issue 15 of the GL_ARB_texture_compression specification.
1547 */
1548 switch (internalFormat) {
1549 case GL_COMPRESSED_ALPHA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001550 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001551 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1552 gl_error(ctx, GL_INVALID_VALUE, message);
1553 return -1;
1554 }
1555 internalFormat = GL_ALPHA;
1556 break;
1557 case GL_COMPRESSED_LUMINANCE_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001558 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001559 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1560 gl_error(ctx, GL_INVALID_VALUE, message);
1561 return -1;
1562 }
1563 internalFormat = GL_LUMINANCE;
1564 break;
1565 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001566 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001567 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1568 gl_error(ctx, GL_INVALID_VALUE, message);
1569 return -1;
1570 }
1571 internalFormat = GL_LUMINANCE_ALPHA;
1572 break;
1573 case GL_COMPRESSED_INTENSITY_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001574 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001575 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1576 gl_error(ctx, GL_INVALID_VALUE, message);
1577 return -1;
1578 }
1579 internalFormat = GL_INTENSITY;
1580 break;
1581 case GL_COMPRESSED_RGB_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001582 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001583 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1584 gl_error(ctx, GL_INVALID_VALUE, message);
1585 return -1;
1586 }
1587 internalFormat = GL_RGB;
1588 break;
1589 case GL_COMPRESSED_RGBA_ARB:
Keith Whitwella96308c2000-10-30 13:31:59 +00001590 if (ctx && !ctx->Extensions.ARB_texture_compression) {
Brian Paul289d47e2000-08-29 23:31:23 +00001591 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1592 gl_error(ctx, GL_INVALID_VALUE, message);
1593 return -1;
1594 }
1595 internalFormat = GL_RGBA;
1596 break;
1597 default:
Brian Paulf93b3dd2000-08-30 18:22:28 +00001598 /* silence compiler warning */
1599 ;
Brian Paul289d47e2000-08-29 23:31:23 +00001600 }
1601 return internalFormat;
1602}
1603
1604
Brian Paul289d47e2000-08-29 23:31:23 +00001605/*
jtgafb833d1999-08-19 00:55:39 +00001606 * Called from the API. Note that width includes the border.
1607 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001608void
Brian Paul43911c82000-03-21 00:49:33 +00001609_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001610 GLsizei width, GLint border, GLenum format,
1611 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001612{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001613 GLsizei postConvWidth;
Brian Paulfbd8f211999-11-11 01:22:25 +00001614 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001615 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1616
Brian Paulf93b3dd2000-08-30 18:22:28 +00001617 postConvWidth = width;
1618 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1619
jtgafb833d1999-08-19 00:55:39 +00001620 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001621 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001622 struct gl_texture_object *texObj;
1623 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001624 GLint ifmt;
1625
Brian Paul37a62112000-09-28 18:30:39 +00001626 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1627 &level,
1628 &width, 0, 0,
1629 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001630 if (ifmt < 0) {
1631 /*
1632 * The error here is that we were sent a generic compressed
1633 * format, but the extension is not supported.
1634 */
1635 return;
1636 }
1637 else {
1638 internalFormat = ifmt;
1639 }
Brian Paulf7b57072000-03-20 14:37:52 +00001640
Brian Paulaea66b12000-05-24 14:04:06 +00001641 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001642 format, type, 1, postConvWidth, 1, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001643 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001644 }
1645
Brian Paulf7b57072000-03-20 14:37:52 +00001646 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00001647 texObj = texUnit->Current1D;
Brian Paul02938782000-03-22 17:38:11 +00001648 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001649
Brian Paul02938782000-03-22 17:38:11 +00001650 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001651 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001652 texObj->Image[level] = texImage;
1653 if (!texImage) {
1654 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1655 return;
1656 }
1657 }
1658 else if (texImage->Data) {
1659 FREE(texImage->Data);
1660 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001661 }
1662
Brian Paul02938782000-03-22 17:38:11 +00001663 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001664 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001665
Brian Paul9499e012000-10-30 16:32:42 +00001666 if (ctx->NewState & _NEW_PIXEL)
1667 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001668
Brian Paul02938782000-03-22 17:38:11 +00001669 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001670 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001671 GLboolean retain = GL_TRUE;
1672 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001673 if (!ctx->_ImageTransferState && ctx->Driver.TexImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00001674 /* let device driver try to use raw image */
1675 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1676 type, pixels, &ctx->Unpack,
1677 texObj, texImage, &retain);
1678 }
1679 if (retain || !success) {
1680 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001681 make_texture_image(ctx, 1, texImage, width, 1, 1,
1682 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001683 if (!success && ctx->Driver.TexImage1D) {
1684 /* let device driver try to use unpacked image */
1685 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1686 GL_UNSIGNED_BYTE, texImage->Data,
1687 &_mesa_native_packing,
1688 texObj, texImage, &retain);
1689 }
1690 }
1691 if (!retain && texImage->Data) {
1692 FREE(texImage->Data);
1693 texImage->Data = NULL;
1694 }
jtgafb833d1999-08-19 00:55:39 +00001695 }
1696 else {
Brian Paul02938782000-03-22 17:38:11 +00001697 make_null_texture(texImage);
1698 if (ctx->Driver.TexImage1D) {
1699 GLboolean retain;
1700 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1701 GL_UNSIGNED_BYTE, texImage->Data,
1702 &_mesa_native_packing,
1703 texObj, texImage, &retain);
1704 }
jtgafb833d1999-08-19 00:55:39 +00001705 }
1706
Brian Paul02938782000-03-22 17:38:11 +00001707 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00001708 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00001709 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001710 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001711 else if (target == GL_PROXY_TEXTURE_1D) {
jtgafb833d1999-08-19 00:55:39 +00001712 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001713 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1714 format, type, 1, width, 1, 1, border);
1715 if (!error && ctx->Driver.TestProxyTexImage) {
1716 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1717 internalFormat, format, type,
1718 width, 1, 1, border);
1719 }
1720 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001721 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001722 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001723 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001724 }
1725 }
1726 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001727 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001728 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001729 width, 1, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001730 }
jtgafb833d1999-08-19 00:55:39 +00001731 }
1732 else {
1733 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1734 return;
1735 }
1736}
1737
1738
Brian Paulfbd8f211999-11-11 01:22:25 +00001739void
Brian Paul43911c82000-03-21 00:49:33 +00001740_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001741 GLsizei width, GLsizei height, GLint border,
1742 GLenum format, GLenum type,
1743 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001744{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001745 GLsizei postConvWidth, postConvHeight;
Brian Paulfbd8f211999-11-11 01:22:25 +00001746 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001747 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1748
Brian Paulf93b3dd2000-08-30 18:22:28 +00001749 postConvWidth = width;
1750 postConvHeight = height;
1751 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1752
Brian Paulfc4b4432000-05-23 15:17:12 +00001753 if (target==GL_TEXTURE_2D ||
Keith Whitwella96308c2000-10-30 13:31:59 +00001754 (ctx->Extensions.ARB_texture_cube_map &&
Brian Paulfc4b4432000-05-23 15:17:12 +00001755 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1756 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001757 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001758 struct gl_texture_object *texObj;
1759 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001760 GLint ifmt;
1761
Brian Paul37a62112000-09-28 18:30:39 +00001762 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1763 &level,
1764 &width, &height, 0,
1765 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001766 if (ifmt < 0) {
1767 /*
1768 * The error here is that we were sent a generic compressed
1769 * format, but the extension is not supported.
1770 */
1771 return;
1772 }
1773 else {
1774 internalFormat = ifmt;
1775 }
Brian Paulf7b57072000-03-20 14:37:52 +00001776
Brian Paulaea66b12000-05-24 14:04:06 +00001777 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001778 format, type, 2, postConvWidth, postConvHeight,
1779 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001780 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001781 }
1782
Brian Paulf7b57072000-03-20 14:37:52 +00001783 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00001784 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paulfc4b4432000-05-23 15:17:12 +00001785 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00001786
Brian Paul02938782000-03-22 17:38:11 +00001787 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001788 texImage = _mesa_alloc_texture_image();
Brian Paulfc4b4432000-05-23 15:17:12 +00001789 set_tex_image(texObj, target, level, texImage);
1790 /*texObj->Image[level] = texImage;*/
Brian Paul02938782000-03-22 17:38:11 +00001791 if (!texImage) {
1792 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1793 return;
1794 }
1795 }
1796 else if (texImage->Data) {
1797 FREE(texImage->Data);
1798 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001799 }
1800
Brian Paul02938782000-03-22 17:38:11 +00001801 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001802 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
Brian Paul289d47e2000-08-29 23:31:23 +00001803 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001804
Brian Paul9499e012000-10-30 16:32:42 +00001805 if (ctx->NewState & _NEW_PIXEL)
1806 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001807
Brian Paul02938782000-03-22 17:38:11 +00001808 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001809 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001810 GLboolean retain = GL_TRUE;
1811 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001812 if (!ctx->_ImageTransferState && ctx->Driver.TexImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00001813 /* let device driver try to use raw image */
1814 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1815 type, pixels, &ctx->Unpack,
1816 texObj, texImage, &retain);
1817 }
1818 if (retain || !success) {
1819 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001820 make_texture_image(ctx, 2, texImage, width, height, 1,
1821 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001822 if (!success && ctx->Driver.TexImage2D) {
1823 /* let device driver try to use unpacked image */
1824 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1825 GL_UNSIGNED_BYTE, texImage->Data,
1826 &_mesa_native_packing,
1827 texObj, texImage, &retain);
1828 }
1829 }
1830 if (!retain && texImage->Data) {
1831 FREE(texImage->Data);
1832 texImage->Data = NULL;
1833 }
jtgafb833d1999-08-19 00:55:39 +00001834 }
1835 else {
Brian Paul02938782000-03-22 17:38:11 +00001836 make_null_texture(texImage);
1837 if (ctx->Driver.TexImage2D) {
1838 GLboolean retain;
1839 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1840 GL_UNSIGNED_BYTE, texImage->Data,
1841 &_mesa_native_packing,
1842 texObj, texImage, &retain);
1843 }
jtgafb833d1999-08-19 00:55:39 +00001844 }
1845
Brian Paul02938782000-03-22 17:38:11 +00001846 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00001847 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00001848 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001849 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001850 else if (target == GL_PROXY_TEXTURE_2D) {
jtgafb833d1999-08-19 00:55:39 +00001851 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001852 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1853 format, type, 2, width, height, 1, border);
1854 if (!error && ctx->Driver.TestProxyTexImage) {
1855 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1856 internalFormat, format, type,
1857 width, height, 1, border);
1858 }
1859 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001860 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001861 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001862 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001863 }
1864 }
1865 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001866 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001867 init_texture_image(ctx,
1868 ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001869 width, height, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001870 }
jtgafb833d1999-08-19 00:55:39 +00001871 }
1872 else {
1873 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1874 return;
1875 }
1876}
1877
1878
jtgafb833d1999-08-19 00:55:39 +00001879/*
1880 * Called by the API or display list executor.
1881 * Note that width and height include the border.
1882 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001883void
Brian Paul43911c82000-03-21 00:49:33 +00001884_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001885 GLsizei width, GLsizei height, GLsizei depth,
1886 GLint border, GLenum format, GLenum type,
1887 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001888{
Brian Paulfbd8f211999-11-11 01:22:25 +00001889 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001890 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001891
Brian Paulfbd8f211999-11-11 01:22:25 +00001892 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001893 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001894 struct gl_texture_object *texObj;
1895 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001896 GLint ifmt;
1897
Brian Paul37a62112000-09-28 18:30:39 +00001898 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1899 &level,
1900 &width, &height, &depth,
1901 &border, &format, &type);
Brian Paul289d47e2000-08-29 23:31:23 +00001902 if (ifmt < 0) {
1903 /*
1904 * The error here is that we were sent a generic compressed
1905 * format, but the extension is not supported.
1906 */
1907 return;
1908 }
1909 else {
1910 internalFormat = ifmt;
1911 }
1912
Brian Paulaea66b12000-05-24 14:04:06 +00001913 if (texture_error_check(ctx, target, level, internalFormat,
1914 format, type, 3, width, height, depth, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001915 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001916 }
1917
Brian Paulf7b57072000-03-20 14:37:52 +00001918 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00001919 texObj = texUnit->Current3D;
Brian Paul02938782000-03-22 17:38:11 +00001920 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001921
Brian Paul02938782000-03-22 17:38:11 +00001922 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001923 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001924 texObj->Image[level] = texImage;
1925 if (!texImage) {
1926 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1927 return;
1928 }
1929 }
1930 else if (texImage->Data) {
1931 FREE(texImage->Data);
1932 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001933 }
1934
Brian Paul02938782000-03-22 17:38:11 +00001935 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00001936 init_texture_image(ctx, texImage, width, height, depth,
Brian Paul02938782000-03-22 17:38:11 +00001937 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001938
Brian Paul9499e012000-10-30 16:32:42 +00001939 if (ctx->NewState & _NEW_PIXEL)
1940 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00001941
Brian Paul02938782000-03-22 17:38:11 +00001942 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001943 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001944 GLboolean retain = GL_TRUE;
1945 GLboolean success = GL_FALSE;
Keith Whitwell14940c42000-11-05 18:40:57 +00001946 if (!ctx->_ImageTransferState && ctx->Driver.TexImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00001947 /* let device driver try to use raw image */
1948 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1949 type, pixels, &ctx->Unpack,
1950 texObj, texImage, &retain);
1951 }
1952 if (retain || !success) {
1953 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001954 make_texture_image(ctx, 3, texImage, width, height, depth,
1955 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001956 if (!success && ctx->Driver.TexImage3D) {
1957 /* let device driver try to use unpacked image */
1958 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1959 GL_UNSIGNED_BYTE, texImage->Data,
1960 &_mesa_native_packing,
1961 texObj, texImage, &retain);
1962 }
1963 }
1964 if (!retain && texImage->Data) {
1965 FREE(texImage->Data);
1966 texImage->Data = NULL;
1967 }
jtgafb833d1999-08-19 00:55:39 +00001968 }
1969 else {
Brian Paul02938782000-03-22 17:38:11 +00001970 make_null_texture(texImage);
1971 if (ctx->Driver.TexImage3D) {
1972 GLboolean retain;
1973 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1974 GL_UNSIGNED_BYTE, texImage->Data,
1975 &_mesa_native_packing,
1976 texObj, texImage, &retain);
1977 }
jtgafb833d1999-08-19 00:55:39 +00001978 }
1979
Brian Paul02938782000-03-22 17:38:11 +00001980 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00001981 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00001982 ctx->NewState |= _NEW_TEXTURE;
jtgafb833d1999-08-19 00:55:39 +00001983 }
Brian Paul38d3f3d2000-09-07 15:38:49 +00001984 else if (target == GL_PROXY_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00001985 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00001986 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1987 format, type, 3, width, height, depth, border);
1988 if (!error && ctx->Driver.TestProxyTexImage) {
1989 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1990 internalFormat, format, type,
1991 width, height, depth, border);
1992 }
1993 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00001994 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001995 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00001996 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
jtgafb833d1999-08-19 00:55:39 +00001997 }
1998 }
1999 else {
Brian Paulaea66b12000-05-24 14:04:06 +00002000 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002001 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002002 width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00002003 }
jtgafb833d1999-08-19 00:55:39 +00002004 }
2005 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00002006 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00002007 return;
2008 }
2009}
2010
2011
Brian Paul663049a2000-01-31 23:10:16 +00002012void
Brian Paul43911c82000-03-21 00:49:33 +00002013_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00002014 GLsizei width, GLsizei height, GLsizei depth,
2015 GLint border, GLenum format, GLenum type,
2016 const GLvoid *pixels )
2017{
Brian Paul43911c82000-03-21 00:49:33 +00002018 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00002019 depth, border, format, type, pixels);
2020}
2021
2022
Brian Paulf7b57072000-03-20 14:37:52 +00002023/*
2024 * Fetch a texture image from the device driver.
2025 * Store the results in the given texture object at the given mipmap level.
2026 */
Brian Paul021a5252000-03-27 17:54:17 +00002027void
2028_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2029 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00002030{
2031 GLvoid *image;
2032 GLenum imgFormat, imgType;
2033 GLboolean freeImage;
2034 struct gl_texture_image *texImage;
2035 GLint destComponents, numPixels, srcBytesPerTexel;
2036
2037 if (!ctx->Driver.GetTexImage)
2038 return;
2039
Brian Paul48271792000-03-29 18:13:59 +00002040 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00002041 &imgFormat, &imgType, &freeImage);
2042 if (!image)
2043 return;
2044
2045 texImage = texObj->Image[level];
2046 ASSERT(texImage);
2047 if (!texImage)
2048 return;
2049
2050 destComponents = components_in_intformat(texImage->Format);
2051 assert(destComponents > 0);
2052 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2053 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00002054 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00002055 assert(srcBytesPerTexel > 0);
2056
2057 if (!texImage->Data) {
2058 /* Allocate memory for the texture image data */
Brian Paul699bc7b2000-10-29 18:12:14 +00002059 texImage->Data = (GLchan *) MALLOC(numPixels * destComponents
2060 * sizeof(GLchan) + EXTRA_BYTE);
Brian Paulf7b57072000-03-20 14:37:52 +00002061 }
2062
2063 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2064 /* We got lucky! The driver's format and type match Mesa's format. */
2065 if (texImage->Data) {
2066 MEMCPY(texImage->Data, image, numPixels * destComponents);
2067 }
2068 }
2069 else {
2070 /* Convert the texture image from the driver's format to Mesa's
2071 * internal format.
2072 */
2073 const GLint width = texImage->Width;
2074 const GLint height = texImage->Height;
2075 const GLint depth = texImage->Depth;
2076 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2077 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2078 const GLenum dstType = GL_UNSIGNED_BYTE;
2079 const GLenum dstFormat = texImage->Format;
Brian Paul699bc7b2000-10-29 18:12:14 +00002080 const GLchan *srcPtr = (const GLchan *) image;
2081 GLchan *destPtr = texImage->Data;
Brian Paulf7b57072000-03-20 14:37:52 +00002082
2083 if (texImage->Format == GL_COLOR_INDEX) {
2084 /* color index texture */
2085 GLint img, row;
2086 assert(imgFormat == GL_COLOR_INDEX);
2087 for (img = 0; img < depth; img++) {
2088 for (row = 0; row < height; row++) {
2089 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002090 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002091 destPtr += destBytesPerRow;
2092 srcPtr += srcBytesPerRow;
2093 }
2094 }
2095 }
2096 else {
2097 /* color texture */
2098 GLint img, row;
2099 for (img = 0; img < depth; img++) {
2100 for (row = 0; row < height; row++) {
Brian Paul699bc7b2000-10-29 18:12:14 +00002101 _mesa_unpack_chan_color_span(ctx, width, dstFormat, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002102 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002103 destPtr += destBytesPerRow;
2104 srcPtr += srcBytesPerRow;
2105 }
2106 }
2107 }
2108 }
2109
2110 if (freeImage)
2111 FREE(image);
2112}
2113
jtgafb833d1999-08-19 00:55:39 +00002114
Brian Paul1873b562000-10-16 23:43:12 +00002115/*
2116 * Get all the mipmap images for a texture object from the device driver.
2117 * Actually, only get mipmap images if we're using a mipmap filter.
2118 */
2119GLboolean
2120_mesa_get_teximages_from_driver(GLcontext *ctx,
2121 struct gl_texture_object *texObj)
2122{
2123 if (ctx->Driver.GetTexImage) {
2124 static const GLenum targets[] = {
2125 GL_TEXTURE_1D,
2126 GL_TEXTURE_2D,
2127 GL_TEXTURE_3D,
2128 GL_TEXTURE_CUBE_MAP_ARB,
2129 GL_TEXTURE_CUBE_MAP_ARB,
2130 GL_TEXTURE_CUBE_MAP_ARB
2131 };
2132 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2133 GLenum target = targets[texObj->Dimensions - 1];
2134 if (needLambda) {
2135 GLint level;
2136 /* Get images for all mipmap levels. We might not need them
2137 * all but this is easier. We're on a (slow) software path
2138 * anyway.
2139 */
Keith Whitwell14940c42000-11-05 18:40:57 +00002140 for (level = 0; level <= texObj->_P; level++) {
Brian Paul1873b562000-10-16 23:43:12 +00002141 struct gl_texture_image *texImg = texObj->Image[level];
2142 if (texImg && !texImg->Data) {
2143 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2144 if (!texImg->Data)
2145 return GL_FALSE; /* out of memory */
2146 }
2147 }
2148 }
2149 else {
2150 GLint level = texObj->BaseLevel;
2151 struct gl_texture_image *texImg = texObj->Image[level];
2152 if (texImg && !texImg->Data) {
2153 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2154 if (!texImg->Data)
2155 return GL_FALSE; /* out of memory */
2156 }
2157 }
2158 return GL_TRUE;
2159 }
2160 return GL_FALSE;
2161}
2162
2163
2164
Brian Paulfbd8f211999-11-11 01:22:25 +00002165void
2166_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2167 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002168{
Brian Paulfbd8f211999-11-11 01:22:25 +00002169 GET_CURRENT_CONTEXT(ctx);
Brian Paul01e54752000-09-05 15:40:34 +00002170 const struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00002171 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00002172 struct gl_texture_image *texImage;
2173 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00002174
2175 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2176
2177 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2178 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2179 return;
2180 }
2181
Brian Paulb7d076f2000-03-21 01:03:40 +00002182 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002183 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2184 return;
2185 }
2186
Brian Paulb7d076f2000-03-21 01:03:40 +00002187 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002188 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2189 return;
2190 }
2191
2192 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00002193 return;
jtgafb833d1999-08-19 00:55:39 +00002194
Brian Paul01e54752000-09-05 15:40:34 +00002195 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2196 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Pauld45fdea2000-11-13 15:25:26 +00002197 if (!texObj ||
Brian Paulc52fc9b2000-09-05 22:11:38 +00002198 target == GL_PROXY_TEXTURE_1D ||
2199 target == GL_PROXY_TEXTURE_2D ||
2200 target == GL_PROXY_TEXTURE_3D) {
Brian Paul01e54752000-09-05 15:40:34 +00002201 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2202 return;
jtgafb833d1999-08-19 00:55:39 +00002203 }
2204
Brian Paul8e3366f2000-11-10 15:32:07 +00002205 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00002206 if (!texImage) {
Brian Paul7298e712000-11-07 16:40:37 +00002207 /* invalid mipmap level, not an error */
Brian Paulf7b57072000-03-20 14:37:52 +00002208 return;
2209 }
2210
2211 if (!texImage->Data) {
2212 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00002213 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00002214 discardImage = GL_TRUE;
2215 }
2216 else {
2217 discardImage = GL_FALSE;
2218 }
2219
2220 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00002221 GLint width = texImage->Width;
2222 GLint height = texImage->Height;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002223 GLint depth = texImage->Depth;
2224 GLint img, row;
jtgafb833d1999-08-19 00:55:39 +00002225
Brian Paul9499e012000-10-30 16:32:42 +00002226 if (ctx->NewState & _NEW_PIXEL)
2227 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002228
Keith Whitwell14940c42000-11-05 18:40:57 +00002229 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
Brian Paulf96ce6a2000-09-06 15:15:43 +00002230 /* convert texture image to GL_RGBA, GL_FLOAT */
2231 GLfloat *tmpImage, *convImage;
2232 const GLint comps = components_in_intformat(texImage->Format);
jtgafb833d1999-08-19 00:55:39 +00002233
Brian Paulf96ce6a2000-09-06 15:15:43 +00002234 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2235 if (!tmpImage) {
2236 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2237 return;
jtgafb833d1999-08-19 00:55:39 +00002238 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002239 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2240 if (!convImage) {
2241 FREE(tmpImage);
2242 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2243 return;
2244 }
2245
2246 for (img = 0; img < depth; img++) {
2247 GLint convWidth, convHeight;
2248
2249 /* convert to GL_RGBA */
2250 for (row = 0; row < height; row++) {
Brian Paul699bc7b2000-10-29 18:12:14 +00002251 const GLchan *src = texImage->Data
Brian Paulf96ce6a2000-09-06 15:15:43 +00002252 + (img * height + row ) * width * comps;
2253 GLfloat *dst = tmpImage + row * width * 4;
2254 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2255 texImage->Format, GL_UNSIGNED_BYTE,
2256 src, &_mesa_native_packing,
Keith Whitwell14940c42000-11-05 18:40:57 +00002257 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002258 GL_FALSE);
jtgafb833d1999-08-19 00:55:39 +00002259 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002260
2261 convWidth = width;
2262 convHeight = height;
2263
2264 /* convolve */
2265 if (target == GL_TEXTURE_1D) {
2266 if (ctx->Pixel.Convolution1DEnabled) {
2267 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2268 }
2269 }
2270 else {
2271 if (ctx->Pixel.Convolution2DEnabled) {
2272 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2273 tmpImage, convImage);
2274 }
2275 else if (ctx->Pixel.Separable2DEnabled) {
2276 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2277 tmpImage, convImage);
2278 }
2279 }
2280
2281 /* pack convolved image */
2282 for (row = 0; row < convHeight; row++) {
2283 const GLfloat *src = convImage + row * convWidth * 4;
2284 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2285 convWidth, convHeight,
2286 format, type, img, row, 0);
2287 _mesa_pack_float_rgba_span(ctx, convWidth,
2288 (const GLfloat(*)[4]) src,
2289 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002290 ctx->_ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
Brian Paulf96ce6a2000-09-06 15:15:43 +00002291 }
jtgafb833d1999-08-19 00:55:39 +00002292 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002293
2294 FREE(tmpImage);
2295 FREE(convImage);
jtgafb833d1999-08-19 00:55:39 +00002296 }
Brian Paulf96ce6a2000-09-06 15:15:43 +00002297 else {
2298 /* no convolution */
2299 for (img = 0; img < depth; img++) {
2300 for (row = 0; row < height; row++) {
2301 /* compute destination address in client memory */
2302 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2303 width, height, format, type, img, row, 0);
2304 assert(dest);
2305 if (texImage->Format == GL_RGBA) {
2306 /* simple case */
Brian Paul699bc7b2000-10-29 18:12:14 +00002307 const GLchan *src = texImage->Data
Brian Paulf96ce6a2000-09-06 15:15:43 +00002308 + (img * height + row ) * width * 4;
Brian Paul699bc7b2000-10-29 18:12:14 +00002309 _mesa_pack_rgba_span( ctx, width, (CONST GLchan (*)[4]) src,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002310 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002311 ctx->_ImageTransferState );
Brian Paulf96ce6a2000-09-06 15:15:43 +00002312 }
2313 else {
2314 /* general case: convert row to RGBA format */
Brian Paul699bc7b2000-10-29 18:12:14 +00002315 GLchan rgba[MAX_WIDTH][4];
Brian Paulf96ce6a2000-09-06 15:15:43 +00002316 GLint i;
Brian Paul699bc7b2000-10-29 18:12:14 +00002317 const GLchan *src;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002318 switch (texImage->Format) {
2319 case GL_ALPHA:
Brian Paul699bc7b2000-10-29 18:12:14 +00002320 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002321 for (i = 0; i < width; i++) {
Brian Paulba643a22000-10-28 18:34:48 +00002322 rgba[i][RCOMP] = CHAN_MAX;
2323 rgba[i][GCOMP] = CHAN_MAX;
2324 rgba[i][BCOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002325 rgba[i][ACOMP] = src[i];
2326 }
2327 break;
2328 case GL_LUMINANCE:
Brian Paul699bc7b2000-10-29 18:12:14 +00002329 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002330 for (i = 0; i < width; i++) {
2331 rgba[i][RCOMP] = src[i];
2332 rgba[i][GCOMP] = src[i];
2333 rgba[i][BCOMP] = src[i];
Brian Paulba643a22000-10-28 18:34:48 +00002334 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002335 }
2336 break;
2337 case GL_LUMINANCE_ALPHA:
Brian Paul699bc7b2000-10-29 18:12:14 +00002338 src = texImage->Data + row * 2 * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002339 for (i = 0; i < width; i++) {
2340 rgba[i][RCOMP] = src[i*2+0];
2341 rgba[i][GCOMP] = src[i*2+0];
2342 rgba[i][BCOMP] = src[i*2+0];
2343 rgba[i][ACOMP] = src[i*2+1];
2344 }
2345 break;
2346 case GL_INTENSITY:
Brian Paul699bc7b2000-10-29 18:12:14 +00002347 src = texImage->Data + row * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002348 for (i = 0; i < width; i++) {
2349 rgba[i][RCOMP] = src[i];
2350 rgba[i][GCOMP] = src[i];
2351 rgba[i][BCOMP] = src[i];
Brian Paulba643a22000-10-28 18:34:48 +00002352 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002353 }
2354 break;
2355 case GL_RGB:
Brian Paul699bc7b2000-10-29 18:12:14 +00002356 src = texImage->Data + row * 3 * width;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002357 for (i = 0; i < width; i++) {
2358 rgba[i][RCOMP] = src[i*3+0];
2359 rgba[i][GCOMP] = src[i*3+1];
2360 rgba[i][BCOMP] = src[i*3+2];
Brian Paulba643a22000-10-28 18:34:48 +00002361 rgba[i][ACOMP] = CHAN_MAX;
Brian Paulf96ce6a2000-09-06 15:15:43 +00002362 }
2363 break;
2364 case GL_COLOR_INDEX:
2365 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2366 break;
2367 case GL_RGBA:
2368 default:
2369 gl_problem( ctx, "bad format in gl_GetTexImage" );
2370 }
Brian Paul699bc7b2000-10-29 18:12:14 +00002371 _mesa_pack_rgba_span( ctx, width, (const GLchan (*)[4])rgba,
Brian Paulf96ce6a2000-09-06 15:15:43 +00002372 format, type, dest, &ctx->Pack,
Keith Whitwell14940c42000-11-05 18:40:57 +00002373 ctx->_ImageTransferState );
Brian Paulf96ce6a2000-09-06 15:15:43 +00002374 } /* format */
2375 } /* row */
2376 } /* img */
2377 } /* convolution */
Brian Paulf7b57072000-03-20 14:37:52 +00002378
2379 /* if we got the teximage from the device driver we'll discard it now */
2380 if (discardImage) {
2381 FREE(texImage->Data);
2382 texImage->Data = NULL;
2383 }
jtgafb833d1999-08-19 00:55:39 +00002384 }
2385}
2386
2387
2388
Brian Paulfbd8f211999-11-11 01:22:25 +00002389void
2390_mesa_TexSubImage1D( GLenum target, GLint level,
2391 GLint xoffset, GLsizei width,
2392 GLenum format, GLenum type,
2393 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002394{
Brian Paulfbd8f211999-11-11 01:22:25 +00002395 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002396 struct gl_texture_unit *texUnit;
2397 struct gl_texture_object *texObj;
2398 struct gl_texture_image *texImage;
2399 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002400 GLsizei postConvWidth;
2401
2402 postConvWidth = width;
2403 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
jtgafb833d1999-08-19 00:55:39 +00002404
Brian Paulc3f0a511999-11-03 17:27:05 +00002405 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002406 postConvWidth, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002407 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002408 }
2409
Brian Paul02938782000-03-22 17:38:11 +00002410 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002411 texObj = texUnit->Current1D;
Brian Paul02938782000-03-22 17:38:11 +00002412 texImage = texObj->Image[level];
2413 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002414
Brian Paulc3f0a511999-11-03 17:27:05 +00002415 if (width == 0 || !pixels)
2416 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002417
Brian Paul9499e012000-10-30 16:32:42 +00002418 if (ctx->NewState & _NEW_PIXEL)
2419 gl_update_state(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002420
Keith Whitwell14940c42000-11-05 18:40:57 +00002421 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00002422 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2423 width, format, type, pixels,
2424 &ctx->Unpack, texObj, texImage );
2425 }
2426 if (!success) {
2427 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
Brian Paul02938782000-03-22 17:38:11 +00002428 GLboolean retain = GL_TRUE;
2429 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002430 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002431 if (!texImage->Data) {
2432 make_null_texture(texImage);
2433 }
2434 if (!texImage->Data)
2435 return; /* we're really out of luck! */
2436 }
2437
Brian Paula805bb92000-09-02 17:52:21 +00002438 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002439 width, 1, 1, xoffset + texImage->Border, 0, 0, /* size and offsets */
Brian Paula805bb92000-09-02 17:52:21 +00002440 0, 0, /* strides */
2441 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002442
2443 if (ctx->Driver.TexImage1D) {
2444 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2445 GL_UNSIGNED_BYTE, texImage->Data,
2446 &_mesa_native_packing, texObj, texImage,
2447 &retain );
2448 }
2449
2450 if (!retain && texImage->Data) {
2451 FREE(texImage->Data);
2452 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00002453 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002454 }
jtgafb833d1999-08-19 00:55:39 +00002455}
2456
2457
Brian Paulfbd8f211999-11-11 01:22:25 +00002458void
2459_mesa_TexSubImage2D( GLenum target, GLint level,
2460 GLint xoffset, GLint yoffset,
2461 GLsizei width, GLsizei height,
2462 GLenum format, GLenum type,
2463 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002464{
Brian Paulfbd8f211999-11-11 01:22:25 +00002465 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002466 struct gl_texture_unit *texUnit;
2467 struct gl_texture_object *texObj;
2468 struct gl_texture_image *texImage;
2469 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002470 GLsizei postConvWidth, postConvHeight;
2471
2472 postConvWidth = width;
2473 postConvHeight = height;
2474 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
jtgafb833d1999-08-19 00:55:39 +00002475
Brian Paulc3f0a511999-11-03 17:27:05 +00002476 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002477 postConvWidth, postConvHeight, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002478 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002479 }
2480
Brian Paul02938782000-03-22 17:38:11 +00002481 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00002482 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paul02938782000-03-22 17:38:11 +00002483 texImage = texObj->Image[level];
2484 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002485
Brian Paulc3f0a511999-11-03 17:27:05 +00002486 if (width == 0 || height == 0 || !pixels)
2487 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002488
Brian Paul9499e012000-10-30 16:32:42 +00002489 if (ctx->NewState & _NEW_PIXEL)
2490 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002491
Keith Whitwell14940c42000-11-05 18:40:57 +00002492 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00002493 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2494 yoffset, width, height, format, type,
2495 pixels, &ctx->Unpack, texObj, texImage );
2496 }
2497 if (!success) {
2498 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002499 const GLint texComps = components_in_intformat(texImage->Format);
Brian Paul699bc7b2000-10-29 18:12:14 +00002500 const GLint texRowStride = texImage->Width * texComps;
Brian Paul02938782000-03-22 17:38:11 +00002501 GLboolean retain = GL_TRUE;
2502
2503 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002504 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002505 if (!texImage->Data) {
2506 make_null_texture(texImage);
2507 }
2508 if (!texImage->Data)
2509 return; /* we're really out of luck! */
2510 }
2511
Brian Paula805bb92000-09-02 17:52:21 +00002512 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002513 width, height, 1, xoffset + texImage->Border,
2514 yoffset + texImage->Border, 0, texRowStride, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002515 format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00002516
Brian Paul02938782000-03-22 17:38:11 +00002517 if (ctx->Driver.TexImage2D) {
2518 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2519 GL_UNSIGNED_BYTE, texImage->Data,
2520 &_mesa_native_packing, texObj, texImage,
2521 &retain);
jtgafb833d1999-08-19 00:55:39 +00002522 }
Brian Paul02938782000-03-22 17:38:11 +00002523
2524 if (!retain && texImage->Data) {
2525 FREE(texImage->Data);
2526 texImage->Data = NULL;
2527 }
jtgafb833d1999-08-19 00:55:39 +00002528 }
2529}
2530
2531
2532
Brian Paulfbd8f211999-11-11 01:22:25 +00002533void
2534_mesa_TexSubImage3D( GLenum target, GLint level,
2535 GLint xoffset, GLint yoffset, GLint zoffset,
2536 GLsizei width, GLsizei height, GLsizei depth,
2537 GLenum format, GLenum type,
2538 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002539{
Brian Paulfbd8f211999-11-11 01:22:25 +00002540 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002541 struct gl_texture_unit *texUnit;
2542 struct gl_texture_object *texObj;
2543 struct gl_texture_image *texImage;
2544 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002545
Brian Paulc3f0a511999-11-03 17:27:05 +00002546 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2547 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002548 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002549 }
2550
Brian Paul02938782000-03-22 17:38:11 +00002551 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002552 texObj = texUnit->Current3D;
Brian Paul02938782000-03-22 17:38:11 +00002553 texImage = texObj->Image[level];
2554 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002555
Brian Paulc3f0a511999-11-03 17:27:05 +00002556 if (width == 0 || height == 0 || height == 0 || !pixels)
2557 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002558
Brian Paul9499e012000-10-30 16:32:42 +00002559 if (ctx->NewState & _NEW_PIXEL)
2560 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002561
Keith Whitwell14940c42000-11-05 18:40:57 +00002562 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00002563 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2564 yoffset, zoffset, width, height, depth, format,
2565 type, pixels, &ctx->Unpack, texObj, texImage );
2566 }
2567 if (!success) {
2568 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002569 const GLint texComps = components_in_intformat(texImage->Format);
Brian Paul699bc7b2000-10-29 18:12:14 +00002570 const GLint texRowStride = texImage->Width * texComps;
Brian Paula805bb92000-09-02 17:52:21 +00002571 const GLint texImgStride = texRowStride * texImage->Height;
Brian Paul02938782000-03-22 17:38:11 +00002572 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00002573
Brian Paula805bb92000-09-02 17:52:21 +00002574 if (!texImage->Data) {
2575 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2576 if (!texImage->Data) {
2577 make_null_texture(texImage);
jtgafb833d1999-08-19 00:55:39 +00002578 }
Brian Paula805bb92000-09-02 17:52:21 +00002579 if (!texImage->Data)
2580 return; /* we're really out of luck! */
jtgafb833d1999-08-19 00:55:39 +00002581 }
Brian Paula805bb92000-09-02 17:52:21 +00002582
2583 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
Brian Paul7298e712000-11-07 16:40:37 +00002584 width, height, depth, xoffset + texImage->Border,
2585 yoffset + texImage->Border,
2586 zoffset + texImage->Border, texRowStride,
2587 texImgStride, format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002588
2589 if (ctx->Driver.TexImage3D) {
2590 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2591 GL_UNSIGNED_BYTE, texImage->Data,
2592 &_mesa_native_packing, texObj, texImage,
2593 &retain);
2594 }
2595
2596 if (!retain && texImage->Data) {
2597 FREE(texImage->Data);
2598 texImage->Data = NULL;
2599 }
jtgafb833d1999-08-19 00:55:39 +00002600 }
jtgafb833d1999-08-19 00:55:39 +00002601}
2602
2603
2604
2605/*
2606 * Read an RGBA image from the frame buffer.
Brian Paula805bb92000-09-02 17:52:21 +00002607 * This is used by glCopyTex[Sub]Image[12]D().
jtgafb833d1999-08-19 00:55:39 +00002608 * Input: ctx - the context
2609 * x, y - lower left corner
2610 * width, height - size of region to read
Brian Paul699bc7b2000-10-29 18:12:14 +00002611 * Return: pointer to block of GL_RGBA, GLchan data.
jtgafb833d1999-08-19 00:55:39 +00002612 */
Brian Paul699bc7b2000-10-29 18:12:14 +00002613static GLchan *
Brian Paulc3f0a511999-11-03 17:27:05 +00002614read_color_image( GLcontext *ctx, GLint x, GLint y,
2615 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00002616{
Brian Paulc3f0a511999-11-03 17:27:05 +00002617 GLint stride, i;
Brian Paul699bc7b2000-10-29 18:12:14 +00002618 GLchan *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00002619
Brian Paul699bc7b2000-10-29 18:12:14 +00002620 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
Brian Paulc3f0a511999-11-03 17:27:05 +00002621 if (!image)
jtgafb833d1999-08-19 00:55:39 +00002622 return NULL;
jtgafb833d1999-08-19 00:55:39 +00002623
2624 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002625 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2626 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002627
Brian Paulc34cea72000-11-21 23:25:40 +00002628 RENDER_START(ctx);
2629
Brian Paulc3f0a511999-11-03 17:27:05 +00002630 dst = image;
Brian Paul699bc7b2000-10-29 18:12:14 +00002631 stride = width * 4;
Brian Paulc3f0a511999-11-03 17:27:05 +00002632 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00002633 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
Brian Paul699bc7b2000-10-29 18:12:14 +00002634 (GLchan (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00002635 dst += stride;
2636 }
jtgafb833d1999-08-19 00:55:39 +00002637
Brian Paulc34cea72000-11-21 23:25:40 +00002638 RENDER_FINISH(ctx);
2639
Brian Paulcea0e8e1999-11-25 17:36:48 +00002640 /* Read from draw buffer (the default) */
2641 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2642 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002643
2644 return image;
2645}
2646
2647
2648
Brian Paulfbd8f211999-11-11 01:22:25 +00002649void
2650_mesa_CopyTexImage1D( GLenum target, GLint level,
2651 GLenum internalFormat,
2652 GLint x, GLint y,
2653 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00002654{
Brian Paulfbd8f211999-11-11 01:22:25 +00002655 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002656 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00002657
Brian Paulf7b57072000-03-20 14:37:52 +00002658 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2659 width, 1, border))
2660 return;
2661
Brian Paul9499e012000-10-30 16:32:42 +00002662 if (ctx->NewState & _NEW_PIXEL)
2663 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002664
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00002665 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002666 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002667 internalFormat, x, y, width, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002668 struct gl_pixelstore_attrib unpackSave;
2669
2670 /* get image from framebuffer */
Brian Paul699bc7b2000-10-29 18:12:14 +00002671 GLchan *image = read_color_image( ctx, x, y, width, 1 );
Brian Paulc3f0a511999-11-03 17:27:05 +00002672 if (!image) {
2673 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2674 return;
2675 }
Brian Paul7dac1322000-06-15 19:57:14 +00002676
2677 /* call glTexImage1D to redefine the texture */
2678 unpackSave = ctx->Unpack;
2679 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002680 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002681 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002682 ctx->Unpack = unpackSave;
2683
Brian Paulc3f0a511999-11-03 17:27:05 +00002684 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002685 }
jtgafb833d1999-08-19 00:55:39 +00002686}
2687
2688
2689
Brian Paulfbd8f211999-11-11 01:22:25 +00002690void
2691_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2692 GLint x, GLint y, GLsizei width, GLsizei height,
2693 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002694{
Brian Paulfbd8f211999-11-11 01:22:25 +00002695 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002696 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002697
Brian Paulf7b57072000-03-20 14:37:52 +00002698 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2699 width, height, border))
2700 return;
2701
Brian Paul9499e012000-10-30 16:32:42 +00002702 if (ctx->NewState & _NEW_PIXEL)
2703 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002704
Keith Whitwell14940c42000-11-05 18:40:57 +00002705 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002706 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002707 internalFormat, x, y, width, height, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002708 struct gl_pixelstore_attrib unpackSave;
2709
2710 /* get image from framebuffer */
Brian Paul699bc7b2000-10-29 18:12:14 +00002711 GLchan *image = read_color_image( ctx, x, y, width, height );
Brian Paulc3f0a511999-11-03 17:27:05 +00002712 if (!image) {
2713 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2714 return;
2715 }
Brian Paul7dac1322000-06-15 19:57:14 +00002716
2717 /* call glTexImage2D to redefine the texture */
2718 unpackSave = ctx->Unpack;
2719 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002720 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002721 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002722 ctx->Unpack = unpackSave;
2723
Brian Paulc3f0a511999-11-03 17:27:05 +00002724 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002725 }
jtgafb833d1999-08-19 00:55:39 +00002726}
2727
2728
2729
Brian Paulfbd8f211999-11-11 01:22:25 +00002730void
2731_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2732 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002733{
Brian Paulfbd8f211999-11-11 01:22:25 +00002734 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002735 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002736
Brian Paulf7b57072000-03-20 14:37:52 +00002737 if (copytexsubimage_error_check(ctx, 1, target, level,
2738 xoffset, 0, 0, width, 1))
2739 return;
2740
Brian Paul9499e012000-10-30 16:32:42 +00002741 if (ctx->NewState & _NEW_PIXEL)
2742 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002743
Keith Whitwell14940c42000-11-05 18:40:57 +00002744 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002745 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2746 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002747 struct gl_texture_unit *texUnit;
2748 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002749 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002750 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002751
Brian Paulc3f0a511999-11-03 17:27:05 +00002752 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002753 teximage = texUnit->Current1D->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00002754 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002755
2756 /* get image from frame buffer */
2757 image = read_color_image(ctx, x, y, width, 1);
2758 if (!image) {
2759 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2760 return;
jtgafb833d1999-08-19 00:55:39 +00002761 }
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00002762
Brian Paul7dac1322000-06-15 19:57:14 +00002763 /* now call glTexSubImage1D to do the real work */
2764 unpackSave = ctx->Unpack;
2765 ctx->Unpack = _mesa_native_packing;
2766 _mesa_TexSubImage1D(target, level, xoffset, width,
2767 GL_RGBA, GL_UNSIGNED_BYTE, image);
2768 ctx->Unpack = unpackSave;
2769
2770 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002771 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002772}
2773
2774
2775
Brian Paulfbd8f211999-11-11 01:22:25 +00002776void
2777_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2778 GLint xoffset, GLint yoffset,
2779 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002780{
Brian Paulfbd8f211999-11-11 01:22:25 +00002781 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002782 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2783
Brian Paulf7b57072000-03-20 14:37:52 +00002784 if (copytexsubimage_error_check(ctx, 2, target, level,
2785 xoffset, yoffset, 0, width, height))
2786 return;
2787
Brian Paul9499e012000-10-30 16:32:42 +00002788 if (ctx->NewState & _NEW_PIXEL)
2789 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002790
Keith Whitwell14940c42000-11-05 18:40:57 +00002791 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002792 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2793 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002794 struct gl_texture_unit *texUnit;
2795 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002796 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002797 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002798
Brian Paulc3f0a511999-11-03 17:27:05 +00002799 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002800 teximage = texUnit->Current2D->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00002801 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002802
2803 /* get image from frame buffer */
2804 image = read_color_image(ctx, x, y, width, height);
2805 if (!image) {
2806 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2807 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002808 }
Brian Paul7dac1322000-06-15 19:57:14 +00002809
2810 /* now call glTexSubImage2D to do the real work */
2811 unpackSave = ctx->Unpack;
2812 ctx->Unpack = _mesa_native_packing;
2813 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2814 GL_RGBA, GL_UNSIGNED_BYTE, image);
2815 ctx->Unpack = unpackSave;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00002816
Brian Paul7dac1322000-06-15 19:57:14 +00002817 FREE(image);
Brian Paulc3f0a511999-11-03 17:27:05 +00002818 }
2819}
2820
2821
2822
Brian Paulfbd8f211999-11-11 01:22:25 +00002823void
2824_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2825 GLint xoffset, GLint yoffset, GLint zoffset,
2826 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002827{
Brian Paulfbd8f211999-11-11 01:22:25 +00002828 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002829 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2830
Brian Paulf7b57072000-03-20 14:37:52 +00002831 if (copytexsubimage_error_check(ctx, 3, target, level,
2832 xoffset, yoffset, zoffset, width, height))
2833 return;
2834
Brian Paul9499e012000-10-30 16:32:42 +00002835 if (ctx->NewState & _NEW_PIXEL)
2836 gl_update_state(ctx);
Brian Paulfa4525e2000-08-21 14:22:24 +00002837
Keith Whitwell14940c42000-11-05 18:40:57 +00002838 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage3D
Brian Paulf7b57072000-03-20 14:37:52 +00002839 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002840 xoffset, yoffset, zoffset, x, y, width, height )) {
2841 struct gl_texture_unit *texUnit;
2842 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002843 struct gl_pixelstore_attrib unpackSave;
Brian Paul699bc7b2000-10-29 18:12:14 +00002844 GLchan *image;
Brian Paul7dac1322000-06-15 19:57:14 +00002845
Brian Paul02938782000-03-22 17:38:11 +00002846 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002847 teximage = texUnit->Current3D->Image[level];
Brian Paul02938782000-03-22 17:38:11 +00002848 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002849
2850 /* get image from frame buffer */
2851 image = read_color_image(ctx, x, y, width, height);
2852 if (!image) {
2853 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2854 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002855 }
Brian Paul7dac1322000-06-15 19:57:14 +00002856
2857 /* now call glTexSubImage2D to do the real work */
2858 unpackSave = ctx->Unpack;
2859 ctx->Unpack = _mesa_native_packing;
2860 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2861 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2862 ctx->Unpack = unpackSave;
Jouk Jansen5e3bc0c2000-11-22 07:32:16 +00002863
Brian Paul7dac1322000-06-15 19:57:14 +00002864 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002865 }
2866}
Brian Paul1207bf02000-05-23 20:10:49 +00002867
2868
2869
2870void
2871_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002872 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002873 GLint border, GLsizei imageSize,
2874 const GLvoid *data)
2875{
Brian Paulaea66b12000-05-24 14:04:06 +00002876 GET_CURRENT_CONTEXT(ctx);
2877 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2878
Brian Paul289d47e2000-08-29 23:31:23 +00002879 switch (internalFormat) {
2880 case GL_COMPRESSED_ALPHA_ARB:
2881 case GL_COMPRESSED_LUMINANCE_ARB:
2882 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2883 case GL_COMPRESSED_INTENSITY_ARB:
2884 case GL_COMPRESSED_RGB_ARB:
2885 case GL_COMPRESSED_RGBA_ARB:
2886 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2887 return;
2888 default:
2889 /* silence compiler warning */
2890 ;
2891 }
2892
Brian Paulaea66b12000-05-24 14:04:06 +00002893 if (target == GL_TEXTURE_1D) {
2894 struct gl_texture_unit *texUnit;
2895 struct gl_texture_object *texObj;
2896 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002897 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002898
2899 if (texture_error_check(ctx, target, level, internalFormat,
2900 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2901 return; /* error in texture image was detected */
2902 }
2903
2904 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00002905 texObj = texUnit->Current1D;
Brian Paulaea66b12000-05-24 14:04:06 +00002906 texImage = texObj->Image[level];
2907
2908 if (!texImage) {
2909 texImage = _mesa_alloc_texture_image();
2910 texObj->Image[level] = texImage;
2911 if (!texImage) {
2912 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2913 return;
2914 }
2915 }
2916 else if (texImage->Data) {
2917 FREE(texImage->Data);
2918 texImage->Data = NULL;
2919 }
2920
2921 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00002922 init_texture_image(ctx, texImage, width, 1, 1,
2923 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00002924
2925 /* process the texture image */
2926 if (data) {
2927 GLboolean retain = GL_TRUE;
2928 GLboolean success = GL_FALSE;
2929 if (ctx->Driver.CompressedTexImage1D) {
Brian Paul289d47e2000-08-29 23:31:23 +00002930 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2931 imageSize, data, texObj, texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002932 }
2933 if (retain || !success) {
2934 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00002935 computedImageSize = _mesa_compressed_image_size(ctx,
2936 internalFormat,
2937 1, /* num dims */
2938 width,
2939 1, /* height */
2940 1); /* depth */
2941 if (computedImageSize != imageSize) {
2942 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2943 return;
2944 }
2945 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002946 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00002947 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002948 }
2949 }
2950 if (!retain && texImage->Data) {
2951 FREE(texImage->Data);
2952 texImage->Data = NULL;
2953 }
2954 }
2955 else {
2956 make_null_texture(texImage);
2957 if (ctx->Driver.CompressedTexImage1D) {
2958 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00002959 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2960 texImage->Data, texObj,
2961 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002962 }
2963 }
2964
2965 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00002966 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00002967 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00002968 }
2969 else if (target == GL_PROXY_TEXTURE_1D) {
2970 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00002971 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2972 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2973 if (!error && ctx->Driver.TestProxyTexImage) {
2974 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2975 internalFormat, GL_NONE, GL_NONE,
2976 width, 1, 1, border);
2977 }
2978 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00002979 /* if error, clear all proxy texture image parameters */
2980 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00002981 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00002982 }
2983 }
2984 else {
2985 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002986 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002987 width, 1, 1, border, internalFormat);
2988 }
2989 }
2990 else {
2991 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2992 return;
2993 }
Brian Paul1207bf02000-05-23 20:10:49 +00002994}
2995
2996
2997void
2998_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002999 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00003000 GLsizei height, GLint border, GLsizei imageSize,
3001 const GLvoid *data)
3002{
Brian Paulaea66b12000-05-24 14:04:06 +00003003 GET_CURRENT_CONTEXT(ctx);
3004 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
3005
Brian Paul289d47e2000-08-29 23:31:23 +00003006 switch (internalFormat) {
3007 case GL_COMPRESSED_ALPHA_ARB:
3008 case GL_COMPRESSED_LUMINANCE_ARB:
3009 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3010 case GL_COMPRESSED_INTENSITY_ARB:
3011 case GL_COMPRESSED_RGB_ARB:
3012 case GL_COMPRESSED_RGBA_ARB:
3013 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3014 return;
3015 default:
3016 /* silence compiler warning */
3017 ;
3018 }
3019
Brian Paul9540a1d2000-06-06 17:03:38 +00003020 if (target==GL_TEXTURE_2D ||
Keith Whitwella96308c2000-10-30 13:31:59 +00003021 (ctx->Extensions.ARB_texture_cube_map &&
Brian Paul9540a1d2000-06-06 17:03:38 +00003022 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3023 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulaea66b12000-05-24 14:04:06 +00003024 struct gl_texture_unit *texUnit;
3025 struct gl_texture_object *texObj;
3026 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00003027 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00003028
3029 if (texture_error_check(ctx, target, level, internalFormat,
3030 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3031 return; /* error in texture image was detected */
3032 }
3033
3034 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00003035 texObj = texUnit->Current2D;
Brian Paulaea66b12000-05-24 14:04:06 +00003036 texImage = texObj->Image[level];
3037
3038 if (!texImage) {
3039 texImage = _mesa_alloc_texture_image();
3040 texObj->Image[level] = texImage;
3041 if (!texImage) {
3042 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3043 return;
3044 }
3045 }
3046 else if (texImage->Data) {
3047 FREE(texImage->Data);
3048 texImage->Data = NULL;
3049 }
3050
3051 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003052 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003053
3054 /* process the texture image */
3055 if (data) {
3056 GLboolean retain = GL_TRUE;
3057 GLboolean success = GL_FALSE;
3058 if (ctx->Driver.CompressedTexImage2D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003059 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3060 target,
3061 level,
3062 imageSize,
3063 data,
3064 texObj,
3065 texImage,
3066 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003067 }
3068 if (retain || !success) {
3069 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003070 computedImageSize = _mesa_compressed_image_size(ctx,
3071 internalFormat,
3072 2, /* num dims */
3073 width,
3074 height,
3075 1); /* depth */
3076 if (computedImageSize != imageSize) {
3077 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3078 return;
3079 }
3080 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003081 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003082 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003083 }
3084 }
3085 if (!retain && texImage->Data) {
3086 FREE(texImage->Data);
3087 texImage->Data = NULL;
3088 }
3089 }
3090 else {
3091 make_null_texture(texImage);
3092 if (ctx->Driver.CompressedTexImage2D) {
3093 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003094 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3095 texImage->Data, texObj,
3096 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003097 }
3098 }
3099
3100 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00003101 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00003102 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00003103 }
3104 else if (target == GL_PROXY_TEXTURE_2D) {
3105 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003106 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3107 GL_NONE, GL_NONE, 2, width, height, 1, border);
3108 if (!error && ctx->Driver.TestProxyTexImage) {
3109 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3110 internalFormat, GL_NONE, GL_NONE,
3111 width, height, 1, border);
3112 }
3113 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003114 /* if error, clear all proxy texture image parameters */
3115 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003116 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003117 }
3118 }
3119 else {
3120 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003121 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003122 width, 1, 1, border, internalFormat);
3123 }
3124 }
3125 else {
3126 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3127 return;
3128 }
Brian Paul1207bf02000-05-23 20:10:49 +00003129}
3130
3131
3132void
3133_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00003134 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00003135 GLsizei height, GLsizei depth, GLint border,
3136 GLsizei imageSize, const GLvoid *data)
3137{
Brian Paulaea66b12000-05-24 14:04:06 +00003138 GET_CURRENT_CONTEXT(ctx);
3139 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3140
Brian Paul289d47e2000-08-29 23:31:23 +00003141 switch (internalFormat) {
3142 case GL_COMPRESSED_ALPHA_ARB:
3143 case GL_COMPRESSED_LUMINANCE_ARB:
3144 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3145 case GL_COMPRESSED_INTENSITY_ARB:
3146 case GL_COMPRESSED_RGB_ARB:
3147 case GL_COMPRESSED_RGBA_ARB:
3148 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3149 return;
3150 default:
3151 /* silence compiler warning */
3152 ;
3153 }
3154
Brian Paul9540a1d2000-06-06 17:03:38 +00003155 if (target == GL_TEXTURE_3D) {
Brian Paulaea66b12000-05-24 14:04:06 +00003156 struct gl_texture_unit *texUnit;
3157 struct gl_texture_object *texObj;
3158 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00003159 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00003160
3161 if (texture_error_check(ctx, target, level, internalFormat,
3162 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3163 return; /* error in texture image was detected */
3164 }
3165
3166 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paula8523782000-11-19 23:10:25 +00003167 texObj = texUnit->Current3D;
Brian Paulaea66b12000-05-24 14:04:06 +00003168 texImage = texObj->Image[level];
3169
3170 if (!texImage) {
3171 texImage = _mesa_alloc_texture_image();
3172 texObj->Image[level] = texImage;
3173 if (!texImage) {
3174 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3175 return;
3176 }
3177 }
3178 else if (texImage->Data) {
3179 FREE(texImage->Data);
3180 texImage->Data = NULL;
3181 }
3182
3183 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003184 init_texture_image(ctx, texImage, width, height, depth,
3185 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003186
3187 /* process the texture image */
3188 if (data) {
3189 GLboolean retain = GL_TRUE;
3190 GLboolean success = GL_FALSE;
3191 if (ctx->Driver.CompressedTexImage3D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003192 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3193 imageSize, data,
3194 texObj, texImage,
3195 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003196 }
3197 if (retain || !success) {
3198 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003199 computedImageSize = _mesa_compressed_image_size(ctx,
3200 internalFormat,
3201 3, /* num dims */
3202 width,
3203 height,
3204 depth);
3205 if (computedImageSize != imageSize) {
3206 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3207 return;
3208 }
3209 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003210 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003211 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003212 }
3213 }
3214 if (!retain && texImage->Data) {
3215 FREE(texImage->Data);
3216 texImage->Data = NULL;
3217 }
3218 }
3219 else {
3220 make_null_texture(texImage);
3221 if (ctx->Driver.CompressedTexImage3D) {
3222 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003223 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3224 texImage->Data, texObj,
3225 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003226 }
3227 }
3228
3229 /* state update */
Brian Paula8523782000-11-19 23:10:25 +00003230 texObj->Complete = GL_FALSE;
Keith Whitwella96308c2000-10-30 13:31:59 +00003231 ctx->NewState |= _NEW_TEXTURE;
Brian Paulaea66b12000-05-24 14:04:06 +00003232 }
3233 else if (target == GL_PROXY_TEXTURE_3D) {
3234 /* Proxy texture: check for errors and update proxy state */
Brian Paul38d3f3d2000-09-07 15:38:49 +00003235 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3236 GL_NONE, GL_NONE, 1, width, height, depth, border);
3237 if (!error && ctx->Driver.TestProxyTexImage) {
3238 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3239 internalFormat, GL_NONE, GL_NONE,
3240 width, height, depth, border);
3241 }
3242 if (error) {
Brian Paulaea66b12000-05-24 14:04:06 +00003243 /* if error, clear all proxy texture image parameters */
3244 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
Brian Paul9c272782000-09-05 22:04:30 +00003245 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
Brian Paulaea66b12000-05-24 14:04:06 +00003246 }
3247 }
3248 else {
3249 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003250 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003251 width, 1, 1, border, internalFormat);
3252 }
3253 }
3254 else {
3255 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3256 return;
3257 }
Brian Paul1207bf02000-05-23 20:10:49 +00003258}
3259
3260
3261void
3262_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3263 GLsizei width, GLenum format,
3264 GLsizei imageSize, const GLvoid *data)
3265{
Brian Paul9540a1d2000-06-06 17:03:38 +00003266 GET_CURRENT_CONTEXT(ctx);
3267 struct gl_texture_unit *texUnit;
3268 struct gl_texture_object *texObj;
3269 struct gl_texture_image *texImage;
3270 GLboolean success = GL_FALSE;
3271
3272 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3273 width, 1, 1, format, GL_NONE)) {
3274 return; /* error was detected */
3275 }
3276
3277 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3278 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3279 texImage = texObj->Image[level];
3280 assert(texImage);
3281
3282 if (width == 0 || !data)
3283 return; /* no-op, not an error */
3284
3285 if (ctx->Driver.CompressedTexSubImage1D) {
3286 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3287 xoffset, width, format, imageSize, data, texObj, texImage);
3288 }
3289 if (!success) {
3290 /* XXX what else can we do? */
3291 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3292 return;
3293 }
Brian Paul1207bf02000-05-23 20:10:49 +00003294}
3295
3296
3297void
3298_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3299 GLint yoffset, GLsizei width, GLsizei height,
3300 GLenum format, GLsizei imageSize,
3301 const GLvoid *data)
3302{
Brian Paul9540a1d2000-06-06 17:03:38 +00003303 GET_CURRENT_CONTEXT(ctx);
3304 struct gl_texture_unit *texUnit;
3305 struct gl_texture_object *texObj;
3306 struct gl_texture_image *texImage;
3307 GLboolean success = GL_FALSE;
3308
3309 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3310 width, height, 1, format, GL_NONE)) {
3311 return; /* error was detected */
3312 }
3313
3314 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3315 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3316 texImage = texObj->Image[level];
3317 assert(texImage);
3318
3319 if (width == 0 || height == 0 || !data)
3320 return; /* no-op, not an error */
3321
3322 if (ctx->Driver.CompressedTexSubImage2D) {
3323 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3324 xoffset, yoffset, width, height, format,
3325 imageSize, data, texObj, texImage);
3326 }
3327 if (!success) {
3328 /* XXX what else can we do? */
3329 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3330 return;
3331 }
Brian Paul1207bf02000-05-23 20:10:49 +00003332}
3333
3334
3335void
3336_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3337 GLint yoffset, GLint zoffset, GLsizei width,
3338 GLsizei height, GLsizei depth, GLenum format,
3339 GLsizei imageSize, const GLvoid *data)
3340{
Brian Paul9540a1d2000-06-06 17:03:38 +00003341 GET_CURRENT_CONTEXT(ctx);
3342 struct gl_texture_unit *texUnit;
3343 struct gl_texture_object *texObj;
3344 struct gl_texture_image *texImage;
3345 GLboolean success = GL_FALSE;
3346
3347 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3348 width, height, depth, format, GL_NONE)) {
3349 return; /* error was detected */
3350 }
3351
3352 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3353 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3354 texImage = texObj->Image[level];
3355 assert(texImage);
3356
3357 if (width == 0 || height == 0 || depth == 0 || !data)
3358 return; /* no-op, not an error */
3359
3360 if (ctx->Driver.CompressedTexSubImage3D) {
3361 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3362 xoffset, yoffset, zoffset, width, height, depth,
3363 format, imageSize, data, texObj, texImage);
3364 }
3365 if (!success) {
3366 /* XXX what else can we do? */
3367 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3368 return;
3369 }
Brian Paul1207bf02000-05-23 20:10:49 +00003370}
3371
3372
3373void
Brian Paul9540a1d2000-06-06 17:03:38 +00003374_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
Brian Paul1207bf02000-05-23 20:10:49 +00003375{
Brian Paul9540a1d2000-06-06 17:03:38 +00003376 GET_CURRENT_CONTEXT(ctx);
3377 const struct gl_texture_object *texObj;
3378 struct gl_texture_image *texImage;
3379
3380 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3381
3382 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3383 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3384 return;
3385 }
3386
3387 switch (target) {
3388 case GL_TEXTURE_1D:
Brian Paula8523782000-11-19 23:10:25 +00003389 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D;
Brian Paul9540a1d2000-06-06 17:03:38 +00003390 texImage = texObj->Image[level];
3391 break;
3392 case GL_TEXTURE_2D:
Brian Paula8523782000-11-19 23:10:25 +00003393 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D;
Brian Paul9540a1d2000-06-06 17:03:38 +00003394 texImage = texObj->Image[level];
3395 break;
3396 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3397 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3398 texImage = texObj->Image[level];
3399 break;
3400 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3401 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3402 texImage = texObj->NegX[level];
3403 break;
3404 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3405 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3406 texImage = texObj->PosY[level];
3407 break;
3408 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3409 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3410 texImage = texObj->NegY[level];
3411 break;
3412 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3413 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3414 texImage = texObj->PosZ[level];
3415 break;
3416 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3417 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3418 texImage = texObj->NegZ[level];
3419 break;
3420 case GL_TEXTURE_3D:
Brian Paula8523782000-11-19 23:10:25 +00003421 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D;
Brian Paul9540a1d2000-06-06 17:03:38 +00003422 texImage = texObj->Image[level];
3423 break;
3424 default:
3425 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3426 return;
3427 }
3428
3429 if (!texImage) {
3430 /* invalid mipmap level */
3431 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3432 return;
3433 }
3434
3435 if (!texImage->IsCompressed) {
3436 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3437 return;
3438 }
3439
3440 if (!img)
3441 return;
3442
3443 if (ctx->Driver.GetCompressedTexImage) {
3444 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3445 texImage);
3446 }
3447 else {
3448 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3449 }
Brian Paul1207bf02000-05-23 20:10:49 +00003450}