blob: a38d0c5a6df3345b6d376134093436f72e57e273 [file] [log] [blame]
Brian Paul959f8022000-03-19 01:10:11 +00001/* $Id: teximage.c,v 1.19 2000/03/19 01:10:12 brianp Exp $ */
jtgafb833d1999-08-19 00:55:39 +00002
3/*
4 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00005 * Version: 3.3
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"
33#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000034#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000035#include "mmath.h"
36#include "span.h"
37#include "teximage.h"
38#include "texstate.h"
39#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000040#endif
41
42
43/*
44 * NOTES:
45 *
Brian Paulc3f0a511999-11-03 17:27:05 +000046 * Mesa's native texture datatype is GLubyte. Native formats are
47 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
48 * and GL_COLOR_INDEX.
49 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000050 */
51
52
53
jtgafb833d1999-08-19 00:55:39 +000054/*
55 * Compute log base 2 of n.
56 * If n isn't an exact power of two return -1.
57 * If n<0 return -1.
58 */
Brian Paulfbd8f211999-11-11 01:22:25 +000059static int
60logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +000061{
62 GLint i = 1;
63 GLint log2 = 0;
64
65 if (n<0) {
66 return -1;
67 }
68
69 while ( n > i ) {
70 i *= 2;
71 log2++;
72 }
73 if (i != n) {
74 return -1;
75 }
76 else {
77 return log2;
78 }
79}
80
81
82
83/*
84 * Given an internal texture format enum or 1, 2, 3, 4 return the
85 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +000086 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
87 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +000088 */
Brian Paulfbd8f211999-11-11 01:22:25 +000089static GLint
90decode_internal_format( GLint format )
jtgafb833d1999-08-19 00:55:39 +000091{
92 switch (format) {
93 case GL_ALPHA:
94 case GL_ALPHA4:
95 case GL_ALPHA8:
96 case GL_ALPHA12:
97 case GL_ALPHA16:
98 return GL_ALPHA;
99 case 1:
100 case GL_LUMINANCE:
101 case GL_LUMINANCE4:
102 case GL_LUMINANCE8:
103 case GL_LUMINANCE12:
104 case GL_LUMINANCE16:
105 return GL_LUMINANCE;
106 case 2:
107 case GL_LUMINANCE_ALPHA:
108 case GL_LUMINANCE4_ALPHA4:
109 case GL_LUMINANCE6_ALPHA2:
110 case GL_LUMINANCE8_ALPHA8:
111 case GL_LUMINANCE12_ALPHA4:
112 case GL_LUMINANCE12_ALPHA12:
113 case GL_LUMINANCE16_ALPHA16:
114 return GL_LUMINANCE_ALPHA;
115 case GL_INTENSITY:
116 case GL_INTENSITY4:
117 case GL_INTENSITY8:
118 case GL_INTENSITY12:
119 case GL_INTENSITY16:
120 return GL_INTENSITY;
121 case 3:
122 case GL_RGB:
123 case GL_R3_G3_B2:
124 case GL_RGB4:
125 case GL_RGB5:
126 case GL_RGB8:
127 case GL_RGB10:
128 case GL_RGB12:
129 case GL_RGB16:
130 return GL_RGB;
131 case 4:
132 case GL_RGBA:
133 case GL_RGBA2:
134 case GL_RGBA4:
135 case GL_RGB5_A1:
136 case GL_RGBA8:
137 case GL_RGB10_A2:
138 case GL_RGBA12:
139 case GL_RGBA16:
140 return GL_RGBA;
141 case GL_COLOR_INDEX:
142 case GL_COLOR_INDEX1_EXT:
143 case GL_COLOR_INDEX2_EXT:
144 case GL_COLOR_INDEX4_EXT:
145 case GL_COLOR_INDEX8_EXT:
146 case GL_COLOR_INDEX12_EXT:
147 case GL_COLOR_INDEX16_EXT:
148 return GL_COLOR_INDEX;
149 default:
150 return -1; /* error */
151 }
152}
153
154
155
156/*
157 * Given an internal texture format enum or 1, 2, 3, 4 return the
158 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
159 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
160 * number of components for the format. Return -1 if invalid enum.
161 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000162static GLint
163components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000164{
165 switch (format) {
166 case GL_ALPHA:
167 case GL_ALPHA4:
168 case GL_ALPHA8:
169 case GL_ALPHA12:
170 case GL_ALPHA16:
171 return 1;
172 case 1:
173 case GL_LUMINANCE:
174 case GL_LUMINANCE4:
175 case GL_LUMINANCE8:
176 case GL_LUMINANCE12:
177 case GL_LUMINANCE16:
178 return 1;
179 case 2:
180 case GL_LUMINANCE_ALPHA:
181 case GL_LUMINANCE4_ALPHA4:
182 case GL_LUMINANCE6_ALPHA2:
183 case GL_LUMINANCE8_ALPHA8:
184 case GL_LUMINANCE12_ALPHA4:
185 case GL_LUMINANCE12_ALPHA12:
186 case GL_LUMINANCE16_ALPHA16:
187 return 2;
188 case GL_INTENSITY:
189 case GL_INTENSITY4:
190 case GL_INTENSITY8:
191 case GL_INTENSITY12:
192 case GL_INTENSITY16:
193 return 1;
194 case 3:
195 case GL_RGB:
196 case GL_R3_G3_B2:
197 case GL_RGB4:
198 case GL_RGB5:
199 case GL_RGB8:
200 case GL_RGB10:
201 case GL_RGB12:
202 case GL_RGB16:
203 return 3;
204 case 4:
205 case GL_RGBA:
206 case GL_RGBA2:
207 case GL_RGBA4:
208 case GL_RGB5_A1:
209 case GL_RGBA8:
210 case GL_RGB10_A2:
211 case GL_RGBA12:
212 case GL_RGBA16:
213 return 4;
214 case GL_COLOR_INDEX:
215 case GL_COLOR_INDEX1_EXT:
216 case GL_COLOR_INDEX2_EXT:
217 case GL_COLOR_INDEX4_EXT:
218 case GL_COLOR_INDEX8_EXT:
219 case GL_COLOR_INDEX12_EXT:
220 case GL_COLOR_INDEX16_EXT:
221 return 1;
222 default:
223 return -1; /* error */
224 }
225}
226
227
228
Brian Paulfbd8f211999-11-11 01:22:25 +0000229struct gl_texture_image *
230gl_alloc_texture_image( void )
jtgafb833d1999-08-19 00:55:39 +0000231{
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000232 return CALLOC_STRUCT(gl_texture_image);
jtgafb833d1999-08-19 00:55:39 +0000233}
234
235
236
Brian Paulfbd8f211999-11-11 01:22:25 +0000237void
238gl_free_texture_image( struct gl_texture_image *teximage )
jtgafb833d1999-08-19 00:55:39 +0000239{
240 if (teximage->Data) {
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000241 FREE( teximage->Data );
Brian Paul91baaa31999-10-17 23:24:16 +0000242 teximage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +0000243 }
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000244 FREE( teximage );
jtgafb833d1999-08-19 00:55:39 +0000245}
246
247
248
249/*
250 * Examine the texImage->Format field and set the Red, Green, Blue, etc
251 * texel component sizes to default values.
252 * These fields are set only here by core Mesa but device drivers may
253 * overwritting these fields to indicate true texel resolution.
254 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000255static void
256set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000257{
258 switch (texImage->Format) {
259 case GL_ALPHA:
260 texImage->RedBits = 0;
261 texImage->GreenBits = 0;
262 texImage->BlueBits = 0;
263 texImage->AlphaBits = 8;
264 texImage->IntensityBits = 0;
265 texImage->LuminanceBits = 0;
266 texImage->IndexBits = 0;
267 break;
268 case GL_LUMINANCE:
269 texImage->RedBits = 0;
270 texImage->GreenBits = 0;
271 texImage->BlueBits = 0;
272 texImage->AlphaBits = 0;
273 texImage->IntensityBits = 0;
274 texImage->LuminanceBits = 8;
275 texImage->IndexBits = 0;
276 break;
277 case GL_LUMINANCE_ALPHA:
278 texImage->RedBits = 0;
279 texImage->GreenBits = 0;
280 texImage->BlueBits = 0;
281 texImage->AlphaBits = 8;
282 texImage->IntensityBits = 0;
283 texImage->LuminanceBits = 8;
284 texImage->IndexBits = 0;
285 break;
286 case GL_INTENSITY:
287 texImage->RedBits = 0;
288 texImage->GreenBits = 0;
289 texImage->BlueBits = 0;
290 texImage->AlphaBits = 0;
291 texImage->IntensityBits = 8;
292 texImage->LuminanceBits = 0;
293 texImage->IndexBits = 0;
294 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000295 case GL_RED:
296 texImage->RedBits = 8;
297 texImage->GreenBits = 0;
298 texImage->BlueBits = 0;
299 texImage->AlphaBits = 0;
300 texImage->IntensityBits = 0;
301 texImage->LuminanceBits = 0;
302 texImage->IndexBits = 0;
303 break;
304 case GL_GREEN:
305 texImage->RedBits = 0;
306 texImage->GreenBits = 8;
307 texImage->BlueBits = 0;
308 texImage->AlphaBits = 0;
309 texImage->IntensityBits = 0;
310 texImage->LuminanceBits = 0;
311 texImage->IndexBits = 0;
312 break;
313 case GL_BLUE:
314 texImage->RedBits = 0;
315 texImage->GreenBits = 0;
316 texImage->BlueBits = 8;
317 texImage->AlphaBits = 0;
318 texImage->IntensityBits = 0;
319 texImage->LuminanceBits = 0;
320 texImage->IndexBits = 0;
321 break;
jtgafb833d1999-08-19 00:55:39 +0000322 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000323 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000324 texImage->RedBits = 8;
325 texImage->GreenBits = 8;
326 texImage->BlueBits = 8;
327 texImage->AlphaBits = 0;
328 texImage->IntensityBits = 0;
329 texImage->LuminanceBits = 0;
330 texImage->IndexBits = 0;
331 break;
332 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000333 case GL_BGRA:
334 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000335 texImage->RedBits = 8;
336 texImage->GreenBits = 8;
337 texImage->BlueBits = 8;
338 texImage->AlphaBits = 8;
339 texImage->IntensityBits = 0;
340 texImage->LuminanceBits = 0;
341 texImage->IndexBits = 0;
342 break;
343 case GL_COLOR_INDEX:
344 texImage->RedBits = 0;
345 texImage->GreenBits = 0;
346 texImage->BlueBits = 0;
347 texImage->AlphaBits = 0;
348 texImage->IntensityBits = 0;
349 texImage->LuminanceBits = 0;
350 texImage->IndexBits = 8;
351 break;
352 default:
353 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
354 }
355}
356
357
358/* Need this to prevent an out-of-bounds memory access when using
359 * X86 optimized code.
360 */
361#ifdef USE_X86_ASM
362# define EXTRA_BYTE 1
363#else
364# define EXTRA_BYTE 0
365#endif
366
367
Brian Paulc3f0a511999-11-03 17:27:05 +0000368
jtgafb833d1999-08-19 00:55:39 +0000369/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000370 * This is called by glTexImage[123]D in order to build a gl_texture_image
371 * object given the client's parameters and image data.
372 *
373 * NOTES: Width, height and depth should include the border.
374 * All texture image parameters should have already been error checked.
jtgafb833d1999-08-19 00:55:39 +0000375 */
376static struct gl_texture_image *
Brian Paulc3f0a511999-11-03 17:27:05 +0000377make_texture_image( GLcontext *ctx, GLint internalFormat,
378 GLint width, GLint height, GLint depth, GLint border,
379 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
380 const struct gl_pixelstore_attrib *unpacking)
jtgafb833d1999-08-19 00:55:39 +0000381{
Brian Paulc3f0a511999-11-03 17:27:05 +0000382 GLint components, numPixels;
jtgafb833d1999-08-19 00:55:39 +0000383 struct gl_texture_image *texImage;
jtgafb833d1999-08-19 00:55:39 +0000384
Brian Paulc3f0a511999-11-03 17:27:05 +0000385 assert(width > 0);
386 assert(height > 0);
387 assert(depth > 0);
388 assert(border == 0 || border == 1);
389 assert(pixels);
390 assert(unpacking);
jtgafb833d1999-08-19 00:55:39 +0000391
jtgafb833d1999-08-19 00:55:39 +0000392
Brian Paulc3f0a511999-11-03 17:27:05 +0000393 /*
394 * Allocate and initialize the texture_image struct
395 */
jtgafb833d1999-08-19 00:55:39 +0000396 texImage = gl_alloc_texture_image();
397 if (!texImage)
398 return NULL;
399
400 texImage->Format = (GLenum) decode_internal_format(internalFormat);
401 set_teximage_component_sizes( texImage );
402 texImage->IntFormat = (GLenum) internalFormat;
403 texImage->Border = border;
Brian Paulc3f0a511999-11-03 17:27:05 +0000404 texImage->Width = width;
405 texImage->Height = height;
406 texImage->Depth = depth;
407 texImage->WidthLog2 = logbase2(width - 2 * border);
408 if (height == 1) /* 1-D texture */
jtgafb833d1999-08-19 00:55:39 +0000409 texImage->HeightLog2 = 0;
410 else
Brian Paulc3f0a511999-11-03 17:27:05 +0000411 texImage->HeightLog2 = logbase2(height - 2 * border);
412 if (depth == 1) /* 2-D texture */
jtgafb833d1999-08-19 00:55:39 +0000413 texImage->DepthLog2 = 0;
414 else
Brian Paulc3f0a511999-11-03 17:27:05 +0000415 texImage->DepthLog2 = logbase2(depth - 2 * border);
jtgafb833d1999-08-19 00:55:39 +0000416 texImage->Width2 = 1 << texImage->WidthLog2;
417 texImage->Height2 = 1 << texImage->HeightLog2;
418 texImage->Depth2 = 1 << texImage->DepthLog2;
Brian Paulc3f0a511999-11-03 17:27:05 +0000419 texImage->MaxLog2 = MAX2(texImage->WidthLog2, texImage->HeightLog2);
420
421 components = components_in_intformat(internalFormat);
422 numPixels = texImage->Width * texImage->Height * texImage->Depth;
423
424 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
jtgafb833d1999-08-19 00:55:39 +0000425
426 if (!texImage->Data) {
427 /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000428 gl_free_texture_image(texImage);
jtgafb833d1999-08-19 00:55:39 +0000429 return NULL;
430 }
431
Brian Paulc3f0a511999-11-03 17:27:05 +0000432
433 /*
434 * OK, the texture image struct has been initialized and the texture
435 * image memory has been allocated.
436 * Now fill in the texture image from the source data.
437 * This includes applying the pixel transfer operations.
438 */
439
440 /* try common 2D texture cases first */
441 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
442 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
443 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
444
445 if (srcFormat == internalFormat) {
446 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
447 * GL_LUMINANCE_ALPHA, etc. texture formats.
448 */
Brian Paul959f8022000-03-19 01:10:11 +0000449 const GLubyte *src = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000450 pixels, width, height, srcFormat, srcType, 0, 0, 0);
Brian Paul959f8022000-03-19 01:10:11 +0000451 const GLubyte *src1 = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000452 pixels, width, height, srcFormat, srcType, 0, 1, 0);
453 const GLint srcStride = src1 - src;
454 GLubyte *dst = texImage->Data;
455 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
456 if (srcStride == dstBytesPerRow) {
457 MEMCPY(dst, src, height * dstBytesPerRow);
458 }
459 else {
460 GLint i;
461 for (i = 0; i < height; i++) {
462 MEMCPY(dst, src, dstBytesPerRow);
463 src += srcStride;
464 dst += dstBytesPerRow;
465 }
466 }
467 return texImage; /* all done */
468 }
469 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
470 /* commonly used by Quake */
Brian Paul959f8022000-03-19 01:10:11 +0000471 const GLubyte *src = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000472 pixels, width, height, srcFormat, srcType, 0, 0, 0);
Brian Paul959f8022000-03-19 01:10:11 +0000473 const GLubyte *src1 = (const GLubyte *) gl_pixel_addr_in_image(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000474 pixels, width, height, srcFormat, srcType, 0, 1, 0);
475 const GLint srcStride = src1 - src;
476 GLubyte *dst = texImage->Data;
477 GLint i, j;
478 for (i = 0; i < height; i++) {
479 const GLubyte *s = src;
480 for (j = 0; j < width; j++) {
481 *dst++ = *s++; /*red*/
482 *dst++ = *s++; /*green*/
483 *dst++ = *s++; /*blue*/
484 s++; /*alpha*/
485 }
486 src += srcStride;
487 }
488 return texImage; /* all done */
489 }
490 }
491
492
493 /*
494 * General case solutions
495 */
496 if (texImage->Format == GL_COLOR_INDEX) {
497 /* color index texture */
498 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
499 const GLenum dstType = GL_UNSIGNED_BYTE;
500 GLubyte *dest = texImage->Data;
501 GLint img, row;
502 for (img = 0; img < depth; img++) {
503 for (row = 0; row < height; row++) {
504 const GLvoid *source = gl_pixel_addr_in_image(unpacking,
505 pixels, width, height, srcFormat, srcType, img, row, 0);
506 _mesa_unpack_index_span(ctx, width, dstType, dest,
507 srcType, source, unpacking, GL_TRUE);
508 dest += destBytesPerRow;
509 }
510 }
jtgafb833d1999-08-19 00:55:39 +0000511 }
512 else {
Brian Paulc3f0a511999-11-03 17:27:05 +0000513 /* regular, color texture */
514 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
515 const GLenum dstFormat = texImage->Format;
516 GLubyte *dest = texImage->Data;
517 GLint img, row;
518 for (img = 0; img < depth; img++) {
519 for (row = 0; row < height; row++) {
520 const GLvoid *source = gl_pixel_addr_in_image(unpacking,
521 pixels, width, height, srcFormat, srcType, img, row, 0);
522 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
523 srcFormat, srcType, source, unpacking, GL_TRUE);
524 dest += destBytesPerRow;
525 }
526 }
jtgafb833d1999-08-19 00:55:39 +0000527 }
528
Brian Paulc3f0a511999-11-03 17:27:05 +0000529 return texImage; /* All done! */
jtgafb833d1999-08-19 00:55:39 +0000530}
531
532
533
534/*
535 * glTexImage[123]D can accept a NULL image pointer. In this case we
536 * create a texture image with unspecified image contents per the OpenGL
537 * spec.
538 */
539static struct gl_texture_image *
540make_null_texture( GLcontext *ctx, GLenum internalFormat,
541 GLsizei width, GLsizei height, GLsizei depth, GLint border )
542{
543 GLint components;
544 struct gl_texture_image *texImage;
545 GLint numPixels;
546 (void) ctx;
547
548 /*internalFormat = decode_internal_format(internalFormat);*/
549 components = components_in_intformat(internalFormat);
550 numPixels = width * height * depth;
551
552 texImage = gl_alloc_texture_image();
553 if (!texImage)
554 return NULL;
555
556 texImage->Format = (GLenum) decode_internal_format(internalFormat);
557 set_teximage_component_sizes( texImage );
558 texImage->IntFormat = internalFormat;
559 texImage->Border = border;
560 texImage->Width = width;
561 texImage->Height = height;
562 texImage->Depth = depth;
563 texImage->WidthLog2 = logbase2(width - 2*border);
564 if (height==1) /* 1-D texture */
565 texImage->HeightLog2 = 0;
566 else
567 texImage->HeightLog2 = logbase2(height - 2*border);
568 if (depth==1) /* 2-D texture */
569 texImage->DepthLog2 = 0;
570 else
571 texImage->DepthLog2 = logbase2(depth - 2*border);
572 texImage->Width2 = 1 << texImage->WidthLog2;
573 texImage->Height2 = 1 << texImage->HeightLog2;
574 texImage->Depth2 = 1 << texImage->DepthLog2;
575 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
576
577 /* XXX should we really allocate memory for the image or let it be NULL? */
578 /*texImage->Data = NULL;*/
579
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000580 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000581
582 /*
583 * Let's see if anyone finds this. If glTexImage2D() is called with
584 * a NULL image pointer then load the texture image with something
585 * interesting instead of leaving it indeterminate.
586 */
587 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000588 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000589 " X X XXXXX XXX X ",
590 " XX XX X X X X X ",
591 " X X X X X X X ",
592 " X X XXXX XXX XXXXX ",
593 " X X X X X X ",
594 " X X X X X X X ",
595 " X X XXXXX XXX X X ",
596 " "
597 };
598
599 GLubyte *imgPtr = texImage->Data;
600 GLint i, j, k;
601 for (i=0;i<height;i++) {
602 GLint srcRow = 7 - i % 8;
603 for (j=0;j<width;j++) {
604 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000605 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000606 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000607 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000608 }
609 }
610 }
611 }
612
613 return texImage;
614}
615
616
617
618/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000619 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +0000620 * Input:
621 * dimensions - must be 1 or 2 or 3
622 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
623 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000624static GLboolean
625texture_error_check( GLcontext *ctx, GLenum target,
626 GLint level, GLint internalFormat,
627 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +0000628 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000629 GLint width, GLint height,
630 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +0000631{
632 GLboolean isProxy;
633 GLint iformat;
634
635 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +0000636 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +0000637 if (target != GL_TEXTURE_1D && !isProxy) {
638 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
639 return GL_TRUE;
640 }
641 }
642 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +0000643 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
jtgafb833d1999-08-19 00:55:39 +0000644 if (target != GL_TEXTURE_2D && !isProxy) {
645 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
646 return GL_TRUE;
647 }
648 }
649 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +0000650 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +0000651 if (target != GL_TEXTURE_3D && !isProxy) {
652 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
653 return GL_TRUE;
654 }
655 }
656 else {
657 gl_problem( ctx, "bad dims in texture_error_check" );
658 return GL_TRUE;
659 }
660
661 /* Border */
662 if (border!=0 && border!=1) {
663 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000664 char message[100];
665 sprintf(message, "glTexImage%dD(border)", dimensions);
666 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000667 }
668 return GL_TRUE;
669 }
670
671 /* Width */
672 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
673 || logbase2( width - 2 * border ) < 0) {
674 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000675 char message[100];
676 sprintf(message, "glTexImage%dD(width)", dimensions);
677 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000678 }
679 return GL_TRUE;
680 }
681
682 /* Height */
683 if (dimensions >= 2) {
684 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
685 || logbase2( height - 2 * border ) < 0) {
686 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000687 char message[100];
688 sprintf(message, "glTexImage%dD(height)", dimensions);
689 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000690 }
Brian Paulc3f0a511999-11-03 17:27:05 +0000691 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000692 }
693 }
694
695 /* Depth */
696 if (dimensions >= 3) {
697 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
698 || logbase2( depth - 2 * border ) < 0) {
699 if (!isProxy) {
700 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
701 }
702 return GL_TRUE;
703 }
704 }
705
706 /* Level */
707 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000708 if (!isProxy) {
709 char message[100];
710 sprintf(message, "glTexImage%dD(level)", dimensions);
711 gl_error(ctx, GL_INVALID_VALUE, message);
712 }
jtgafb833d1999-08-19 00:55:39 +0000713 return GL_TRUE;
714 }
715
716 iformat = decode_internal_format( internalFormat );
717 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000718 if (!isProxy) {
719 char message[100];
720 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
721 gl_error(ctx, GL_INVALID_VALUE, message);
722 }
jtgafb833d1999-08-19 00:55:39 +0000723 return GL_TRUE;
724 }
725
726 if (!gl_is_legal_format_and_type( format, type )) {
Brian Pauld53573d1999-10-19 20:36:20 +0000727 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
728 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
729 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000730 if (!isProxy) {
731 char message[100];
732 sprintf(message, "glTexImage%dD(format or type)", dimensions);
733 gl_error(ctx, GL_INVALID_OPERATION, message);
734 }
jtgafb833d1999-08-19 00:55:39 +0000735 return GL_TRUE;
736 }
737
738 /* if we get here, the parameters are OK */
739 return GL_FALSE;
740}
741
742
743
744/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000745 * Test glTexSubImage[123]D() parameters for errors.
746 * Input:
747 * dimensions - must be 1 or 2 or 3
748 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
749 */
750static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000751subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000752 GLenum target, GLint level,
753 GLint xoffset, GLint yoffset, GLint zoffset,
754 GLint width, GLint height, GLint depth,
755 GLenum format, GLenum type )
756{
757 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
758 struct gl_texture_image *destTex;
759
760 if (dimensions == 1) {
761 if (target != GL_TEXTURE_1D) {
762 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
763 return GL_TRUE;
764 }
765 }
766 else if (dimensions == 2) {
767 if (target != GL_TEXTURE_2D) {
768 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
769 return GL_TRUE;
770 }
771 }
772 else if (dimensions == 3) {
773 if (target != GL_TEXTURE_3D) {
774 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
775 return GL_TRUE;
776 }
777 }
778 else {
779 gl_problem( ctx, "bad dims in texture_error_check" );
780 return GL_TRUE;
781 }
782
783 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
784 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
785 return GL_TRUE;
786 }
787
788 if (width < 0) {
789 char message[100];
790 sprintf(message, "glTexSubImage%dD(width)", dimensions);
791 gl_error(ctx, GL_INVALID_VALUE, message);
792 return GL_TRUE;
793 }
794 if (height < 0 && dimensions > 1) {
795 char message[100];
796 sprintf(message, "glTexSubImage%dD(height)", dimensions);
797 gl_error(ctx, GL_INVALID_VALUE, message);
798 return GL_TRUE;
799 }
800 if (depth < 0 && dimensions > 2) {
801 char message[100];
802 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
803 gl_error(ctx, GL_INVALID_VALUE, message);
804 return GL_TRUE;
805 }
806
807 destTex = texUnit->CurrentD[2]->Image[level];
808 if (!destTex) {
809 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
810 return GL_TRUE;
811 }
812
813 if (xoffset < -((GLint)destTex->Border)) {
814 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
815 return GL_TRUE;
816 }
817 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
818 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
819 return GL_TRUE;
820 }
821 if (dimensions > 1) {
822 if (yoffset < -((GLint)destTex->Border)) {
823 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
824 return GL_TRUE;
825 }
826 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
827 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
828 return GL_TRUE;
829 }
830 }
831 if (dimensions > 2) {
832 if (zoffset < -((GLint)destTex->Border)) {
833 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
834 return GL_TRUE;
835 }
836 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
837 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
838 return GL_TRUE;
839 }
840 }
841
842 if (!gl_is_legal_format_and_type(format, type)) {
843 char message[100];
844 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
845 gl_error(ctx, GL_INVALID_ENUM, message);
846 return GL_TRUE;
847 }
848
849 return GL_FALSE;
850}
851
852
853/*
854 * Test glCopyTexImage[12]D() parameters for errors.
855 * Input: dimensions - must be 1 or 2 or 3
856 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
857 */
858static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000859copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000860 GLenum target, GLint level, GLint internalFormat,
861 GLint width, GLint height, GLint border )
862{
863 GLint iformat;
864
865 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
866 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
867 return GL_TRUE;
868 }
869
870 if (dimensions == 1 && target != GL_TEXTURE_1D) {
871 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
872 return GL_TRUE;
873 }
874 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
875 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
876 return GL_TRUE;
877 }
878
879 /* Border */
880 if (border!=0 && border!=1) {
881 char message[100];
882 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
883 gl_error(ctx, GL_INVALID_VALUE, message);
884 return GL_TRUE;
885 }
886
887 /* Width */
888 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
889 || logbase2( width - 2 * border ) < 0) {
890 char message[100];
891 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
892 gl_error(ctx, GL_INVALID_VALUE, message);
893 return GL_TRUE;
894 }
895
896 /* Height */
897 if (dimensions >= 2) {
898 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
899 || logbase2( height - 2 * border ) < 0) {
900 char message[100];
901 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
902 gl_error(ctx, GL_INVALID_VALUE, message);
903 return GL_TRUE;
904 }
905 }
906
907 /* Level */
908 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
909 char message[100];
910 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
911 gl_error(ctx, GL_INVALID_VALUE, message);
912 return GL_TRUE;
913 }
914
915 iformat = decode_internal_format( internalFormat );
916 if (iformat < 0) {
917 char message[100];
918 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
919 gl_error(ctx, GL_INVALID_VALUE, message);
920 return GL_TRUE;
921 }
922
923 /* if we get here, the parameters are OK */
924 return GL_FALSE;
925}
926
927
928static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000929copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000930 GLenum target, GLint level,
931 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +0000932 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +0000933{
934 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
935 struct gl_texture_image *teximage;
936
937 if (dimensions == 1 && target != GL_TEXTURE_1D) {
938 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
939 return GL_TRUE;
940 }
941 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
942 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
943 return GL_TRUE;
944 }
945 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
946 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
947 return GL_TRUE;
948 }
949
950 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
951 char message[100];
952 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
953 gl_error(ctx, GL_INVALID_VALUE, message);
954 return GL_TRUE;
955 }
956
957 if (width < 0) {
958 char message[100];
959 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
960 gl_error(ctx, GL_INVALID_VALUE, message);
961 return GL_TRUE;
962 }
963 if (dimensions > 1 && height < 0) {
964 char message[100];
965 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
966 gl_error(ctx, GL_INVALID_VALUE, message);
967 return GL_TRUE;
968 }
969
Brian Pauldf6a28d2000-02-21 16:34:21 +0000970 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +0000971 if (!teximage) {
972 char message[100];
973 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
974 gl_error(ctx, GL_INVALID_OPERATION, message);
975 return GL_TRUE;
976 }
977
978 if (xoffset < -((GLint)teximage->Border)) {
979 char message[100];
980 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
981 gl_error(ctx, GL_INVALID_VALUE, message);
982 return GL_TRUE;
983 }
984 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
985 char message[100];
986 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
987 gl_error(ctx, GL_INVALID_VALUE, message);
988 return GL_TRUE;
989 }
990 if (dimensions > 1) {
991 if (yoffset < -((GLint)teximage->Border)) {
992 char message[100];
993 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
994 gl_error(ctx, GL_INVALID_VALUE, message);
995 return GL_TRUE;
996 }
997 /* NOTE: we're adding the border here, not subtracting! */
998 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
999 char message[100];
1000 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1001 gl_error(ctx, GL_INVALID_VALUE, message);
1002 return GL_TRUE;
1003 }
1004 }
1005
1006 if (dimensions > 2) {
1007 if (zoffset < -((GLint)teximage->Border)) {
1008 char message[100];
1009 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1010 gl_error(ctx, GL_INVALID_VALUE, message);
1011 return GL_TRUE;
1012 }
1013 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1014 char message[100];
1015 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1016 gl_error(ctx, GL_INVALID_VALUE, message);
1017 return GL_TRUE;
1018 }
1019 }
1020
1021 /* if we get here, the parameters are OK */
1022 return GL_FALSE;
1023}
1024
1025
1026
1027
1028/*
jtgafb833d1999-08-19 00:55:39 +00001029 * Called from the API. Note that width includes the border.
1030 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001031void
1032_mesa_TexImage1D( GLenum target, GLint level, GLint internalformat,
1033 GLsizei width, GLint border, GLenum format,
1034 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001035{
Brian Paulfbd8f211999-11-11 01:22:25 +00001036 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001037 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1038 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1039
1040 if (target==GL_TEXTURE_1D) {
1041 struct gl_texture_image *teximage;
1042 if (texture_error_check( ctx, target, level, internalformat,
1043 format, type, 1, width, 1, 1, border )) {
1044 /* error in texture image was detected */
1045 return;
1046 }
1047
1048 /* free current texture image, if any */
1049 if (texUnit->CurrentD[1]->Image[level]) {
1050 gl_free_texture_image( texUnit->CurrentD[1]->Image[level] );
1051 }
1052
1053 /* make new texture from source image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001054 if (pixels) {
1055 teximage = make_texture_image(ctx, internalformat, width, 1, 1,
1056 border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001057 }
1058 else {
1059 teximage = make_null_texture(ctx, (GLenum) internalformat,
1060 width, 1, 1, border);
1061 }
1062
1063 /* install new texture image */
jtgafb833d1999-08-19 00:55:39 +00001064 texUnit->CurrentD[1]->Image[level] = teximage;
1065 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1066 ctx->NewState |= NEW_TEXTURING;
1067
jtgafb833d1999-08-19 00:55:39 +00001068 /* tell driver about change */
1069 if (ctx->Driver.TexImage) {
1070 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1071 texUnit->CurrentD[1],
1072 level, internalformat, teximage );
1073 }
1074 }
1075 else if (target==GL_PROXY_TEXTURE_1D) {
1076 /* Proxy texture: check for errors and update proxy state */
1077 if (texture_error_check( ctx, target, level, internalformat,
1078 format, type, 1, width, 1, 1, border )) {
1079 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1080 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1081 sizeof(struct gl_texture_image) );
1082 }
1083 }
1084 else {
1085 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1086 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
1087 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat;
1088 ctx->Texture.Proxy1D->Image[level]->Border = border;
1089 ctx->Texture.Proxy1D->Image[level]->Width = width;
1090 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1091 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1092 }
jtgafb833d1999-08-19 00:55:39 +00001093 }
1094 else {
1095 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1096 return;
1097 }
1098}
1099
1100
Brian Paulfbd8f211999-11-11 01:22:25 +00001101void
1102_mesa_TexImage2D( GLenum target, GLint level, GLint internalformat,
1103 GLsizei width, GLsizei height, GLint border,
1104 GLenum format, GLenum type,
1105 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001106{
Brian Paulfbd8f211999-11-11 01:22:25 +00001107 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001108 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1109 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1110
1111 if (target==GL_TEXTURE_2D) {
1112 struct gl_texture_image *teximage;
1113 if (texture_error_check( ctx, target, level, internalformat,
1114 format, type, 2, width, height, 1, border )) {
1115 /* error in texture image was detected */
1116 return;
1117 }
1118
1119 /* free current texture image, if any */
1120 if (texUnit->CurrentD[2]->Image[level]) {
1121 gl_free_texture_image( texUnit->CurrentD[2]->Image[level] );
1122 }
1123
1124 /* make new texture from source image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001125 if (pixels) {
1126 teximage = make_texture_image(ctx, internalformat, width, height, 1,
1127 border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001128 }
1129 else {
1130 teximage = make_null_texture(ctx, (GLenum) internalformat,
1131 width, height, 1, border);
1132 }
1133
1134 /* install new texture image */
1135 texUnit->CurrentD[2]->Image[level] = teximage;
1136 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1137 ctx->NewState |= NEW_TEXTURING;
1138
jtgafb833d1999-08-19 00:55:39 +00001139 /* tell driver about change */
1140 if (ctx->Driver.TexImage) {
1141 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
1142 texUnit->CurrentD[2],
1143 level, internalformat, teximage );
1144 }
1145 }
1146 else if (target==GL_PROXY_TEXTURE_2D) {
1147 /* Proxy texture: check for errors and update proxy state */
1148 if (texture_error_check( ctx, target, level, internalformat,
1149 format, type, 2, width, height, 1, border )) {
1150 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1151 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1152 sizeof(struct gl_texture_image) );
1153 }
1154 }
1155 else {
1156 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1157 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
1158 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalformat;
1159 ctx->Texture.Proxy2D->Image[level]->Border = border;
1160 ctx->Texture.Proxy2D->Image[level]->Width = width;
1161 ctx->Texture.Proxy2D->Image[level]->Height = height;
1162 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1163 }
jtgafb833d1999-08-19 00:55:39 +00001164 }
1165 else {
1166 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1167 return;
1168 }
1169}
1170
1171
1172
1173/*
1174 * Called by the API or display list executor.
1175 * Note that width and height include the border.
1176 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001177void
1178_mesa_TexImage3D( GLenum target, GLint level, GLint internalformat,
1179 GLsizei width, GLsizei height, GLsizei depth,
1180 GLint border, GLenum format, GLenum type,
1181 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001182{
Brian Paulfbd8f211999-11-11 01:22:25 +00001183 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001184 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paulfbd8f211999-11-11 01:22:25 +00001185 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT");
jtgafb833d1999-08-19 00:55:39 +00001186
Brian Paulfbd8f211999-11-11 01:22:25 +00001187 if (target==GL_TEXTURE_3D_EXT) {
jtgafb833d1999-08-19 00:55:39 +00001188 struct gl_texture_image *teximage;
1189 if (texture_error_check( ctx, target, level, internalformat,
1190 format, type, 3, width, height, depth,
1191 border )) {
1192 /* error in texture image was detected */
1193 return;
1194 }
1195
1196 /* free current texture image, if any */
1197 if (texUnit->CurrentD[3]->Image[level]) {
1198 gl_free_texture_image( texUnit->CurrentD[3]->Image[level] );
1199 }
1200
1201 /* make new texture from source image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001202 if (pixels) {
1203 teximage = make_texture_image(ctx, internalformat, width, height,
1204 depth, border, format, type, pixels, &ctx->Unpack);
jtgafb833d1999-08-19 00:55:39 +00001205 }
1206 else {
1207 teximage = make_null_texture(ctx, (GLenum) internalformat,
1208 width, height, depth, border);
1209 }
1210
1211 /* install new texture image */
1212 texUnit->CurrentD[3]->Image[level] = teximage;
1213 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
1214 ctx->NewState |= NEW_TEXTURING;
1215
jtgafb833d1999-08-19 00:55:39 +00001216 /* tell driver about change */
1217 if (ctx->Driver.TexImage) {
1218 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT,
1219 texUnit->CurrentD[3],
1220 level, internalformat, teximage );
1221 }
1222 }
1223 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1224 /* Proxy texture: check for errors and update proxy state */
1225 if (texture_error_check( ctx, target, level, internalformat,
1226 format, type, 3, width, height, depth,
1227 border )) {
1228 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1229 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1230 sizeof(struct gl_texture_image) );
1231 }
1232 }
1233 else {
1234 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1235 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
1236 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalformat;
1237 ctx->Texture.Proxy3D->Image[level]->Border = border;
1238 ctx->Texture.Proxy3D->Image[level]->Width = width;
1239 ctx->Texture.Proxy3D->Image[level]->Height = height;
1240 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1241 }
jtgafb833d1999-08-19 00:55:39 +00001242 }
1243 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001244 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001245 return;
1246 }
1247}
1248
1249
Brian Paul663049a2000-01-31 23:10:16 +00001250void
1251_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalformat,
1252 GLsizei width, GLsizei height, GLsizei depth,
1253 GLint border, GLenum format, GLenum type,
1254 const GLvoid *pixels )
1255{
1256 _mesa_TexImage3D(target, level, (GLint) internalformat, width, height,
1257 depth, border, format, type, pixels);
1258}
1259
1260
jtgafb833d1999-08-19 00:55:39 +00001261
Brian Paulfbd8f211999-11-11 01:22:25 +00001262void
1263_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1264 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001265{
Brian Paulfbd8f211999-11-11 01:22:25 +00001266 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001267 const struct gl_texture_object *texObj;
1268
1269 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1270
1271 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1272 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1273 return;
1274 }
1275
1276 if (gl_sizeof_type(type) <= 0) {
1277 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1278 return;
1279 }
1280
1281 if (gl_components_in_format(format) <= 0) {
1282 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1283 return;
1284 }
1285
1286 if (!pixels)
1287 return; /* XXX generate an error??? */
1288
1289 switch (target) {
1290 case GL_TEXTURE_1D:
1291 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1292 break;
1293 case GL_TEXTURE_2D:
1294 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1295 break;
1296 case GL_TEXTURE_3D:
1297 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1298 break;
1299 default:
1300 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1301 return;
1302 }
1303
1304 if (texObj->Image[level] && texObj->Image[level]->Data) {
1305 const struct gl_texture_image *texImage = texObj->Image[level];
1306 GLint width = texImage->Width;
1307 GLint height = texImage->Height;
1308 GLint row;
1309
1310 for (row = 0; row < height; row++) {
1311 /* compute destination address in client memory */
1312 GLvoid *dest = gl_pixel_addr_in_image( &ctx->Unpack, pixels,
1313 width, height,
1314 format, type, 0, row, 0);
1315
1316 assert(dest);
1317 if (texImage->Format == GL_RGBA) {
1318 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
Brian Paul959f8022000-03-19 01:10:11 +00001319 gl_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1320 format, type, dest,
jtgafb833d1999-08-19 00:55:39 +00001321 &ctx->Pack, GL_TRUE );
1322 }
1323 else {
1324 /* fetch RGBA row from texture image then pack it in client mem */
1325 GLubyte rgba[MAX_WIDTH][4];
1326 GLint i;
1327 const GLubyte *src;
1328 switch (texImage->Format) {
1329 case GL_ALPHA:
1330 src = texImage->Data + row * width * sizeof(GLubyte);
1331 for (i = 0; i < width; i++) {
1332 rgba[i][RCOMP] = 255;
1333 rgba[i][GCOMP] = 255;
1334 rgba[i][BCOMP] = 255;
1335 rgba[i][ACOMP] = src[i];
1336 }
1337 break;
1338 case GL_LUMINANCE:
1339 src = texImage->Data + row * width * sizeof(GLubyte);
1340 for (i = 0; i < width; i++) {
1341 rgba[i][RCOMP] = src[i];
1342 rgba[i][GCOMP] = src[i];
1343 rgba[i][BCOMP] = src[i];
1344 rgba[i][ACOMP] = 255;
1345 }
1346 break;
1347 case GL_LUMINANCE_ALPHA:
1348 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1349 for (i = 0; i < width; i++) {
1350 rgba[i][RCOMP] = src[i*2+0];
1351 rgba[i][GCOMP] = src[i*2+0];
1352 rgba[i][BCOMP] = src[i*2+0];
1353 rgba[i][ACOMP] = src[i*2+1];
1354 }
1355 break;
1356 case GL_INTENSITY:
1357 src = texImage->Data + row * width * sizeof(GLubyte);
1358 for (i = 0; i < width; i++) {
1359 rgba[i][RCOMP] = src[i];
1360 rgba[i][GCOMP] = src[i];
1361 rgba[i][BCOMP] = src[i];
1362 rgba[i][ACOMP] = 255;
1363 }
1364 break;
1365 case GL_RGB:
1366 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1367 for (i = 0; i < width; i++) {
1368 rgba[i][RCOMP] = src[i*3+0];
1369 rgba[i][GCOMP] = src[i*3+1];
1370 rgba[i][BCOMP] = src[i*3+2];
1371 rgba[i][ACOMP] = 255;
1372 }
1373 break;
1374 case GL_RGBA:
1375 /* this special case should have been handled above! */
1376 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1377 break;
1378 case GL_COLOR_INDEX:
1379 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1380 break;
1381 default:
1382 gl_problem( ctx, "bad format in gl_GetTexImage" );
1383 }
1384 gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1385 format, type, dest, &ctx->Pack, GL_TRUE );
1386 }
1387 }
1388 }
1389}
1390
1391
1392
Brian Paulfbd8f211999-11-11 01:22:25 +00001393void
1394_mesa_TexSubImage1D( GLenum target, GLint level,
1395 GLint xoffset, GLsizei width,
1396 GLenum format, GLenum type,
1397 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001398{
Brian Paulfbd8f211999-11-11 01:22:25 +00001399 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001400 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1401 struct gl_texture_image *destTex;
1402
Brian Paulc3f0a511999-11-03 17:27:05 +00001403 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1404 width, 1, 1, format, type)) {
1405 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001406 return;
1407 }
1408
1409 destTex = texUnit->CurrentD[1]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001410 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001411
Brian Paulc3f0a511999-11-03 17:27:05 +00001412 if (width == 0 || !pixels)
1413 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001414
Brian Paulc3f0a511999-11-03 17:27:05 +00001415
1416 /*
1417 * Replace the texture subimage
1418 */
1419 {
1420 const GLint texComponents = components_in_intformat(destTex->Format);
1421 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001422 const GLint xoffsetb = xoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001423 GLubyte *dst = destTex->Data + xoffsetb * texComponents;
1424 if (texFormat == GL_COLOR_INDEX) {
1425 /* color index texture */
1426 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1427 width, 1, format, type, 0, 0, 0);
1428 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1429 type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001430 }
1431 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001432 /* color texture */
1433 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1434 width, 1, format, type, 0, 0, 0);
1435 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1436 format, type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001437 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001438 }
jtgafb833d1999-08-19 00:55:39 +00001439
Brian Paulc3f0a511999-11-03 17:27:05 +00001440 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
jtgafb833d1999-08-19 00:55:39 +00001441
Brian Paulc3f0a511999-11-03 17:27:05 +00001442 /*
1443 * Inform device driver of texture image change.
1444 */
1445 if (ctx->Driver.TexSubImage) {
1446 (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1],
1447 level, xoffset, 0, width, 1,
1448 texUnit->CurrentD[1]->Image[level]->IntFormat,
1449 destTex );
jtgafb833d1999-08-19 00:55:39 +00001450 }
1451 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001452 if (ctx->Driver.TexImage) {
1453 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1],
1454 level,
1455 texUnit->CurrentD[1]->Image[level]->IntFormat,
1456 destTex );
jtgafb833d1999-08-19 00:55:39 +00001457 }
jtgafb833d1999-08-19 00:55:39 +00001458 }
1459}
1460
1461
Brian Paulfbd8f211999-11-11 01:22:25 +00001462void
1463_mesa_TexSubImage2D( GLenum target, GLint level,
1464 GLint xoffset, GLint yoffset,
1465 GLsizei width, GLsizei height,
1466 GLenum format, GLenum type,
1467 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001468{
Brian Paulfbd8f211999-11-11 01:22:25 +00001469 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001470 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1471 struct gl_texture_image *destTex;
1472
Brian Paulc3f0a511999-11-03 17:27:05 +00001473 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1474 width, height, 1, format, type)) {
1475 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001476 return;
1477 }
1478
1479 destTex = texUnit->CurrentD[2]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001480 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001481
Brian Paulc3f0a511999-11-03 17:27:05 +00001482 if (width == 0 || height == 0 || !pixels)
1483 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001484
Brian Paulc3f0a511999-11-03 17:27:05 +00001485
1486 /*
1487 * Replace the texture subimage
1488 */
1489 {
1490 const GLint texComponents = components_in_intformat(destTex->Format);
1491 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001492 const GLint xoffsetb = xoffset + destTex->Border;
1493 const GLint yoffsetb = yoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001494 GLubyte *dst = destTex->Data
1495 + (yoffsetb * destTex->Width + xoffsetb) * texComponents;
1496 if (texFormat == GL_COLOR_INDEX) {
1497 /* color index texture */
1498 const GLint stride = destTex->Width * sizeof(GLubyte);
1499 GLint row;
1500 for (row = 0; row < height; row++) {
1501 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1502 width, height, format, type, 0, row, 0);
1503 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1504 type, src, &ctx->Unpack, GL_TRUE);
1505 dst += stride;
Brian Paul64a79b21999-10-22 10:43:35 +00001506 }
1507 }
jtgafb833d1999-08-19 00:55:39 +00001508 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001509 /* color texture */
1510 const GLint stride = destTex->Width * texComponents * sizeof(GLubyte);
1511 GLint row;
1512 for (row = 0; row < height; row++) {
1513 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1514 width, height, format, type, 0, row, 0);
1515 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1516 format, type, src, &ctx->Unpack, GL_TRUE);
1517 dst += stride;
jtgafb833d1999-08-19 00:55:39 +00001518 }
jtgafb833d1999-08-19 00:55:39 +00001519 }
1520 }
jtgafb833d1999-08-19 00:55:39 +00001521
Brian Paulc3f0a511999-11-03 17:27:05 +00001522 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1523
1524 /*
1525 * Inform device driver of texture image change.
1526 */
1527 if (ctx->Driver.TexSubImage) {
1528 (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2],
1529 level, xoffset, yoffset, width, height,
1530 texUnit->CurrentD[2]->Image[level]->IntFormat,
1531 destTex );
1532 }
1533 else {
1534 if (ctx->Driver.TexImage) {
1535 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2],
1536 level,
1537 texUnit->CurrentD[2]->Image[level]->IntFormat,
1538 destTex );
jtgafb833d1999-08-19 00:55:39 +00001539 }
jtgafb833d1999-08-19 00:55:39 +00001540 }
1541}
1542
1543
1544
Brian Paulfbd8f211999-11-11 01:22:25 +00001545void
1546_mesa_TexSubImage3D( GLenum target, GLint level,
1547 GLint xoffset, GLint yoffset, GLint zoffset,
1548 GLsizei width, GLsizei height, GLsizei depth,
1549 GLenum format, GLenum type,
1550 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001551{
Brian Paulfbd8f211999-11-11 01:22:25 +00001552 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001553 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1554 struct gl_texture_image *destTex;
1555
Brian Paulc3f0a511999-11-03 17:27:05 +00001556 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1557 width, height, depth, format, type)) {
1558 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001559 return;
1560 }
1561
1562 destTex = texUnit->CurrentD[3]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001563 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001564
Brian Paulc3f0a511999-11-03 17:27:05 +00001565 if (width == 0 || height == 0 || height == 0 || !pixels)
1566 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001567
Brian Paulc3f0a511999-11-03 17:27:05 +00001568 /*
1569 * Replace the texture subimage
1570 */
1571 {
1572 const GLint texComponents = components_in_intformat(destTex->Format);
1573 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001574 const GLint xoffsetb = xoffset + destTex->Border;
1575 const GLint yoffsetb = yoffset + destTex->Border;
1576 const GLint zoffsetb = zoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001577 GLint dstRectArea = destTex->Width * destTex->Height;
1578 GLubyte *dst = destTex->Data
1579 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
1580 * texComponents;
jtgafb833d1999-08-19 00:55:39 +00001581
Brian Paulc3f0a511999-11-03 17:27:05 +00001582 if (texFormat == GL_COLOR_INDEX) {
1583 /* color index texture */
1584 const GLint stride = destTex->Width * sizeof(GLubyte);
1585 GLint img, row;
1586 for (img = 0; img < depth; img++) {
1587 for (row = 0; row < height; row++) {
1588 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1589 width, height, format, type, img, row, 0);
1590 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1591 type, src, &ctx->Unpack, GL_TRUE);
1592 dst += stride;
1593 }
jtgafb833d1999-08-19 00:55:39 +00001594 }
1595 }
1596 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001597 /* color texture */
1598 const GLint stride = destTex->Width * texComponents * sizeof(GLubyte);
1599 GLint img, row;
1600 for (img = 0; img < depth; img++) {
1601 for (row = 0; row < height; row++) {
1602 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1603 width, height, format, type, img, row, 0);
1604 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1605 format, type, src, &ctx->Unpack, GL_TRUE);
1606 dst += stride;
1607 }
jtgafb833d1999-08-19 00:55:39 +00001608 }
jtgafb833d1999-08-19 00:55:39 +00001609 }
1610 }
jtgafb833d1999-08-19 00:55:39 +00001611
Brian Paulc3f0a511999-11-03 17:27:05 +00001612 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1613
1614 /*
1615 * Inform device driver of texture image change.
1616 */
1617 /* XXX todo */
jtgafb833d1999-08-19 00:55:39 +00001618}
1619
1620
1621
1622/*
1623 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00001624 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00001625 * Input: ctx - the context
1626 * x, y - lower left corner
1627 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00001628 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00001629 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001630static GLubyte *
1631read_color_image( GLcontext *ctx, GLint x, GLint y,
1632 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00001633{
Brian Paulc3f0a511999-11-03 17:27:05 +00001634 GLint stride, i;
1635 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00001636
Brian Paul959f8022000-03-19 01:10:11 +00001637 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00001638 if (!image)
jtgafb833d1999-08-19 00:55:39 +00001639 return NULL;
jtgafb833d1999-08-19 00:55:39 +00001640
1641 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001642 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1643 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001644
Brian Paulc3f0a511999-11-03 17:27:05 +00001645 dst = image;
1646 stride = width * 4 * sizeof(GLubyte);
1647 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00001648 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1649 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00001650 dst += stride;
1651 }
jtgafb833d1999-08-19 00:55:39 +00001652
Brian Paulcea0e8e1999-11-25 17:36:48 +00001653 /* Read from draw buffer (the default) */
1654 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1655 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001656
1657 return image;
1658}
1659
1660
1661
Brian Paulfbd8f211999-11-11 01:22:25 +00001662void
1663_mesa_CopyTexImage1D( GLenum target, GLint level,
1664 GLenum internalFormat,
1665 GLint x, GLint y,
1666 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001667{
Brian Paulfbd8f211999-11-11 01:22:25 +00001668 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001669 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00001670
Brian Paulc3f0a511999-11-03 17:27:05 +00001671 if (!copytexture_error_check(ctx, 1, target, level, internalFormat,
1672 width, 1, border)) {
1673 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
1674 if (!image) {
1675 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1676 return;
1677 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001678 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulfbd8f211999-11-11 01:22:25 +00001679 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001680 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001681 }
jtgafb833d1999-08-19 00:55:39 +00001682}
1683
1684
1685
Brian Paulfbd8f211999-11-11 01:22:25 +00001686void
1687_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1688 GLint x, GLint y, GLsizei width, GLsizei height,
1689 GLint border )
jtgafb833d1999-08-19 00:55:39 +00001690{
Brian Paulfbd8f211999-11-11 01:22:25 +00001691 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001692 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00001693
Brian Paulc3f0a511999-11-03 17:27:05 +00001694 if (!copytexture_error_check(ctx, 2, target, level, internalFormat,
1695 width, height, border)) {
1696 GLubyte *image = read_color_image( ctx, x, y, width, height );
1697 if (!image) {
1698 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1699 return;
1700 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001701 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulc3f0a511999-11-03 17:27:05 +00001702 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001703 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001704 }
jtgafb833d1999-08-19 00:55:39 +00001705}
1706
1707
1708
jtgafb833d1999-08-19 00:55:39 +00001709/*
1710 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00001711 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001712static void
1713copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
1714 GLint width, GLint height,
1715 GLint srcx, GLint srcy,
1716 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00001717{
Brian Paulc3f0a511999-11-03 17:27:05 +00001718 static struct gl_pixelstore_attrib packing = {
1719 1, /* Alignment */
1720 0, /* RowLength */
1721 0, /* SkipPixels */
1722 0, /* SkipRows */
1723 0, /* ImageHeight */
1724 0, /* SkipImages */
1725 GL_FALSE, /* SwapBytes */
1726 GL_FALSE /* LsbFirst */
1727 };
1728
1729 GLint i;
jtgafb833d1999-08-19 00:55:39 +00001730 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00001731 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00001732
Brian Paul91baaa31999-10-17 23:24:16 +00001733 /* dst[xyz] may be negative if we have a texture border! */
1734 dstx += dest->Border;
1735 dsty += dest->Border;
1736 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00001737 texwidth = dest->Width;
1738 texheight = dest->Height;
1739 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00001740 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00001741 format = dest->Format;
1742 components = components_in_intformat( format );
1743
1744 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001745 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1746 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001747
Brian Paulc3f0a511999-11-03 17:27:05 +00001748 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00001749 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00001750 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00001751 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00001752 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
1753 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
1754 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
1755 &packing, GL_TRUE);
1756 }
jtgafb833d1999-08-19 00:55:39 +00001757
Brian Paulcea0e8e1999-11-25 17:36:48 +00001758 /* Read from draw buffer (the default) */
1759 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1760 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001761}
1762
1763
1764
1765
Brian Paulfbd8f211999-11-11 01:22:25 +00001766void
1767_mesa_CopyTexSubImage1D( GLenum target, GLint level,
1768 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00001769{
Brian Paulfbd8f211999-11-11 01:22:25 +00001770 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001771 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00001772
Brian Paulc3f0a511999-11-03 17:27:05 +00001773 if (!copytexsubimage_error_check(ctx, 1, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001774 xoffset, 0, 0, width, 1)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001775 struct gl_texture_unit *texUnit;
1776 struct gl_texture_image *teximage;
1777 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1778 teximage = texUnit->CurrentD[1]->Image[level];
1779 assert(teximage);
jtgafb833d1999-08-19 00:55:39 +00001780 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001781 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
1782 /* tell driver about the change */
jtgafb833d1999-08-19 00:55:39 +00001783 if (ctx->Driver.TexImage) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001784 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1785 texUnit->CurrentD[1],
1786 level, teximage->IntFormat, teximage );
jtgafb833d1999-08-19 00:55:39 +00001787 }
1788 }
1789 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001790}
1791
1792
1793
Brian Paulfbd8f211999-11-11 01:22:25 +00001794void
1795_mesa_CopyTexSubImage2D( GLenum target, GLint level,
1796 GLint xoffset, GLint yoffset,
1797 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001798{
Brian Paulfbd8f211999-11-11 01:22:25 +00001799 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001800 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
1801
1802 if (!copytexsubimage_error_check(ctx, 2, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001803 xoffset, yoffset, 0, width, height)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001804 struct gl_texture_unit *texUnit;
1805 struct gl_texture_image *teximage;
1806 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1807 teximage = texUnit->CurrentD[2]->Image[level];
1808 assert(teximage);
1809 if (teximage->Data) {
1810 copy_tex_sub_image(ctx, teximage, width, height,
1811 x, y, xoffset, yoffset, 0);
1812 /* tell driver about the change */
1813 if (ctx->Driver.TexImage) {
1814 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
1815 texUnit->CurrentD[2],
1816 level, teximage->IntFormat, teximage );
1817 }
1818 }
1819 }
1820}
1821
1822
1823
Brian Paulfbd8f211999-11-11 01:22:25 +00001824void
1825_mesa_CopyTexSubImage3D( GLenum target, GLint level,
1826 GLint xoffset, GLint yoffset, GLint zoffset,
1827 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001828{
Brian Paulfbd8f211999-11-11 01:22:25 +00001829 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001830 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
1831
1832 if (!copytexsubimage_error_check(ctx, 3, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001833 xoffset, yoffset, zoffset, width, height)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001834 struct gl_texture_unit *texUnit;
1835 struct gl_texture_image *teximage;
1836 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1837 teximage = texUnit->CurrentD[3]->Image[level];
1838 assert(teximage);
1839 if (teximage->Data) {
1840 copy_tex_sub_image(ctx, teximage, width, height,
1841 x, y, xoffset, yoffset, zoffset);
1842 /* tell driver about the change */
1843 if (ctx->Driver.TexImage) {
1844 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
1845 texUnit->CurrentD[3],
1846 level, teximage->IntFormat, teximage );
1847 }
1848 }
jtgafb833d1999-08-19 00:55:39 +00001849 }
1850}
1851