blob: d52b051d7fa90a2a33964d5f4d899ddff0ef3160 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001
2/*
3 * Mesa 3-D graphics library
Brian Paulfbd8f211999-11-11 01:22:25 +00004 * Version: 3.3
jtgafb833d1999-08-19 00:55:39 +00005 *
Brian Paul663049a2000-01-31 23:10:16 +00006 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
jtgafb833d1999-08-19 00:55:39 +00007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27#ifdef PC_HEADER
28#include "all.h"
29#else
Brian Paulfbd8f211999-11-11 01:22:25 +000030#include "glheader.h"
jtgafb833d1999-08-19 00:55:39 +000031#include "context.h"
32#include "image.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000033#include "mem.h"
jtgafb833d1999-08-19 00:55:39 +000034#include "mmath.h"
35#include "span.h"
36#include "teximage.h"
37#include "texstate.h"
38#include "types.h"
jtgafb833d1999-08-19 00:55:39 +000039#endif
40
41
42/*
43 * NOTES:
44 *
Brian Paulc3f0a511999-11-03 17:27:05 +000045 * Mesa's native texture datatype is GLubyte. Native formats are
46 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
47 * and GL_COLOR_INDEX.
48 * Device drivers are free to implement any internal format they want.
jtgafb833d1999-08-19 00:55:39 +000049 */
50
51
Brian Paulf7b57072000-03-20 14:37:52 +000052/*
jtgafb833d1999-08-19 00:55:39 +000053 * Compute log base 2 of n.
54 * If n isn't an exact power of two return -1.
55 * If n<0 return -1.
56 */
Brian Paulfbd8f211999-11-11 01:22:25 +000057static int
58logbase2( int n )
jtgafb833d1999-08-19 00:55:39 +000059{
60 GLint i = 1;
61 GLint log2 = 0;
62
63 if (n<0) {
64 return -1;
65 }
66
67 while ( n > i ) {
68 i *= 2;
69 log2++;
70 }
71 if (i != n) {
72 return -1;
73 }
74 else {
75 return log2;
76 }
77}
78
79
80
81/*
82 * Given an internal texture format enum or 1, 2, 3, 4 return the
83 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
Brian Paulc3f0a511999-11-03 17:27:05 +000084 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
85 * Return -1 if invalid enum.
jtgafb833d1999-08-19 00:55:39 +000086 */
Brian Paulb132e8d2000-03-23 16:23:14 +000087GLint
88_mesa_base_tex_format( GLint format )
jtgafb833d1999-08-19 00:55:39 +000089{
90 switch (format) {
91 case GL_ALPHA:
92 case GL_ALPHA4:
93 case GL_ALPHA8:
94 case GL_ALPHA12:
95 case GL_ALPHA16:
96 return GL_ALPHA;
97 case 1:
98 case GL_LUMINANCE:
99 case GL_LUMINANCE4:
100 case GL_LUMINANCE8:
101 case GL_LUMINANCE12:
102 case GL_LUMINANCE16:
103 return GL_LUMINANCE;
104 case 2:
105 case GL_LUMINANCE_ALPHA:
106 case GL_LUMINANCE4_ALPHA4:
107 case GL_LUMINANCE6_ALPHA2:
108 case GL_LUMINANCE8_ALPHA8:
109 case GL_LUMINANCE12_ALPHA4:
110 case GL_LUMINANCE12_ALPHA12:
111 case GL_LUMINANCE16_ALPHA16:
112 return GL_LUMINANCE_ALPHA;
113 case GL_INTENSITY:
114 case GL_INTENSITY4:
115 case GL_INTENSITY8:
116 case GL_INTENSITY12:
117 case GL_INTENSITY16:
118 return GL_INTENSITY;
119 case 3:
120 case GL_RGB:
121 case GL_R3_G3_B2:
122 case GL_RGB4:
123 case GL_RGB5:
124 case GL_RGB8:
125 case GL_RGB10:
126 case GL_RGB12:
127 case GL_RGB16:
128 return GL_RGB;
129 case 4:
130 case GL_RGBA:
131 case GL_RGBA2:
132 case GL_RGBA4:
133 case GL_RGB5_A1:
134 case GL_RGBA8:
135 case GL_RGB10_A2:
136 case GL_RGBA12:
137 case GL_RGBA16:
138 return GL_RGBA;
139 case GL_COLOR_INDEX:
140 case GL_COLOR_INDEX1_EXT:
141 case GL_COLOR_INDEX2_EXT:
142 case GL_COLOR_INDEX4_EXT:
143 case GL_COLOR_INDEX8_EXT:
144 case GL_COLOR_INDEX12_EXT:
145 case GL_COLOR_INDEX16_EXT:
146 return GL_COLOR_INDEX;
147 default:
148 return -1; /* error */
149 }
150}
151
152
153
154/*
155 * Given an internal texture format enum or 1, 2, 3, 4 return the
156 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
157 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
158 * number of components for the format. Return -1 if invalid enum.
159 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000160static GLint
161components_in_intformat( GLint format )
jtgafb833d1999-08-19 00:55:39 +0000162{
163 switch (format) {
164 case GL_ALPHA:
165 case GL_ALPHA4:
166 case GL_ALPHA8:
167 case GL_ALPHA12:
168 case GL_ALPHA16:
169 return 1;
170 case 1:
171 case GL_LUMINANCE:
172 case GL_LUMINANCE4:
173 case GL_LUMINANCE8:
174 case GL_LUMINANCE12:
175 case GL_LUMINANCE16:
176 return 1;
177 case 2:
178 case GL_LUMINANCE_ALPHA:
179 case GL_LUMINANCE4_ALPHA4:
180 case GL_LUMINANCE6_ALPHA2:
181 case GL_LUMINANCE8_ALPHA8:
182 case GL_LUMINANCE12_ALPHA4:
183 case GL_LUMINANCE12_ALPHA12:
184 case GL_LUMINANCE16_ALPHA16:
185 return 2;
186 case GL_INTENSITY:
187 case GL_INTENSITY4:
188 case GL_INTENSITY8:
189 case GL_INTENSITY12:
190 case GL_INTENSITY16:
191 return 1;
192 case 3:
193 case GL_RGB:
194 case GL_R3_G3_B2:
195 case GL_RGB4:
196 case GL_RGB5:
197 case GL_RGB8:
198 case GL_RGB10:
199 case GL_RGB12:
200 case GL_RGB16:
201 return 3;
202 case 4:
203 case GL_RGBA:
204 case GL_RGBA2:
205 case GL_RGBA4:
206 case GL_RGB5_A1:
207 case GL_RGBA8:
208 case GL_RGB10_A2:
209 case GL_RGBA12:
210 case GL_RGBA16:
211 return 4;
212 case GL_COLOR_INDEX:
213 case GL_COLOR_INDEX1_EXT:
214 case GL_COLOR_INDEX2_EXT:
215 case GL_COLOR_INDEX4_EXT:
216 case GL_COLOR_INDEX8_EXT:
217 case GL_COLOR_INDEX12_EXT:
218 case GL_COLOR_INDEX16_EXT:
219 return 1;
220 default:
221 return -1; /* error */
222 }
223}
224
225
226
jtgafb833d1999-08-19 00:55:39 +0000227/*
228 * Examine the texImage->Format field and set the Red, Green, Blue, etc
229 * texel component sizes to default values.
230 * These fields are set only here by core Mesa but device drivers may
231 * overwritting these fields to indicate true texel resolution.
232 */
Brian Paulfbd8f211999-11-11 01:22:25 +0000233static void
234set_teximage_component_sizes( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000235{
236 switch (texImage->Format) {
237 case GL_ALPHA:
238 texImage->RedBits = 0;
239 texImage->GreenBits = 0;
240 texImage->BlueBits = 0;
241 texImage->AlphaBits = 8;
242 texImage->IntensityBits = 0;
243 texImage->LuminanceBits = 0;
244 texImage->IndexBits = 0;
245 break;
246 case GL_LUMINANCE:
247 texImage->RedBits = 0;
248 texImage->GreenBits = 0;
249 texImage->BlueBits = 0;
250 texImage->AlphaBits = 0;
251 texImage->IntensityBits = 0;
252 texImage->LuminanceBits = 8;
253 texImage->IndexBits = 0;
254 break;
255 case GL_LUMINANCE_ALPHA:
256 texImage->RedBits = 0;
257 texImage->GreenBits = 0;
258 texImage->BlueBits = 0;
259 texImage->AlphaBits = 8;
260 texImage->IntensityBits = 0;
261 texImage->LuminanceBits = 8;
262 texImage->IndexBits = 0;
263 break;
264 case GL_INTENSITY:
265 texImage->RedBits = 0;
266 texImage->GreenBits = 0;
267 texImage->BlueBits = 0;
268 texImage->AlphaBits = 0;
269 texImage->IntensityBits = 8;
270 texImage->LuminanceBits = 0;
271 texImage->IndexBits = 0;
272 break;
Brian Paul91baaa31999-10-17 23:24:16 +0000273 case GL_RED:
274 texImage->RedBits = 8;
275 texImage->GreenBits = 0;
276 texImage->BlueBits = 0;
277 texImage->AlphaBits = 0;
278 texImage->IntensityBits = 0;
279 texImage->LuminanceBits = 0;
280 texImage->IndexBits = 0;
281 break;
282 case GL_GREEN:
283 texImage->RedBits = 0;
284 texImage->GreenBits = 8;
285 texImage->BlueBits = 0;
286 texImage->AlphaBits = 0;
287 texImage->IntensityBits = 0;
288 texImage->LuminanceBits = 0;
289 texImage->IndexBits = 0;
290 break;
291 case GL_BLUE:
292 texImage->RedBits = 0;
293 texImage->GreenBits = 0;
294 texImage->BlueBits = 8;
295 texImage->AlphaBits = 0;
296 texImage->IntensityBits = 0;
297 texImage->LuminanceBits = 0;
298 texImage->IndexBits = 0;
299 break;
jtgafb833d1999-08-19 00:55:39 +0000300 case GL_RGB:
Brian Pauld53573d1999-10-19 20:36:20 +0000301 case GL_BGR:
jtgafb833d1999-08-19 00:55:39 +0000302 texImage->RedBits = 8;
303 texImage->GreenBits = 8;
304 texImage->BlueBits = 8;
305 texImage->AlphaBits = 0;
306 texImage->IntensityBits = 0;
307 texImage->LuminanceBits = 0;
308 texImage->IndexBits = 0;
309 break;
310 case GL_RGBA:
Brian Pauld53573d1999-10-19 20:36:20 +0000311 case GL_BGRA:
312 case GL_ABGR_EXT:
jtgafb833d1999-08-19 00:55:39 +0000313 texImage->RedBits = 8;
314 texImage->GreenBits = 8;
315 texImage->BlueBits = 8;
316 texImage->AlphaBits = 8;
317 texImage->IntensityBits = 0;
318 texImage->LuminanceBits = 0;
319 texImage->IndexBits = 0;
320 break;
321 case GL_COLOR_INDEX:
322 texImage->RedBits = 0;
323 texImage->GreenBits = 0;
324 texImage->BlueBits = 0;
325 texImage->AlphaBits = 0;
326 texImage->IntensityBits = 0;
327 texImage->LuminanceBits = 0;
328 texImage->IndexBits = 8;
329 break;
330 default:
331 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
332 }
333}
334
335
Brian Paul77ce6da2000-03-20 23:40:12 +0000336
337/*
338 * Return new gl_texture_image struct with all fields initialized to zero.
339 */
340struct gl_texture_image *
341gl_alloc_texture_image( void )
342{
343 return CALLOC_STRUCT(gl_texture_image);
344}
345
346
347
348/*
Brian Paul02938782000-03-22 17:38:11 +0000349 * Initialize most fields of a gl_texture_image struct.
Brian Paul77ce6da2000-03-20 23:40:12 +0000350 */
Brian Paul02938782000-03-22 17:38:11 +0000351static void
352init_texture_image( struct gl_texture_image *img,
353 GLsizei width, GLsizei height, GLsizei depth,
354 GLint border, GLenum internalFormat )
Brian Paul77ce6da2000-03-20 23:40:12 +0000355{
Brian Paul02938782000-03-22 17:38:11 +0000356 ASSERT(img);
357 ASSERT(!img->Data);
Brian Paulb132e8d2000-03-23 16:23:14 +0000358 img->Format = (GLenum) _mesa_base_tex_format(internalFormat);
Brian Paul77ce6da2000-03-20 23:40:12 +0000359 set_teximage_component_sizes( img );
360 img->IntFormat = (GLenum) internalFormat;
361 img->Border = border;
362 img->Width = width;
363 img->Height = height;
364 img->Depth = depth;
365 img->WidthLog2 = logbase2(width - 2 * border);
366 if (height == 1) /* 1-D texture */
367 img->HeightLog2 = 0;
368 else
369 img->HeightLog2 = logbase2(height - 2 * border);
370 if (depth == 1) /* 2-D texture */
371 img->DepthLog2 = 0;
372 else
373 img->DepthLog2 = logbase2(depth - 2 * border);
374 img->Width2 = 1 << img->WidthLog2;
375 img->Height2 = 1 << img->HeightLog2;
376 img->Depth2 = 1 << img->DepthLog2;
377 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
Brian Paul77ce6da2000-03-20 23:40:12 +0000378}
379
380
381
382void
383gl_free_texture_image( struct gl_texture_image *teximage )
384{
385 if (teximage->Data) {
386 FREE( teximage->Data );
387 teximage->Data = NULL;
388 }
389 FREE( teximage );
390}
391
392
393
jtgafb833d1999-08-19 00:55:39 +0000394/* Need this to prevent an out-of-bounds memory access when using
395 * X86 optimized code.
396 */
397#ifdef USE_X86_ASM
398# define EXTRA_BYTE 1
399#else
400# define EXTRA_BYTE 0
401#endif
402
403
Brian Paulc3f0a511999-11-03 17:27:05 +0000404
jtgafb833d1999-08-19 00:55:39 +0000405/*
Brian Paul43911c82000-03-21 00:49:33 +0000406 * Called by glTexImage[123]D. Fill in a texture image with data given
407 * by the client. All pixel transfer and unpack modes are handled here.
408 * NOTE: All texture image parameters should have already been error checked.
jtgafb833d1999-08-19 00:55:39 +0000409 */
Brian Paul43911c82000-03-21 00:49:33 +0000410static void
411make_texture_image( GLcontext *ctx,
412 struct gl_texture_image *texImage,
Brian Paulc3f0a511999-11-03 17:27:05 +0000413 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
414 const struct gl_pixelstore_attrib *unpacking)
jtgafb833d1999-08-19 00:55:39 +0000415{
Brian Paulc3f0a511999-11-03 17:27:05 +0000416 GLint components, numPixels;
Brian Paul43911c82000-03-21 00:49:33 +0000417 GLint internalFormat, width, height, depth, border;
jtgafb833d1999-08-19 00:55:39 +0000418
Brian Paul43911c82000-03-21 00:49:33 +0000419 ASSERT(ctx);
420 ASSERT(texImage);
421 ASSERT(!texImage->Data);
422 ASSERT(pixels);
423 ASSERT(unpacking);
jtgafb833d1999-08-19 00:55:39 +0000424
Brian Paul43911c82000-03-21 00:49:33 +0000425 internalFormat = texImage->IntFormat;
426 width = texImage->Width;
427 height = texImage->Height;
428 depth = texImage->Depth;
429 border = texImage->Border;
Brian Paulc3f0a511999-11-03 17:27:05 +0000430 components = components_in_intformat(internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +0000431
432 ASSERT(width > 0);
433 ASSERT(height > 0);
434 ASSERT(depth > 0);
435 ASSERT(border == 0 || border == 1);
436 ASSERT(pixels);
437 ASSERT(unpacking);
438 ASSERT(components);
439
440 numPixels = width * height * depth;
Brian Paulc3f0a511999-11-03 17:27:05 +0000441
442 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE);
Brian Paul43911c82000-03-21 00:49:33 +0000443 if (!texImage->Data)
444 return; /* out of memory */
Brian Paulc3f0a511999-11-03 17:27:05 +0000445
446 /*
447 * OK, the texture image struct has been initialized and the texture
448 * image memory has been allocated.
449 * Now fill in the texture image from the source data.
450 * This includes applying the pixel transfer operations.
451 */
452
453 /* try common 2D texture cases first */
454 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag
455 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift
456 && srcType == GL_UNSIGNED_BYTE && depth == 1) {
457
Brian Paul43911c82000-03-21 00:49:33 +0000458 if (srcFormat == internalFormat ||
459 (srcFormat == GL_LUMINANCE && internalFormat == 1) ||
460 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) ||
461 (srcFormat == GL_RGB && internalFormat == 3) ||
462 (srcFormat == GL_RGBA && internalFormat == 4)) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000463 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
464 * GL_LUMINANCE_ALPHA, etc. texture formats.
465 */
Brian Paulb7d076f2000-03-21 01:03:40 +0000466 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000467 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
468 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
469 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000470 GLubyte *dst = texImage->Data;
471 GLint dstBytesPerRow = width * components * sizeof(GLubyte);
472 if (srcStride == dstBytesPerRow) {
473 MEMCPY(dst, src, height * dstBytesPerRow);
474 }
475 else {
476 GLint i;
477 for (i = 0; i < height; i++) {
478 MEMCPY(dst, src, dstBytesPerRow);
479 src += srcStride;
480 dst += dstBytesPerRow;
481 }
482 }
Brian Paul43911c82000-03-21 00:49:33 +0000483 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000484 }
485 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) {
486 /* commonly used by Quake */
Brian Paulb7d076f2000-03-21 01:03:40 +0000487 const GLubyte *src = (const GLubyte *) _mesa_image_address(
Brian Paul43911c82000-03-21 00:49:33 +0000488 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0);
489 const GLint srcStride = _mesa_image_row_stride(unpacking, width,
490 srcFormat, srcType);
Brian Paulc3f0a511999-11-03 17:27:05 +0000491 GLubyte *dst = texImage->Data;
492 GLint i, j;
493 for (i = 0; i < height; i++) {
494 const GLubyte *s = src;
495 for (j = 0; j < width; j++) {
496 *dst++ = *s++; /*red*/
497 *dst++ = *s++; /*green*/
498 *dst++ = *s++; /*blue*/
499 s++; /*alpha*/
500 }
501 src += srcStride;
502 }
Brian Paul43911c82000-03-21 00:49:33 +0000503 return; /* all done */
Brian Paulc3f0a511999-11-03 17:27:05 +0000504 }
505 }
506
507
508 /*
509 * General case solutions
510 */
511 if (texImage->Format == GL_COLOR_INDEX) {
512 /* color index texture */
513 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
514 const GLenum dstType = GL_UNSIGNED_BYTE;
515 GLubyte *dest = texImage->Data;
516 GLint img, row;
517 for (img = 0; img < depth; img++) {
518 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000519 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000520 pixels, width, height, srcFormat, srcType, img, row, 0);
521 _mesa_unpack_index_span(ctx, width, dstType, dest,
522 srcType, source, unpacking, GL_TRUE);
523 dest += destBytesPerRow;
524 }
525 }
jtgafb833d1999-08-19 00:55:39 +0000526 }
527 else {
Brian Paulc3f0a511999-11-03 17:27:05 +0000528 /* regular, color texture */
529 const GLint destBytesPerRow = width * components * sizeof(GLubyte);
530 const GLenum dstFormat = texImage->Format;
531 GLubyte *dest = texImage->Data;
532 GLint img, row;
533 for (img = 0; img < depth; img++) {
534 for (row = 0; row < height; row++) {
Brian Paulb7d076f2000-03-21 01:03:40 +0000535 const GLvoid *source = _mesa_image_address(unpacking,
Brian Paulc3f0a511999-11-03 17:27:05 +0000536 pixels, width, height, srcFormat, srcType, img, row, 0);
537 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest,
538 srcFormat, srcType, source, unpacking, GL_TRUE);
539 dest += destBytesPerRow;
540 }
541 }
jtgafb833d1999-08-19 00:55:39 +0000542 }
jtgafb833d1999-08-19 00:55:39 +0000543}
544
545
546
547/*
548 * glTexImage[123]D can accept a NULL image pointer. In this case we
549 * create a texture image with unspecified image contents per the OpenGL
Brian Paul43911c82000-03-21 00:49:33 +0000550 * spec. This function creates an empty image for the given texture image.
jtgafb833d1999-08-19 00:55:39 +0000551 */
Brian Paul43911c82000-03-21 00:49:33 +0000552static void
553make_null_texture( struct gl_texture_image *texImage )
jtgafb833d1999-08-19 00:55:39 +0000554{
555 GLint components;
jtgafb833d1999-08-19 00:55:39 +0000556 GLint numPixels;
jtgafb833d1999-08-19 00:55:39 +0000557
Brian Paul43911c82000-03-21 00:49:33 +0000558 ASSERT(texImage);
559 ASSERT(!texImage->Data);
jtgafb833d1999-08-19 00:55:39 +0000560
Brian Paul43911c82000-03-21 00:49:33 +0000561 components = components_in_intformat(texImage->IntFormat);
562 numPixels = texImage->Width * texImage->Height * texImage->Depth;
jtgafb833d1999-08-19 00:55:39 +0000563
Brian Paulbd5cdaf1999-10-13 18:42:49 +0000564 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE );
jtgafb833d1999-08-19 00:55:39 +0000565
566 /*
567 * Let's see if anyone finds this. If glTexImage2D() is called with
568 * a NULL image pointer then load the texture image with something
569 * interesting instead of leaving it indeterminate.
570 */
571 if (texImage->Data) {
Brian Paul65d54602000-03-01 23:28:20 +0000572 static const char message[8][32] = {
jtgafb833d1999-08-19 00:55:39 +0000573 " X X XXXXX XXX X ",
574 " XX XX X X X X X ",
575 " X X X X X X X ",
576 " X X XXXX XXX XXXXX ",
577 " X X X X X X ",
578 " X X X X X X X ",
579 " X X XXXXX XXX X X ",
580 " "
581 };
582
583 GLubyte *imgPtr = texImage->Data;
584 GLint i, j, k;
Brian Paul43911c82000-03-21 00:49:33 +0000585 for (i = 0; i < texImage->Height; i++) {
jtgafb833d1999-08-19 00:55:39 +0000586 GLint srcRow = 7 - i % 8;
Brian Paul43911c82000-03-21 00:49:33 +0000587 for (j = 0; j < texImage->Width; j++) {
jtgafb833d1999-08-19 00:55:39 +0000588 GLint srcCol = j % 32;
Brian Paul5b37c321999-11-05 06:43:10 +0000589 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
jtgafb833d1999-08-19 00:55:39 +0000590 for (k=0;k<components;k++) {
Brian Paul5b37c321999-11-05 06:43:10 +0000591 *imgPtr++ = (GLubyte) texel;
jtgafb833d1999-08-19 00:55:39 +0000592 }
593 }
594 }
595 }
jtgafb833d1999-08-19 00:55:39 +0000596}
597
598
599
600/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000601 * Test glTexImage[123]D() parameters for errors.
jtgafb833d1999-08-19 00:55:39 +0000602 * Input:
603 * dimensions - must be 1 or 2 or 3
604 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
605 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000606static GLboolean
607texture_error_check( GLcontext *ctx, GLenum target,
608 GLint level, GLint internalFormat,
609 GLenum format, GLenum type,
Brian Paul5b37c321999-11-05 06:43:10 +0000610 GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000611 GLint width, GLint height,
612 GLint depth, GLint border )
jtgafb833d1999-08-19 00:55:39 +0000613{
614 GLboolean isProxy;
615 GLint iformat;
616
617 if (dimensions == 1) {
Brian Paul5b37c321999-11-05 06:43:10 +0000618 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
jtgafb833d1999-08-19 00:55:39 +0000619 if (target != GL_TEXTURE_1D && !isProxy) {
620 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
621 return GL_TRUE;
622 }
623 }
624 else if (dimensions == 2) {
Brian Paul5b37c321999-11-05 06:43:10 +0000625 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
jtgafb833d1999-08-19 00:55:39 +0000626 if (target != GL_TEXTURE_2D && !isProxy) {
627 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
628 return GL_TRUE;
629 }
630 }
631 else if (dimensions == 3) {
Brian Paul5b37c321999-11-05 06:43:10 +0000632 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
jtgafb833d1999-08-19 00:55:39 +0000633 if (target != GL_TEXTURE_3D && !isProxy) {
634 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
635 return GL_TRUE;
636 }
637 }
638 else {
639 gl_problem( ctx, "bad dims in texture_error_check" );
640 return GL_TRUE;
641 }
642
643 /* Border */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000644 if (border != 0 && border != 1) {
jtgafb833d1999-08-19 00:55:39 +0000645 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000646 char message[100];
647 sprintf(message, "glTexImage%dD(border)", dimensions);
648 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000649 }
650 return GL_TRUE;
651 }
652
653 /* Width */
654 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
655 || logbase2( width - 2 * border ) < 0) {
656 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000657 char message[100];
658 sprintf(message, "glTexImage%dD(width)", dimensions);
659 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000660 }
661 return GL_TRUE;
662 }
663
664 /* Height */
665 if (dimensions >= 2) {
666 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
667 || logbase2( height - 2 * border ) < 0) {
668 if (!isProxy) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000669 char message[100];
670 sprintf(message, "glTexImage%dD(height)", dimensions);
671 gl_error(ctx, GL_INVALID_VALUE, message);
jtgafb833d1999-08-19 00:55:39 +0000672 }
Brian Paulc3f0a511999-11-03 17:27:05 +0000673 return GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +0000674 }
675 }
676
677 /* Depth */
678 if (dimensions >= 3) {
679 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
680 || logbase2( depth - 2 * border ) < 0) {
681 if (!isProxy) {
682 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
683 }
684 return GL_TRUE;
685 }
686 }
687
688 /* Level */
Brian Paul9fd2b0a2000-03-24 23:59:06 +0000689 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000690 if (!isProxy) {
691 char message[100];
692 sprintf(message, "glTexImage%dD(level)", dimensions);
693 gl_error(ctx, GL_INVALID_VALUE, message);
694 }
jtgafb833d1999-08-19 00:55:39 +0000695 return GL_TRUE;
696 }
697
Brian Paulb132e8d2000-03-23 16:23:14 +0000698 iformat = _mesa_base_tex_format( internalFormat );
jtgafb833d1999-08-19 00:55:39 +0000699 if (iformat < 0) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000700 if (!isProxy) {
701 char message[100];
702 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
703 gl_error(ctx, GL_INVALID_VALUE, message);
704 }
jtgafb833d1999-08-19 00:55:39 +0000705 return GL_TRUE;
706 }
707
Brian Paulb7d076f2000-03-21 01:03:40 +0000708 if (!_mesa_is_legal_format_and_type( format, type )) {
Brian Pauld53573d1999-10-19 20:36:20 +0000709 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
710 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
711 */
Brian Paulc3f0a511999-11-03 17:27:05 +0000712 if (!isProxy) {
713 char message[100];
714 sprintf(message, "glTexImage%dD(format or type)", dimensions);
715 gl_error(ctx, GL_INVALID_OPERATION, message);
716 }
jtgafb833d1999-08-19 00:55:39 +0000717 return GL_TRUE;
718 }
719
720 /* if we get here, the parameters are OK */
721 return GL_FALSE;
722}
723
724
725
726/*
Brian Paulc3f0a511999-11-03 17:27:05 +0000727 * Test glTexSubImage[123]D() parameters for errors.
728 * Input:
729 * dimensions - must be 1 or 2 or 3
730 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
731 */
732static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000733subtexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000734 GLenum target, GLint level,
735 GLint xoffset, GLint yoffset, GLint zoffset,
736 GLint width, GLint height, GLint depth,
737 GLenum format, GLenum type )
738{
739 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
740 struct gl_texture_image *destTex;
741
742 if (dimensions == 1) {
743 if (target != GL_TEXTURE_1D) {
744 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
745 return GL_TRUE;
746 }
747 }
748 else if (dimensions == 2) {
749 if (target != GL_TEXTURE_2D) {
750 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
751 return GL_TRUE;
752 }
753 }
754 else if (dimensions == 3) {
755 if (target != GL_TEXTURE_3D) {
756 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
757 return GL_TRUE;
758 }
759 }
760 else {
761 gl_problem( ctx, "bad dims in texture_error_check" );
762 return GL_TRUE;
763 }
764
765 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
766 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
767 return GL_TRUE;
768 }
769
770 if (width < 0) {
771 char message[100];
772 sprintf(message, "glTexSubImage%dD(width)", dimensions);
773 gl_error(ctx, GL_INVALID_VALUE, message);
774 return GL_TRUE;
775 }
776 if (height < 0 && dimensions > 1) {
777 char message[100];
778 sprintf(message, "glTexSubImage%dD(height)", dimensions);
779 gl_error(ctx, GL_INVALID_VALUE, message);
780 return GL_TRUE;
781 }
782 if (depth < 0 && dimensions > 2) {
783 char message[100];
784 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
785 gl_error(ctx, GL_INVALID_VALUE, message);
786 return GL_TRUE;
787 }
788
789 destTex = texUnit->CurrentD[2]->Image[level];
790 if (!destTex) {
791 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
792 return GL_TRUE;
793 }
794
795 if (xoffset < -((GLint)destTex->Border)) {
796 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
797 return GL_TRUE;
798 }
799 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
800 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
801 return GL_TRUE;
802 }
803 if (dimensions > 1) {
804 if (yoffset < -((GLint)destTex->Border)) {
805 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
806 return GL_TRUE;
807 }
808 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
809 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
810 return GL_TRUE;
811 }
812 }
813 if (dimensions > 2) {
814 if (zoffset < -((GLint)destTex->Border)) {
815 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
816 return GL_TRUE;
817 }
818 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
819 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
820 return GL_TRUE;
821 }
822 }
823
Brian Paulb7d076f2000-03-21 01:03:40 +0000824 if (!_mesa_is_legal_format_and_type(format, type)) {
Brian Paulc3f0a511999-11-03 17:27:05 +0000825 char message[100];
826 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
827 gl_error(ctx, GL_INVALID_ENUM, message);
828 return GL_TRUE;
829 }
830
831 return GL_FALSE;
832}
833
834
835/*
836 * Test glCopyTexImage[12]D() parameters for errors.
837 * Input: dimensions - must be 1 or 2 or 3
838 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
839 */
840static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000841copytexture_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000842 GLenum target, GLint level, GLint internalFormat,
843 GLint width, GLint height, GLint border )
844{
845 GLint iformat;
846
847 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) {
848 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" );
849 return GL_TRUE;
850 }
851
852 if (dimensions == 1 && target != GL_TEXTURE_1D) {
853 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
854 return GL_TRUE;
855 }
856 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
857 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
858 return GL_TRUE;
859 }
860
861 /* Border */
862 if (border!=0 && border!=1) {
863 char message[100];
864 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
865 gl_error(ctx, GL_INVALID_VALUE, message);
866 return GL_TRUE;
867 }
868
869 /* Width */
870 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
871 || logbase2( width - 2 * border ) < 0) {
872 char message[100];
873 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
874 gl_error(ctx, GL_INVALID_VALUE, message);
875 return GL_TRUE;
876 }
877
878 /* Height */
879 if (dimensions >= 2) {
880 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
881 || logbase2( height - 2 * border ) < 0) {
882 char message[100];
883 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
884 gl_error(ctx, GL_INVALID_VALUE, message);
885 return GL_TRUE;
886 }
887 }
888
889 /* Level */
890 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
891 char message[100];
892 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
893 gl_error(ctx, GL_INVALID_VALUE, message);
894 return GL_TRUE;
895 }
896
Brian Paulb132e8d2000-03-23 16:23:14 +0000897 iformat = _mesa_base_tex_format( internalFormat );
Brian Paulc3f0a511999-11-03 17:27:05 +0000898 if (iformat < 0) {
899 char message[100];
900 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
901 gl_error(ctx, GL_INVALID_VALUE, message);
902 return GL_TRUE;
903 }
904
905 /* if we get here, the parameters are OK */
906 return GL_FALSE;
907}
908
909
910static GLboolean
Brian Paulfbd8f211999-11-11 01:22:25 +0000911copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
Brian Paulc3f0a511999-11-03 17:27:05 +0000912 GLenum target, GLint level,
913 GLint xoffset, GLint yoffset, GLint zoffset,
Brian Paul5b37c321999-11-05 06:43:10 +0000914 GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +0000915{
916 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
917 struct gl_texture_image *teximage;
918
919 if (dimensions == 1 && target != GL_TEXTURE_1D) {
920 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
921 return GL_TRUE;
922 }
923 else if (dimensions == 2 && target != GL_TEXTURE_2D) {
924 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
925 return GL_TRUE;
926 }
927 else if (dimensions == 3 && target != GL_TEXTURE_3D) {
928 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
929 return GL_TRUE;
930 }
931
932 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
933 char message[100];
934 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
935 gl_error(ctx, GL_INVALID_VALUE, message);
936 return GL_TRUE;
937 }
938
939 if (width < 0) {
940 char message[100];
941 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
942 gl_error(ctx, GL_INVALID_VALUE, message);
943 return GL_TRUE;
944 }
945 if (dimensions > 1 && height < 0) {
946 char message[100];
947 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
948 gl_error(ctx, GL_INVALID_VALUE, message);
949 return GL_TRUE;
950 }
951
Brian Pauldf6a28d2000-02-21 16:34:21 +0000952 teximage = texUnit->CurrentD[dimensions]->Image[level];
Brian Paulc3f0a511999-11-03 17:27:05 +0000953 if (!teximage) {
954 char message[100];
955 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
956 gl_error(ctx, GL_INVALID_OPERATION, message);
957 return GL_TRUE;
958 }
959
960 if (xoffset < -((GLint)teximage->Border)) {
961 char message[100];
962 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
963 gl_error(ctx, GL_INVALID_VALUE, message);
964 return GL_TRUE;
965 }
966 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
967 char message[100];
968 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
969 gl_error(ctx, GL_INVALID_VALUE, message);
970 return GL_TRUE;
971 }
972 if (dimensions > 1) {
973 if (yoffset < -((GLint)teximage->Border)) {
974 char message[100];
975 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
976 gl_error(ctx, GL_INVALID_VALUE, message);
977 return GL_TRUE;
978 }
979 /* NOTE: we're adding the border here, not subtracting! */
980 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
981 char message[100];
982 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
983 gl_error(ctx, GL_INVALID_VALUE, message);
984 return GL_TRUE;
985 }
986 }
987
988 if (dimensions > 2) {
989 if (zoffset < -((GLint)teximage->Border)) {
990 char message[100];
991 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
992 gl_error(ctx, GL_INVALID_VALUE, message);
993 return GL_TRUE;
994 }
995 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
996 char message[100];
997 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
998 gl_error(ctx, GL_INVALID_VALUE, message);
999 return GL_TRUE;
1000 }
1001 }
1002
1003 /* if we get here, the parameters are OK */
1004 return GL_FALSE;
1005}
1006
1007
1008
1009
1010/*
jtgafb833d1999-08-19 00:55:39 +00001011 * Called from the API. Note that width includes the border.
1012 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001013void
Brian Paul43911c82000-03-21 00:49:33 +00001014_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001015 GLsizei width, GLint border, GLenum format,
1016 GLenum type, const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001017{
Brian Paulfbd8f211999-11-11 01:22:25 +00001018 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001019 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1020
1021 if (target==GL_TEXTURE_1D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001022 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001023 struct gl_texture_object *texObj;
1024 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001025
Brian Paul43911c82000-03-21 00:49:33 +00001026 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001027 format, type, 1, width, 1, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001028 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001029 }
1030
Brian Paulf7b57072000-03-20 14:37:52 +00001031 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001032 texObj = texUnit->CurrentD[1];
1033 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001034
Brian Paul02938782000-03-22 17:38:11 +00001035 if (!texImage) {
1036 texImage = gl_alloc_texture_image();
1037 texObj->Image[level] = texImage;
1038 if (!texImage) {
1039 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1040 return;
1041 }
1042 }
1043 else if (texImage->Data) {
1044 FREE(texImage->Data);
1045 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001046 }
1047
Brian Paul02938782000-03-22 17:38:11 +00001048 /* setup the teximage struct's fields */
1049 init_texture_image(texImage, width, 1, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001050
Brian Paul02938782000-03-22 17:38:11 +00001051 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001052 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001053 GLboolean retain = GL_TRUE;
1054 GLboolean success = GL_FALSE;
1055 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1056 && ctx->Driver.TexImage1D) {
1057 /* let device driver try to use raw image */
1058 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1059 type, pixels, &ctx->Unpack,
1060 texObj, texImage, &retain);
1061 }
1062 if (retain || !success) {
1063 /* make internal copy of the texture image */
1064 make_texture_image(ctx, texImage, format, type,
1065 pixels, &ctx->Unpack);
1066 if (!success && ctx->Driver.TexImage1D) {
1067 /* let device driver try to use unpacked image */
1068 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1069 GL_UNSIGNED_BYTE, texImage->Data,
1070 &_mesa_native_packing,
1071 texObj, texImage, &retain);
1072 }
1073 }
1074 if (!retain && texImage->Data) {
1075 FREE(texImage->Data);
1076 texImage->Data = NULL;
1077 }
jtgafb833d1999-08-19 00:55:39 +00001078 }
1079 else {
Brian Paul02938782000-03-22 17:38:11 +00001080 make_null_texture(texImage);
1081 if (ctx->Driver.TexImage1D) {
1082 GLboolean retain;
1083 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1084 GL_UNSIGNED_BYTE, texImage->Data,
1085 &_mesa_native_packing,
1086 texObj, texImage, &retain);
1087 }
jtgafb833d1999-08-19 00:55:39 +00001088 }
1089
Brian Paul02938782000-03-22 17:38:11 +00001090 /* state update */
1091 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001092 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001093 }
1094 else if (target==GL_PROXY_TEXTURE_1D) {
1095 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001096 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001097 format, type, 1, width, 1, 1, border )) {
1098 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1099 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1100 sizeof(struct gl_texture_image) );
1101 }
1102 }
1103 else {
1104 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
1105 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001106 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001107 ctx->Texture.Proxy1D->Image[level]->Border = border;
1108 ctx->Texture.Proxy1D->Image[level]->Width = width;
1109 ctx->Texture.Proxy1D->Image[level]->Height = 1;
1110 ctx->Texture.Proxy1D->Image[level]->Depth = 1;
1111 }
jtgafb833d1999-08-19 00:55:39 +00001112 }
1113 else {
1114 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1115 return;
1116 }
1117}
1118
1119
Brian Paulfbd8f211999-11-11 01:22:25 +00001120void
Brian Paul43911c82000-03-21 00:49:33 +00001121_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001122 GLsizei width, GLsizei height, GLint border,
1123 GLenum format, GLenum type,
1124 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001125{
Brian Paulfbd8f211999-11-11 01:22:25 +00001126 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001127 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1128
1129 if (target==GL_TEXTURE_2D) {
Brian Paulf7b57072000-03-20 14:37:52 +00001130 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001131 struct gl_texture_object *texObj;
1132 struct gl_texture_image *texImage;
Brian Paulf7b57072000-03-20 14:37:52 +00001133
Brian Paul43911c82000-03-21 00:49:33 +00001134 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001135 format, type, 2, width, height, 1, border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001136 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001137 }
1138
Brian Paulf7b57072000-03-20 14:37:52 +00001139 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001140 texObj = texUnit->CurrentD[2];
1141 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001142
Brian Paul02938782000-03-22 17:38:11 +00001143 if (!texImage) {
1144 texImage = gl_alloc_texture_image();
1145 texObj->Image[level] = texImage;
1146 if (!texImage) {
1147 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1148 return;
1149 }
1150 }
1151 else if (texImage->Data) {
1152 FREE(texImage->Data);
1153 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001154 }
1155
Brian Paul02938782000-03-22 17:38:11 +00001156 /* setup the teximage struct's fields */
1157 init_texture_image(texImage, width, height, 1, border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001158
Brian Paul02938782000-03-22 17:38:11 +00001159 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001160 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001161 GLboolean retain = GL_TRUE;
1162 GLboolean success = GL_FALSE;
1163 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1164 && ctx->Driver.TexImage2D) {
1165 /* let device driver try to use raw image */
1166 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1167 type, pixels, &ctx->Unpack,
1168 texObj, texImage, &retain);
1169 }
1170 if (retain || !success) {
1171 /* make internal copy of the texture image */
1172 make_texture_image(ctx, texImage, format, type,
1173 pixels, &ctx->Unpack);
1174 if (!success && ctx->Driver.TexImage2D) {
1175 /* let device driver try to use unpacked image */
1176 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1177 GL_UNSIGNED_BYTE, texImage->Data,
1178 &_mesa_native_packing,
1179 texObj, texImage, &retain);
1180 }
1181 }
1182 if (!retain && texImage->Data) {
1183 FREE(texImage->Data);
1184 texImage->Data = NULL;
1185 }
jtgafb833d1999-08-19 00:55:39 +00001186 }
1187 else {
Brian Paul02938782000-03-22 17:38:11 +00001188 make_null_texture(texImage);
1189 if (ctx->Driver.TexImage2D) {
1190 GLboolean retain;
1191 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1192 GL_UNSIGNED_BYTE, texImage->Data,
1193 &_mesa_native_packing,
1194 texObj, texImage, &retain);
1195 }
jtgafb833d1999-08-19 00:55:39 +00001196 }
1197
Brian Paul02938782000-03-22 17:38:11 +00001198#define OLD_DD_TEXTURE
1199#ifdef OLD_DD_TEXTURE
1200 /* XXX this will be removed in the future */
jtgafb833d1999-08-19 00:55:39 +00001201 if (ctx->Driver.TexImage) {
Brian Paul02938782000-03-22 17:38:11 +00001202 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1203 texImage );
jtgafb833d1999-08-19 00:55:39 +00001204 }
Brian Paul02938782000-03-22 17:38:11 +00001205#endif
1206
1207 /* state update */
1208 gl_put_texobj_on_dirty_list( ctx, texObj );
1209 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001210 }
1211 else if (target==GL_PROXY_TEXTURE_2D) {
1212 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001213 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001214 format, type, 2, width, height, 1, border )) {
1215 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1216 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1217 sizeof(struct gl_texture_image) );
1218 }
1219 }
1220 else {
1221 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
1222 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001223 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001224 ctx->Texture.Proxy2D->Image[level]->Border = border;
1225 ctx->Texture.Proxy2D->Image[level]->Width = width;
1226 ctx->Texture.Proxy2D->Image[level]->Height = height;
1227 ctx->Texture.Proxy2D->Image[level]->Depth = 1;
1228 }
jtgafb833d1999-08-19 00:55:39 +00001229 }
1230 else {
1231 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1232 return;
1233 }
1234}
1235
1236
1237
1238/*
1239 * Called by the API or display list executor.
1240 * Note that width and height include the border.
1241 */
Brian Paulfbd8f211999-11-11 01:22:25 +00001242void
Brian Paul43911c82000-03-21 00:49:33 +00001243_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
Brian Paulfbd8f211999-11-11 01:22:25 +00001244 GLsizei width, GLsizei height, GLsizei depth,
1245 GLint border, GLenum format, GLenum type,
1246 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001247{
Brian Paulfbd8f211999-11-11 01:22:25 +00001248 GET_CURRENT_CONTEXT(ctx);
Brian Paulf7b57072000-03-20 14:37:52 +00001249 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
jtgafb833d1999-08-19 00:55:39 +00001250
Brian Paulfbd8f211999-11-11 01:22:25 +00001251 if (target==GL_TEXTURE_3D_EXT) {
Brian Paulf7b57072000-03-20 14:37:52 +00001252 struct gl_texture_unit *texUnit;
Brian Paul02938782000-03-22 17:38:11 +00001253 struct gl_texture_object *texObj;
1254 struct gl_texture_image *texImage;
Brian Paul43911c82000-03-21 00:49:33 +00001255 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001256 format, type, 3, width, height, depth,
1257 border )) {
Brian Paulf7b57072000-03-20 14:37:52 +00001258 return; /* error in texture image was detected */
jtgafb833d1999-08-19 00:55:39 +00001259 }
1260
Brian Paulf7b57072000-03-20 14:37:52 +00001261 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
Brian Paul02938782000-03-22 17:38:11 +00001262 texObj = texUnit->CurrentD[3];
1263 texImage = texObj->Image[level];
Brian Paulf7b57072000-03-20 14:37:52 +00001264
Brian Paul02938782000-03-22 17:38:11 +00001265 if (!texImage) {
1266 texImage = gl_alloc_texture_image();
1267 texObj->Image[level] = texImage;
1268 if (!texImage) {
1269 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1270 return;
1271 }
1272 }
1273 else if (texImage->Data) {
1274 FREE(texImage->Data);
1275 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001276 }
1277
Brian Paul02938782000-03-22 17:38:11 +00001278 /* setup the teximage struct's fields */
1279 init_texture_image(texImage, width, height, depth,
1280 border, internalFormat);
Brian Paul43911c82000-03-21 00:49:33 +00001281
Brian Paul02938782000-03-22 17:38:11 +00001282 /* process the texture image */
Brian Paulc3f0a511999-11-03 17:27:05 +00001283 if (pixels) {
Brian Paul02938782000-03-22 17:38:11 +00001284 GLboolean retain = GL_TRUE;
1285 GLboolean success = GL_FALSE;
1286 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1287 && ctx->Driver.TexImage3D) {
1288 /* let device driver try to use raw image */
1289 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1290 type, pixels, &ctx->Unpack,
1291 texObj, texImage, &retain);
1292 }
1293 if (retain || !success) {
1294 /* make internal copy of the texture image */
1295 make_texture_image(ctx, texImage, format, type,
1296 pixels, &ctx->Unpack);
1297 if (!success && ctx->Driver.TexImage3D) {
1298 /* let device driver try to use unpacked image */
1299 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1300 GL_UNSIGNED_BYTE, texImage->Data,
1301 &_mesa_native_packing,
1302 texObj, texImage, &retain);
1303 }
1304 }
1305 if (!retain && texImage->Data) {
1306 FREE(texImage->Data);
1307 texImage->Data = NULL;
1308 }
jtgafb833d1999-08-19 00:55:39 +00001309 }
1310 else {
Brian Paul02938782000-03-22 17:38:11 +00001311 make_null_texture(texImage);
1312 if (ctx->Driver.TexImage3D) {
1313 GLboolean retain;
1314 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1315 GL_UNSIGNED_BYTE, texImage->Data,
1316 &_mesa_native_packing,
1317 texObj, texImage, &retain);
1318 }
jtgafb833d1999-08-19 00:55:39 +00001319 }
1320
Brian Paul02938782000-03-22 17:38:11 +00001321 /* state update */
1322 gl_put_texobj_on_dirty_list( ctx, texObj );
jtgafb833d1999-08-19 00:55:39 +00001323 ctx->NewState |= NEW_TEXTURING;
jtgafb833d1999-08-19 00:55:39 +00001324 }
1325 else if (target==GL_PROXY_TEXTURE_3D_EXT) {
1326 /* Proxy texture: check for errors and update proxy state */
Brian Paul43911c82000-03-21 00:49:33 +00001327 if (texture_error_check( ctx, target, level, internalFormat,
jtgafb833d1999-08-19 00:55:39 +00001328 format, type, 3, width, height, depth,
1329 border )) {
1330 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1331 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1332 sizeof(struct gl_texture_image) );
1333 }
1334 }
1335 else {
1336 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
1337 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
Brian Paul43911c82000-03-21 00:49:33 +00001338 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat;
jtgafb833d1999-08-19 00:55:39 +00001339 ctx->Texture.Proxy3D->Image[level]->Border = border;
1340 ctx->Texture.Proxy3D->Image[level]->Width = width;
1341 ctx->Texture.Proxy3D->Image[level]->Height = height;
1342 ctx->Texture.Proxy3D->Image[level]->Depth = depth;
1343 }
jtgafb833d1999-08-19 00:55:39 +00001344 }
1345 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001346 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
jtgafb833d1999-08-19 00:55:39 +00001347 return;
1348 }
1349}
1350
1351
Brian Paul663049a2000-01-31 23:10:16 +00001352void
Brian Paul43911c82000-03-21 00:49:33 +00001353_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
Brian Paul663049a2000-01-31 23:10:16 +00001354 GLsizei width, GLsizei height, GLsizei depth,
1355 GLint border, GLenum format, GLenum type,
1356 const GLvoid *pixels )
1357{
Brian Paul43911c82000-03-21 00:49:33 +00001358 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
Brian Paul663049a2000-01-31 23:10:16 +00001359 depth, border, format, type, pixels);
1360}
1361
1362
Brian Paulf7b57072000-03-20 14:37:52 +00001363/*
1364 * Fetch a texture image from the device driver.
1365 * Store the results in the given texture object at the given mipmap level.
1366 */
1367static void
1368get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1369 const struct gl_texture_object *texObj )
1370{
1371 GLvoid *image;
1372 GLenum imgFormat, imgType;
1373 GLboolean freeImage;
1374 struct gl_texture_image *texImage;
1375 GLint destComponents, numPixels, srcBytesPerTexel;
1376
1377 if (!ctx->Driver.GetTexImage)
1378 return;
1379
1380 image = (*ctx->Driver.GetTexImage)( ctx, target, level,
1381 &imgFormat, &imgType, &freeImage);
1382 if (!image)
1383 return;
1384
1385 texImage = texObj->Image[level];
1386 ASSERT(texImage);
1387 if (!texImage)
1388 return;
1389
1390 destComponents = components_in_intformat(texImage->Format);
1391 assert(destComponents > 0);
1392 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1393 assert(numPixels > 0);
Brian Paulb7d076f2000-03-21 01:03:40 +00001394 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
Brian Paulf7b57072000-03-20 14:37:52 +00001395 assert(srcBytesPerTexel > 0);
1396
1397 if (!texImage->Data) {
1398 /* Allocate memory for the texture image data */
1399 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1400 }
1401
1402 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1403 /* We got lucky! The driver's format and type match Mesa's format. */
1404 if (texImage->Data) {
1405 MEMCPY(texImage->Data, image, numPixels * destComponents);
1406 }
1407 }
1408 else {
1409 /* Convert the texture image from the driver's format to Mesa's
1410 * internal format.
1411 */
1412 const GLint width = texImage->Width;
1413 const GLint height = texImage->Height;
1414 const GLint depth = texImage->Depth;
1415 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1416 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1417 const GLenum dstType = GL_UNSIGNED_BYTE;
1418 const GLenum dstFormat = texImage->Format;
1419 const GLubyte *srcPtr = (const GLubyte *) image;
1420 GLubyte *destPtr = texImage->Data;
1421
1422 if (texImage->Format == GL_COLOR_INDEX) {
1423 /* color index texture */
1424 GLint img, row;
1425 assert(imgFormat == GL_COLOR_INDEX);
1426 for (img = 0; img < depth; img++) {
1427 for (row = 0; row < height; row++) {
1428 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001429 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001430 destPtr += destBytesPerRow;
1431 srcPtr += srcBytesPerRow;
1432 }
1433 }
1434 }
1435 else {
1436 /* color texture */
1437 GLint img, row;
1438 for (img = 0; img < depth; img++) {
1439 for (row = 0; row < height; row++) {
1440 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
Brian Paul02938782000-03-22 17:38:11 +00001441 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
Brian Paulf7b57072000-03-20 14:37:52 +00001442 destPtr += destBytesPerRow;
1443 srcPtr += srcBytesPerRow;
1444 }
1445 }
1446 }
1447 }
1448
1449 if (freeImage)
1450 FREE(image);
1451}
1452
jtgafb833d1999-08-19 00:55:39 +00001453
Brian Paulfbd8f211999-11-11 01:22:25 +00001454void
1455_mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1456 GLenum type, GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001457{
Brian Paulfbd8f211999-11-11 01:22:25 +00001458 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001459 const struct gl_texture_object *texObj;
Brian Paulf7b57072000-03-20 14:37:52 +00001460 struct gl_texture_image *texImage;
1461 GLboolean discardImage;
jtgafb833d1999-08-19 00:55:39 +00001462
1463 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1464
1465 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1466 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1467 return;
1468 }
1469
Brian Paulb7d076f2000-03-21 01:03:40 +00001470 if (_mesa_sizeof_type(type) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001471 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1472 return;
1473 }
1474
Brian Paulb7d076f2000-03-21 01:03:40 +00001475 if (_mesa_components_in_format(format) <= 0) {
jtgafb833d1999-08-19 00:55:39 +00001476 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1477 return;
1478 }
1479
1480 if (!pixels)
Brian Paulf7b57072000-03-20 14:37:52 +00001481 return;
jtgafb833d1999-08-19 00:55:39 +00001482
1483 switch (target) {
1484 case GL_TEXTURE_1D:
1485 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1486 break;
1487 case GL_TEXTURE_2D:
1488 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1489 break;
1490 case GL_TEXTURE_3D:
1491 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1492 break;
1493 default:
1494 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1495 return;
1496 }
1497
Brian Paulf7b57072000-03-20 14:37:52 +00001498 texImage = texObj->Image[level];
1499 if (!texImage) {
1500 /* invalid mipmap level */
1501 return;
1502 }
1503
1504 if (!texImage->Data) {
1505 /* try to get the texture image from the device driver */
1506 get_teximage_from_driver(ctx, target, level, texObj);
1507 discardImage = GL_TRUE;
1508 }
1509 else {
1510 discardImage = GL_FALSE;
1511 }
1512
1513 if (texImage->Data) {
jtgafb833d1999-08-19 00:55:39 +00001514 GLint width = texImage->Width;
1515 GLint height = texImage->Height;
1516 GLint row;
1517
1518 for (row = 0; row < height; row++) {
1519 /* compute destination address in client memory */
Brian Paulb7d076f2000-03-21 01:03:40 +00001520 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
jtgafb833d1999-08-19 00:55:39 +00001521 width, height,
1522 format, type, 0, row, 0);
1523
1524 assert(dest);
1525 if (texImage->Format == GL_RGBA) {
1526 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
Brian Paulb7d076f2000-03-21 01:03:40 +00001527 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1528 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001529 }
1530 else {
1531 /* fetch RGBA row from texture image then pack it in client mem */
1532 GLubyte rgba[MAX_WIDTH][4];
1533 GLint i;
1534 const GLubyte *src;
1535 switch (texImage->Format) {
1536 case GL_ALPHA:
1537 src = texImage->Data + row * width * sizeof(GLubyte);
1538 for (i = 0; i < width; i++) {
1539 rgba[i][RCOMP] = 255;
1540 rgba[i][GCOMP] = 255;
1541 rgba[i][BCOMP] = 255;
1542 rgba[i][ACOMP] = src[i];
1543 }
1544 break;
1545 case GL_LUMINANCE:
1546 src = texImage->Data + row * width * sizeof(GLubyte);
1547 for (i = 0; i < width; i++) {
1548 rgba[i][RCOMP] = src[i];
1549 rgba[i][GCOMP] = src[i];
1550 rgba[i][BCOMP] = src[i];
1551 rgba[i][ACOMP] = 255;
1552 }
1553 break;
1554 case GL_LUMINANCE_ALPHA:
1555 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1556 for (i = 0; i < width; i++) {
1557 rgba[i][RCOMP] = src[i*2+0];
1558 rgba[i][GCOMP] = src[i*2+0];
1559 rgba[i][BCOMP] = src[i*2+0];
1560 rgba[i][ACOMP] = src[i*2+1];
1561 }
1562 break;
1563 case GL_INTENSITY:
1564 src = texImage->Data + row * width * sizeof(GLubyte);
1565 for (i = 0; i < width; i++) {
1566 rgba[i][RCOMP] = src[i];
1567 rgba[i][GCOMP] = src[i];
1568 rgba[i][BCOMP] = src[i];
1569 rgba[i][ACOMP] = 255;
1570 }
1571 break;
1572 case GL_RGB:
1573 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1574 for (i = 0; i < width; i++) {
1575 rgba[i][RCOMP] = src[i*3+0];
1576 rgba[i][GCOMP] = src[i*3+1];
1577 rgba[i][BCOMP] = src[i*3+2];
1578 rgba[i][ACOMP] = 255;
1579 }
1580 break;
1581 case GL_RGBA:
1582 /* this special case should have been handled above! */
1583 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1584 break;
1585 case GL_COLOR_INDEX:
1586 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1587 break;
1588 default:
1589 gl_problem( ctx, "bad format in gl_GetTexImage" );
1590 }
Brian Paulb7d076f2000-03-21 01:03:40 +00001591 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1592 format, type, dest, &ctx->Pack, GL_TRUE );
jtgafb833d1999-08-19 00:55:39 +00001593 }
1594 }
Brian Paulf7b57072000-03-20 14:37:52 +00001595
1596 /* if we got the teximage from the device driver we'll discard it now */
1597 if (discardImage) {
1598 FREE(texImage->Data);
1599 texImage->Data = NULL;
1600 }
jtgafb833d1999-08-19 00:55:39 +00001601 }
1602}
1603
1604
1605
Brian Paulfbd8f211999-11-11 01:22:25 +00001606void
1607_mesa_TexSubImage1D( GLenum target, GLint level,
1608 GLint xoffset, GLsizei width,
1609 GLenum format, GLenum type,
1610 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001611{
Brian Paulfbd8f211999-11-11 01:22:25 +00001612 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001613 struct gl_texture_unit *texUnit;
1614 struct gl_texture_object *texObj;
1615 struct gl_texture_image *texImage;
1616 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001617
Brian Paulc3f0a511999-11-03 17:27:05 +00001618 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1619 width, 1, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001620 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001621 }
1622
Brian Paul02938782000-03-22 17:38:11 +00001623 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1624 texObj = texUnit->CurrentD[1];
1625 texImage = texObj->Image[level];
1626 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001627
Brian Paulc3f0a511999-11-03 17:27:05 +00001628 if (width == 0 || !pixels)
1629 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001630
Brian Paulc3f0a511999-11-03 17:27:05 +00001631
Brian Paul02938782000-03-22 17:38:11 +00001632 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1633 && ctx->Driver.TexSubImage1D) {
1634 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1635 width, format, type, pixels,
1636 &ctx->Unpack, texObj, texImage );
1637 }
1638 if (!success) {
1639 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1640
1641 const GLint texComponents = components_in_intformat(texImage->Format);
1642 const GLenum texFormat = texImage->Format;
1643 const GLint xoffsetb = xoffset + texImage->Border;
1644 GLboolean retain = GL_TRUE;
1645 if (!texImage->Data) {
1646 get_teximage_from_driver( ctx, target, level, texObj );
1647 if (!texImage->Data) {
1648 make_null_texture(texImage);
1649 }
1650 if (!texImage->Data)
1651 return; /* we're really out of luck! */
1652 }
1653
Brian Paulc3f0a511999-11-03 17:27:05 +00001654 if (texFormat == GL_COLOR_INDEX) {
1655 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00001656 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1657 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1658 1, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001659 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00001660 type, src, &ctx->Unpack, GL_TRUE);
jtgafb833d1999-08-19 00:55:39 +00001661 }
1662 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001663 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00001664 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1665 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1666 1, format, type, 0, 0, 0);
1667 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1668 type, src, &ctx->Unpack, GL_TRUE);
1669 }
1670
1671 if (ctx->Driver.TexImage1D) {
1672 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1673 GL_UNSIGNED_BYTE, texImage->Data,
1674 &_mesa_native_packing, texObj, texImage,
1675 &retain );
1676 }
1677
1678 if (!retain && texImage->Data) {
1679 FREE(texImage->Data);
1680 texImage->Data = NULL;
jtgafb833d1999-08-19 00:55:39 +00001681 }
Brian Paulc3f0a511999-11-03 17:27:05 +00001682 }
jtgafb833d1999-08-19 00:55:39 +00001683
Brian Paul02938782000-03-22 17:38:11 +00001684 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
jtgafb833d1999-08-19 00:55:39 +00001685}
1686
1687
Brian Paulfbd8f211999-11-11 01:22:25 +00001688void
1689_mesa_TexSubImage2D( GLenum target, GLint level,
1690 GLint xoffset, GLint yoffset,
1691 GLsizei width, GLsizei height,
1692 GLenum format, GLenum type,
1693 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001694{
Brian Paulfbd8f211999-11-11 01:22:25 +00001695 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001696 struct gl_texture_unit *texUnit;
1697 struct gl_texture_object *texObj;
1698 struct gl_texture_image *texImage;
1699 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001700
Brian Paulc3f0a511999-11-03 17:27:05 +00001701 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
1702 width, height, 1, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001703 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001704 }
1705
Brian Paul02938782000-03-22 17:38:11 +00001706 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1707 texObj = texUnit->CurrentD[2];
1708 texImage = texObj->Image[level];
1709 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001710
Brian Paulc3f0a511999-11-03 17:27:05 +00001711 if (width == 0 || height == 0 || !pixels)
1712 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001713
Brian Paul02938782000-03-22 17:38:11 +00001714 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1715 && ctx->Driver.TexSubImage2D) {
1716 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
1717 yoffset, width, height, format, type,
1718 pixels, &ctx->Unpack, texObj, texImage );
1719 }
1720 if (!success) {
1721 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
Brian Paulc3f0a511999-11-03 17:27:05 +00001722
Brian Paul02938782000-03-22 17:38:11 +00001723 const GLint texComponents = components_in_intformat(texImage->Format);
1724 const GLenum texFormat = texImage->Format;
1725 const GLint xoffsetb = xoffset + texImage->Border;
1726 const GLint yoffsetb = yoffset + texImage->Border;
1727 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
1728 format, type);
1729 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
1730 GLboolean retain = GL_TRUE;
1731
1732 if (!texImage->Data) {
1733 get_teximage_from_driver( ctx, target, level, texObj );
1734 if (!texImage->Data) {
1735 make_null_texture(texImage);
1736 }
1737 if (!texImage->Data)
1738 return; /* we're really out of luck! */
1739 }
1740
Brian Paulc3f0a511999-11-03 17:27:05 +00001741 if (texFormat == GL_COLOR_INDEX) {
1742 /* color index texture */
Brian Paul02938782000-03-22 17:38:11 +00001743 GLubyte *dst = texImage->Data
1744 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1745 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1746 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001747 GLint row;
1748 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00001749 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
1750 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1751 src += srcStride;
1752 dst += dstStride;
Brian Paul64a79b21999-10-22 10:43:35 +00001753 }
1754 }
jtgafb833d1999-08-19 00:55:39 +00001755 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001756 /* color texture */
Brian Paul02938782000-03-22 17:38:11 +00001757 GLubyte *dst = texImage->Data
1758 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
1759 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1760 width, height, format, type, 0, 0, 0);
Brian Paulc3f0a511999-11-03 17:27:05 +00001761 GLint row;
1762 for (row = 0; row < height; row++) {
Brian Paul02938782000-03-22 17:38:11 +00001763 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1764 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1765 src += srcStride;
1766 dst += dstStride;
jtgafb833d1999-08-19 00:55:39 +00001767 }
jtgafb833d1999-08-19 00:55:39 +00001768 }
jtgafb833d1999-08-19 00:55:39 +00001769
Brian Paul02938782000-03-22 17:38:11 +00001770 if (ctx->Driver.TexImage2D) {
1771 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
1772 GL_UNSIGNED_BYTE, texImage->Data,
1773 &_mesa_native_packing, texObj, texImage,
1774 &retain);
jtgafb833d1999-08-19 00:55:39 +00001775 }
Brian Paul02938782000-03-22 17:38:11 +00001776
1777 if (!retain && texImage->Data) {
1778 FREE(texImage->Data);
1779 texImage->Data = NULL;
1780 }
1781
1782#ifdef OLD_DD_TEXTURE
1783 /* XXX this will be removed in the future */
1784 if (ctx->Driver.TexSubImage) {
1785 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
1786 xoffset, yoffset, width, height,
1787 texImage->IntFormat, texImage);
1788 }
1789 else if (ctx->Driver.TexImage) {
Brian Paul9fd2b0a2000-03-24 23:59:06 +00001790 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
Brian Paul02938782000-03-22 17:38:11 +00001791 level, texImage->IntFormat, texImage );
1792 }
1793#endif
jtgafb833d1999-08-19 00:55:39 +00001794 }
1795}
1796
1797
1798
Brian Paulfbd8f211999-11-11 01:22:25 +00001799void
1800_mesa_TexSubImage3D( GLenum target, GLint level,
1801 GLint xoffset, GLint yoffset, GLint zoffset,
1802 GLsizei width, GLsizei height, GLsizei depth,
1803 GLenum format, GLenum type,
1804 const GLvoid *pixels )
jtgafb833d1999-08-19 00:55:39 +00001805{
Brian Paulfbd8f211999-11-11 01:22:25 +00001806 GET_CURRENT_CONTEXT(ctx);
Brian Paul02938782000-03-22 17:38:11 +00001807 struct gl_texture_unit *texUnit;
1808 struct gl_texture_object *texObj;
1809 struct gl_texture_image *texImage;
1810 GLboolean success = GL_FALSE;
jtgafb833d1999-08-19 00:55:39 +00001811
Brian Paulc3f0a511999-11-03 17:27:05 +00001812 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
1813 width, height, depth, format, type)) {
Brian Paulf7b57072000-03-20 14:37:52 +00001814 return; /* error was detected */
jtgafb833d1999-08-19 00:55:39 +00001815 }
1816
Brian Paul02938782000-03-22 17:38:11 +00001817 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1818 texObj = texUnit->CurrentD[3];
1819 texImage = texObj->Image[level];
1820 assert(texImage);
jtgafb833d1999-08-19 00:55:39 +00001821
Brian Paulc3f0a511999-11-03 17:27:05 +00001822 if (width == 0 || height == 0 || height == 0 || !pixels)
1823 return; /* no-op, not an error */
jtgafb833d1999-08-19 00:55:39 +00001824
Brian Paul02938782000-03-22 17:38:11 +00001825 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1826 && ctx->Driver.TexSubImage3D) {
1827 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
1828 yoffset, zoffset, width, height, depth, format,
1829 type, pixels, &ctx->Unpack, texObj, texImage );
1830 }
1831 if (!success) {
1832 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
1833
1834 const GLint texComponents = components_in_intformat(texImage->Format);
1835 const GLenum texFormat = texImage->Format;
1836 const GLint xoffsetb = xoffset + texImage->Border;
1837 const GLint yoffsetb = yoffset + texImage->Border;
1838 const GLint zoffsetb = zoffset + texImage->Border;
1839 const GLint texWidth = texImage->Width;
1840 const GLint dstRectArea = texWidth * texImage->Height;
1841 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
1842 width, format, type);
1843 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
1844 GLboolean retain = GL_TRUE;
jtgafb833d1999-08-19 00:55:39 +00001845
Brian Paulc3f0a511999-11-03 17:27:05 +00001846 if (texFormat == GL_COLOR_INDEX) {
1847 /* color index texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00001848 GLint img, row;
1849 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00001850 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1851 width, height, format, type, img, 0, 0);
1852 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1853 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00001854 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001855 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
Brian Paul02938782000-03-22 17:38:11 +00001856 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1857 src += srcStride;
1858 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00001859 }
jtgafb833d1999-08-19 00:55:39 +00001860 }
1861 }
1862 else {
Brian Paulc3f0a511999-11-03 17:27:05 +00001863 /* color texture */
Brian Paulc3f0a511999-11-03 17:27:05 +00001864 GLint img, row;
1865 for (img = 0; img < depth; img++) {
Brian Paul02938782000-03-22 17:38:11 +00001866 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
1867 width, height, format, type, img, 0, 0);
1868 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
1869 + yoffsetb * texWidth + xoffsetb) * texComponents;
Brian Paulc3f0a511999-11-03 17:27:05 +00001870 for (row = 0; row < height; row++) {
Brian Paulc3f0a511999-11-03 17:27:05 +00001871 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
Brian Paul02938782000-03-22 17:38:11 +00001872 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
1873 src += srcStride;
1874 dst += dstStride;
Brian Paulc3f0a511999-11-03 17:27:05 +00001875 }
jtgafb833d1999-08-19 00:55:39 +00001876 }
jtgafb833d1999-08-19 00:55:39 +00001877 }
Brian Paul02938782000-03-22 17:38:11 +00001878
1879 if (ctx->Driver.TexImage3D) {
1880 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
1881 GL_UNSIGNED_BYTE, texImage->Data,
1882 &_mesa_native_packing, texObj, texImage,
1883 &retain);
1884 }
1885
1886 if (!retain && texImage->Data) {
1887 FREE(texImage->Data);
1888 texImage->Data = NULL;
1889 }
jtgafb833d1999-08-19 00:55:39 +00001890 }
jtgafb833d1999-08-19 00:55:39 +00001891}
1892
1893
1894
1895/*
1896 * Read an RGBA image from the frame buffer.
Brian Paulc3f0a511999-11-03 17:27:05 +00001897 * This is used by glCopyTexSubImage[12]D().
jtgafb833d1999-08-19 00:55:39 +00001898 * Input: ctx - the context
1899 * x, y - lower left corner
1900 * width, height - size of region to read
Brian Paulc3f0a511999-11-03 17:27:05 +00001901 * Return: pointer to block of GL_RGBA, GLubyte data.
jtgafb833d1999-08-19 00:55:39 +00001902 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001903static GLubyte *
1904read_color_image( GLcontext *ctx, GLint x, GLint y,
1905 GLsizei width, GLsizei height )
jtgafb833d1999-08-19 00:55:39 +00001906{
Brian Paulc3f0a511999-11-03 17:27:05 +00001907 GLint stride, i;
1908 GLubyte *image, *dst;
jtgafb833d1999-08-19 00:55:39 +00001909
Brian Paul959f8022000-03-19 01:10:11 +00001910 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
Brian Paulc3f0a511999-11-03 17:27:05 +00001911 if (!image)
jtgafb833d1999-08-19 00:55:39 +00001912 return NULL;
jtgafb833d1999-08-19 00:55:39 +00001913
1914 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00001915 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
1916 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00001917
Brian Paulc3f0a511999-11-03 17:27:05 +00001918 dst = image;
1919 stride = width * 4 * sizeof(GLubyte);
1920 for (i = 0; i < height; i++) {
Brian Paul3f02f901999-11-24 18:48:30 +00001921 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
1922 (GLubyte (*)[4]) dst );
Brian Paulc3f0a511999-11-03 17:27:05 +00001923 dst += stride;
1924 }
jtgafb833d1999-08-19 00:55:39 +00001925
Brian Paulcea0e8e1999-11-25 17:36:48 +00001926 /* Read from draw buffer (the default) */
1927 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
1928 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00001929
1930 return image;
1931}
1932
1933
1934
Brian Paulfbd8f211999-11-11 01:22:25 +00001935void
1936_mesa_CopyTexImage1D( GLenum target, GLint level,
1937 GLenum internalFormat,
1938 GLint x, GLint y,
1939 GLsizei width, GLint border )
jtgafb833d1999-08-19 00:55:39 +00001940{
Brian Paulfbd8f211999-11-11 01:22:25 +00001941 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001942 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
jtgafb833d1999-08-19 00:55:39 +00001943
Brian Paulf7b57072000-03-20 14:37:52 +00001944 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
1945 width, 1, border))
1946 return;
1947
1948 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1949 || !ctx->Driver.CopyTexImage1D
1950 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
1951 internalFormat, x, y, width, border))
1952 {
Brian Paulc3f0a511999-11-03 17:27:05 +00001953 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
1954 if (!image) {
1955 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
1956 return;
1957 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001958 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00001959 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001960 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001961 }
jtgafb833d1999-08-19 00:55:39 +00001962}
1963
1964
1965
Brian Paulfbd8f211999-11-11 01:22:25 +00001966void
1967_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
1968 GLint x, GLint y, GLsizei width, GLsizei height,
1969 GLint border )
jtgafb833d1999-08-19 00:55:39 +00001970{
Brian Paulfbd8f211999-11-11 01:22:25 +00001971 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00001972 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
jtgafb833d1999-08-19 00:55:39 +00001973
Brian Paulf7b57072000-03-20 14:37:52 +00001974 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
1975 width, height, border))
1976 return;
1977
1978 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
1979 || !ctx->Driver.CopyTexImage2D
1980 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
1981 internalFormat, x, y, width, height, border))
1982 {
Brian Paulc3f0a511999-11-03 17:27:05 +00001983 GLubyte *image = read_color_image( ctx, x, y, width, height );
1984 if (!image) {
1985 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
1986 return;
1987 }
Brian Paul3ab6bbe2000-02-12 17:26:15 +00001988 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
Brian Paulf7b57072000-03-20 14:37:52 +00001989 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
Brian Paulc3f0a511999-11-03 17:27:05 +00001990 FREE(image);
jtgafb833d1999-08-19 00:55:39 +00001991 }
jtgafb833d1999-08-19 00:55:39 +00001992}
1993
1994
1995
jtgafb833d1999-08-19 00:55:39 +00001996/*
1997 * Do the work of glCopyTexSubImage[123]D.
jtgafb833d1999-08-19 00:55:39 +00001998 */
Brian Paulc3f0a511999-11-03 17:27:05 +00001999static void
2000copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2001 GLint width, GLint height,
2002 GLint srcx, GLint srcy,
2003 GLint dstx, GLint dsty, GLint dstz )
jtgafb833d1999-08-19 00:55:39 +00002004{
Brian Paulc3f0a511999-11-03 17:27:05 +00002005 GLint i;
jtgafb833d1999-08-19 00:55:39 +00002006 GLint format, components, rectarea;
Brian Paul91baaa31999-10-17 23:24:16 +00002007 GLint texwidth, texheight, zoffset;
jtgafb833d1999-08-19 00:55:39 +00002008
Brian Paul91baaa31999-10-17 23:24:16 +00002009 /* dst[xyz] may be negative if we have a texture border! */
2010 dstx += dest->Border;
2011 dsty += dest->Border;
2012 dstz += dest->Border;
jtgafb833d1999-08-19 00:55:39 +00002013 texwidth = dest->Width;
2014 texheight = dest->Height;
2015 rectarea = texwidth * texheight;
Brian Paul91baaa31999-10-17 23:24:16 +00002016 zoffset = dstz * rectarea;
jtgafb833d1999-08-19 00:55:39 +00002017 format = dest->Format;
2018 components = components_in_intformat( format );
2019
2020 /* Select buffer to read from */
Brian Paulcea0e8e1999-11-25 17:36:48 +00002021 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2022 ctx->Pixel.DriverReadBuffer );
jtgafb833d1999-08-19 00:55:39 +00002023
Brian Paulc3f0a511999-11-03 17:27:05 +00002024 for (i = 0;i < height; i++) {
jtgafb833d1999-08-19 00:55:39 +00002025 GLubyte rgba[MAX_WIDTH][4];
Brian Paulc3f0a511999-11-03 17:27:05 +00002026 GLubyte *dst;
Brian Paul3f02f901999-11-24 18:48:30 +00002027 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
Brian Paulc3f0a511999-11-03 17:27:05 +00002028 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2029 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2030 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
Brian Paul02938782000-03-22 17:38:11 +00002031 &_mesa_native_packing, GL_TRUE);
Brian Paulc3f0a511999-11-03 17:27:05 +00002032 }
jtgafb833d1999-08-19 00:55:39 +00002033
Brian Paulcea0e8e1999-11-25 17:36:48 +00002034 /* Read from draw buffer (the default) */
2035 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2036 ctx->Color.DriverDrawBuffer );
jtgafb833d1999-08-19 00:55:39 +00002037}
2038
2039
2040
2041
Brian Paulfbd8f211999-11-11 01:22:25 +00002042void
2043_mesa_CopyTexSubImage1D( GLenum target, GLint level,
2044 GLint xoffset, GLint x, GLint y, GLsizei width )
jtgafb833d1999-08-19 00:55:39 +00002045{
Brian Paulfbd8f211999-11-11 01:22:25 +00002046 GET_CURRENT_CONTEXT(ctx);
jtgafb833d1999-08-19 00:55:39 +00002047 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
jtgafb833d1999-08-19 00:55:39 +00002048
Brian Paulf7b57072000-03-20 14:37:52 +00002049 if (copytexsubimage_error_check(ctx, 1, target, level,
2050 xoffset, 0, 0, width, 1))
2051 return;
2052
2053 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2054 || !ctx->Driver.CopyTexSubImage1D
2055 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2056 xoffset, x, y, width)) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002057 struct gl_texture_unit *texUnit;
2058 struct gl_texture_image *teximage;
2059 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2060 teximage = texUnit->CurrentD[1]->Image[level];
2061 assert(teximage);
jtgafb833d1999-08-19 00:55:39 +00002062 if (teximage->Data) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002063 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002064 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002065 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002066 if (ctx->Driver.TexImage) {
2067 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2068 texUnit->CurrentD[1],
2069 level, teximage->IntFormat, teximage );
2070 }
jtgafb833d1999-08-19 00:55:39 +00002071 }
2072 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002073}
2074
2075
2076
Brian Paulfbd8f211999-11-11 01:22:25 +00002077void
2078_mesa_CopyTexSubImage2D( GLenum target, GLint level,
2079 GLint xoffset, GLint yoffset,
2080 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002081{
Brian Paulfbd8f211999-11-11 01:22:25 +00002082 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002083 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2084
Brian Paulf7b57072000-03-20 14:37:52 +00002085 if (copytexsubimage_error_check(ctx, 2, target, level,
2086 xoffset, yoffset, 0, width, height))
2087 return;
2088
2089 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2090 || !ctx->Driver.CopyTexSubImage2D
2091 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2092 xoffset, yoffset, x, y, width, height )) {
Brian Paulc3f0a511999-11-03 17:27:05 +00002093 struct gl_texture_unit *texUnit;
2094 struct gl_texture_image *teximage;
2095 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2096 teximage = texUnit->CurrentD[2]->Image[level];
2097 assert(teximage);
2098 if (teximage->Data) {
2099 copy_tex_sub_image(ctx, teximage, width, height,
2100 x, y, xoffset, yoffset, 0);
Brian Paulf7b57072000-03-20 14:37:52 +00002101 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002102 /* XXX this is obsolete */
Brian Paulf7b57072000-03-20 14:37:52 +00002103 if (ctx->Driver.TexImage) {
2104 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2105 texUnit->CurrentD[2],
2106 level, teximage->IntFormat, teximage );
Brian Paulc3f0a511999-11-03 17:27:05 +00002107 }
2108 }
2109 }
2110}
2111
2112
2113
Brian Paulfbd8f211999-11-11 01:22:25 +00002114void
2115_mesa_CopyTexSubImage3D( GLenum target, GLint level,
2116 GLint xoffset, GLint yoffset, GLint zoffset,
2117 GLint x, GLint y, GLsizei width, GLsizei height )
Brian Paulc3f0a511999-11-03 17:27:05 +00002118{
Brian Paulfbd8f211999-11-11 01:22:25 +00002119 GET_CURRENT_CONTEXT(ctx);
Brian Paulc3f0a511999-11-03 17:27:05 +00002120 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2121
Brian Paulf7b57072000-03-20 14:37:52 +00002122 if (copytexsubimage_error_check(ctx, 3, target, level,
2123 xoffset, yoffset, zoffset, width, height))
2124 return;
2125
Brian Paul02938782000-03-22 17:38:11 +00002126 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
Brian Paulf7b57072000-03-20 14:37:52 +00002127 || !ctx->Driver.CopyTexSubImage3D
2128 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
Brian Paul02938782000-03-22 17:38:11 +00002129 xoffset, yoffset, zoffset, x, y, width, height )) {
2130 struct gl_texture_unit *texUnit;
2131 struct gl_texture_image *teximage;
2132 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2133 teximage = texUnit->CurrentD[3]->Image[level];
2134 assert(teximage);
2135 if (teximage->Data) {
2136 copy_tex_sub_image(ctx, teximage, width, height,
Brian Paulc3f0a511999-11-03 17:27:05 +00002137 x, y, xoffset, yoffset, zoffset);
Brian Paul02938782000-03-22 17:38:11 +00002138 /* tell driver about the change */
Brian Paul9fd2b0a2000-03-24 23:59:06 +00002139 /* XXX this is obsolete */
Brian Paul02938782000-03-22 17:38:11 +00002140 if (ctx->Driver.TexImage) {
2141 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2142 texUnit->CurrentD[3],
2143 level, teximage->IntFormat, teximage );
Brian Paulf7b57072000-03-20 14:37:52 +00002144 }
Brian Paulc3f0a511999-11-03 17:27:05 +00002145 }
jtgafb833d1999-08-19 00:55:39 +00002146 }
2147}