blob: 1353d69f74d72a3c52c5991b595e1fd04beb0ffd [file] [log] [blame]
Brian Paul01e54752000-09-05 15:40:34 +00001/* $Id: teximage.c,v 1.46 2000/09/05 15:40:34 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paul01e54752000-09-05 15:40:34 +00005 * Version: 3.5
jtgafb833d1999-08-19 00:55:39 +00006 *
Brian Paul663049a2000-01-31 23:10:16 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00008 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#ifdef PC_HEADER
29#include "all.h"
30#else
Brian Paulfbd8f211999-11-11 01:22:25 +000031#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000032#include "context.h"
Brian Paulf93b3dd2000-08-30 18:22:28 +000033#include "convolve.h"
jtgafb833d1999-08-19 00:55:39 +000034#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000035#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000036#include "mmath.h"
37#include "span.h"
Brian Paulfa4525e2000-08-21 14:22:24 +000038#include "state.h"
jtgafb833d1999-08-19 00:55:39 +000039#include "teximage.h"
40#include "texstate.h"
41#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000042#endif
43
44
45/*
46 * NOTES:
47 *
Brian Paulc3f0a511999-11-03 17:27:05 +000048 * Mesa's native texture datatype is GLubyte. Native formats are
49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
50 * and GL_COLOR_INDEX.
51 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000052 */
53
54
Brian Paul48271792000-03-29 18:13:59 +000055#ifdef DEBUG
Brian Paule5d68a22000-03-30 18:37:51 +000056static void PrintTexture(const struct gl_texture_image *img)
Brian Paul48271792000-03-29 18:13:59 +000057{
Brian Paule5d68a22000-03-30 18:37:51 +000058 int i, j, c;
59 GLubyte *data = img->Data;
60
61 if (!data) {
62 printf("No texture data\n");
63 return;
64 }
65
66 switch (img->Format) {
67 case GL_ALPHA:
68 case GL_LUMINANCE:
69 case GL_INTENSITY:
70 case GL_COLOR_INDEX:
71 c = 1;
72 break;
73 case GL_LUMINANCE_ALPHA:
74 c = 2;
75 break;
76 case GL_RGB:
77 c = 3;
78 break;
79 case GL_RGBA:
80 c = 4;
81 break;
82 default:
83 gl_problem(NULL, "error in PrintTexture\n");
84 return;
85 }
86
87
88 for (i = 0; i < img->Height; i++) {
89 for (j = 0; j < img->Width; j++) {
Brian Paul48271792000-03-29 18:13:59 +000090 if (c==1)
91 printf("%02x ", data[0]);
92 else if (c==2)
Brian Paule5d68a22000-03-30 18:37:51 +000093 printf("%02x%02x ", data[0], data[1]);
Brian Paul48271792000-03-29 18:13:59 +000094 else if (c==3)
Brian Paule5d68a22000-03-30 18:37:51 +000095 printf("%02x%02x%02x ", data[0], data[1], data[2]);
Brian Paul48271792000-03-29 18:13:59 +000096 else if (c==4)
Brian Paule5d68a22000-03-30 18:37:51 +000097 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
Brian Paul48271792000-03-29 18:13:59 +000098 data += c;
99 }
100 printf("\n");
101 }
102}
103#endif
104
105
106
Brian Paulf7b57072000-03-20 14:37:52 +0000107/*
jtgafb833d1999-08-19 00:55:39 +0000108 * Compute log base 2 of n.
109 * If n isn't an exact power of two return -1.
110 * If n<0 return -1.
111 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000112static int
113logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +0000114{
115 GLint i = 1;
116 GLint log2 = 0;
117
118 if (n<0) {
119 return -1;
120 }
121
122 while ( n > i ) {
123 i *= 2;
124 log2++;
125 }
126 if (i != n) {
127 return -1;
128 }
129 else {
130 return log2;
131 }
132}
133
134
135
136/*
137 * Given an internal texture format enum or 1, 2, 3, 4 return the
138 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +0000139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
140 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +0000141 */
Brian Paulb132e8d2000-03-23 16:23:14 +0000142GLint
Brian Paulaea66b12000-05-24 14:04:06 +0000143_mesa_base_tex_format( GLcontext *ctx, GLint format )
jtgafb833d1999-08-19 00:55:39 +0000144{
Brian Paul289d47e2000-08-29 23:31:23 +0000145 /*
146 * Ask the driver for the base format, if it doesn't
147 * know, it will return -1;
148 */
149 if (ctx->Driver.BaseCompressedTexFormat) {
150 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
151 if (ifmt >= 0) {
152 return ifmt;
153 }
154 }
jtgafb833d1999-08-19 00:55:39 +0000155 switch (format) {
156 case GL_ALPHA:
157 case GL_ALPHA4:
158 case GL_ALPHA8:
159 case GL_ALPHA12:
160 case GL_ALPHA16:
161 return GL_ALPHA;
162 case 1:
163 case GL_LUMINANCE:
164 case GL_LUMINANCE4:
165 case GL_LUMINANCE8:
166 case GL_LUMINANCE12:
167 case GL_LUMINANCE16:
168 return GL_LUMINANCE;
169 case 2:
170 case GL_LUMINANCE_ALPHA:
171 case GL_LUMINANCE4_ALPHA4:
172 case GL_LUMINANCE6_ALPHA2:
173 case GL_LUMINANCE8_ALPHA8:
174 case GL_LUMINANCE12_ALPHA4:
175 case GL_LUMINANCE12_ALPHA12:
176 case GL_LUMINANCE16_ALPHA16:
177 return GL_LUMINANCE_ALPHA;
178 case GL_INTENSITY:
179 case GL_INTENSITY4:
180 case GL_INTENSITY8:
181 case GL_INTENSITY12:
182 case GL_INTENSITY16:
183 return GL_INTENSITY;
184 case 3:
185 case GL_RGB:
186 case GL_R3_G3_B2:
187 case GL_RGB4:
188 case GL_RGB5:
189 case GL_RGB8:
190 case GL_RGB10:
191 case GL_RGB12:
192 case GL_RGB16:
193 return GL_RGB;
194 case 4:
195 case GL_RGBA:
196 case GL_RGBA2:
197 case GL_RGBA4:
198 case GL_RGB5_A1:
199 case GL_RGBA8:
200 case GL_RGB10_A2:
201 case GL_RGBA12:
202 case GL_RGBA16:
203 return GL_RGBA;
204 case GL_COLOR_INDEX:
205 case GL_COLOR_INDEX1_EXT:
206 case GL_COLOR_INDEX2_EXT:
207 case GL_COLOR_INDEX4_EXT:
208 case GL_COLOR_INDEX8_EXT:
209 case GL_COLOR_INDEX12_EXT:
210 case GL_COLOR_INDEX16_EXT:
211 return GL_COLOR_INDEX;
212 default:
213 return -1; /* error */
214 }
215}
216
217
218
219/*
220 * Given an internal texture format enum or 1, 2, 3, 4 return the
221 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
223 * number of components for the format. Return -1 if invalid enum.
224 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000225static GLint
226components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000227{
228 switch (format) {
229 case GL_ALPHA:
230 case GL_ALPHA4:
231 case GL_ALPHA8:
232 case GL_ALPHA12:
233 case GL_ALPHA16:
234 return 1;
235 case 1:
236 case GL_LUMINANCE:
237 case GL_LUMINANCE4:
238 case GL_LUMINANCE8:
239 case GL_LUMINANCE12:
240 case GL_LUMINANCE16:
241 return 1;
242 case 2:
243 case GL_LUMINANCE_ALPHA:
244 case GL_LUMINANCE4_ALPHA4:
245 case GL_LUMINANCE6_ALPHA2:
246 case GL_LUMINANCE8_ALPHA8:
247 case GL_LUMINANCE12_ALPHA4:
248 case GL_LUMINANCE12_ALPHA12:
249 case GL_LUMINANCE16_ALPHA16:
250 return 2;
251 case GL_INTENSITY:
252 case GL_INTENSITY4:
253 case GL_INTENSITY8:
254 case GL_INTENSITY12:
255 case GL_INTENSITY16:
256 return 1;
257 case 3:
258 case GL_RGB:
259 case GL_R3_G3_B2:
260 case GL_RGB4:
261 case GL_RGB5:
262 case GL_RGB8:
263 case GL_RGB10:
264 case GL_RGB12:
265 case GL_RGB16:
266 return 3;
267 case 4:
268 case GL_RGBA:
269 case GL_RGBA2:
270 case GL_RGBA4:
271 case GL_RGB5_A1:
272 case GL_RGBA8:
273 case GL_RGB10_A2:
274 case GL_RGBA12:
275 case GL_RGBA16:
276 return 4;
277 case GL_COLOR_INDEX:
278 case GL_COLOR_INDEX1_EXT:
279 case GL_COLOR_INDEX2_EXT:
280 case GL_COLOR_INDEX4_EXT:
281 case GL_COLOR_INDEX8_EXT:
282 case GL_COLOR_INDEX12_EXT:
283 case GL_COLOR_INDEX16_EXT:
284 return 1;
285 default:
286 return -1; /* error */
287 }
288}
289
290
Brian Paulaea66b12000-05-24 14:04:06 +0000291/*
292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
293 * otherwise.
294 */
295static GLboolean
Brian Paul289d47e2000-08-29 23:31:23 +0000296is_compressed_format(GLcontext *ctx, GLenum internalFormat)
Brian Paulaea66b12000-05-24 14:04:06 +0000297{
Brian Paul289d47e2000-08-29 23:31:23 +0000298 if (ctx->Driver.IsCompressedFormat) {
299 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
300 }
301 return GL_FALSE;
Brian Paulaea66b12000-05-24 14:04:06 +0000302}
303
304
jtgafb833d1999-08-19 00:55:39 +0000305
jtgafb833d1999-08-19 00:55:39 +0000306/*
307 * Examine the texImage->Format field and set the Red, Green, Blue, etc
308 * texel component sizes to default values.
309 * These fields are set only here by core Mesa but device drivers may
310 * overwritting these fields to indicate true texel resolution.
311 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000312static void
313set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000314{
315 switch (texImage->Format) {
316 case GL_ALPHA:
317 texImage->RedBits = 0;
318 texImage->GreenBits = 0;
319 texImage->BlueBits = 0;
320 texImage->AlphaBits = 8;
321 texImage->IntensityBits = 0;
322 texImage->LuminanceBits = 0;
323 texImage->IndexBits = 0;
324 break;
325 case GL_LUMINANCE:
326 texImage->RedBits = 0;
327 texImage->GreenBits = 0;
328 texImage->BlueBits = 0;
329 texImage->AlphaBits = 0;
330 texImage->IntensityBits = 0;
331 texImage->LuminanceBits = 8;
332 texImage->IndexBits = 0;
333 break;
334 case GL_LUMINANCE_ALPHA:
335 texImage->RedBits = 0;
336 texImage->GreenBits = 0;
337 texImage->BlueBits = 0;
338 texImage->AlphaBits = 8;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 8;
341 texImage->IndexBits = 0;
342 break;
343 case GL_INTENSITY:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 0;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 8;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 0;
351 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000352 case GL_RED:
353 texImage->RedBits = 8;
354 texImage->GreenBits = 0;
355 texImage->BlueBits = 0;
356 texImage->AlphaBits = 0;
357 texImage->IntensityBits = 0;
358 texImage->LuminanceBits = 0;
359 texImage->IndexBits = 0;
360 break;
361 case GL_GREEN:
362 texImage->RedBits = 0;
363 texImage->GreenBits = 8;
364 texImage->BlueBits = 0;
365 texImage->AlphaBits = 0;
366 texImage->IntensityBits = 0;
367 texImage->LuminanceBits = 0;
368 texImage->IndexBits = 0;
369 break;
370 case GL_BLUE:
371 texImage->RedBits = 0;
372 texImage->GreenBits = 0;
373 texImage->BlueBits = 8;
374 texImage->AlphaBits = 0;
375 texImage->IntensityBits = 0;
376 texImage->LuminanceBits = 0;
377 texImage->IndexBits = 0;
378 break;
jtgafb833d1999-08-19 00:55:39 +0000379 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000380 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000381 texImage->RedBits = 8;
382 texImage->GreenBits = 8;
383 texImage->BlueBits = 8;
384 texImage->AlphaBits = 0;
385 texImage->IntensityBits = 0;
386 texImage->LuminanceBits = 0;
387 texImage->IndexBits = 0;
388 break;
389 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000390 case GL_BGRA:
391 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000392 texImage->RedBits = 8;
393 texImage->GreenBits = 8;
394 texImage->BlueBits = 8;
395 texImage->AlphaBits = 8;
396 texImage->IntensityBits = 0;
397 texImage->LuminanceBits = 0;
398 texImage->IndexBits = 0;
399 break;
400 case GL_COLOR_INDEX:
401 texImage->RedBits = 0;
402 texImage->GreenBits = 0;
403 texImage->BlueBits = 0;
404 texImage->AlphaBits = 0;
405 texImage->IntensityBits = 0;
406 texImage->LuminanceBits = 0;
407 texImage->IndexBits = 8;
408 break;
409 default:
410 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
411 }
412}
413
414
Brian Paulfc4b4432000-05-23 15:17:12 +0000415static void
416set_tex_image(struct gl_texture_object *tObj,
417 GLenum target, GLint level,
418 struct gl_texture_image *texImage)
419{
420 ASSERT(tObj);
421 ASSERT(texImage);
422 switch (target) {
423 case GL_TEXTURE_2D:
424 tObj->Image[level] = texImage;
425 return;
426 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
Brian Paul413d6a22000-05-26 14:44:59 +0000427 tObj->Image[level] = texImage;
Brian Paulfc4b4432000-05-23 15:17:12 +0000428 return;
429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
430 tObj->NegX[level] = texImage;
431 return;
432 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
433 tObj->PosY[level] = texImage;
434 return;
435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
436 tObj->NegY[level] = texImage;
437 return;
438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
439 tObj->PosZ[level] = texImage;
440 return;
441 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
442 tObj->NegZ[level] = texImage;
443 return;
444 default:
445 gl_problem(NULL, "bad target in set_tex_image()");
446 return;
447 }
448}
449
450
Brian Paul77ce6da2000-03-20 23:40:12 +0000451/*
452 * Return new gl_texture_image struct with all fields initialized to zero.
453 */
454struct gl_texture_image *
Brian Paul021a5252000-03-27 17:54:17 +0000455_mesa_alloc_texture_image( void )
Brian Paul77ce6da2000-03-20 23:40:12 +0000456{
457 return CALLOC_STRUCT(gl_texture_image);
458}
459
460
461
462/*
Brian Paul02938782000-03-22 17:38:11 +0000463 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000464 */
Brian Paul02938782000-03-22 17:38:11 +0000465static void
Brian Paul289d47e2000-08-29 23:31:23 +0000466init_texture_image( GLcontext *ctx,
467 struct gl_texture_image *img,
Brian Paul02938782000-03-22 17:38:11 +0000468 GLsizei width, GLsizei height, GLsizei depth,
469 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000470{
Brian Paul02938782000-03-22 17:38:11 +0000471 ASSERT(img);
472 ASSERT(!img->Data);
Brian Paul289d47e2000-08-29 23:31:23 +0000473 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000474 set_teximage_component_sizes( img );
475 img->IntFormat = (GLenum) internalFormat;
476 img->Border = border;
477 img->Width = width;
478 img->Height = height;
479 img->Depth = depth;
480 img->WidthLog2 = logbase2(width - 2 * border);
481 if (height == 1) /* 1-D texture */
482 img->HeightLog2 = 0;
483 else
484 img->HeightLog2 = logbase2(height - 2 * border);
485 if (depth == 1) /* 2-D texture */
486 img->DepthLog2 = 0;
487 else
488 img->DepthLog2 = logbase2(depth - 2 * border);
489 img->Width2 = 1 << img->WidthLog2;
490 img->Height2 = 1 << img->HeightLog2;
491 img->Depth2 = 1 << img->DepthLog2;
492 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paul289d47e2000-08-29 23:31:23 +0000493 img->IsCompressed = is_compressed_format(ctx, internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000494}
495
496
497
498void
Brian Paul021a5252000-03-27 17:54:17 +0000499_mesa_free_texture_image( struct gl_texture_image *teximage )
Brian Paul77ce6da2000-03-20 23:40:12 +0000500{
501 if (teximage->Data) {
502 FREE( teximage->Data );
503 teximage->Data = NULL;
504 }
505 FREE( teximage );
506}
507
508
509
Brian Paulfc4b4432000-05-23 15:17:12 +0000510/*
Brian Paulaea66b12000-05-24 14:04:06 +0000511 * Return number of bytes of storage needed to store a compressed texture
Brian Paul289d47e2000-08-29 23:31:23 +0000512 * image. Only the driver knows for sure. If the driver can't help us,
513 * we must return 0.
Brian Paulaea66b12000-05-24 14:04:06 +0000514 */
515GLuint
Brian Paul289d47e2000-08-29 23:31:23 +0000516_mesa_compressed_image_size(GLcontext *ctx,
517 GLenum internalFormat,
518 GLint numDimensions,
519 GLint width,
520 GLint height,
521 GLint depth)
Brian Paulaea66b12000-05-24 14:04:06 +0000522{
Brian Paul289d47e2000-08-29 23:31:23 +0000523 if (ctx->Driver.CompressedImageSize) {
524 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
525 numDimensions,
526 width, height, depth);
527 }
528 else {
529 /* Shouldn't this be an internal error of some sort? */
530 return 0;
531 }
Brian Paulaea66b12000-05-24 14:04:06 +0000532}
533
534
535
536/*
Brian Paul35d53012000-05-23 17:14:49 +0000537 * Given a texture unit and a texture target, return the corresponding
538 * texture object.
539 */
540struct gl_texture_object *
Brian Paul01e54752000-09-05 15:40:34 +0000541_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
Brian Paul35d53012000-05-23 17:14:49 +0000542 GLenum target)
543{
544 switch (target) {
545 case GL_TEXTURE_1D:
546 return texUnit->CurrentD[1];
547 case GL_PROXY_TEXTURE_1D:
548 return ctx->Texture.Proxy1D;
549 case GL_TEXTURE_2D:
550 return texUnit->CurrentD[2];
551 case GL_PROXY_TEXTURE_2D:
552 return ctx->Texture.Proxy2D;
553 case GL_TEXTURE_3D:
554 return texUnit->CurrentD[3];
555 case GL_PROXY_TEXTURE_3D:
556 return ctx->Texture.Proxy3D;
557 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
561 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
563 return ctx->Extensions.HaveTextureCubeMap
564 ? texUnit->CurrentCubeMap : NULL;
565 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
566 return ctx->Extensions.HaveTextureCubeMap
567 ? ctx->Texture.ProxyCubeMap : NULL;
568 default:
569 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
570 return NULL;
571 }
572}
573
574
575/*
Brian Paulfc4b4432000-05-23 15:17:12 +0000576 * Return the texture image struct which corresponds to target and level
577 * for the given texture unit.
578 */
579struct gl_texture_image *
580_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
581 GLenum target, GLint level)
582{
583 ASSERT(texUnit);
584 switch (target) {
585 case GL_TEXTURE_1D:
586 return texUnit->CurrentD[1]->Image[level];
587 case GL_PROXY_TEXTURE_1D:
588 return ctx->Texture.Proxy1D->Image[level];
589 case GL_TEXTURE_2D:
590 return texUnit->CurrentD[2]->Image[level];
591 case GL_PROXY_TEXTURE_2D:
592 return ctx->Texture.Proxy2D->Image[level];
593 case GL_TEXTURE_3D:
594 return texUnit->CurrentD[3]->Image[level];
595 case GL_PROXY_TEXTURE_3D:
596 return ctx->Texture.Proxy3D->Image[level];
597 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
598 if (ctx->Extensions.HaveTextureCubeMap)
Brian Paul413d6a22000-05-26 14:44:59 +0000599 return texUnit->CurrentCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000600 else
601 return NULL;
602 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
603 if (ctx->Extensions.HaveTextureCubeMap)
604 return texUnit->CurrentCubeMap->NegX[level];
605 else
606 return NULL;
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
608 if (ctx->Extensions.HaveTextureCubeMap)
609 return texUnit->CurrentCubeMap->PosY[level];
610 else
611 return NULL;
612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
613 if (ctx->Extensions.HaveTextureCubeMap)
614 return texUnit->CurrentCubeMap->NegY[level];
615 else
616 return NULL;
617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
618 if (ctx->Extensions.HaveTextureCubeMap)
619 return texUnit->CurrentCubeMap->PosZ[level];
620 else
621 return NULL;
622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
623 if (ctx->Extensions.HaveTextureCubeMap)
624 return texUnit->CurrentCubeMap->NegZ[level];
625 else
626 return NULL;
627 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
628 if (ctx->Extensions.HaveTextureCubeMap)
Brian Paul413d6a22000-05-26 14:44:59 +0000629 return ctx->Texture.ProxyCubeMap->Image[level];
Brian Paulfc4b4432000-05-23 15:17:12 +0000630 else
631 return NULL;
632 default:
633 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
634 return NULL;
635 }
636}
637
638
639
Brian Paulf93b3dd2000-08-30 18:22:28 +0000640/*
641 * Calling glTexImage and related functions when convolution is enabled
642 * with GL_REDUCE border mode causes some complications.
643 * The incoming image must be extra large so that the post-convolution
644 * image size is reduced to a power of two size (plus 2 * border).
645 * This function adjusts a texture width and height accordingly if
646 * convolution with GL_REDUCE is enabled.
647 */
648static void
649adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
650 GLsizei *width, GLsizei *height)
651{
652 if (ctx->Pixel.Convolution1DEnabled
653 && dimensions == 1
654 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
655 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
656 }
657 else if (ctx->Pixel.Convolution2DEnabled
658 && dimensions > 1
659 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
660 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
661 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
662 }
663 else if (ctx->Pixel.Separable2DEnabled
664 && dimensions > 1
665 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
666 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
667 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
668 }
669}
670
671
672
Brian Paula805bb92000-09-02 17:52:21 +0000673/*
674 * This function is used to move user image data into a texture image.
675 * We handle full texture images and subtexture images. We also take
676 * care of all image transfer operations here, including convolution.
677 * Input:
678 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
679 * dstRowStride, dstImageStride - strides in bytes
680 */
681static void
682fill_texture_image( GLcontext *ctx, GLuint dimensions,
683 GLenum texFormat, GLubyte *texAddr,
684 GLint srcWidth, GLint srcHeight, GLint srcDepth,
685 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
686 GLint dstRowStride, GLint dstImageStride,
687 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
688 const struct gl_pixelstore_attrib *srcPacking)
689{
690 GLint texComponents;
691
692 ASSERT(ctx);
693 ASSERT(dimensions >= 1 && dimensions <= 3);
694 ASSERT(texAddr);
695 ASSERT(srcWidth >= 1);
696 ASSERT(srcHeight >= 1);
697 ASSERT(srcDepth >= 1);
698 ASSERT(dstXoffset >= 0);
699 ASSERT(dstYoffset >= 0);
700 ASSERT(dstZoffset >= 0);
701 ASSERT(dstRowStride >= 0);
702 ASSERT(dstImageStride >= 0);
703 ASSERT(srcAddr);
704 ASSERT(srcPacking);
705
706 texComponents = components_in_intformat(texFormat);
707
708 /* try common 2D texture cases first */
709 if (!ctx->ImageTransferState && dimensions == 2
710 && srcType == GL_UNSIGNED_BYTE) {
711
712 if (srcFormat == texFormat) {
713 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
714 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
715 */
716 const GLubyte *src = (const GLubyte *) _mesa_image_address(
717 srcPacking, srcAddr, srcWidth, srcHeight,
718 srcFormat, srcType, 0, 0, 0);
719 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
720 srcWidth, srcFormat, srcType);
721 const GLint widthInBytes = srcWidth * texComponents;
722 GLubyte *dst = texAddr + dstYoffset * dstRowStride
723 + dstXoffset * texComponents * sizeof(GLubyte);
724 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
725 MEMCPY(dst, src, srcHeight * widthInBytes);
726 }
727 else {
728 GLint i;
729 for (i = 0; i < srcHeight; i++) {
730 MEMCPY(dst, src, widthInBytes);
731 src += srcRowStride;
732 dst += dstRowStride;
733 }
734 }
735 return; /* all done */
736 }
737 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
738 /* commonly used by Quake */
739 const GLubyte *src = (const GLubyte *) _mesa_image_address(
740 srcPacking, srcAddr, srcWidth, srcHeight,
741 srcFormat, srcType, 0, 0, 0);
742 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
743 srcWidth, srcFormat, srcType);
744 GLubyte *dst = texAddr + dstYoffset * dstRowStride
745 + dstXoffset * texComponents * sizeof(GLubyte);
746 GLint i, j;
747 for (i = 0; i < srcHeight; i++) {
748 const GLubyte *s = src;
749 GLubyte *d = dst;
750 for (j = 0; j < srcWidth; j++) {
751 *d++ = *s++; /*red*/
752 *d++ = *s++; /*green*/
753 *d++ = *s++; /*blue*/
754 s++; /*alpha*/
755 }
756 src += srcRowStride;
757 dst += dstRowStride;
758 }
759 return; /* all done */
760 }
761 }
762
763 /*
764 * General case solutions
765 */
766 if (texFormat == GL_COLOR_INDEX) {
767 /* color index texture */
768 const GLenum texType = GL_UNSIGNED_BYTE;
769 GLint img, row;
770 GLubyte *dest = texAddr + dstZoffset * dstImageStride
771 + dstYoffset * dstRowStride
772 + dstXoffset * texComponents * sizeof(GLubyte);
773 for (img = 0; img < srcDepth; img++) {
774 GLubyte *destRow = dest;
775 for (row = 0; row < srcHeight; row++) {
776 const GLvoid *src = _mesa_image_address(srcPacking,
777 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
778 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
779 srcType, src, srcPacking,
780 ctx->ImageTransferState);
781 destRow += dstRowStride;
782 }
783 dest += dstImageStride;
784 }
785 }
786 else {
787 /* regular, color texture */
788 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
789 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
790 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
791 /*
792 * Fill texture image with convolution
793 */
794 GLint img, row;
795 GLint convWidth = srcWidth, convHeight = srcHeight;
796 GLfloat *tmpImage, *convImage;
797 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
798 if (!tmpImage) {
799 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
800 return;
801 }
802 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
803 if (!convImage) {
804 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
805 FREE(tmpImage);
806 return;
807 }
808
809 for (img = 0; img < srcDepth; img++) {
810 const GLfloat *srcf;
811 GLfloat *dstf = tmpImage;
812 GLubyte *dest;
813
814 /* unpack and do transfer ops up to convolution */
815 for (row = 0; row < srcHeight; row++) {
816 const GLvoid *src = _mesa_image_address(srcPacking,
817 srcAddr, srcWidth, srcHeight,
818 srcFormat, srcType, img, row, 0);
819 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
820 srcFormat, srcType, src, srcPacking,
821 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
822 GL_TRUE);
823 dstf += srcWidth * 4;
824 }
825
826 /* convolve */
827 if (dimensions == 1) {
828 ASSERT(ctx->Pixel.Convolution1DEnabled);
829 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
830 }
831 else {
832 if (ctx->Pixel.Convolution2DEnabled) {
833 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
834 tmpImage, convImage);
835 }
836 else {
837 ASSERT(ctx->Pixel.Separable2DEnabled);
838 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
839 tmpImage, convImage);
840 }
841 }
842
843 /* packing and transfer ops after convolution */
844 srcf = convImage;
845 dest = texAddr + (dstZoffset + img) * dstImageStride
846 + dstYoffset * dstRowStride;
847 for (row = 0; row < convHeight; row++) {
848 _mesa_pack_float_rgba_span(ctx, convWidth,
849 (const GLfloat (*)[4]) srcf,
850 texFormat, GL_UNSIGNED_BYTE,
851 dest, &_mesa_native_packing,
852 ctx->ImageTransferState
853 & IMAGE_POST_CONVOLUTION_BITS);
854 srcf += convWidth * 4;
855 dest += dstRowStride;
856 }
857 }
858
859 FREE(convImage);
860 FREE(tmpImage);
861 }
862 else {
863 /*
864 * no convolution
865 */
866 GLint img, row;
867 GLubyte *dest = texAddr + dstZoffset * dstImageStride
868 + dstYoffset * dstRowStride
869 + dstXoffset * texComponents * sizeof(GLubyte);
870 for (img = 0; img < srcDepth; img++) {
871 GLubyte *destRow = dest;
872 for (row = 0; row < srcHeight; row++) {
Brian Paul01e54752000-09-05 15:40:34 +0000873 const GLvoid *srcRow = _mesa_image_address(srcPacking,
Brian Paula805bb92000-09-02 17:52:21 +0000874 srcAddr, srcWidth, srcHeight,
875 srcFormat, srcType, img, row, 0);
876 _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow,
Brian Paul01e54752000-09-05 15:40:34 +0000877 srcFormat, srcType, srcRow, srcPacking,
Brian Paula805bb92000-09-02 17:52:21 +0000878 ctx->ImageTransferState);
879 destRow += dstRowStride;
880 }
881 dest += dstImageStride;
882 }
883 }
884 }
885}
886
887
888
jtgafb833d1999-08-19 00:55:39 +0000889/* Need this to prevent an out-of-bounds memory access when using
890 * X86 optimized code.
891 */
892#ifdef USE_X86_ASM
893# define EXTRA_BYTE 1
894#else
895# define EXTRA_BYTE 0
896#endif
897
898
Brian Paulc3f0a511999-11-03 17:27:05 +0000899
jtgafb833d1999-08-19 00:55:39 +0000900/*
Brian Paul43911c82000-03-21 00:49:33 +0000901 * Called by glTexImage[123]D. Fill in a texture image with data given
902 * by the client. All pixel transfer and unpack modes are handled here.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000903 * Input: dimensions (1, 2, or 3)
904 * texImage - destination texture image (we'll malloc the memory)
905 * width, height, depth - size of source image
906 * srcFormat, srcType - source image format and type
907 * pixels - source image data
908 * srcPacking - source image packing parameters
909 *
Brian Paul43911c82000-03-21 00:49:33 +0000910 * NOTE: All texture image parameters should have already been error checked.
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000911 *
912 * NOTE: the texImage dimensions and source image dimensions must be correct
913 * with respect to convolution with border mode = reduce.
jtgafb833d1999-08-19 00:55:39 +0000914 */
Brian Paul43911c82000-03-21 00:49:33 +0000915static void
Brian Paulf93b3dd2000-08-30 18:22:28 +0000916make_texture_image( GLcontext *ctx, GLuint dimensions,
Brian Paul43911c82000-03-21 00:49:33 +0000917 struct gl_texture_image *texImage,
Brian Paul5a0d3dc2000-08-31 15:24:39 +0000918 GLint width, GLint height, GLint depth,
Brian Paulc3f0a511999-11-03 17:27:05 +0000919 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
Brian Paulf93b3dd2000-08-30 18:22:28 +0000920 const struct gl_pixelstore_attrib *srcPacking)
jtgafb833d1999-08-19 00:55:39 +0000921{
Brian Paula805bb92000-09-02 17:52:21 +0000922 const GLint internalFormat = texImage->IntFormat;
923 const GLint components = components_in_intformat(internalFormat);
924 GLint convWidth = width, convHeight = height;
jtgafb833d1999-08-19 00:55:39 +0000925
Brian Paula805bb92000-09-02 17:52:21 +0000926 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) {
927 _mesa_update_image_transfer_state(ctx);
928 }
jtgafb833d1999-08-19 00:55:39 +0000929
Brian Paula805bb92000-09-02 17:52:21 +0000930 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
931 adjust_texture_size_for_convolution(ctx, dimensions,
932 &convWidth, &convHeight);
933 }
Brian Paul43911c82000-03-21 00:49:33 +0000934
Brian Paula805bb92000-09-02 17:52:21 +0000935 texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth
936 * components + EXTRA_BYTE);
Brian Paul43911c82000-03-21 00:49:33 +0000937 if (!texImage->Data)
938 return; /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000939
Brian Paula805bb92000-09-02 17:52:21 +0000940 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
941 width, height, depth, 0, 0, 0,
942 convWidth * components * sizeof(GLubyte),
943 convWidth * convHeight * components * sizeof(GLubyte),
944 srcFormat, srcType, pixels, srcPacking);
jtgafb833d1999-08-19 00:55:39 +0000945}
946
947
948
949/*
950 * glTexImage[123]D can accept a NULL image pointer. In this case we
951 * create a texture image with unspecified image contents per the OpenGL
Brian Paul43911c82000-03-21 00:49:33 +0000952 * spec. This function creates an empty image for the given texture image.
jtgafb833d1999-08-19 00:55:39 +0000953 */
Brian Paul43911c82000-03-21 00:49:33 +0000954static void
955make_null_texture( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000956{
957 GLint components;
jtgafb833d1999-08-19 00:55:39 +0000958 GLint numPixels;
jtgafb833d1999-08-19 00:55:39 +0000959
Brian Paul43911c82000-03-21 00:49:33 +0000960 ASSERT(texImage);
961 ASSERT(!texImage->Data);
jtgafb833d1999-08-19 00:55:39 +0000962
Brian Paul43911c82000-03-21 00:49:33 +0000963 components = components_in_intformat(texImage->IntFormat);
964 numPixels = texImage->Width * texImage->Height * texImage->Depth;
jtgafb833d1999-08-19 00:55:39 +0000965
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000966 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000967
968 /*
969 * Let's see if anyone finds this. If glTexImage2D() is called with
970 * a NULL image pointer then load the texture image with something
971 * interesting instead of leaving it indeterminate.
972 */
973 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000974 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000975 " X X XXXXX XXX X ",
976 " XX XX X X X X X ",
977 " X X X X X X X ",
978 " X X XXXX XXX XXXXX ",
979 " X X X X X X ",
980 " X X X X X X X ",
981 " X X XXXXX XXX X X ",
982 " "
983 };
984
985 GLubyte *imgPtr = texImage->Data;
986 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000987 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000988 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000989 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000990 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000991 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000992 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000993 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000994 }
995 }
996 }
997 }
jtgafb833d1999-08-19 00:55:39 +0000998}
999
1000
1001
1002/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001003 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +00001004 * Input:
1005 * dimensions - must be 1 or 2 or 3
1006 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1007 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001008static GLboolean
1009texture_error_check( GLcontext *ctx, GLenum target,
1010 GLint level, GLint internalFormat,
1011 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +00001012 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001013 GLint width, GLint height,
1014 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001015{
1016 GLboolean isProxy;
1017 GLint iformat;
1018
1019 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +00001020 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +00001021 if (target != GL_TEXTURE_1D && !isProxy) {
1022 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1023 return GL_TRUE;
1024 }
1025 }
1026 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +00001027 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
Brian Paul413d6a22000-05-26 14:44:59 +00001028 if (target != GL_TEXTURE_2D && !isProxy &&
1029 !(ctx->Extensions.HaveTextureCubeMap &&
1030 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1031 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
jtgafb833d1999-08-19 00:55:39 +00001032 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1033 return GL_TRUE;
1034 }
1035 }
1036 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +00001037 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +00001038 if (target != GL_TEXTURE_3D && !isProxy) {
1039 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1040 return GL_TRUE;
1041 }
1042 }
1043 else {
1044 gl_problem( ctx, "bad dims in texture_error_check" );
1045 return GL_TRUE;
1046 }
1047
1048 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001049 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +00001050 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001051 char message[100];
1052 sprintf(message, "glTexImage%dD(border)", dimensions);
1053 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001054 }
1055 return GL_TRUE;
1056 }
1057
1058 /* Width */
1059 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1060 || logbase2( width - 2 * border ) < 0) {
1061 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001062 char message[100];
1063 sprintf(message, "glTexImage%dD(width)", dimensions);
1064 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001065 }
1066 return GL_TRUE;
1067 }
1068
1069 /* Height */
1070 if (dimensions >= 2) {
1071 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1072 || logbase2( height - 2 * border ) < 0) {
1073 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001074 char message[100];
1075 sprintf(message, "glTexImage%dD(height)", dimensions);
1076 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +00001077 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001078 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00001079 }
1080 }
1081
Brian Paulad817702000-05-30 00:27:24 +00001082 /* For cube map, width must equal height */
1083 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1084 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1085 if (width != height) {
1086 if (!isProxy) {
1087 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1088 }
1089 return GL_TRUE;
1090 }
1091 }
1092
jtgafb833d1999-08-19 00:55:39 +00001093 /* Depth */
1094 if (dimensions >= 3) {
1095 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1096 || logbase2( depth - 2 * border ) < 0) {
1097 if (!isProxy) {
1098 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1099 }
1100 return GL_TRUE;
1101 }
1102 }
1103
1104 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001105 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001106 if (!isProxy) {
1107 char message[100];
1108 sprintf(message, "glTexImage%dD(level)", dimensions);
1109 gl_error(ctx, GL_INVALID_VALUE, message);
1110 }
jtgafb833d1999-08-19 00:55:39 +00001111 return GL_TRUE;
1112 }
1113
Brian Paulaea66b12000-05-24 14:04:06 +00001114 iformat = _mesa_base_tex_format( ctx, internalFormat );
jtgafb833d1999-08-19 00:55:39 +00001115 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001116 if (!isProxy) {
1117 char message[100];
1118 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1119 gl_error(ctx, GL_INVALID_VALUE, message);
1120 }
jtgafb833d1999-08-19 00:55:39 +00001121 return GL_TRUE;
1122 }
1123
Brian Paul289d47e2000-08-29 23:31:23 +00001124 if (!is_compressed_format(ctx, internalFormat)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001125 if (!_mesa_is_legal_format_and_type( format, type )) {
1126 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1127 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1128 */
1129 if (!isProxy) {
1130 char message[100];
1131 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1132 gl_error(ctx, GL_INVALID_OPERATION, message);
1133 }
1134 return GL_TRUE;
Brian Paulc3f0a511999-11-03 17:27:05 +00001135 }
jtgafb833d1999-08-19 00:55:39 +00001136 }
1137
1138 /* if we get here, the parameters are OK */
1139 return GL_FALSE;
1140}
1141
1142
1143
1144/*
Brian Paulc3f0a511999-11-03 17:27:05 +00001145 * Test glTexSubImage[123]D() parameters for errors.
1146 * Input:
1147 * dimensions - must be 1 or 2 or 3
1148 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1149 */
1150static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001151subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001152 GLenum target, GLint level,
1153 GLint xoffset, GLint yoffset, GLint zoffset,
1154 GLint width, GLint height, GLint depth,
1155 GLenum format, GLenum type )
1156{
1157 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1158 struct gl_texture_image *destTex;
1159
1160 if (dimensions == 1) {
1161 if (target != GL_TEXTURE_1D) {
1162 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1163 return GL_TRUE;
1164 }
1165 }
1166 else if (dimensions == 2) {
Brian Paulfc4b4432000-05-23 15:17:12 +00001167 if (ctx->Extensions.HaveTextureCubeMap) {
1168 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1169 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1170 target != GL_TEXTURE_2D) {
1171 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1172 return GL_TRUE;
1173 }
1174 }
1175 else if (target != GL_TEXTURE_2D) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001176 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1177 return GL_TRUE;
1178 }
1179 }
1180 else if (dimensions == 3) {
1181 if (target != GL_TEXTURE_3D) {
1182 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1183 return GL_TRUE;
1184 }
1185 }
1186 else {
1187 gl_problem( ctx, "bad dims in texture_error_check" );
1188 return GL_TRUE;
1189 }
1190
1191 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1192 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1193 return GL_TRUE;
1194 }
1195
1196 if (width < 0) {
1197 char message[100];
1198 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1199 gl_error(ctx, GL_INVALID_VALUE, message);
1200 return GL_TRUE;
1201 }
1202 if (height < 0 && dimensions > 1) {
1203 char message[100];
1204 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1205 gl_error(ctx, GL_INVALID_VALUE, message);
1206 return GL_TRUE;
1207 }
1208 if (depth < 0 && dimensions > 2) {
1209 char message[100];
1210 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1211 gl_error(ctx, GL_INVALID_VALUE, message);
1212 return GL_TRUE;
1213 }
1214
1215 destTex = texUnit->CurrentD[2]->Image[level];
1216 if (!destTex) {
1217 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1218 return GL_TRUE;
1219 }
1220
1221 if (xoffset < -((GLint)destTex->Border)) {
1222 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1223 return GL_TRUE;
1224 }
1225 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1226 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1227 return GL_TRUE;
1228 }
1229 if (dimensions > 1) {
1230 if (yoffset < -((GLint)destTex->Border)) {
1231 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1232 return GL_TRUE;
1233 }
1234 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1235 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1236 return GL_TRUE;
1237 }
1238 }
1239 if (dimensions > 2) {
1240 if (zoffset < -((GLint)destTex->Border)) {
1241 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1242 return GL_TRUE;
1243 }
1244 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1245 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1246 return GL_TRUE;
1247 }
1248 }
1249
Brian Paul289d47e2000-08-29 23:31:23 +00001250 if (!is_compressed_format(ctx, destTex->IntFormat)) {
Brian Paul9540a1d2000-06-06 17:03:38 +00001251 if (!_mesa_is_legal_format_and_type(format, type)) {
1252 char message[100];
1253 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1254 gl_error(ctx, GL_INVALID_ENUM, message);
1255 return GL_TRUE;
1256 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001257 }
1258
1259 return GL_FALSE;
1260}
1261
1262
1263/*
1264 * Test glCopyTexImage[12]D() parameters for errors.
1265 * Input: dimensions - must be 1 or 2 or 3
1266 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1267 */
1268static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001269copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001270 GLenum target, GLint level, GLint internalFormat,
1271 GLint width, GLint height, GLint border )
1272{
1273 GLint iformat;
1274
Brian Paulfc4b4432000-05-23 15:17:12 +00001275 if (dimensions == 1) {
1276 if (target != GL_TEXTURE_1D) {
1277 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1278 return GL_TRUE;
1279 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001280 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001281 else if (dimensions == 2) {
1282 if (ctx->Extensions.HaveTextureCubeMap) {
1283 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1284 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1285 target != GL_TEXTURE_2D) {
1286 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1287 return GL_TRUE;
1288 }
1289 }
1290 else if (target != GL_TEXTURE_2D) {
1291 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1292 return GL_TRUE;
1293 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001294 }
1295
1296 /* Border */
1297 if (border!=0 && border!=1) {
1298 char message[100];
1299 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1300 gl_error(ctx, GL_INVALID_VALUE, message);
1301 return GL_TRUE;
1302 }
1303
1304 /* Width */
1305 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1306 || logbase2( width - 2 * border ) < 0) {
1307 char message[100];
1308 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1309 gl_error(ctx, GL_INVALID_VALUE, message);
1310 return GL_TRUE;
1311 }
1312
1313 /* Height */
1314 if (dimensions >= 2) {
1315 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1316 || logbase2( height - 2 * border ) < 0) {
1317 char message[100];
1318 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1319 gl_error(ctx, GL_INVALID_VALUE, message);
1320 return GL_TRUE;
1321 }
1322 }
1323
Brian Paulad817702000-05-30 00:27:24 +00001324 /* For cube map, width must equal height */
1325 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1326 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1327 if (width != height) {
1328 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1329 return GL_TRUE;
1330 }
1331 }
1332
Brian Paulc3f0a511999-11-03 17:27:05 +00001333 /* Level */
1334 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1335 char message[100];
1336 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1337 gl_error(ctx, GL_INVALID_VALUE, message);
1338 return GL_TRUE;
1339 }
1340
Brian Paulaea66b12000-05-24 14:04:06 +00001341 iformat = _mesa_base_tex_format( ctx, internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +00001342 if (iformat < 0) {
1343 char message[100];
1344 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1345 gl_error(ctx, GL_INVALID_VALUE, message);
1346 return GL_TRUE;
1347 }
1348
1349 /* if we get here, the parameters are OK */
1350 return GL_FALSE;
1351}
1352
1353
1354static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +00001355copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +00001356 GLenum target, GLint level,
1357 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +00001358 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001359{
1360 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1361 struct gl_texture_image *teximage;
1362
Brian Paulfc4b4432000-05-23 15:17:12 +00001363 if (dimensions == 1) {
1364 if (target != GL_TEXTURE_1D) {
1365 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1366 return GL_TRUE;
1367 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001368 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001369 else if (dimensions == 2) {
1370 if (ctx->Extensions.HaveTextureCubeMap) {
1371 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1372 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1373 target != GL_TEXTURE_2D) {
1374 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1375 return GL_TRUE;
1376 }
1377 }
1378 else if (target != GL_TEXTURE_2D) {
1379 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1380 return GL_TRUE;
1381 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001382 }
Brian Paulfc4b4432000-05-23 15:17:12 +00001383 else if (dimensions == 3) {
1384 if (target != GL_TEXTURE_3D) {
1385 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1386 return GL_TRUE;
1387 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001388 }
1389
1390 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1391 char message[100];
1392 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1393 gl_error(ctx, GL_INVALID_VALUE, message);
1394 return GL_TRUE;
1395 }
1396
1397 if (width < 0) {
1398 char message[100];
1399 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1400 gl_error(ctx, GL_INVALID_VALUE, message);
1401 return GL_TRUE;
1402 }
1403 if (dimensions > 1 && height < 0) {
1404 char message[100];
1405 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1406 gl_error(ctx, GL_INVALID_VALUE, message);
1407 return GL_TRUE;
1408 }
1409
Brian Pauldf6a28d2000-02-21 16:34:21 +00001410 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001411 if (!teximage) {
1412 char message[100];
1413 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1414 gl_error(ctx, GL_INVALID_OPERATION, message);
1415 return GL_TRUE;
1416 }
1417
1418 if (xoffset < -((GLint)teximage->Border)) {
1419 char message[100];
1420 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1421 gl_error(ctx, GL_INVALID_VALUE, message);
1422 return GL_TRUE;
1423 }
1424 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1425 char message[100];
1426 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1427 gl_error(ctx, GL_INVALID_VALUE, message);
1428 return GL_TRUE;
1429 }
1430 if (dimensions > 1) {
1431 if (yoffset < -((GLint)teximage->Border)) {
1432 char message[100];
1433 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1434 gl_error(ctx, GL_INVALID_VALUE, message);
1435 return GL_TRUE;
1436 }
1437 /* NOTE: we're adding the border here, not subtracting! */
1438 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1439 char message[100];
1440 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1441 gl_error(ctx, GL_INVALID_VALUE, message);
1442 return GL_TRUE;
1443 }
1444 }
1445
1446 if (dimensions > 2) {
1447 if (zoffset < -((GLint)teximage->Border)) {
1448 char message[100];
1449 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1450 gl_error(ctx, GL_INVALID_VALUE, message);
1451 return GL_TRUE;
1452 }
1453 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1454 char message[100];
1455 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1456 gl_error(ctx, GL_INVALID_VALUE, message);
1457 return GL_TRUE;
1458 }
1459 }
1460
1461 /* if we get here, the parameters are OK */
1462 return GL_FALSE;
1463}
1464
1465
1466
1467
1468/*
Brian Paul289d47e2000-08-29 23:31:23 +00001469 * Turn generic compressed formats into specific compressed format.
1470 * Some of the compressed formats we don't support, so we
1471 * fall back to the uncompressed format. (See issue 15 of
1472 * the GL_ARB_texture_compression specification.)
1473 */
1474static GLint
1475get_specific_compressed_tex_format(GLcontext *ctx,
1476 GLint ifmt, GLint numDimensions)
1477{
1478 char message[100];
1479 GLint internalFormat = ifmt;
1480
1481 if (ctx->Extensions.HaveTextureCompression
1482 && ctx->Driver.SpecificCompressedTexFormat) {
1483 /*
1484 * First, ask the driver for the specific format.
1485 */
1486 switch (internalFormat) {
1487 case GL_COMPRESSED_ALPHA_ARB:
1488 case GL_COMPRESSED_LUMINANCE_ARB:
1489 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1490 case GL_COMPRESSED_INTENSITY_ARB:
1491 case GL_COMPRESSED_RGB_ARB:
1492 case GL_COMPRESSED_RGBA_ARB:
1493 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1494 (ctx, internalFormat, numDimensions);
1495 /* XXX shouldn't we return now? */
1496 break;
1497 default:
1498 /* silence compiler warnings */
1499 ;
1500 }
1501 }
1502
1503 /*
1504 * Now, convert any generic format left to an uncompressed
1505 * specific format. If the driver does not support compression
1506 * of the format, we must drop back to the uncompressed format.
1507 * See issue 15 of the GL_ARB_texture_compression specification.
1508 */
1509 switch (internalFormat) {
1510 case GL_COMPRESSED_ALPHA_ARB:
1511 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1512 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1513 gl_error(ctx, GL_INVALID_VALUE, message);
1514 return -1;
1515 }
1516 internalFormat = GL_ALPHA;
1517 break;
1518 case GL_COMPRESSED_LUMINANCE_ARB:
1519 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1520 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1521 gl_error(ctx, GL_INVALID_VALUE, message);
1522 return -1;
1523 }
1524 internalFormat = GL_LUMINANCE;
1525 break;
1526 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1527 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1528 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1529 gl_error(ctx, GL_INVALID_VALUE, message);
1530 return -1;
1531 }
1532 internalFormat = GL_LUMINANCE_ALPHA;
1533 break;
1534 case GL_COMPRESSED_INTENSITY_ARB:
1535 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1536 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1537 gl_error(ctx, GL_INVALID_VALUE, message);
1538 return -1;
1539 }
1540 internalFormat = GL_INTENSITY;
1541 break;
1542 case GL_COMPRESSED_RGB_ARB:
1543 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1544 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1545 gl_error(ctx, GL_INVALID_VALUE, message);
1546 return -1;
1547 }
1548 internalFormat = GL_RGB;
1549 break;
1550 case GL_COMPRESSED_RGBA_ARB:
1551 if (ctx && !ctx->Extensions.HaveTextureCompression) {
1552 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1553 gl_error(ctx, GL_INVALID_VALUE, message);
1554 return -1;
1555 }
1556 internalFormat = GL_RGBA;
1557 break;
1558 default:
Brian Paulf93b3dd2000-08-30 18:22:28 +00001559 /* silence compiler warning */
1560 ;
Brian Paul289d47e2000-08-29 23:31:23 +00001561 }
1562 return internalFormat;
1563}
1564
1565
1566
1567/*
jtgafb833d1999-08-19 00:55:39 +00001568 * Called from the API. Note that width includes the border.
1569 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001570void
Brian Paul43911c82000-03-21 00:49:33 +00001571_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001572 GLsizei width, GLint border, GLenum format,
1573 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001574{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001575 GLsizei postConvWidth;
Brian Paulfbd8f211999-11-11 01:22:25 +00001576 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001577 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1578
Brian Paulf93b3dd2000-08-30 18:22:28 +00001579 postConvWidth = width;
1580 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1581
jtgafb833d1999-08-19 00:55:39 +00001582 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001583 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001584 struct gl_texture_object *texObj;
1585 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001586 GLint ifmt;
1587
1588 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1);
1589 if (ifmt < 0) {
1590 /*
1591 * The error here is that we were sent a generic compressed
1592 * format, but the extension is not supported.
1593 */
1594 return;
1595 }
1596 else {
1597 internalFormat = ifmt;
1598 }
Brian Paulf7b57072000-03-20 14:37:52 +00001599
Brian Paulaea66b12000-05-24 14:04:06 +00001600 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001601 format, type, 1, postConvWidth, 1, 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001602 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001603 }
1604
Brian Paulf7b57072000-03-20 14:37:52 +00001605 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001606 texObj = texUnit->CurrentD[1];
1607 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001608
Brian Paul02938782000-03-22 17:38:11 +00001609 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001610 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001611 texObj->Image[level] = texImage;
1612 if (!texImage) {
1613 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1614 return;
1615 }
1616 }
1617 else if (texImage->Data) {
1618 FREE(texImage->Data);
1619 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001620 }
1621
Brian Paul02938782000-03-22 17:38:11 +00001622 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001623 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001624
Brian Paulfa4525e2000-08-21 14:22:24 +00001625 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1626 _mesa_update_image_transfer_state(ctx);
1627
Brian Paul02938782000-03-22 17:38:11 +00001628 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001629 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001630 GLboolean retain = GL_TRUE;
1631 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001632 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00001633 /* let device driver try to use raw image */
1634 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1635 type, pixels, &ctx->Unpack,
1636 texObj, texImage, &retain);
1637 }
1638 if (retain || !success) {
1639 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001640 make_texture_image(ctx, 1, texImage, width, 1, 1,
1641 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001642 if (!success && ctx->Driver.TexImage1D) {
1643 /* let device driver try to use unpacked image */
1644 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1645 GL_UNSIGNED_BYTE, texImage->Data,
1646 &_mesa_native_packing,
1647 texObj, texImage, &retain);
1648 }
1649 }
1650 if (!retain && texImage->Data) {
1651 FREE(texImage->Data);
1652 texImage->Data = NULL;
1653 }
jtgafb833d1999-08-19 00:55:39 +00001654 }
1655 else {
Brian Paul02938782000-03-22 17:38:11 +00001656 make_null_texture(texImage);
1657 if (ctx->Driver.TexImage1D) {
1658 GLboolean retain;
1659 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1660 GL_UNSIGNED_BYTE, texImage->Data,
1661 &_mesa_native_packing,
1662 texObj, texImage, &retain);
1663 }
jtgafb833d1999-08-19 00:55:39 +00001664 }
1665
Brian Paul02938782000-03-22 17:38:11 +00001666 /* state update */
1667 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001668 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001669 }
1670 else if (target==GL_PROXY_TEXTURE_1D) {
1671 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001672 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001673 format, type, 1, postConvWidth, 1, 1, border)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001674 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001675 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1676 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1677 sizeof(struct gl_texture_image) );
1678 }
1679 }
1680 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001681 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001682 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001683 width, 1, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001684 }
jtgafb833d1999-08-19 00:55:39 +00001685 }
1686 else {
1687 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1688 return;
1689 }
1690}
1691
1692
Brian Paulfbd8f211999-11-11 01:22:25 +00001693void
Brian Paul43911c82000-03-21 00:49:33 +00001694_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001695 GLsizei width, GLsizei height, GLint border,
1696 GLenum format, GLenum type,
1697 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001698{
Brian Paulf93b3dd2000-08-30 18:22:28 +00001699 GLsizei postConvWidth, postConvHeight;
Brian Paulfbd8f211999-11-11 01:22:25 +00001700 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001701 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1702
Brian Paulf93b3dd2000-08-30 18:22:28 +00001703 postConvWidth = width;
1704 postConvHeight = height;
1705 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1706
Brian Paulfc4b4432000-05-23 15:17:12 +00001707 if (target==GL_TEXTURE_2D ||
1708 (ctx->Extensions.HaveTextureCubeMap &&
1709 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1710 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001711 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001712 struct gl_texture_object *texObj;
1713 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001714 GLint ifmt;
1715
1716 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2);
1717 if (ifmt < 0) {
1718 /*
1719 * The error here is that we were sent a generic compressed
1720 * format, but the extension is not supported.
1721 */
1722 return;
1723 }
1724 else {
1725 internalFormat = ifmt;
1726 }
Brian Paulf7b57072000-03-20 14:37:52 +00001727
Brian Paulaea66b12000-05-24 14:04:06 +00001728 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001729 format, type, 2, postConvWidth, postConvHeight,
1730 1, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001731 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001732 }
1733
Brian Paulf7b57072000-03-20 14:37:52 +00001734 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00001735 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paulfc4b4432000-05-23 15:17:12 +00001736 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
Brian Paulf7b57072000-03-20 14:37:52 +00001737
Brian Paul02938782000-03-22 17:38:11 +00001738 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001739 texImage = _mesa_alloc_texture_image();
Brian Paulfc4b4432000-05-23 15:17:12 +00001740 set_tex_image(texObj, target, level, texImage);
1741 /*texObj->Image[level] = texImage;*/
Brian Paul02938782000-03-22 17:38:11 +00001742 if (!texImage) {
1743 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1744 return;
1745 }
1746 }
1747 else if (texImage->Data) {
1748 FREE(texImage->Data);
1749 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001750 }
1751
Brian Paul02938782000-03-22 17:38:11 +00001752 /* setup the teximage struct's fields */
Brian Paulf93b3dd2000-08-30 18:22:28 +00001753 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
Brian Paul289d47e2000-08-29 23:31:23 +00001754 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001755
Brian Paulfa4525e2000-08-21 14:22:24 +00001756 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1757 _mesa_update_image_transfer_state(ctx);
1758
Brian Paul02938782000-03-22 17:38:11 +00001759 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001760 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001761 GLboolean retain = GL_TRUE;
1762 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001763 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00001764 /* let device driver try to use raw image */
1765 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1766 type, pixels, &ctx->Unpack,
1767 texObj, texImage, &retain);
1768 }
1769 if (retain || !success) {
1770 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001771 make_texture_image(ctx, 2, texImage, width, height, 1,
1772 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001773 if (!success && ctx->Driver.TexImage2D) {
1774 /* let device driver try to use unpacked image */
1775 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1776 GL_UNSIGNED_BYTE, texImage->Data,
1777 &_mesa_native_packing,
1778 texObj, texImage, &retain);
1779 }
1780 }
1781 if (!retain && texImage->Data) {
1782 FREE(texImage->Data);
1783 texImage->Data = NULL;
1784 }
jtgafb833d1999-08-19 00:55:39 +00001785 }
1786 else {
Brian Paul02938782000-03-22 17:38:11 +00001787 make_null_texture(texImage);
1788 if (ctx->Driver.TexImage2D) {
1789 GLboolean retain;
1790 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1791 GL_UNSIGNED_BYTE, texImage->Data,
1792 &_mesa_native_packing,
1793 texObj, texImage, &retain);
1794 }
jtgafb833d1999-08-19 00:55:39 +00001795 }
1796
Brian Paul02938782000-03-22 17:38:11 +00001797#define OLD_DD_TEXTURE
1798#ifdef OLD_DD_TEXTURE
1799 /* XXX this will be removed in the future */
jtgafb833d1999-08-19 00:55:39 +00001800 if (ctx->Driver.TexImage) {
Brian Paul02938782000-03-22 17:38:11 +00001801 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1802 texImage );
jtgafb833d1999-08-19 00:55:39 +00001803 }
Brian Paul02938782000-03-22 17:38:11 +00001804#endif
1805
1806 /* state update */
1807 gl_put_texobj_on_dirty_list( ctx, texObj );
1808 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001809 }
1810 else if (target==GL_PROXY_TEXTURE_2D) {
1811 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001812 if (texture_error_check(ctx, target, level, internalFormat,
Brian Paulf93b3dd2000-08-30 18:22:28 +00001813 format, type, 2, postConvWidth, height, 1, border)) {
Brian Paulaea66b12000-05-24 14:04:06 +00001814 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001815 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1816 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1817 sizeof(struct gl_texture_image) );
1818 }
1819 }
1820 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001821 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001822 init_texture_image(ctx,
1823 ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001824 width, height, 1, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001825 }
jtgafb833d1999-08-19 00:55:39 +00001826 }
1827 else {
1828 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1829 return;
1830 }
1831}
1832
1833
1834
1835/*
1836 * Called by the API or display list executor.
1837 * Note that width and height include the border.
1838 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001839void
Brian Paul43911c82000-03-21 00:49:33 +00001840_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001841 GLsizei width, GLsizei height, GLsizei depth,
1842 GLint border, GLenum format, GLenum type,
1843 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001844{
Brian Paulfbd8f211999-11-11 01:22:25 +00001845 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001846 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001847
Brian Paulfbd8f211999-11-11 01:22:25 +00001848 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001849 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001850 struct gl_texture_object *texObj;
1851 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00001852 GLint ifmt;
1853
1854 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3);
1855 if (ifmt < 0) {
1856 /*
1857 * The error here is that we were sent a generic compressed
1858 * format, but the extension is not supported.
1859 */
1860 return;
1861 }
1862 else {
1863 internalFormat = ifmt;
1864 }
1865
Brian Paulaea66b12000-05-24 14:04:06 +00001866 if (texture_error_check(ctx, target, level, internalFormat,
1867 format, type, 3, width, height, depth, border)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001868 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001869 }
1870
Brian Paulf7b57072000-03-20 14:37:52 +00001871 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001872 texObj = texUnit->CurrentD[3];
1873 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001874
Brian Paul02938782000-03-22 17:38:11 +00001875 if (!texImage) {
Brian Paul021a5252000-03-27 17:54:17 +00001876 texImage = _mesa_alloc_texture_image();
Brian Paul02938782000-03-22 17:38:11 +00001877 texObj->Image[level] = texImage;
1878 if (!texImage) {
1879 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1880 return;
1881 }
1882 }
1883 else if (texImage->Data) {
1884 FREE(texImage->Data);
1885 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001886 }
1887
Brian Paul02938782000-03-22 17:38:11 +00001888 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00001889 init_texture_image(ctx, texImage, width, height, depth,
Brian Paul02938782000-03-22 17:38:11 +00001890 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001891
Brian Paulfa4525e2000-08-21 14:22:24 +00001892 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1893 _mesa_update_image_transfer_state(ctx);
1894
Brian Paul02938782000-03-22 17:38:11 +00001895 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001896 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001897 GLboolean retain = GL_TRUE;
1898 GLboolean success = GL_FALSE;
Brian Paulfa4525e2000-08-21 14:22:24 +00001899 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00001900 /* let device driver try to use raw image */
1901 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1902 type, pixels, &ctx->Unpack,
1903 texObj, texImage, &retain);
1904 }
1905 if (retain || !success) {
1906 /* make internal copy of the texture image */
Brian Paul5a0d3dc2000-08-31 15:24:39 +00001907 make_texture_image(ctx, 3, texImage, width, height, depth,
1908 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00001909 if (!success && ctx->Driver.TexImage3D) {
1910 /* let device driver try to use unpacked image */
1911 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1912 GL_UNSIGNED_BYTE, texImage->Data,
1913 &_mesa_native_packing,
1914 texObj, texImage, &retain);
1915 }
1916 }
1917 if (!retain && texImage->Data) {
1918 FREE(texImage->Data);
1919 texImage->Data = NULL;
1920 }
jtgafb833d1999-08-19 00:55:39 +00001921 }
1922 else {
Brian Paul02938782000-03-22 17:38:11 +00001923 make_null_texture(texImage);
1924 if (ctx->Driver.TexImage3D) {
1925 GLboolean retain;
1926 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1927 GL_UNSIGNED_BYTE, texImage->Data,
1928 &_mesa_native_packing,
1929 texObj, texImage, &retain);
1930 }
jtgafb833d1999-08-19 00:55:39 +00001931 }
1932
Brian Paul02938782000-03-22 17:38:11 +00001933 /* state update */
1934 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001935 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001936 }
Brian Paulaea66b12000-05-24 14:04:06 +00001937 else if (target==GL_PROXY_TEXTURE_3D) {
jtgafb833d1999-08-19 00:55:39 +00001938 /* Proxy texture: check for errors and update proxy state */
Brian Paulaea66b12000-05-24 14:04:06 +00001939 if (texture_error_check(ctx, target, level, internalFormat,
1940 format, type, 3, width, height, depth, border)) {
1941 /* if error, clear all proxy texture image parameters */
jtgafb833d1999-08-19 00:55:39 +00001942 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1943 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1944 sizeof(struct gl_texture_image) );
1945 }
1946 }
1947 else {
Brian Paulaea66b12000-05-24 14:04:06 +00001948 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00001949 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00001950 width, height, depth, border, internalFormat);
jtgafb833d1999-08-19 00:55:39 +00001951 }
jtgafb833d1999-08-19 00:55:39 +00001952 }
1953 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001954 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001955 return;
1956 }
1957}
1958
1959
Brian Paul663049a2000-01-31 23:10:16 +00001960void
Brian Paul43911c82000-03-21 00:49:33 +00001961_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00001962 GLsizei width, GLsizei height, GLsizei depth,
1963 GLint border, GLenum format, GLenum type,
1964 const GLvoid *pixels )
1965{
Brian Paul43911c82000-03-21 00:49:33 +00001966 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00001967 depth, border, format, type, pixels);
1968}
1969
1970
Brian Paulf7b57072000-03-20 14:37:52 +00001971/*
1972 * Fetch a texture image from the device driver.
1973 * Store the results in the given texture object at the given mipmap level.
1974 */
Brian Paul021a5252000-03-27 17:54:17 +00001975void
1976_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1977 const struct gl_texture_object *texObj )
Brian Paulf7b57072000-03-20 14:37:52 +00001978{
1979 GLvoid *image;
1980 GLenum imgFormat, imgType;
1981 GLboolean freeImage;
1982 struct gl_texture_image *texImage;
1983 GLint destComponents, numPixels, srcBytesPerTexel;
1984
1985 if (!ctx->Driver.GetTexImage)
1986 return;
1987
Brian Paul48271792000-03-29 18:13:59 +00001988 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
Brian Paulf7b57072000-03-20 14:37:52 +00001989 &imgFormat, &imgType, &freeImage);
1990 if (!image)
1991 return;
1992
1993 texImage = texObj->Image[level];
1994 ASSERT(texImage);
1995 if (!texImage)
1996 return;
1997
1998 destComponents = components_in_intformat(texImage->Format);
1999 assert(destComponents > 0);
2000 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2001 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00002002 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00002003 assert(srcBytesPerTexel > 0);
2004
2005 if (!texImage->Data) {
2006 /* Allocate memory for the texture image data */
2007 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
2008 }
2009
2010 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2011 /* We got lucky! The driver's format and type match Mesa's format. */
2012 if (texImage->Data) {
2013 MEMCPY(texImage->Data, image, numPixels * destComponents);
2014 }
2015 }
2016 else {
2017 /* Convert the texture image from the driver's format to Mesa's
2018 * internal format.
2019 */
2020 const GLint width = texImage->Width;
2021 const GLint height = texImage->Height;
2022 const GLint depth = texImage->Depth;
2023 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2024 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2025 const GLenum dstType = GL_UNSIGNED_BYTE;
2026 const GLenum dstFormat = texImage->Format;
2027 const GLubyte *srcPtr = (const GLubyte *) image;
2028 GLubyte *destPtr = texImage->Data;
2029
2030 if (texImage->Format == GL_COLOR_INDEX) {
2031 /* color index texture */
2032 GLint img, row;
2033 assert(imgFormat == GL_COLOR_INDEX);
2034 for (img = 0; img < depth; img++) {
2035 for (row = 0; row < height; row++) {
2036 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002037 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002038 destPtr += destBytesPerRow;
2039 srcPtr += srcBytesPerRow;
2040 }
2041 }
2042 }
2043 else {
2044 /* color texture */
2045 GLint img, row;
2046 for (img = 0; img < depth; img++) {
2047 for (row = 0; row < height; row++) {
2048 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
Brian Paul289d47e2000-08-29 23:31:23 +00002049 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00002050 destPtr += destBytesPerRow;
2051 srcPtr += srcBytesPerRow;
2052 }
2053 }
2054 }
2055 }
2056
2057 if (freeImage)
2058 FREE(image);
2059}
2060
jtgafb833d1999-08-19 00:55:39 +00002061
Brian Paulfbd8f211999-11-11 01:22:25 +00002062void
2063_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2064 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002065{
Brian Paulfbd8f211999-11-11 01:22:25 +00002066 GET_CURRENT_CONTEXT(ctx);
Brian Paul01e54752000-09-05 15:40:34 +00002067 const struct gl_texture_unit *texUnit;
jtgafb833d1999-08-19 00:55:39 +00002068 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00002069 struct gl_texture_image *texImage;
2070 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00002071
2072 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2073
2074 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2075 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2076 return;
2077 }
2078
Brian Paulb7d076f2000-03-21 01:03:40 +00002079 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002080 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2081 return;
2082 }
2083
Brian Paulb7d076f2000-03-21 01:03:40 +00002084 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00002085 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2086 return;
2087 }
2088
2089 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00002090 return;
jtgafb833d1999-08-19 00:55:39 +00002091
Brian Paul01e54752000-09-05 15:40:34 +00002092 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2093 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2094 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2095 if (!texObj || !texImage) {
2096 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2097 return;
jtgafb833d1999-08-19 00:55:39 +00002098 }
2099
Brian Paulf7b57072000-03-20 14:37:52 +00002100 if (!texImage) {
2101 /* invalid mipmap level */
2102 return;
2103 }
2104
2105 if (!texImage->Data) {
2106 /* try to get the texture image from the device driver */
Brian Paul021a5252000-03-27 17:54:17 +00002107 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
Brian Paulf7b57072000-03-20 14:37:52 +00002108 discardImage = GL_TRUE;
2109 }
2110 else {
2111 discardImage = GL_FALSE;
2112 }
2113
2114 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00002115 GLint width = texImage->Width;
2116 GLint height = texImage->Height;
2117 GLint row;
2118
Brian Paulfa4525e2000-08-21 14:22:24 +00002119 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2120 _mesa_update_image_transfer_state(ctx);
2121
jtgafb833d1999-08-19 00:55:39 +00002122 for (row = 0; row < height; row++) {
2123 /* compute destination address in client memory */
Brian Paulb7d076f2000-03-21 01:03:40 +00002124 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
jtgafb833d1999-08-19 00:55:39 +00002125 width, height,
2126 format, type, 0, row, 0);
2127
2128 assert(dest);
2129 if (texImage->Format == GL_RGBA) {
2130 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
Brian Paulf93b3dd2000-08-30 18:22:28 +00002131 /* XXX convolution */
Brian Paulb7d076f2000-03-21 01:03:40 +00002132 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
Brian Paulfa4525e2000-08-21 14:22:24 +00002133 format, type, dest, &ctx->Pack,
2134 ctx->ImageTransferState );
jtgafb833d1999-08-19 00:55:39 +00002135 }
2136 else {
2137 /* fetch RGBA row from texture image then pack it in client mem */
2138 GLubyte rgba[MAX_WIDTH][4];
2139 GLint i;
2140 const GLubyte *src;
2141 switch (texImage->Format) {
2142 case GL_ALPHA:
2143 src = texImage->Data + row * width * sizeof(GLubyte);
2144 for (i = 0; i < width; i++) {
2145 rgba[i][RCOMP] = 255;
2146 rgba[i][GCOMP] = 255;
2147 rgba[i][BCOMP] = 255;
2148 rgba[i][ACOMP] = src[i];
2149 }
2150 break;
2151 case GL_LUMINANCE:
2152 src = texImage->Data + row * width * sizeof(GLubyte);
2153 for (i = 0; i < width; i++) {
2154 rgba[i][RCOMP] = src[i];
2155 rgba[i][GCOMP] = src[i];
2156 rgba[i][BCOMP] = src[i];
2157 rgba[i][ACOMP] = 255;
2158 }
2159 break;
2160 case GL_LUMINANCE_ALPHA:
2161 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
2162 for (i = 0; i < width; i++) {
2163 rgba[i][RCOMP] = src[i*2+0];
2164 rgba[i][GCOMP] = src[i*2+0];
2165 rgba[i][BCOMP] = src[i*2+0];
2166 rgba[i][ACOMP] = src[i*2+1];
2167 }
2168 break;
2169 case GL_INTENSITY:
2170 src = texImage->Data + row * width * sizeof(GLubyte);
2171 for (i = 0; i < width; i++) {
2172 rgba[i][RCOMP] = src[i];
2173 rgba[i][GCOMP] = src[i];
2174 rgba[i][BCOMP] = src[i];
2175 rgba[i][ACOMP] = 255;
2176 }
2177 break;
2178 case GL_RGB:
2179 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
2180 for (i = 0; i < width; i++) {
2181 rgba[i][RCOMP] = src[i*3+0];
2182 rgba[i][GCOMP] = src[i*3+1];
2183 rgba[i][BCOMP] = src[i*3+2];
2184 rgba[i][ACOMP] = 255;
2185 }
2186 break;
2187 case GL_RGBA:
2188 /* this special case should have been handled above! */
2189 gl_problem( ctx, "error 1 in gl_GetTexImage" );
2190 break;
2191 case GL_COLOR_INDEX:
2192 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2193 break;
2194 default:
2195 gl_problem( ctx, "bad format in gl_GetTexImage" );
2196 }
Brian Paulf93b3dd2000-08-30 18:22:28 +00002197 /* XXX convolution */
Brian Paulb7d076f2000-03-21 01:03:40 +00002198 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
Brian Paulfa4525e2000-08-21 14:22:24 +00002199 format, type, dest, &ctx->Pack,
2200 ctx->ImageTransferState );
jtgafb833d1999-08-19 00:55:39 +00002201 }
2202 }
Brian Paulf7b57072000-03-20 14:37:52 +00002203
2204 /* if we got the teximage from the device driver we'll discard it now */
2205 if (discardImage) {
2206 FREE(texImage->Data);
2207 texImage->Data = NULL;
2208 }
jtgafb833d1999-08-19 00:55:39 +00002209 }
2210}
2211
2212
2213
Brian Paulfbd8f211999-11-11 01:22:25 +00002214void
2215_mesa_TexSubImage1D( GLenum target, GLint level,
2216 GLint xoffset, GLsizei width,
2217 GLenum format, GLenum type,
2218 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002219{
Brian Paulfbd8f211999-11-11 01:22:25 +00002220 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002221 struct gl_texture_unit *texUnit;
2222 struct gl_texture_object *texObj;
2223 struct gl_texture_image *texImage;
2224 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002225 GLsizei postConvWidth;
2226
2227 postConvWidth = width;
2228 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
jtgafb833d1999-08-19 00:55:39 +00002229
Brian Paulc3f0a511999-11-03 17:27:05 +00002230 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002231 postConvWidth, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002232 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002233 }
2234
Brian Paul02938782000-03-22 17:38:11 +00002235 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2236 texObj = texUnit->CurrentD[1];
2237 texImage = texObj->Image[level];
2238 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002239
Brian Paulc3f0a511999-11-03 17:27:05 +00002240 if (width == 0 || !pixels)
2241 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002242
Brian Paulfa4525e2000-08-21 14:22:24 +00002243 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2244 _mesa_update_image_transfer_state(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002245
Brian Paulfa4525e2000-08-21 14:22:24 +00002246 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
Brian Paul02938782000-03-22 17:38:11 +00002247 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2248 width, format, type, pixels,
2249 &ctx->Unpack, texObj, texImage );
2250 }
2251 if (!success) {
2252 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
Brian Paul02938782000-03-22 17:38:11 +00002253 GLboolean retain = GL_TRUE;
2254 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002255 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002256 if (!texImage->Data) {
2257 make_null_texture(texImage);
2258 }
2259 if (!texImage->Data)
2260 return; /* we're really out of luck! */
2261 }
2262
Brian Paula805bb92000-09-02 17:52:21 +00002263 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2264 width, 1, 1, xoffset, 0, 0, /* size and offsets */
2265 0, 0, /* strides */
2266 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002267
2268 if (ctx->Driver.TexImage1D) {
2269 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2270 GL_UNSIGNED_BYTE, texImage->Data,
2271 &_mesa_native_packing, texObj, texImage,
2272 &retain );
2273 }
2274
2275 if (!retain && texImage->Data) {
2276 FREE(texImage->Data);
2277 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00002278 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002279 }
jtgafb833d1999-08-19 00:55:39 +00002280}
2281
2282
Brian Paulfbd8f211999-11-11 01:22:25 +00002283void
2284_mesa_TexSubImage2D( GLenum target, GLint level,
2285 GLint xoffset, GLint yoffset,
2286 GLsizei width, GLsizei height,
2287 GLenum format, GLenum type,
2288 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002289{
Brian Paulfbd8f211999-11-11 01:22:25 +00002290 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002291 struct gl_texture_unit *texUnit;
2292 struct gl_texture_object *texObj;
2293 struct gl_texture_image *texImage;
2294 GLboolean success = GL_FALSE;
Brian Paula805bb92000-09-02 17:52:21 +00002295 GLsizei postConvWidth, postConvHeight;
2296
2297 postConvWidth = width;
2298 postConvHeight = height;
2299 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
jtgafb833d1999-08-19 00:55:39 +00002300
Brian Paulc3f0a511999-11-03 17:27:05 +00002301 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
Brian Paula805bb92000-09-02 17:52:21 +00002302 postConvWidth, postConvHeight, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002303 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002304 }
2305
Brian Paul02938782000-03-22 17:38:11 +00002306 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul35d53012000-05-23 17:14:49 +00002307 texObj = _mesa_select_tex_object(ctx, texUnit, target);
Brian Paul02938782000-03-22 17:38:11 +00002308 texImage = texObj->Image[level];
2309 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002310
Brian Paulc3f0a511999-11-03 17:27:05 +00002311 if (width == 0 || height == 0 || !pixels)
2312 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002313
Brian Paulfa4525e2000-08-21 14:22:24 +00002314 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2315 _mesa_update_image_transfer_state(ctx);
2316
2317 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
Brian Paul02938782000-03-22 17:38:11 +00002318 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2319 yoffset, width, height, format, type,
2320 pixels, &ctx->Unpack, texObj, texImage );
2321 }
2322 if (!success) {
2323 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002324 const GLint texComps = components_in_intformat(texImage->Format);
2325 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
Brian Paul02938782000-03-22 17:38:11 +00002326 GLboolean retain = GL_TRUE;
2327
2328 if (!texImage->Data) {
Brian Paul021a5252000-03-27 17:54:17 +00002329 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
Brian Paul02938782000-03-22 17:38:11 +00002330 if (!texImage->Data) {
2331 make_null_texture(texImage);
2332 }
2333 if (!texImage->Data)
2334 return; /* we're really out of luck! */
2335 }
2336
Brian Paula805bb92000-09-02 17:52:21 +00002337 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2338 width, height, 1, xoffset, yoffset, 0,
2339 texRowStride, 0,
2340 format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00002341
Brian Paul02938782000-03-22 17:38:11 +00002342 if (ctx->Driver.TexImage2D) {
2343 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2344 GL_UNSIGNED_BYTE, texImage->Data,
2345 &_mesa_native_packing, texObj, texImage,
2346 &retain);
jtgafb833d1999-08-19 00:55:39 +00002347 }
Brian Paul02938782000-03-22 17:38:11 +00002348
2349 if (!retain && texImage->Data) {
2350 FREE(texImage->Data);
2351 texImage->Data = NULL;
2352 }
2353
2354#ifdef OLD_DD_TEXTURE
2355 /* XXX this will be removed in the future */
2356 if (ctx->Driver.TexSubImage) {
2357 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2358 xoffset, yoffset, width, height,
2359 texImage->IntFormat, texImage);
2360 }
2361 else if (ctx->Driver.TexImage) {
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002362 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
Brian Paul02938782000-03-22 17:38:11 +00002363 level, texImage->IntFormat, texImage );
2364 }
2365#endif
jtgafb833d1999-08-19 00:55:39 +00002366 }
2367}
2368
2369
2370
Brian Paulfbd8f211999-11-11 01:22:25 +00002371void
2372_mesa_TexSubImage3D( GLenum target, GLint level,
2373 GLint xoffset, GLint yoffset, GLint zoffset,
2374 GLsizei width, GLsizei height, GLsizei depth,
2375 GLenum format, GLenum type,
2376 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00002377{
Brian Paulfbd8f211999-11-11 01:22:25 +00002378 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00002379 struct gl_texture_unit *texUnit;
2380 struct gl_texture_object *texObj;
2381 struct gl_texture_image *texImage;
2382 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00002383
Brian Paulc3f0a511999-11-03 17:27:05 +00002384 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2385 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00002386 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00002387 }
2388
Brian Paul02938782000-03-22 17:38:11 +00002389 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2390 texObj = texUnit->CurrentD[3];
2391 texImage = texObj->Image[level];
2392 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00002393
Brian Paulc3f0a511999-11-03 17:27:05 +00002394 if (width == 0 || height == 0 || height == 0 || !pixels)
2395 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00002396
Brian Paulfa4525e2000-08-21 14:22:24 +00002397 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2398 _mesa_update_image_transfer_state(ctx);
2399
2400 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
Brian Paul02938782000-03-22 17:38:11 +00002401 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2402 yoffset, zoffset, width, height, depth, format,
2403 type, pixels, &ctx->Unpack, texObj, texImage );
2404 }
2405 if (!success) {
2406 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
Brian Paula805bb92000-09-02 17:52:21 +00002407 const GLint texComps = components_in_intformat(texImage->Format);
2408 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte);
2409 const GLint texImgStride = texRowStride * texImage->Height;
Brian Paul02938782000-03-22 17:38:11 +00002410 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00002411
Brian Paula805bb92000-09-02 17:52:21 +00002412 if (!texImage->Data) {
2413 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2414 if (!texImage->Data) {
2415 make_null_texture(texImage);
jtgafb833d1999-08-19 00:55:39 +00002416 }
Brian Paula805bb92000-09-02 17:52:21 +00002417 if (!texImage->Data)
2418 return; /* we're really out of luck! */
jtgafb833d1999-08-19 00:55:39 +00002419 }
Brian Paula805bb92000-09-02 17:52:21 +00002420
2421 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2422 width, height, depth, xoffset, yoffset, zoffset,
2423 texRowStride, texImgStride,
2424 format, type, pixels, &ctx->Unpack);
Brian Paul02938782000-03-22 17:38:11 +00002425
2426 if (ctx->Driver.TexImage3D) {
2427 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2428 GL_UNSIGNED_BYTE, texImage->Data,
2429 &_mesa_native_packing, texObj, texImage,
2430 &retain);
2431 }
2432
2433 if (!retain && texImage->Data) {
2434 FREE(texImage->Data);
2435 texImage->Data = NULL;
2436 }
jtgafb833d1999-08-19 00:55:39 +00002437 }
jtgafb833d1999-08-19 00:55:39 +00002438}
2439
2440
2441
2442/*
2443 * Read an RGBA image from the frame buffer.
Brian Paula805bb92000-09-02 17:52:21 +00002444 * This is used by glCopyTex[Sub]Image[12]D().
jtgafb833d1999-08-19 00:55:39 +00002445 * Input: ctx - the context
2446 * x, y - lower left corner
2447 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00002448 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00002449 */
Brian Paulc3f0a511999-11-03 17:27:05 +00002450static GLubyte *
2451read_color_image( GLcontext *ctx, GLint x, GLint y,
2452 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00002453{
Brian Paulc3f0a511999-11-03 17:27:05 +00002454 GLint stride, i;
2455 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00002456
Brian Paul959f8022000-03-19 01:10:11 +00002457 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00002458 if (!image)
jtgafb833d1999-08-19 00:55:39 +00002459 return NULL;
jtgafb833d1999-08-19 00:55:39 +00002460
2461 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002462 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2463 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002464
Brian Paulc3f0a511999-11-03 17:27:05 +00002465 dst = image;
2466 stride = width * 4 * sizeof(GLubyte);
2467 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00002468 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2469 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00002470 dst += stride;
2471 }
jtgafb833d1999-08-19 00:55:39 +00002472
Brian Paulcea0e8e1999-11-25 17:36:48 +00002473 /* Read from draw buffer (the default) */
2474 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2475 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002476
2477 return image;
2478}
2479
2480
2481
Brian Paulfbd8f211999-11-11 01:22:25 +00002482void
2483_mesa_CopyTexImage1D( GLenum target, GLint level,
2484 GLenum internalFormat,
2485 GLint x, GLint y,
2486 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00002487{
Brian Paulfbd8f211999-11-11 01:22:25 +00002488 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002489 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00002490
Brian Paulf7b57072000-03-20 14:37:52 +00002491 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2492 width, 1, border))
2493 return;
2494
Brian Paulfa4525e2000-08-21 14:22:24 +00002495 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2496 _mesa_update_image_transfer_state(ctx);
2497
2498 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002499 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002500 internalFormat, x, y, width, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002501 struct gl_pixelstore_attrib unpackSave;
2502
2503 /* get image from framebuffer */
Brian Paula805bb92000-09-02 17:52:21 +00002504 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
Brian Paulc3f0a511999-11-03 17:27:05 +00002505 if (!image) {
2506 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2507 return;
2508 }
Brian Paul7dac1322000-06-15 19:57:14 +00002509
2510 /* call glTexImage1D to redefine the texture */
2511 unpackSave = ctx->Unpack;
2512 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002513 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002514 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002515 ctx->Unpack = unpackSave;
2516
Brian Paulc3f0a511999-11-03 17:27:05 +00002517 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002518 }
jtgafb833d1999-08-19 00:55:39 +00002519}
2520
2521
2522
Brian Paulfbd8f211999-11-11 01:22:25 +00002523void
2524_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2525 GLint x, GLint y, GLsizei width, GLsizei height,
2526 GLint border )
jtgafb833d1999-08-19 00:55:39 +00002527{
Brian Paulfbd8f211999-11-11 01:22:25 +00002528 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002529 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00002530
Brian Paulf7b57072000-03-20 14:37:52 +00002531 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2532 width, height, border))
2533 return;
2534
Brian Paulfa4525e2000-08-21 14:22:24 +00002535 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2536 _mesa_update_image_transfer_state(ctx);
2537
2538 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002539 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
Brian Paula805bb92000-09-02 17:52:21 +00002540 internalFormat, x, y, width, height, border)) {
Brian Paul7dac1322000-06-15 19:57:14 +00002541 struct gl_pixelstore_attrib unpackSave;
2542
2543 /* get image from framebuffer */
Brian Paula805bb92000-09-02 17:52:21 +00002544 GLubyte *image = read_color_image( ctx, x, y, width, height );
Brian Paulc3f0a511999-11-03 17:27:05 +00002545 if (!image) {
2546 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2547 return;
2548 }
Brian Paul7dac1322000-06-15 19:57:14 +00002549
2550 /* call glTexImage2D to redefine the texture */
2551 unpackSave = ctx->Unpack;
2552 ctx->Unpack = _mesa_native_packing;
Brian Paul3ab6bbe2000-02-12 17:26:15 +00002553 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00002554 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paul7dac1322000-06-15 19:57:14 +00002555 ctx->Unpack = unpackSave;
2556
Brian Paulc3f0a511999-11-03 17:27:05 +00002557 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002558 }
jtgafb833d1999-08-19 00:55:39 +00002559}
2560
2561
2562
Brian Paulfbd8f211999-11-11 01:22:25 +00002563void
2564_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2565 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002566{
Brian Paulfbd8f211999-11-11 01:22:25 +00002567 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002568 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002569
Brian Paulf7b57072000-03-20 14:37:52 +00002570 if (copytexsubimage_error_check(ctx, 1, target, level,
2571 xoffset, 0, 0, width, 1))
2572 return;
2573
Brian Paulfa4525e2000-08-21 14:22:24 +00002574 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2575 _mesa_update_image_transfer_state(ctx);
2576
2577 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
Brian Paulf7b57072000-03-20 14:37:52 +00002578 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2579 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002580 struct gl_texture_unit *texUnit;
2581 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002582 struct gl_pixelstore_attrib unpackSave;
2583 GLubyte *image;
2584
Brian Paulc3f0a511999-11-03 17:27:05 +00002585 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2586 teximage = texUnit->CurrentD[1]->Image[level];
2587 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002588
2589 /* get image from frame buffer */
2590 image = read_color_image(ctx, x, y, width, 1);
2591 if (!image) {
2592 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2593 return;
jtgafb833d1999-08-19 00:55:39 +00002594 }
Brian Paul7dac1322000-06-15 19:57:14 +00002595
2596 /* now call glTexSubImage1D to do the real work */
2597 unpackSave = ctx->Unpack;
2598 ctx->Unpack = _mesa_native_packing;
2599 _mesa_TexSubImage1D(target, level, xoffset, width,
2600 GL_RGBA, GL_UNSIGNED_BYTE, image);
2601 ctx->Unpack = unpackSave;
2602
2603 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002604 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002605}
2606
2607
2608
Brian Paulfbd8f211999-11-11 01:22:25 +00002609void
2610_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2611 GLint xoffset, GLint yoffset,
2612 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002613{
Brian Paulfbd8f211999-11-11 01:22:25 +00002614 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002615 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2616
Brian Paulf7b57072000-03-20 14:37:52 +00002617 if (copytexsubimage_error_check(ctx, 2, target, level,
2618 xoffset, yoffset, 0, width, height))
2619 return;
2620
Brian Paulfa4525e2000-08-21 14:22:24 +00002621 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2622 _mesa_update_image_transfer_state(ctx);
2623
2624 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
Brian Paulf7b57072000-03-20 14:37:52 +00002625 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2626 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002627 struct gl_texture_unit *texUnit;
2628 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002629 struct gl_pixelstore_attrib unpackSave;
2630 GLubyte *image;
2631
Brian Paulc3f0a511999-11-03 17:27:05 +00002632 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2633 teximage = texUnit->CurrentD[2]->Image[level];
2634 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002635
2636 /* get image from frame buffer */
2637 image = read_color_image(ctx, x, y, width, height);
2638 if (!image) {
2639 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2640 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002641 }
Brian Paul7dac1322000-06-15 19:57:14 +00002642
2643 /* now call glTexSubImage2D to do the real work */
2644 unpackSave = ctx->Unpack;
2645 ctx->Unpack = _mesa_native_packing;
2646 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2647 GL_RGBA, GL_UNSIGNED_BYTE, image);
2648 ctx->Unpack = unpackSave;
2649
2650 FREE(image);
Brian Paulc3f0a511999-11-03 17:27:05 +00002651 }
2652}
2653
2654
2655
Brian Paulfbd8f211999-11-11 01:22:25 +00002656void
2657_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2658 GLint xoffset, GLint yoffset, GLint zoffset,
2659 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002660{
Brian Paulfbd8f211999-11-11 01:22:25 +00002661 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002662 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2663
Brian Paulf7b57072000-03-20 14:37:52 +00002664 if (copytexsubimage_error_check(ctx, 3, target, level,
2665 xoffset, yoffset, zoffset, width, height))
2666 return;
2667
Brian Paulfa4525e2000-08-21 14:22:24 +00002668 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2669 _mesa_update_image_transfer_state(ctx);
2670
2671 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
Brian Paulf7b57072000-03-20 14:37:52 +00002672 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002673 xoffset, yoffset, zoffset, x, y, width, height )) {
2674 struct gl_texture_unit *texUnit;
2675 struct gl_texture_image *teximage;
Brian Paul7dac1322000-06-15 19:57:14 +00002676 struct gl_pixelstore_attrib unpackSave;
2677 GLubyte *image;
2678
Brian Paul02938782000-03-22 17:38:11 +00002679 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2680 teximage = texUnit->CurrentD[3]->Image[level];
2681 assert(teximage);
Brian Paul7dac1322000-06-15 19:57:14 +00002682
2683 /* get image from frame buffer */
2684 image = read_color_image(ctx, x, y, width, height);
2685 if (!image) {
2686 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2687 return;
Brian Paulc3f0a511999-11-03 17:27:05 +00002688 }
Brian Paul7dac1322000-06-15 19:57:14 +00002689
2690 /* now call glTexSubImage2D to do the real work */
2691 unpackSave = ctx->Unpack;
2692 ctx->Unpack = _mesa_native_packing;
2693 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2694 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2695 ctx->Unpack = unpackSave;
2696
2697 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00002698 }
2699}
Brian Paul1207bf02000-05-23 20:10:49 +00002700
2701
2702
2703void
2704_mesa_CompressedTexImage1DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002705 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002706 GLint border, GLsizei imageSize,
2707 const GLvoid *data)
2708{
Brian Paulaea66b12000-05-24 14:04:06 +00002709 GET_CURRENT_CONTEXT(ctx);
2710 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2711
Brian Paul289d47e2000-08-29 23:31:23 +00002712 switch (internalFormat) {
2713 case GL_COMPRESSED_ALPHA_ARB:
2714 case GL_COMPRESSED_LUMINANCE_ARB:
2715 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2716 case GL_COMPRESSED_INTENSITY_ARB:
2717 case GL_COMPRESSED_RGB_ARB:
2718 case GL_COMPRESSED_RGBA_ARB:
2719 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2720 return;
2721 default:
2722 /* silence compiler warning */
2723 ;
2724 }
2725
Brian Paulaea66b12000-05-24 14:04:06 +00002726 if (target == GL_TEXTURE_1D) {
2727 struct gl_texture_unit *texUnit;
2728 struct gl_texture_object *texObj;
2729 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002730 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002731
2732 if (texture_error_check(ctx, target, level, internalFormat,
2733 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2734 return; /* error in texture image was detected */
2735 }
2736
2737 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2738 texObj = texUnit->CurrentD[1];
2739 texImage = texObj->Image[level];
2740
2741 if (!texImage) {
2742 texImage = _mesa_alloc_texture_image();
2743 texObj->Image[level] = texImage;
2744 if (!texImage) {
2745 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2746 return;
2747 }
2748 }
2749 else if (texImage->Data) {
2750 FREE(texImage->Data);
2751 texImage->Data = NULL;
2752 }
2753
2754 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00002755 init_texture_image(ctx, texImage, width, 1, 1,
2756 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00002757
2758 /* process the texture image */
2759 if (data) {
2760 GLboolean retain = GL_TRUE;
2761 GLboolean success = GL_FALSE;
2762 if (ctx->Driver.CompressedTexImage1D) {
Brian Paul289d47e2000-08-29 23:31:23 +00002763 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2764 imageSize, data, texObj, texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002765 }
2766 if (retain || !success) {
2767 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00002768 computedImageSize = _mesa_compressed_image_size(ctx,
2769 internalFormat,
2770 1, /* num dims */
2771 width,
2772 1, /* height */
2773 1); /* depth */
2774 if (computedImageSize != imageSize) {
2775 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2776 return;
2777 }
2778 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002779 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00002780 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002781 }
2782 }
2783 if (!retain && texImage->Data) {
2784 FREE(texImage->Data);
2785 texImage->Data = NULL;
2786 }
2787 }
2788 else {
2789 make_null_texture(texImage);
2790 if (ctx->Driver.CompressedTexImage1D) {
2791 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00002792 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2793 texImage->Data, texObj,
2794 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002795 }
2796 }
2797
2798 /* state update */
2799 gl_put_texobj_on_dirty_list( ctx, texObj );
2800 ctx->NewState |= NEW_TEXTURING;
2801 }
2802 else if (target == GL_PROXY_TEXTURE_1D) {
2803 /* Proxy texture: check for errors and update proxy state */
2804 if (texture_error_check(ctx, target, level, internalFormat,
2805 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2806 /* if error, clear all proxy texture image parameters */
2807 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2808 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
2809 sizeof(struct gl_texture_image) );
2810 }
2811 }
2812 else {
2813 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002814 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002815 width, 1, 1, border, internalFormat);
2816 }
2817 }
2818 else {
2819 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2820 return;
2821 }
Brian Paul1207bf02000-05-23 20:10:49 +00002822}
2823
2824
2825void
2826_mesa_CompressedTexImage2DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002827 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002828 GLsizei height, GLint border, GLsizei imageSize,
2829 const GLvoid *data)
2830{
Brian Paulaea66b12000-05-24 14:04:06 +00002831 GET_CURRENT_CONTEXT(ctx);
2832 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2833
Brian Paul289d47e2000-08-29 23:31:23 +00002834 switch (internalFormat) {
2835 case GL_COMPRESSED_ALPHA_ARB:
2836 case GL_COMPRESSED_LUMINANCE_ARB:
2837 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2838 case GL_COMPRESSED_INTENSITY_ARB:
2839 case GL_COMPRESSED_RGB_ARB:
2840 case GL_COMPRESSED_RGBA_ARB:
2841 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
2842 return;
2843 default:
2844 /* silence compiler warning */
2845 ;
2846 }
2847
Brian Paul9540a1d2000-06-06 17:03:38 +00002848 if (target==GL_TEXTURE_2D ||
2849 (ctx->Extensions.HaveTextureCubeMap &&
2850 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2851 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
Brian Paulaea66b12000-05-24 14:04:06 +00002852 struct gl_texture_unit *texUnit;
2853 struct gl_texture_object *texObj;
2854 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002855 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002856
2857 if (texture_error_check(ctx, target, level, internalFormat,
2858 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2859 return; /* error in texture image was detected */
2860 }
2861
2862 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2863 texObj = texUnit->CurrentD[2];
2864 texImage = texObj->Image[level];
2865
2866 if (!texImage) {
2867 texImage = _mesa_alloc_texture_image();
2868 texObj->Image[level] = texImage;
2869 if (!texImage) {
2870 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2871 return;
2872 }
2873 }
2874 else if (texImage->Data) {
2875 FREE(texImage->Data);
2876 texImage->Data = NULL;
2877 }
2878
2879 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00002880 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00002881
2882 /* process the texture image */
2883 if (data) {
2884 GLboolean retain = GL_TRUE;
2885 GLboolean success = GL_FALSE;
2886 if (ctx->Driver.CompressedTexImage2D) {
Brian Paul289d47e2000-08-29 23:31:23 +00002887 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
2888 target,
2889 level,
2890 imageSize,
2891 data,
2892 texObj,
2893 texImage,
2894 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002895 }
2896 if (retain || !success) {
2897 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00002898 computedImageSize = _mesa_compressed_image_size(ctx,
2899 internalFormat,
2900 2, /* num dims */
2901 width,
2902 height,
2903 1); /* depth */
2904 if (computedImageSize != imageSize) {
2905 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
2906 return;
2907 }
2908 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002909 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00002910 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00002911 }
2912 }
2913 if (!retain && texImage->Data) {
2914 FREE(texImage->Data);
2915 texImage->Data = NULL;
2916 }
2917 }
2918 else {
2919 make_null_texture(texImage);
2920 if (ctx->Driver.CompressedTexImage2D) {
2921 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00002922 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
2923 texImage->Data, texObj,
2924 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00002925 }
2926 }
2927
2928 /* state update */
2929 gl_put_texobj_on_dirty_list( ctx, texObj );
2930 ctx->NewState |= NEW_TEXTURING;
2931 }
2932 else if (target == GL_PROXY_TEXTURE_2D) {
2933 /* Proxy texture: check for errors and update proxy state */
2934 if (texture_error_check(ctx, target, level, internalFormat,
2935 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2936 /* if error, clear all proxy texture image parameters */
2937 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2938 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
2939 sizeof(struct gl_texture_image) );
2940 }
2941 }
2942 else {
2943 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00002944 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00002945 width, 1, 1, border, internalFormat);
2946 }
2947 }
2948 else {
2949 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
2950 return;
2951 }
Brian Paul1207bf02000-05-23 20:10:49 +00002952}
2953
2954
2955void
2956_mesa_CompressedTexImage3DARB(GLenum target, GLint level,
Brian Paulaea66b12000-05-24 14:04:06 +00002957 GLenum internalFormat, GLsizei width,
Brian Paul1207bf02000-05-23 20:10:49 +00002958 GLsizei height, GLsizei depth, GLint border,
2959 GLsizei imageSize, const GLvoid *data)
2960{
Brian Paulaea66b12000-05-24 14:04:06 +00002961 GET_CURRENT_CONTEXT(ctx);
2962 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
2963
Brian Paul289d47e2000-08-29 23:31:23 +00002964 switch (internalFormat) {
2965 case GL_COMPRESSED_ALPHA_ARB:
2966 case GL_COMPRESSED_LUMINANCE_ARB:
2967 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2968 case GL_COMPRESSED_INTENSITY_ARB:
2969 case GL_COMPRESSED_RGB_ARB:
2970 case GL_COMPRESSED_RGBA_ARB:
2971 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
2972 return;
2973 default:
2974 /* silence compiler warning */
2975 ;
2976 }
2977
Brian Paul9540a1d2000-06-06 17:03:38 +00002978 if (target == GL_TEXTURE_3D) {
Brian Paulaea66b12000-05-24 14:04:06 +00002979 struct gl_texture_unit *texUnit;
2980 struct gl_texture_object *texObj;
2981 struct gl_texture_image *texImage;
Brian Paul289d47e2000-08-29 23:31:23 +00002982 GLsizei computedImageSize;
Brian Paulaea66b12000-05-24 14:04:06 +00002983
2984 if (texture_error_check(ctx, target, level, internalFormat,
2985 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2986 return; /* error in texture image was detected */
2987 }
2988
2989 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2990 texObj = texUnit->CurrentD[3];
2991 texImage = texObj->Image[level];
2992
2993 if (!texImage) {
2994 texImage = _mesa_alloc_texture_image();
2995 texObj->Image[level] = texImage;
2996 if (!texImage) {
2997 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2998 return;
2999 }
3000 }
3001 else if (texImage->Data) {
3002 FREE(texImage->Data);
3003 texImage->Data = NULL;
3004 }
3005
3006 /* setup the teximage struct's fields */
Brian Paul289d47e2000-08-29 23:31:23 +00003007 init_texture_image(ctx, texImage, width, height, depth,
3008 border, internalFormat);
Brian Paulaea66b12000-05-24 14:04:06 +00003009
3010 /* process the texture image */
3011 if (data) {
3012 GLboolean retain = GL_TRUE;
3013 GLboolean success = GL_FALSE;
3014 if (ctx->Driver.CompressedTexImage3D) {
Brian Paul289d47e2000-08-29 23:31:23 +00003015 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3016 imageSize, data,
3017 texObj, texImage,
3018 &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003019 }
3020 if (retain || !success) {
3021 /* make internal copy of the texture image */
Brian Paul289d47e2000-08-29 23:31:23 +00003022 computedImageSize = _mesa_compressed_image_size(ctx,
3023 internalFormat,
3024 3, /* num dims */
3025 width,
3026 height,
3027 depth);
3028 if (computedImageSize != imageSize) {
3029 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3030 return;
3031 }
3032 texImage->Data = MALLOC(computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003033 if (texImage->Data) {
Brian Paul289d47e2000-08-29 23:31:23 +00003034 MEMCPY(texImage->Data, data, computedImageSize);
Brian Paulaea66b12000-05-24 14:04:06 +00003035 }
3036 }
3037 if (!retain && texImage->Data) {
3038 FREE(texImage->Data);
3039 texImage->Data = NULL;
3040 }
3041 }
3042 else {
3043 make_null_texture(texImage);
3044 if (ctx->Driver.CompressedTexImage3D) {
3045 GLboolean retain;
Brian Paul289d47e2000-08-29 23:31:23 +00003046 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3047 texImage->Data, texObj,
3048 texImage, &retain);
Brian Paulaea66b12000-05-24 14:04:06 +00003049 }
3050 }
3051
3052 /* state update */
3053 gl_put_texobj_on_dirty_list( ctx, texObj );
3054 ctx->NewState |= NEW_TEXTURING;
3055 }
3056 else if (target == GL_PROXY_TEXTURE_3D) {
3057 /* Proxy texture: check for errors and update proxy state */
3058 if (texture_error_check(ctx, target, level, internalFormat,
3059 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3060 /* if error, clear all proxy texture image parameters */
3061 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3062 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
3063 sizeof(struct gl_texture_image) );
3064 }
3065 }
3066 else {
3067 /* if no error, update proxy texture image parameters */
Brian Paul289d47e2000-08-29 23:31:23 +00003068 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
Brian Paulaea66b12000-05-24 14:04:06 +00003069 width, 1, 1, border, internalFormat);
3070 }
3071 }
3072 else {
3073 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3074 return;
3075 }
Brian Paul1207bf02000-05-23 20:10:49 +00003076}
3077
3078
3079void
3080_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3081 GLsizei width, GLenum format,
3082 GLsizei imageSize, const GLvoid *data)
3083{
Brian Paul9540a1d2000-06-06 17:03:38 +00003084 GET_CURRENT_CONTEXT(ctx);
3085 struct gl_texture_unit *texUnit;
3086 struct gl_texture_object *texObj;
3087 struct gl_texture_image *texImage;
3088 GLboolean success = GL_FALSE;
3089
3090 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3091 width, 1, 1, format, GL_NONE)) {
3092 return; /* error was detected */
3093 }
3094
3095 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3096 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3097 texImage = texObj->Image[level];
3098 assert(texImage);
3099
3100 if (width == 0 || !data)
3101 return; /* no-op, not an error */
3102
3103 if (ctx->Driver.CompressedTexSubImage1D) {
3104 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3105 xoffset, width, format, imageSize, data, texObj, texImage);
3106 }
3107 if (!success) {
3108 /* XXX what else can we do? */
3109 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3110 return;
3111 }
Brian Paul1207bf02000-05-23 20:10:49 +00003112}
3113
3114
3115void
3116_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3117 GLint yoffset, GLsizei width, GLsizei height,
3118 GLenum format, GLsizei imageSize,
3119 const GLvoid *data)
3120{
Brian Paul9540a1d2000-06-06 17:03:38 +00003121 GET_CURRENT_CONTEXT(ctx);
3122 struct gl_texture_unit *texUnit;
3123 struct gl_texture_object *texObj;
3124 struct gl_texture_image *texImage;
3125 GLboolean success = GL_FALSE;
3126
3127 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3128 width, height, 1, format, GL_NONE)) {
3129 return; /* error was detected */
3130 }
3131
3132 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3133 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3134 texImage = texObj->Image[level];
3135 assert(texImage);
3136
3137 if (width == 0 || height == 0 || !data)
3138 return; /* no-op, not an error */
3139
3140 if (ctx->Driver.CompressedTexSubImage2D) {
3141 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3142 xoffset, yoffset, width, height, format,
3143 imageSize, data, texObj, texImage);
3144 }
3145 if (!success) {
3146 /* XXX what else can we do? */
3147 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3148 return;
3149 }
Brian Paul1207bf02000-05-23 20:10:49 +00003150}
3151
3152
3153void
3154_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3155 GLint yoffset, GLint zoffset, GLsizei width,
3156 GLsizei height, GLsizei depth, GLenum format,
3157 GLsizei imageSize, const GLvoid *data)
3158{
Brian Paul9540a1d2000-06-06 17:03:38 +00003159 GET_CURRENT_CONTEXT(ctx);
3160 struct gl_texture_unit *texUnit;
3161 struct gl_texture_object *texObj;
3162 struct gl_texture_image *texImage;
3163 GLboolean success = GL_FALSE;
3164
3165 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3166 width, height, depth, format, GL_NONE)) {
3167 return; /* error was detected */
3168 }
3169
3170 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3171 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3172 texImage = texObj->Image[level];
3173 assert(texImage);
3174
3175 if (width == 0 || height == 0 || depth == 0 || !data)
3176 return; /* no-op, not an error */
3177
3178 if (ctx->Driver.CompressedTexSubImage3D) {
3179 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3180 xoffset, yoffset, zoffset, width, height, depth,
3181 format, imageSize, data, texObj, texImage);
3182 }
3183 if (!success) {
3184 /* XXX what else can we do? */
3185 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3186 return;
3187 }
Brian Paul1207bf02000-05-23 20:10:49 +00003188}
3189
3190
3191void
Brian Paul9540a1d2000-06-06 17:03:38 +00003192_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
Brian Paul1207bf02000-05-23 20:10:49 +00003193{
Brian Paul9540a1d2000-06-06 17:03:38 +00003194 GET_CURRENT_CONTEXT(ctx);
3195 const struct gl_texture_object *texObj;
3196 struct gl_texture_image *texImage;
3197
3198 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3199
3200 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3201 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3202 return;
3203 }
3204
3205 switch (target) {
3206 case GL_TEXTURE_1D:
3207 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3208 texImage = texObj->Image[level];
3209 break;
3210 case GL_TEXTURE_2D:
3211 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3212 texImage = texObj->Image[level];
3213 break;
3214 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3215 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3216 texImage = texObj->Image[level];
3217 break;
3218 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3219 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3220 texImage = texObj->NegX[level];
3221 break;
3222 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3223 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3224 texImage = texObj->PosY[level];
3225 break;
3226 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3227 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3228 texImage = texObj->NegY[level];
3229 break;
3230 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3231 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3232 texImage = texObj->PosZ[level];
3233 break;
3234 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3235 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3236 texImage = texObj->NegZ[level];
3237 break;
3238 case GL_TEXTURE_3D:
3239 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3240 texImage = texObj->Image[level];
3241 break;
3242 default:
3243 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3244 return;
3245 }
3246
3247 if (!texImage) {
3248 /* invalid mipmap level */
3249 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3250 return;
3251 }
3252
3253 if (!texImage->IsCompressed) {
3254 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3255 return;
3256 }
3257
3258 if (!img)
3259 return;
3260
3261 if (ctx->Driver.GetCompressedTexImage) {
3262 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3263 texImage);
3264 }
3265 else {
3266 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3267 }
Brian Paul1207bf02000-05-23 20:10:49 +00003268}