blob: f2b40b8c4a6ee2782bc5a67672167837a042d3fa [file] [log] [blame]
Brian Pauldf6a28d2000-02-21 16:34:21 +00001/* $Id: teximage.c,v 1.17 2000/02/21 16:34:21 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 */
449 const GLubyte *src = gl_pixel_addr_in_image(unpacking,
450 pixels, width, height, srcFormat, srcType, 0, 0, 0);
451 const GLubyte *src1 = gl_pixel_addr_in_image(unpacking,
452 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 */
471 const GLubyte *src = gl_pixel_addr_in_image(unpacking,
472 pixels, width, height, srcFormat, srcType, 0, 0, 0);
473 const GLubyte *src1 = gl_pixel_addr_in_image(unpacking,
474 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) {
588 char message[8][32] = {
589 " 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);
1319 gl_pack_rgba_span( ctx, width, (void *) src, format, type, dest,
1320 &ctx->Pack, GL_TRUE );
1321 }
1322 else {
1323 /* fetch RGBA row from texture image then pack it in client mem */
1324 GLubyte rgba[MAX_WIDTH][4];
1325 GLint i;
1326 const GLubyte *src;
1327 switch (texImage->Format) {
1328 case GL_ALPHA:
1329 src = texImage->Data + row * width * sizeof(GLubyte);
1330 for (i = 0; i < width; i++) {
1331 rgba[i][RCOMP] = 255;
1332 rgba[i][GCOMP] = 255;
1333 rgba[i][BCOMP] = 255;
1334 rgba[i][ACOMP] = src[i];
1335 }
1336 break;
1337 case GL_LUMINANCE:
1338 src = texImage->Data + row * width * sizeof(GLubyte);
1339 for (i = 0; i < width; i++) {
1340 rgba[i][RCOMP] = src[i];
1341 rgba[i][GCOMP] = src[i];
1342 rgba[i][BCOMP] = src[i];
1343 rgba[i][ACOMP] = 255;
1344 }
1345 break;
1346 case GL_LUMINANCE_ALPHA:
1347 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1348 for (i = 0; i < width; i++) {
1349 rgba[i][RCOMP] = src[i*2+0];
1350 rgba[i][GCOMP] = src[i*2+0];
1351 rgba[i][BCOMP] = src[i*2+0];
1352 rgba[i][ACOMP] = src[i*2+1];
1353 }
1354 break;
1355 case GL_INTENSITY:
1356 src = texImage->Data + row * width * sizeof(GLubyte);
1357 for (i = 0; i < width; i++) {
1358 rgba[i][RCOMP] = src[i];
1359 rgba[i][GCOMP] = src[i];
1360 rgba[i][BCOMP] = src[i];
1361 rgba[i][ACOMP] = 255;
1362 }
1363 break;
1364 case GL_RGB:
1365 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1366 for (i = 0; i < width; i++) {
1367 rgba[i][RCOMP] = src[i*3+0];
1368 rgba[i][GCOMP] = src[i*3+1];
1369 rgba[i][BCOMP] = src[i*3+2];
1370 rgba[i][ACOMP] = 255;
1371 }
1372 break;
1373 case GL_RGBA:
1374 /* this special case should have been handled above! */
1375 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1376 break;
1377 case GL_COLOR_INDEX:
1378 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1379 break;
1380 default:
1381 gl_problem( ctx, "bad format in gl_GetTexImage" );
1382 }
1383 gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1384 format, type, dest, &ctx->Pack, GL_TRUE );
1385 }
1386 }
1387 }
1388}
1389
1390
1391
Brian Paulfbd8f211999-11-11 01:22:25 +00001392void
1393_mesa_TexSubImage1D( GLenum target, GLint level,
1394 GLint xoffset, GLsizei width,
1395 GLenum format, GLenum type,
1396 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001397{
Brian Paulfbd8f211999-11-11 01:22:25 +00001398 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001399 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1400 struct gl_texture_image *destTex;
1401
Brian Paulc3f0a511999-11-03 17:27:05 +00001402 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1403 width, 1, 1, format, type)) {
1404 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001405 return;
1406 }
1407
1408 destTex = texUnit->CurrentD[1]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001409 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001410
Brian Paulc3f0a511999-11-03 17:27:05 +00001411 if (width == 0 || !pixels)
1412 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001413
Brian Paulc3f0a511999-11-03 17:27:05 +00001414
1415 /*
1416 * Replace the texture subimage
1417 */
1418 {
1419 const GLint texComponents = components_in_intformat(destTex->Format);
1420 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001421 const GLint xoffsetb = xoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001422 GLubyte *dst = destTex->Data + xoffsetb * texComponents;
1423 if (texFormat == GL_COLOR_INDEX) {
1424 /* color index texture */
1425 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1426 width, 1, format, type, 0, 0, 0);
1427 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1428 type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001429 }
1430 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001431 /* color texture */
1432 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1433 width, 1, format, type, 0, 0, 0);
1434 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1435 format, type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001436 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001437 }
jtgafb833d1999-08-19 00:55:39 +00001438
Brian Paulc3f0a511999-11-03 17:27:05 +00001439 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
jtgafb833d1999-08-19 00:55:39 +00001440
Brian Paulc3f0a511999-11-03 17:27:05 +00001441 /*
1442 * Inform device driver of texture image change.
1443 */
1444 if (ctx->Driver.TexSubImage) {
1445 (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1],
1446 level, xoffset, 0, width, 1,
1447 texUnit->CurrentD[1]->Image[level]->IntFormat,
1448 destTex );
jtgafb833d1999-08-19 00:55:39 +00001449 }
1450 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001451 if (ctx->Driver.TexImage) {
1452 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, texUnit->CurrentD[1],
1453 level,
1454 texUnit->CurrentD[1]->Image[level]->IntFormat,
1455 destTex );
jtgafb833d1999-08-19 00:55:39 +00001456 }
jtgafb833d1999-08-19 00:55:39 +00001457 }
1458}
1459
1460
Brian Paulfbd8f211999-11-11 01:22:25 +00001461void
1462_mesa_TexSubImage2D( GLenum target, GLint level,
1463 GLint xoffset, GLint yoffset,
1464 GLsizei width, GLsizei height,
1465 GLenum format, GLenum type,
1466 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001467{
Brian Paulfbd8f211999-11-11 01:22:25 +00001468 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001469 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1470 struct gl_texture_image *destTex;
1471
Brian Paulc3f0a511999-11-03 17:27:05 +00001472 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1473 width, height, 1, format, type)) {
1474 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001475 return;
1476 }
1477
1478 destTex = texUnit->CurrentD[2]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001479 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001480
Brian Paulc3f0a511999-11-03 17:27:05 +00001481 if (width == 0 || height == 0 || !pixels)
1482 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001483
Brian Paulc3f0a511999-11-03 17:27:05 +00001484
1485 /*
1486 * Replace the texture subimage
1487 */
1488 {
1489 const GLint texComponents = components_in_intformat(destTex->Format);
1490 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001491 const GLint xoffsetb = xoffset + destTex->Border;
1492 const GLint yoffsetb = yoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001493 GLubyte *dst = destTex->Data
1494 + (yoffsetb * destTex->Width + xoffsetb) * texComponents;
1495 if (texFormat == GL_COLOR_INDEX) {
1496 /* color index texture */
1497 const GLint stride = destTex->Width * sizeof(GLubyte);
1498 GLint row;
1499 for (row = 0; row < height; row++) {
1500 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1501 width, height, format, type, 0, row, 0);
1502 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1503 type, src, &ctx->Unpack, GL_TRUE);
1504 dst += stride;
Brian Paul64a79b21999-10-22 10:43:35 +00001505 }
1506 }
jtgafb833d1999-08-19 00:55:39 +00001507 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001508 /* color texture */
1509 const GLint stride = destTex->Width * texComponents * sizeof(GLubyte);
1510 GLint row;
1511 for (row = 0; row < height; row++) {
1512 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1513 width, height, format, type, 0, row, 0);
1514 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1515 format, type, src, &ctx->Unpack, GL_TRUE);
1516 dst += stride;
jtgafb833d1999-08-19 00:55:39 +00001517 }
jtgafb833d1999-08-19 00:55:39 +00001518 }
1519 }
jtgafb833d1999-08-19 00:55:39 +00001520
Brian Paulc3f0a511999-11-03 17:27:05 +00001521 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
1522
1523 /*
1524 * Inform device driver of texture image change.
1525 */
1526 if (ctx->Driver.TexSubImage) {
1527 (*ctx->Driver.TexSubImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2],
1528 level, xoffset, yoffset, width, height,
1529 texUnit->CurrentD[2]->Image[level]->IntFormat,
1530 destTex );
1531 }
1532 else {
1533 if (ctx->Driver.TexImage) {
1534 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texUnit->CurrentD[2],
1535 level,
1536 texUnit->CurrentD[2]->Image[level]->IntFormat,
1537 destTex );
jtgafb833d1999-08-19 00:55:39 +00001538 }
jtgafb833d1999-08-19 00:55:39 +00001539 }
1540}
1541
1542
1543
Brian Paulfbd8f211999-11-11 01:22:25 +00001544void
1545_mesa_TexSubImage3D( GLenum target, GLint level,
1546 GLint xoffset, GLint yoffset, GLint zoffset,
1547 GLsizei width, GLsizei height, GLsizei depth,
1548 GLenum format, GLenum type,
1549 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001550{
Brian Paulfbd8f211999-11-11 01:22:25 +00001551 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001552 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1553 struct gl_texture_image *destTex;
1554
Brian Paulc3f0a511999-11-03 17:27:05 +00001555 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1556 width, height, depth, format, type)) {
1557 /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001558 return;
1559 }
1560
1561 destTex = texUnit->CurrentD[3]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +00001562 assert(destTex);
jtgafb833d1999-08-19 00:55:39 +00001563
Brian Paulc3f0a511999-11-03 17:27:05 +00001564 if (width == 0 || height == 0 || height == 0 || !pixels)
1565 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001566
Brian Paulc3f0a511999-11-03 17:27:05 +00001567 /*
1568 * Replace the texture subimage
1569 */
1570 {
1571 const GLint texComponents = components_in_intformat(destTex->Format);
1572 const GLenum texFormat = destTex->Format;
Brian Paul91baaa31999-10-17 23:24:16 +00001573 const GLint xoffsetb = xoffset + destTex->Border;
1574 const GLint yoffsetb = yoffset + destTex->Border;
1575 const GLint zoffsetb = zoffset + destTex->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +00001576 GLint dstRectArea = destTex->Width * destTex->Height;
1577 GLubyte *dst = destTex->Data
1578 + (zoffsetb * dstRectArea + yoffsetb * destTex->Width + xoffsetb)
1579 * texComponents;
jtgafb833d1999-08-19 00:55:39 +00001580
Brian Paulc3f0a511999-11-03 17:27:05 +00001581 if (texFormat == GL_COLOR_INDEX) {
1582 /* color index texture */
1583 const GLint stride = destTex->Width * sizeof(GLubyte);
1584 GLint img, row;
1585 for (img = 0; img < depth; img++) {
1586 for (row = 0; row < height; row++) {
1587 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1588 width, height, format, type, img, row, 0);
1589 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1590 type, src, &ctx->Unpack, GL_TRUE);
1591 dst += stride;
1592 }
jtgafb833d1999-08-19 00:55:39 +00001593 }
1594 }
1595 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001596 /* color texture */
1597 const GLint stride = destTex->Width * texComponents * sizeof(GLubyte);
1598 GLint img, row;
1599 for (img = 0; img < depth; img++) {
1600 for (row = 0; row < height; row++) {
1601 const GLvoid *src = gl_pixel_addr_in_image(&ctx->Unpack, pixels,
1602 width, height, format, type, img, row, 0);
1603 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
1604 format, type, src, &ctx->Unpack, GL_TRUE);
1605 dst += stride;
1606 }
jtgafb833d1999-08-19 00:55:39 +00001607 }
jtgafb833d1999-08-19 00:55:39 +00001608 }
1609 }
jtgafb833d1999-08-19 00:55:39 +00001610
Brian Paulc3f0a511999-11-03 17:27:05 +00001611 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
1612
1613 /*
1614 * Inform device driver of texture image change.
1615 */
1616 /* XXX todo */
jtgafb833d1999-08-19 00:55:39 +00001617}
1618
1619
1620
1621/*
1622 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00001623 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00001624 * Input: ctx - the context
1625 * x, y - lower left corner
1626 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00001627 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00001628 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001629static GLubyte *
1630read_color_image( GLcontext *ctx, GLint x, GLint y,
1631 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00001632{
Brian Paulc3f0a511999-11-03 17:27:05 +00001633 GLint stride, i;
1634 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00001635
Brian Paulc3f0a511999-11-03 17:27:05 +00001636 image = MALLOC(width * height * 4 * sizeof(GLubyte));
1637 if (!image)
jtgafb833d1999-08-19 00:55:39 +00001638 return NULL;
jtgafb833d1999-08-19 00:55:39 +00001639
1640 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001641 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1642 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001643
Brian Paulc3f0a511999-11-03 17:27:05 +00001644 dst = image;
1645 stride = width * 4 * sizeof(GLubyte);
1646 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00001647 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1648 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00001649 dst += stride;
1650 }
jtgafb833d1999-08-19 00:55:39 +00001651
Brian Paulcea0e8e1999-11-25 17:36:48 +00001652 /* Read from draw buffer (the default) */
1653 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1654 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001655
1656 return image;
1657}
1658
1659
1660
Brian Paulfbd8f211999-11-11 01:22:25 +00001661void
1662_mesa_CopyTexImage1D( GLenum target, GLint level,
1663 GLenum internalFormat,
1664 GLint x, GLint y,
1665 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001666{
Brian Paulfbd8f211999-11-11 01:22:25 +00001667 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001668 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00001669
Brian Paulc3f0a511999-11-03 17:27:05 +00001670 if (!copytexture_error_check(ctx, 1, target, level, internalFormat,
1671 width, 1, border)) {
1672 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
1673 if (!image) {
1674 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1675 return;
1676 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001677 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulfbd8f211999-11-11 01:22:25 +00001678 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001679 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001680 }
jtgafb833d1999-08-19 00:55:39 +00001681}
1682
1683
1684
Brian Paulfbd8f211999-11-11 01:22:25 +00001685void
1686_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1687 GLint x, GLint y, GLsizei width, GLsizei height,
1688 GLint border )
jtgafb833d1999-08-19 00:55:39 +00001689{
Brian Paulfbd8f211999-11-11 01:22:25 +00001690 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001691 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00001692
Brian Paulc3f0a511999-11-03 17:27:05 +00001693 if (!copytexture_error_check(ctx, 2, target, level, internalFormat,
1694 width, height, border)) {
1695 GLubyte *image = read_color_image( ctx, x, y, width, height );
1696 if (!image) {
1697 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1698 return;
1699 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001700 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulc3f0a511999-11-03 17:27:05 +00001701 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001702 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001703 }
jtgafb833d1999-08-19 00:55:39 +00001704}
1705
1706
1707
jtgafb833d1999-08-19 00:55:39 +00001708/*
1709 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00001710 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001711static void
1712copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
1713 GLint width, GLint height,
1714 GLint srcx, GLint srcy,
1715 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00001716{
Brian Paulc3f0a511999-11-03 17:27:05 +00001717 static struct gl_pixelstore_attrib packing = {
1718 1, /* Alignment */
1719 0, /* RowLength */
1720 0, /* SkipPixels */
1721 0, /* SkipRows */
1722 0, /* ImageHeight */
1723 0, /* SkipImages */
1724 GL_FALSE, /* SwapBytes */
1725 GL_FALSE /* LsbFirst */
1726 };
1727
1728 GLint i;
jtgafb833d1999-08-19 00:55:39 +00001729 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00001730 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00001731
Brian Paul91baaa31999-10-17 23:24:16 +00001732 /* dst[xyz] may be negative if we have a texture border! */
1733 dstx += dest->Border;
1734 dsty += dest->Border;
1735 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00001736 texwidth = dest->Width;
1737 texheight = dest->Height;
1738 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00001739 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00001740 format = dest->Format;
1741 components = components_in_intformat( format );
1742
1743 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001744 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1745 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001746
Brian Paulc3f0a511999-11-03 17:27:05 +00001747 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00001748 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00001749 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00001750 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00001751 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
1752 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
1753 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
1754 &packing, GL_TRUE);
1755 }
jtgafb833d1999-08-19 00:55:39 +00001756
Brian Paulcea0e8e1999-11-25 17:36:48 +00001757 /* Read from draw buffer (the default) */
1758 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1759 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001760}
1761
1762
1763
1764
Brian Paulfbd8f211999-11-11 01:22:25 +00001765void
1766_mesa_CopyTexSubImage1D( GLenum target, GLint level,
1767 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00001768{
Brian Paulfbd8f211999-11-11 01:22:25 +00001769 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001770 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00001771
Brian Paulc3f0a511999-11-03 17:27:05 +00001772 if (!copytexsubimage_error_check(ctx, 1, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001773 xoffset, 0, 0, width, 1)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001774 struct gl_texture_unit *texUnit;
1775 struct gl_texture_image *teximage;
1776 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1777 teximage = texUnit->CurrentD[1]->Image[level];
1778 assert(teximage);
jtgafb833d1999-08-19 00:55:39 +00001779 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001780 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
1781 /* tell driver about the change */
jtgafb833d1999-08-19 00:55:39 +00001782 if (ctx->Driver.TexImage) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001783 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
1784 texUnit->CurrentD[1],
1785 level, teximage->IntFormat, teximage );
jtgafb833d1999-08-19 00:55:39 +00001786 }
1787 }
1788 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001789}
1790
1791
1792
Brian Paulfbd8f211999-11-11 01:22:25 +00001793void
1794_mesa_CopyTexSubImage2D( GLenum target, GLint level,
1795 GLint xoffset, GLint yoffset,
1796 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001797{
Brian Paulfbd8f211999-11-11 01:22:25 +00001798 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001799 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
1800
1801 if (!copytexsubimage_error_check(ctx, 2, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001802 xoffset, yoffset, 0, width, height)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001803 struct gl_texture_unit *texUnit;
1804 struct gl_texture_image *teximage;
1805 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1806 teximage = texUnit->CurrentD[2]->Image[level];
1807 assert(teximage);
1808 if (teximage->Data) {
1809 copy_tex_sub_image(ctx, teximage, width, height,
1810 x, y, xoffset, yoffset, 0);
1811 /* tell driver about the change */
1812 if (ctx->Driver.TexImage) {
1813 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
1814 texUnit->CurrentD[2],
1815 level, teximage->IntFormat, teximage );
1816 }
1817 }
1818 }
1819}
1820
1821
1822
Brian Paulfbd8f211999-11-11 01:22:25 +00001823void
1824_mesa_CopyTexSubImage3D( GLenum target, GLint level,
1825 GLint xoffset, GLint yoffset, GLint zoffset,
1826 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00001827{
Brian Paulfbd8f211999-11-11 01:22:25 +00001828 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00001829 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
1830
1831 if (!copytexsubimage_error_check(ctx, 3, target, level,
Brian Paul5b37c321999-11-05 06:43:10 +00001832 xoffset, yoffset, zoffset, width, height)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001833 struct gl_texture_unit *texUnit;
1834 struct gl_texture_image *teximage;
1835 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1836 teximage = texUnit->CurrentD[3]->Image[level];
1837 assert(teximage);
1838 if (teximage->Data) {
1839 copy_tex_sub_image(ctx, teximage, width, height,
1840 x, y, xoffset, yoffset, zoffset);
1841 /* tell driver about the change */
1842 if (ctx->Driver.TexImage) {
1843 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
1844 texUnit->CurrentD[3],
1845 level, teximage->IntFormat, teximage );
1846 }
1847 }
jtgafb833d1999-08-19 00:55:39 +00001848 }
1849}
1850