VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c@ 36300

Last change on this file since 36300 was 25154, checked in by vboxsync, 15 years ago

crOpenGL: fix various texture tracking issues

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 50.3 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7
8#include "state.h"
9#include "state/cr_statetypes.h"
10#include "state/cr_texture.h"
11#include "cr_pixeldata.h"
12#include "cr_string.h"
13#include "cr_mem.h"
14#include "cr_version.h"
15#include "state_internals.h"
16
17#ifndef IN_GUEST
18/*# define CR_DUMP_TEXTURES_2D*/
19#endif
20
21#ifdef CR_DUMP_TEXTURES_2D
22static int _tnum = 0;
23
24#pragma pack(1)
25typedef struct tgaheader_tag
26{
27 char idlen;
28
29 char colormap;
30
31 char imagetype;
32
33 short cm_index;
34 short cm_len;
35 char cm_entrysize;
36
37 short x, y, w, h;
38 char depth;
39 char imagedesc;
40
41} tgaheader_t;
42#pragma pack()
43
44static crDumpTGA(short w, short h, char* data)
45{
46 char fname[200];
47 tgaheader_t header;
48 FILE *out;
49
50 if (!w || !h) return;
51
52 sprintf(fname, "tex%i.tga", _tnum++);
53 out = fopen(fname, "w");
54 if (!out) crError("can't create %s!", fname);
55
56 header.idlen = 0;
57 header.colormap = 0;
58 header.imagetype = 2;
59 header.cm_index = 0;
60 header.cm_len = 0;
61 header.cm_entrysize = 0;
62 header.x = 0;
63 header.y = 0;
64 header.w = w;
65 header.h = h;
66 header.depth = 32;
67 header.imagedesc = 0x08;
68 fwrite(&header, sizeof(header), 1, out);
69
70 fwrite(data, w*h*4, 1, out);
71
72 fclose(out);
73}
74#endif
75
76
77static int
78bitcount(int value)
79{
80 int bits = 0;
81 for (; value > 0; value >>= 1) {
82 if (value & 0x1)
83 bits++;
84 }
85 return bits;
86}
87
88
89/**
90 * Return 1 if the target is a proxy target, 0 otherwise.
91 */
92static GLboolean
93IsProxyTarget(GLenum target)
94{
95 return (target == GL_PROXY_TEXTURE_1D ||
96 target == GL_PROXY_TEXTURE_2D ||
97 target == GL_PROXY_TEXTURE_3D ||
98 target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
99 target == GL_PROXY_TEXTURE_CUBE_MAP);
100}
101
102
103/**
104 * Test if a texture width, height or depth is legal.
105 * It must be true that 0 <= size <= max.
106 * Furthermore, if the ARB_texture_non_power_of_two extension isn't
107 * present, size must also be a power of two.
108 */
109static GLboolean
110isLegalSize(CRContext *g, GLsizei size, GLsizei max)
111{
112 if (size < 0 || size > max)
113 return GL_FALSE;
114 if (!g->extensions.ARB_texture_non_power_of_two) {
115 /* check for power of two */
116 if (size > 0 && bitcount(size) != 1)
117 return GL_FALSE;
118 }
119 return GL_TRUE;
120}
121
122
123/**
124 * Return the max legal texture level parameter for the given target.
125 */
126static GLint
127MaxTextureLevel(CRContext *g, GLenum target)
128{
129 CRTextureState *t = &(g->texture);
130 switch (target) {
131 case GL_TEXTURE_1D:
132 case GL_PROXY_TEXTURE_1D:
133 case GL_TEXTURE_2D:
134 case GL_PROXY_TEXTURE_2D:
135 return t->maxLevel;
136 case GL_TEXTURE_3D:
137 case GL_PROXY_TEXTURE_3D:
138 return t->max3DLevel;
139 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
140 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
141 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
142 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
143 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
144 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
145 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
146 return t->maxCubeMapLevel;
147 case GL_TEXTURE_RECTANGLE_NV:
148 case GL_PROXY_TEXTURE_RECTANGLE_NV:
149 return t->maxRectLevel;
150 default:
151 return 0;
152 }
153}
154
155
156/**
157 * If GL_GENERATE_MIPMAP_SGIS is true and we modify the base level texture
158 * image we have to finish the mipmap.
159 * All we really have to do is fill in the width/height/format/etc for the
160 * remaining image levels. The image data doesn't matter here - the back-
161 * end OpenGL library will fill those in.
162 */
163static void
164generate_mipmap(CRTextureObj *tobj, GLenum target)
165{
166 CRTextureLevel *levels;
167 GLint level, width, height, depth;
168
169 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
170 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
171 levels = tobj->level[target - GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB];
172 }
173 else {
174 levels = tobj->level[0];
175 }
176
177 width = levels[tobj->baseLevel].width;
178 height = levels[tobj->baseLevel].height;
179 depth = levels[tobj->baseLevel].depth;
180
181 for (level = tobj->baseLevel + 1; level <= tobj->maxLevel; level++)
182 {
183 if (width > 1)
184 width /= 2;
185 if (height > 1)
186 height /= 2;
187 if (depth > 1)
188 depth /= 2;
189 levels[level].width = width;
190 levels[level].height = height;
191 levels[level].depth = depth;
192 levels[level].internalFormat = levels[tobj->baseLevel].internalFormat;
193 levels[level].format = levels[tobj->baseLevel].format;
194 levels[level].type = levels[tobj->baseLevel].type;
195#ifdef CR_ARB_texture_compression
196 levels[level].compressed = levels[tobj->baseLevel].compressed;
197#endif
198 levels[level].texFormat = levels[tobj->baseLevel].texFormat;
199 if (width == 1 && height == 1 && depth == 1)
200 break;
201 }
202
203 /* Set this flag so when we do the state diff, we enable GENERATE_MIPMAP
204 * prior to calling diff.TexImage().
205 */
206 levels[tobj->baseLevel].generateMipmap = GL_TRUE;
207}
208
209
210/**
211 * Given a texture target and level, return pointers to the corresponding
212 * texture object and texture image level.
213 */
214void
215crStateGetTextureObjectAndImage(CRContext *g, GLenum texTarget, GLint level,
216 CRTextureObj **obj, CRTextureLevel **img)
217{
218 CRTextureState *t = &(g->texture);
219 CRTextureUnit *unit = t->unit + t->curTextureUnit;
220
221 switch (texTarget) {
222 case GL_TEXTURE_1D:
223 *obj = unit->currentTexture1D;
224 *img = unit->currentTexture1D->level[0] + level;
225 return;
226 case GL_PROXY_TEXTURE_1D:
227 *obj = &(t->proxy1D);
228 *img = t->proxy1D.level[0] + level;
229 return;
230 case GL_TEXTURE_2D:
231 *obj = unit->currentTexture2D;
232 *img = unit->currentTexture2D->level[0] + level;
233 return;
234 case GL_PROXY_TEXTURE_2D:
235 *obj = &(t->proxy2D);
236 *img = t->proxy2D.level[0] + level;
237 return;
238 case GL_TEXTURE_3D:
239 *obj = unit->currentTexture3D;
240 *img = unit->currentTexture3D->level[0] + level;
241 return;
242 case GL_PROXY_TEXTURE_3D:
243 *obj = &(t->proxy3D);
244 *img = t->proxy3D.level[0] + level;
245 return;
246 default:
247 /* fall-through */
248 ;
249 }
250
251#ifdef CR_NV_texture_rectangle
252 if (g->extensions.NV_texture_rectangle) {
253 switch (texTarget) {
254 case GL_PROXY_TEXTURE_RECTANGLE_NV:
255 *obj = &(t->proxyRect);
256 *img = t->proxyRect.level[0] + level;
257 return;
258 case GL_TEXTURE_RECTANGLE_NV:
259 *obj = unit->currentTextureRect;
260 *img = unit->currentTextureRect->level[0] + level;
261 return;
262 default:
263 /* fall-through */
264 ;
265 }
266 }
267#endif
268
269#ifdef CR_ARB_texture_cube_map
270 if (g->extensions.ARB_texture_cube_map) {
271 switch (texTarget) {
272 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
273 *obj = &(t->proxyCubeMap);
274 *img = t->proxyCubeMap.level[0] + level;
275 return;
276 case GL_TEXTURE_CUBE_MAP_ARB:
277 *obj = unit->currentTextureCubeMap;
278 *img = NULL;
279 return;
280 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
281 *obj = unit->currentTextureCubeMap;
282 *img = unit->currentTextureCubeMap->level[0] + level;
283 return;
284 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
285 *obj = unit->currentTextureCubeMap;
286 *img = unit->currentTextureCubeMap->level[1] + level;
287 return;
288 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
289 *obj = unit->currentTextureCubeMap;
290 *img = unit->currentTextureCubeMap->level[2] + level;
291 return;
292 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
293 *obj = unit->currentTextureCubeMap;
294 *img = unit->currentTextureCubeMap->level[3] + level;
295 return;
296 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
297 *obj = unit->currentTextureCubeMap;
298 *img = unit->currentTextureCubeMap->level[4] + level;
299 return;
300 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
301 *obj = unit->currentTextureCubeMap;
302 *img = unit->currentTextureCubeMap->level[5] + level;
303 return;
304 default:
305 /* fall-through */
306 ;
307 }
308 }
309#endif
310
311 *obj = NULL;
312 *img = NULL;
313}
314
315
316/**
317 * Do parameter error checking for glTexImagexD functions.
318 * We'll call crStateError if we detect any errors, unless it's a proxy target.
319 * Return GL_TRUE if any errors, GL_FALSE if no errors.
320 */
321static GLboolean
322ErrorCheckTexImage(GLuint dims, GLenum target, GLint level,
323 GLsizei width, GLsizei height, GLsizei depth, GLint border)
324{
325 CRContext *g = GetCurrentContext();
326
327 if (g->current.inBeginEnd)
328 {
329 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
330 "glTexImage%uD called in Begin/End", dims);
331 return GL_TRUE;
332 }
333
334 /*
335 * Test target
336 */
337 switch (target)
338 {
339 case GL_TEXTURE_1D:
340 case GL_PROXY_TEXTURE_1D:
341 if (dims != 1) {
342 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
343 "glTexImage(invalid target=0x%x)", target);
344 return GL_TRUE;
345 }
346 break;
347 case GL_TEXTURE_2D:
348 case GL_PROXY_TEXTURE_2D:
349 if (dims != 2) {
350 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
351 "glTexImage(invalid target=0x%x)", target);
352 return GL_TRUE;
353 }
354 break;
355 case GL_TEXTURE_3D:
356 case GL_PROXY_TEXTURE_3D:
357 if (dims != 3) {
358 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
359 "glTexImage(invalid target=0x%x)", target);
360 return GL_TRUE;
361 }
362 break;
363#ifdef CR_NV_texture_rectangle
364 case GL_TEXTURE_RECTANGLE_NV:
365 case GL_PROXY_TEXTURE_RECTANGLE_NV:
366 if (dims != 2 || !g->extensions.NV_texture_rectangle) {
367 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
368 "glTexImage2D(invalid target=0x%x)", target);
369 return GL_TRUE;
370 }
371 break;
372#endif
373#ifdef CR_ARB_texture_cube_map
374 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
375 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
376 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
377 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
378 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
379 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
380 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
381 if (dims != 2 || !g->extensions.ARB_texture_cube_map) {
382 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
383 "glTexImage2D(invalid target=0x%x)", target);
384 return GL_TRUE;
385 }
386 break;
387#endif
388 default:
389 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
390 "glTexImage%uD(invalid target=0x%x)", dims, target);
391 return GL_TRUE;
392 }
393
394 /*
395 * Test level
396 */
397 if (level < 0 || level > MaxTextureLevel(g, target)) {
398 if (!IsProxyTarget(target))
399 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
400 "glTexImage%uD(level=%d)", dims, level);
401 return GL_TRUE;
402 }
403
404 /*
405 * Test border
406 */
407 if (border != 0 && border != 1) {
408 if (!IsProxyTarget(target))
409 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
410 "glTexImage%uD(border=%d)", dims, border);
411 return GL_TRUE;
412 }
413
414 if ((target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
415 target == GL_TEXTURE_RECTANGLE_NV) && border != 0) {
416 if (!IsProxyTarget(target))
417 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
418 "glTexImage2D(border=%d)", border);
419 return GL_TRUE;
420 }
421
422 /*
423 * Test width, height, depth
424 */
425 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
426 if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize)) {
427 if (!IsProxyTarget(target))
428 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
429 "glTexImage1D(width=%d)", width);
430 return GL_TRUE;
431 }
432 }
433 else if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
434 if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize) ||
435 !isLegalSize(g, height - 2 * border, g->limits.maxTextureSize)) {
436 if (!IsProxyTarget(target))
437 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
438 "glTexImage2D(width=%d, height=%d)", width, height);
439 return GL_TRUE;
440 }
441 }
442 else if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
443 if (!isLegalSize(g, width - 2 * border, g->limits.max3DTextureSize) ||
444 !isLegalSize(g, height - 2 * border, g->limits.max3DTextureSize) ||
445 !isLegalSize(g, depth - 2 * border, g->limits.max3DTextureSize)) {
446 if (!IsProxyTarget(target))
447 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
448 "glTexImage3D(width=%d, height=%d, depth=%d)",
449 width, height, depth);
450 return GL_TRUE;
451 }
452 }
453 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
454 target == GL_TEXTURE_RECTANGLE_NV) {
455 if (width < 0 || width > (int) g->limits.maxRectTextureSize ||
456 height < 0 || height > (int) g->limits.maxRectTextureSize) {
457 if (!IsProxyTarget(target))
458 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
459 "glTexImage2D(width=%d, height=%d)", width, height);
460 return GL_TRUE;
461 }
462 }
463 else {
464 /* cube map */
465 if (!isLegalSize(g, width - 2*border, g->limits.maxCubeMapTextureSize) ||
466 !isLegalSize(g, height - 2*border, g->limits.maxCubeMapTextureSize) ||
467 width != height) {
468 if (!IsProxyTarget(target))
469 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
470 "glTexImage2D(width=%d, height=%d)", width, height);
471 return GL_TRUE;
472 }
473 }
474
475 /* OK, no errors */
476 return GL_FALSE;
477}
478
479
480/**
481 * Do error check for glTexSubImage() functions.
482 * We'll call crStateError if we detect any errors.
483 * Return GL_TRUE if any errors, GL_FALSE if no errors.
484 */
485static GLboolean
486ErrorCheckTexSubImage(GLuint dims, GLenum target, GLint level,
487 GLint xoffset, GLint yoffset, GLint zoffset,
488 GLsizei width, GLsizei height, GLsizei depth)
489{
490 CRContext *g = GetCurrentContext();
491 CRTextureObj *tobj;
492 CRTextureLevel *tl;
493
494 if (g->current.inBeginEnd) {
495 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
496 "glTexSubImage%uD called in Begin/End", dims);
497 return GL_TRUE;
498 }
499
500 if (dims == 1) {
501 if (target != GL_TEXTURE_1D) {
502 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
503 "glTexSubImage1D(target=0x%x)", target);
504 return GL_TRUE;
505 }
506 }
507 else if (dims == 2) {
508 if (target != GL_TEXTURE_2D &&
509 target != GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
510 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB &&
511 target != GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB &&
512 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB &&
513 target != GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB &&
514 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB &&
515 target != GL_TEXTURE_RECTANGLE_NV) {
516 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
517 "glTexSubImage2D(target=0x%x)", target);
518 return GL_TRUE;
519 }
520 }
521 else if (dims == 3) {
522 if (target != GL_TEXTURE_3D) {
523 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
524 "glTexSubImage3D(target=0x%x)", target);
525 return GL_TRUE;
526 }
527 }
528
529 /* test level */
530 if (level < 0 || level > MaxTextureLevel(g, target)) {
531 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
532 "glTexSubImage%uD(level=%d)", dims, level);
533 return GL_TRUE;
534 }
535
536 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
537 if (!tobj || !tl) {
538 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
539 "glTexSubImage%uD(target or level)", dims);
540 return GL_TRUE;
541 }
542
543 /* test x/y/zoffset and size */
544 if (xoffset < -tl->border || xoffset + width > tl->width) {
545 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
546 "glTexSubImage%uD(xoffset=%d + width=%d > %d)",
547 dims, xoffset, width, tl->width);
548 return GL_TRUE;
549 }
550 if (dims > 1 && (yoffset < -tl->border || yoffset + height > tl->height)) {
551 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
552 "glTexSubImage%uD(yoffset=%d + height=%d > %d)",
553 dims, yoffset, height, tl->height);
554 return GL_TRUE;
555 }
556 if (dims > 2 && (zoffset < -tl->border || zoffset + depth > tl->depth)) {
557 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
558 "glTexSubImage%uD(zoffset=%d and/or depth=%d)",
559 dims, zoffset, depth);
560 return GL_TRUE;
561 }
562
563 /* OK, no errors */
564 return GL_FALSE;
565}
566
567
568
569void STATE_APIENTRY
570crStateTexImage1D(GLenum target, GLint level, GLint internalFormat,
571 GLsizei width, GLint border, GLenum format,
572 GLenum type, const GLvoid * pixels)
573{
574 CRContext *g = GetCurrentContext();
575 CRTextureState *t = &(g->texture);
576 CRClientState *c = &(g->client);
577 CRTextureObj *tobj;
578 CRTextureLevel *tl;
579 CRStateBits *sb = GetCurrentBits();
580 CRTextureBits *tb = &(sb->texture);
581
582 FLUSH();
583
584 if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
585 if (IsProxyTarget(target)) {
586 /* clear all state, but don't generate error */
587 crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
588 }
589 else {
590 /* error was already recorded */
591 }
592 return;
593 }
594
595 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
596 CRASSERT(tobj);
597 CRASSERT(tl);
598
599 if (IsProxyTarget(target))
600 tl->bytes = 0;
601 else
602 tl->bytes = crImageSize(format, type, width, 1);
603
604#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
605 if (tl->bytes)
606 {
607 /* this is not a proxy texture target so alloc storage */
608 if (tl->img)
609 crFree(tl->img);
610 tl->img = (GLubyte *) crAlloc(tl->bytes);
611 if (!tl->img)
612 {
613 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
614 "glTexImage1D out of memory");
615 return;
616 }
617 if (pixels)
618 crPixelCopy1D((GLvoid *) tl->img, format, type,
619 pixels, format, type, width, &(c->unpack));
620 }
621#endif
622
623 tl->width = width;
624 tl->height = 1;
625 tl->depth = 1;
626 tl->format = format;
627 tl->border = border;
628 tl->internalFormat = internalFormat;
629 crStateTextureInitTextureFormat(tl, internalFormat);
630 tl->type = type;
631 tl->compressed = GL_FALSE;
632 if (width)
633 tl->bytesPerPixel = tl->bytes / width;
634 else
635 tl->bytesPerPixel = 0;
636
637#ifdef CR_SGIS_generate_mipmap
638 if (level == tobj->baseLevel && tobj->generateMipmap) {
639 generate_mipmap(tobj, target);
640 }
641 else {
642 tl->generateMipmap = GL_FALSE;
643 }
644#endif
645
646 /* XXX may need to do some fine-tuning here for proxy textures */
647 DIRTY(tobj->dirty, g->neg_bitid);
648 DIRTY(tobj->imageBit, g->neg_bitid);
649 DIRTY(tl->dirty, g->neg_bitid);
650 DIRTY(tb->dirty, g->neg_bitid);
651}
652
653static void crStateNukeMipmaps(CRTextureObj *tobj)
654{
655 int i, face;
656
657 for (face = 0; face < 6; face++)
658 {
659 CRTextureLevel *levels = tobj->level[face];
660
661 if (levels)
662 {
663 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++)
664 {
665 if (levels[i].img)
666 {
667 crFree(levels[i].img);
668 }
669 levels[i].img = NULL;
670 levels[i].bytes = 0;
671 levels[i].internalFormat = GL_ONE;
672 levels[i].format = GL_RGBA;
673 levels[i].type = GL_UNSIGNED_BYTE;
674
675 }
676 }
677 }
678}
679
680void STATE_APIENTRY
681crStateCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
682{
683 CRContext *g = GetCurrentContext();
684 CRTextureObj *tobj = NULL;
685 CRTextureLevel *tl = NULL;
686
687 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
688 CRASSERT(tobj);
689 CRASSERT(tl);
690
691 crStateNukeMipmaps(tobj);
692
693 tl->bytes = crImageSize(GL_RGBA, GL_UNSIGNED_BYTE, width, height);
694
695 tl->width = width;
696 tl->height = height;
697 tl->depth = 1;
698 tl->format = GL_RGBA;
699 tl->internalFormat = internalFormat;
700 crStateTextureInitTextureFormat(tl, internalFormat);
701 tl->border = border;
702 tl->type = GL_UNSIGNED_BYTE;
703 tl->compressed = GL_FALSE;
704 if (width && height)
705 {
706 tl->bytesPerPixel = tl->bytes / (width * height);
707 }
708 else
709 tl->bytesPerPixel = 0;
710
711#ifdef CR_SGIS_generate_mipmap
712 if (level == tobj->baseLevel && tobj->generateMipmap) {
713 generate_mipmap(tobj, target);
714 }
715 else {
716 tl->generateMipmap = GL_FALSE;
717 }
718#endif
719}
720
721void STATE_APIENTRY
722crStateTexImage2D(GLenum target, GLint level, GLint internalFormat,
723 GLsizei width, GLsizei height, GLint border,
724 GLenum format, GLenum type, const GLvoid * pixels)
725{
726 CRContext *g = GetCurrentContext();
727 CRTextureState *t = &(g->texture);
728 CRClientState *c = &(g->client);
729 CRTextureObj *tobj = NULL;
730 CRTextureLevel *tl = NULL;
731 CRStateBits *sb = GetCurrentBits();
732 CRTextureBits *tb = &(sb->texture);
733 const int is_distrib = ((type == GL_TRUE) || (type == GL_FALSE));
734
735 FLUSH();
736
737 /* NOTE: we skip parameter error checking if this is a distributed
738 * texture! The user better provide correct parameters!!!
739 */
740 if (!is_distrib
741 && ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
742 if (IsProxyTarget(target)) {
743 /* clear all state, but don't generate error */
744 crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
745 }
746 else {
747 /* error was already recorded */
748 }
749 return;
750 }
751
752 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
753 CRASSERT(tobj);
754 CRASSERT(tl);
755
756 if (level==tobj->baseLevel && (tl->width!=width || tl->height!=height))
757 {
758 crStateNukeMipmaps(tobj);
759 }
760
761 /* compute size of image buffer */
762 if (is_distrib) {
763 tl->bytes = crStrlen((char *) pixels) + 1;
764 tl->bytes += crImageSize(format, GL_UNSIGNED_BYTE, width, height);
765 }
766 else if (IsProxyTarget(target)) {
767 tl->bytes = 0;
768 }
769 else {
770 tl->bytes = crImageSize(format, type, width, height);
771 }
772
773#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
774 /* allocate the image buffer and fill it */
775 if (tl->bytes)
776 {
777 /* this is not a proxy texture target so alloc storage */
778 if (tl->img)
779 crFree(tl->img);
780 tl->img = (GLubyte *) crAlloc(tl->bytes);
781 if (!tl->img)
782 {
783 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
784 "glTexImage2D out of memory");
785 return;
786 }
787 if (pixels)
788 {
789 if (is_distrib)
790 {
791 crMemcpy((void *) tl->img, (void *) pixels, tl->bytes);
792 }
793 else
794 {
795 crPixelCopy2D(width, height,
796 (GLvoid *) tl->img, format, type, NULL, /* dst */
797 pixels, format, type, &(c->unpack)); /* src */
798 }
799 }
800 }
801#endif
802
803 tl->width = width;
804 tl->height = height;
805 tl->depth = 1;
806 tl->format = format;
807 tl->internalFormat = internalFormat;
808 crStateTextureInitTextureFormat(tl, internalFormat);
809 tl->border = border;
810 tl->type = type;
811 tl->compressed = GL_FALSE;
812 if (width && height)
813 {
814 if (is_distrib)
815 tl->bytesPerPixel = 3; /* only support GL_RGB */
816 else
817 tl->bytesPerPixel = tl->bytes / (width * height);
818 }
819 else
820 tl->bytesPerPixel = 0;
821
822#ifdef CR_SGIS_generate_mipmap
823 if (level == tobj->baseLevel && tobj->generateMipmap) {
824 generate_mipmap(tobj, target);
825 }
826 else {
827 tl->generateMipmap = GL_FALSE;
828 }
829#endif
830
831 /* XXX may need to do some fine-tuning here for proxy textures */
832 DIRTY(tobj->dirty, g->neg_bitid);
833 DIRTY(tobj->imageBit, g->neg_bitid);
834 DIRTY(tl->dirty, g->neg_bitid);
835 DIRTY(tb->dirty, g->neg_bitid);
836
837#ifdef CR_DUMP_TEXTURES_2D
838 if (pixels)
839 {
840 GLint w,h;
841 char *data;
842
843 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
844 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
845
846 data = crAlloc(w*h*4);
847 if (!data) crError("no memory!");
848 diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
849 crDumpTGA(w, h, data);
850 crFree(data);
851 }
852#endif
853}
854
855#if defined( CR_OPENGL_VERSION_1_2 ) || defined( GL_EXT_texture3D )
856void STATE_APIENTRY
857crStateTexImage3D(GLenum target, GLint level,
858 GLint internalFormat,
859 GLsizei width, GLsizei height,
860 GLsizei depth, GLint border,
861 GLenum format, GLenum type, const GLvoid * pixels)
862{
863 CRContext *g = GetCurrentContext();
864 CRTextureState *t = &(g->texture);
865 CRClientState *c = &(g->client);
866 CRTextureObj *tobj = NULL;
867 CRTextureLevel *tl = NULL;
868 CRStateBits *sb = GetCurrentBits();
869 CRTextureBits *tb = &(sb->texture);
870
871 FLUSH();
872
873 if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
874 if (IsProxyTarget(target)) {
875 /* clear all state, but don't generate error */
876 crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
877 }
878 else {
879 /* error was already recorded */
880 }
881 return;
882 }
883
884 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
885 CRASSERT(tobj);
886 CRASSERT(tl);
887
888 if (IsProxyTarget(target))
889 tl->bytes = 0;
890 else
891 tl->bytes = crTextureSize(format, type, width, height, depth);
892
893#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
894 if (tl->bytes)
895 {
896 /* this is not a proxy texture target so alloc storage */
897 if (tl->img)
898 crFree(tl->img);
899 tl->img = (GLubyte *) crAlloc(tl->bytes);
900 if (!tl->img)
901 {
902 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
903 "glTexImage3D out of memory");
904 return;
905 }
906 if (pixels)
907 crPixelCopy3D(width, height, depth, (GLvoid *) (tl->img), format, type,
908 NULL, pixels, format, type, &(c->unpack));
909 }
910#endif
911
912 tl->internalFormat = internalFormat;
913 tl->border = border;
914 tl->width = width;
915 tl->height = height;
916 tl->depth = depth;
917 tl->format = format;
918 tl->type = type;
919 tl->compressed = GL_FALSE;
920
921#ifdef CR_SGIS_generate_mipmap
922 if (level == tobj->baseLevel && tobj->generateMipmap) {
923 generate_mipmap(tobj, target);
924 }
925 else {
926 tl->generateMipmap = GL_FALSE;
927 }
928#endif
929
930 /* XXX may need to do some fine-tuning here for proxy textures */
931 DIRTY(tobj->dirty, g->neg_bitid);
932 DIRTY(tobj->imageBit, g->neg_bitid);
933 DIRTY(tl->dirty, g->neg_bitid);
934 DIRTY(tb->dirty, g->neg_bitid);
935}
936#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
937
938
939#ifdef GL_EXT_texture3D
940void STATE_APIENTRY
941crStateTexImage3DEXT(GLenum target, GLint level,
942 GLenum internalFormat,
943 GLsizei width, GLsizei height, GLsizei depth,
944 GLint border, GLenum format, GLenum type,
945 const GLvoid * pixels)
946{
947 crStateTexImage3D(target, level, (GLint) internalFormat, width, height,
948 depth, border, format, type, pixels);
949}
950#endif /* GL_EXT_texture3D */
951
952
953void STATE_APIENTRY
954crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset,
955 GLsizei width, GLenum format,
956 GLenum type, const GLvoid * pixels)
957{
958 CRContext *g = GetCurrentContext();
959 CRTextureState *t = &(g->texture);
960 CRClientState *c = &(g->client);
961 CRStateBits *sb = GetCurrentBits();
962 CRTextureBits *tb = &(sb->texture);
963 CRTextureUnit *unit = t->unit + t->curTextureUnit;
964 CRTextureObj *tobj = unit->currentTexture1D;
965 CRTextureLevel *tl = tobj->level[0] + level;
966
967 FLUSH();
968
969 if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0,
970 width, 1, 1)) {
971 return; /* GL error state already set */
972 }
973
974#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
975 xoffset += tl->border;
976
977 crPixelCopy1D((void *) (tl->img + xoffset * tl->bytesPerPixel),
978 tl->format, tl->type,
979 pixels, format, type, width, &(c->unpack));
980#endif
981
982#ifdef CR_SGIS_generate_mipmap
983 if (level == tobj->baseLevel && tobj->generateMipmap) {
984 generate_mipmap(tobj, target);
985 }
986 else {
987 tl->generateMipmap = GL_FALSE;
988 }
989#endif
990
991 DIRTY(tobj->dirty, g->neg_bitid);
992 DIRTY(tobj->imageBit, g->neg_bitid);
993 DIRTY(tl->dirty, g->neg_bitid);
994 DIRTY(tb->dirty, g->neg_bitid);
995}
996
997
998void STATE_APIENTRY
999crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
1000 GLsizei width, GLsizei height,
1001 GLenum format, GLenum type, const GLvoid * pixels)
1002{
1003 CRContext *g = GetCurrentContext();
1004 CRClientState *c = &(g->client);
1005 CRStateBits *sb = GetCurrentBits();
1006 CRTextureBits *tb = &(sb->texture);
1007 CRTextureObj *tobj;
1008 CRTextureLevel *tl;
1009 GLubyte *subimg = NULL;
1010 GLubyte *img = NULL;
1011#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1012 GLubyte *src;
1013 int i;
1014#endif
1015
1016 FLUSH();
1017
1018 if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
1019 width, height, 1)) {
1020 return; /* GL error state already set */
1021 }
1022
1023 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1024 CRASSERT(tobj);
1025 CRASSERT(tl);
1026
1027#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1028 xoffset += tl->border;
1029 yoffset += tl->border;
1030
1031 subimg = (GLubyte *) crAlloc(crImageSize(tl->format, tl->type, width, height));
1032
1033 crPixelCopy2D(width, height, subimg, tl->format, tl->type, NULL, /* dst */
1034 pixels, format, type, &(c->unpack)); /* src */
1035
1036 img = tl->img +
1037 xoffset * tl->bytesPerPixel + yoffset * tl->width * tl->bytesPerPixel;
1038
1039 src = subimg;
1040
1041 /* Copy the data into the texture */
1042 for (i = 0; i < height; i++)
1043 {
1044 crMemcpy(img, src, tl->bytesPerPixel * width);
1045 img += tl->width * tl->bytesPerPixel;
1046 src += width * tl->bytesPerPixel;
1047 }
1048
1049 crFree(subimg);
1050#endif
1051
1052#ifdef CR_SGIS_generate_mipmap
1053 if (level == tobj->baseLevel && tobj->generateMipmap) {
1054 generate_mipmap(tobj, target);
1055 }
1056 else {
1057 tl->generateMipmap = GL_FALSE;
1058 }
1059#endif
1060
1061 DIRTY(tobj->dirty, g->neg_bitid);
1062 DIRTY(tobj->imageBit, g->neg_bitid);
1063 DIRTY(tl->dirty, g->neg_bitid);
1064 DIRTY(tb->dirty, g->neg_bitid);
1065
1066#ifdef CR_DUMP_TEXTURES_2D
1067 {
1068 GLint w,h;
1069 char *data;
1070
1071 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
1072 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
1073
1074 data = crAlloc(w*h*4);
1075 if (!data) crError("no memory!");
1076 diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
1077 crDumpTGA(w, h, data);
1078 crFree(data);
1079 }
1080#endif
1081}
1082
1083#if defined( CR_OPENGL_VERSION_1_2 )
1084void STATE_APIENTRY
1085crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
1086 GLint zoffset, GLsizei width, GLsizei height,
1087 GLsizei depth, GLenum format, GLenum type,
1088 const GLvoid * pixels)
1089{
1090 CRContext *g = GetCurrentContext();
1091 CRTextureState *t = &(g->texture);
1092 CRClientState *c = &(g->client);
1093 CRStateBits *sb = GetCurrentBits();
1094 CRTextureBits *tb = &(sb->texture);
1095 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1096 CRTextureObj *tobj = unit->currentTexture3D;
1097 CRTextureLevel *tl = tobj->level[0] + level;
1098 GLubyte *subimg = NULL;
1099 GLubyte *img = NULL;
1100#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1101 GLubyte *src;
1102 int i;
1103#endif
1104
1105 FLUSH();
1106
1107 if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
1108 width, height, depth)) {
1109 return; /* GL error state already set */
1110 }
1111
1112#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1113 xoffset += tl->border;
1114 yoffset += tl->border;
1115 zoffset += tl->border;
1116
1117 subimg =
1118 (GLubyte *)
1119 crAlloc(crTextureSize(tl->format, tl->type, width, height, depth));
1120
1121 crPixelCopy3D(width, height, depth, subimg, tl->format, tl->type, NULL,
1122 pixels, format, type, &(c->unpack));
1123
1124 img = tl->img + xoffset * tl->bytesPerPixel +
1125 yoffset * tl->width * tl->bytesPerPixel +
1126 zoffset * tl->width * tl->height * tl->bytesPerPixel;
1127
1128 src = subimg;
1129
1130 /* Copy the data into the texture */
1131 for (i = 0; i < depth; i++)
1132 {
1133 crMemcpy(img, src, tl->bytesPerPixel * width * height);
1134 img += tl->width * tl->height * tl->bytesPerPixel;
1135 src += width * height * tl->bytesPerPixel;
1136 }
1137
1138 crFree(subimg);
1139#endif
1140
1141#ifdef CR_SGIS_generate_mipmap
1142 if (level == tobj->baseLevel && tobj->generateMipmap) {
1143 generate_mipmap(tobj, target);
1144 }
1145 else {
1146 tl->generateMipmap = GL_FALSE;
1147 }
1148#endif
1149
1150 DIRTY(tobj->dirty, g->neg_bitid);
1151 DIRTY(tobj->imageBit, g->neg_bitid);
1152 DIRTY(tl->dirty, g->neg_bitid);
1153 DIRTY(tb->dirty, g->neg_bitid);
1154}
1155#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
1156
1157
1158void STATE_APIENTRY
1159crStateCompressedTexImage1DARB(GLenum target, GLint level,
1160 GLenum internalFormat, GLsizei width,
1161 GLint border, GLsizei imageSize,
1162 const GLvoid * data)
1163{
1164 CRContext *g = GetCurrentContext();
1165 CRTextureState *t = &(g->texture);
1166 CRTextureObj *tobj;
1167 CRTextureLevel *tl;
1168 CRStateBits *sb = GetCurrentBits();
1169 CRTextureBits *tb = &(sb->texture);
1170
1171 FLUSH();
1172
1173 if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
1174 if (IsProxyTarget(target)) {
1175 /* clear all state, but don't generate error */
1176 crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
1177 }
1178 else {
1179 /* error was already recorded */
1180 }
1181 return;
1182 }
1183
1184 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1185 CRASSERT(tobj);
1186 CRASSERT(tl);
1187
1188 if (IsProxyTarget(target))
1189 tl->bytes = 0;
1190 else
1191 tl->bytes = imageSize;
1192
1193#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1194 if (tl->bytes)
1195 {
1196 /* this is not a proxy texture target so alloc storage */
1197 if (tl->img)
1198 crFree(tl->img);
1199 tl->img = (GLubyte *) crAlloc(tl->bytes);
1200 if (!tl->img)
1201 {
1202 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1203 "glTexImage1D out of memory");
1204 return;
1205 }
1206 if (data)
1207 crMemcpy(tl->img, data, imageSize);
1208 }
1209#endif
1210
1211 tl->width = width;
1212 tl->height = 1;
1213 tl->depth = 1;
1214 tl->border = border;
1215 tl->format = GL_NONE;
1216 tl->type = GL_NONE;
1217 tl->internalFormat = internalFormat;
1218 crStateTextureInitTextureFormat(tl, internalFormat);
1219 tl->compressed = GL_TRUE;
1220 tl->bytesPerPixel = 0; /* n/a */
1221
1222#ifdef CR_SGIS_generate_mipmap
1223 if (level == tobj->baseLevel && tobj->generateMipmap) {
1224 generate_mipmap(tobj, target);
1225 }
1226 else {
1227 tl->generateMipmap = GL_FALSE;
1228 }
1229#endif
1230
1231 DIRTY(tobj->dirty, g->neg_bitid);
1232 DIRTY(tobj->imageBit, g->neg_bitid);
1233 DIRTY(tl->dirty, g->neg_bitid);
1234 DIRTY(tb->dirty, g->neg_bitid);
1235}
1236
1237
1238void STATE_APIENTRY
1239crStateCompressedTexImage2DARB(GLenum target, GLint level,
1240 GLenum internalFormat, GLsizei width,
1241 GLsizei height, GLint border,
1242 GLsizei imageSize, const GLvoid * data)
1243{
1244 CRContext *g = GetCurrentContext();
1245 CRTextureState *t = &(g->texture);
1246 CRTextureObj *tobj = NULL;
1247 CRTextureLevel *tl = NULL;
1248 CRStateBits *sb = GetCurrentBits();
1249 CRTextureBits *tb = &(sb->texture);
1250
1251 FLUSH();
1252
1253 if (ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
1254 if (IsProxyTarget(target)) {
1255 /* clear all state, but don't generate error */
1256 crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
1257 }
1258 else {
1259 /* error was already recorded */
1260 }
1261 return;
1262 }
1263
1264 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1265 CRASSERT(tobj);
1266 CRASSERT(tl);
1267
1268 if (IsProxyTarget(target))
1269 tl->bytes = 0;
1270 else
1271 tl->bytes = imageSize;
1272
1273#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1274 if (tl->bytes)
1275 {
1276 /* this is not a proxy texture target so alloc storage */
1277 if (tl->img)
1278 crFree(tl->img);
1279 tl->img = (GLubyte *) crAlloc(tl->bytes);
1280 if (!tl->img)
1281 {
1282 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1283 "glTexImage2D out of memory");
1284 return;
1285 }
1286 if (data)
1287 crMemcpy(tl->img, data, imageSize);
1288 }
1289#endif
1290
1291 tl->width = width;
1292 tl->height = height;
1293 tl->depth = 1;
1294 tl->border = border;
1295 tl->format = GL_NONE;
1296 tl->type = GL_NONE;
1297 tl->internalFormat = internalFormat;
1298 crStateTextureInitTextureFormat(tl, internalFormat);
1299 tl->compressed = GL_TRUE;
1300 tl->bytesPerPixel = 0; /* n/a */
1301
1302#ifdef CR_SGIS_generate_mipmap
1303 if (level == tobj->baseLevel && tobj->generateMipmap) {
1304 generate_mipmap(tobj, target);
1305 }
1306 else {
1307 tl->generateMipmap = GL_FALSE;
1308 }
1309#endif
1310
1311 /* XXX may need to do some fine-tuning here for proxy textures */
1312 DIRTY(tobj->dirty, g->neg_bitid);
1313 DIRTY(tobj->imageBit, g->neg_bitid);
1314 DIRTY(tl->dirty, g->neg_bitid);
1315 DIRTY(tb->dirty, g->neg_bitid);
1316}
1317
1318
1319void STATE_APIENTRY
1320crStateCompressedTexImage3DARB(GLenum target, GLint level,
1321 GLenum internalFormat, GLsizei width,
1322 GLsizei height, GLsizei depth, GLint border,
1323 GLsizei imageSize, const GLvoid * data)
1324{
1325 CRContext *g = GetCurrentContext();
1326 CRTextureState *t = &(g->texture);
1327 CRTextureObj *tobj = NULL;
1328 CRTextureLevel *tl = NULL;
1329 CRStateBits *sb = GetCurrentBits();
1330 CRTextureBits *tb = &(sb->texture);
1331
1332 FLUSH();
1333
1334 if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
1335 if (IsProxyTarget(target)) {
1336 /* clear all state, but don't generate error */
1337 crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
1338 }
1339 else {
1340 /* error was already recorded */
1341 }
1342 return;
1343 }
1344
1345 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1346 CRASSERT(tobj);
1347 CRASSERT(tl);
1348
1349 if (IsProxyTarget(target))
1350 tl->bytes = 0;
1351 else
1352 tl->bytes = imageSize;
1353
1354#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1355 if (tl->bytes)
1356 {
1357 /* this is not a proxy texture target so alloc storage */
1358 if (tl->img)
1359 crFree(tl->img);
1360 tl->img = (GLubyte *) crAlloc(tl->bytes);
1361 if (!tl->img)
1362 {
1363 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1364 "glCompressedTexImage3D out of memory");
1365 return;
1366 }
1367 if (data)
1368 crMemcpy(tl->img, data, imageSize);
1369 }
1370#endif
1371
1372 tl->width = width;
1373 tl->height = height;
1374 tl->depth = depth;
1375 tl->border = border;
1376 tl->format = GL_NONE;
1377 tl->type = GL_NONE;
1378 tl->internalFormat = internalFormat;
1379 crStateTextureInitTextureFormat(tl, internalFormat);
1380 tl->compressed = GL_TRUE;
1381 tl->bytesPerPixel = 0; /* n/a */
1382
1383#ifdef CR_SGIS_generate_mipmap
1384 if (level == tobj->baseLevel && tobj->generateMipmap) {
1385 generate_mipmap(tobj, target);
1386 }
1387 else {
1388 tl->generateMipmap = GL_FALSE;
1389 }
1390#endif
1391
1392 /* XXX may need to do some fine-tuning here for proxy textures */
1393 DIRTY(tobj->dirty, g->neg_bitid);
1394 DIRTY(tobj->imageBit, g->neg_bitid);
1395 DIRTY(tl->dirty, g->neg_bitid);
1396 DIRTY(tb->dirty, g->neg_bitid);
1397}
1398
1399
1400void STATE_APIENTRY
1401crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
1402 GLsizei width, GLenum format,
1403 GLsizei imageSize, const GLvoid * data)
1404{
1405 CRContext *g = GetCurrentContext();
1406 CRTextureState *t = &(g->texture);
1407 CRStateBits *sb = GetCurrentBits();
1408 CRTextureBits *tb = &(sb->texture);
1409 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1410 CRTextureObj *tobj = unit->currentTexture1D;
1411 CRTextureLevel *tl = tobj->level[0] + level;
1412
1413 FLUSH();
1414
1415 if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0, width, 1, 1)) {
1416 return; /* GL error state already set */
1417 }
1418
1419#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1420 xoffset += tl->border;
1421
1422 if (xoffset == 0 && width == tl->width) {
1423 /* just memcpy */
1424 crMemcpy(tl->img, data, imageSize);
1425 }
1426 else {
1427 /* XXX this depends on the exact compression method */
1428 crWarning("Not implemented part crStateCompressedTexSubImage1DARB");
1429 }
1430#endif
1431
1432#ifdef CR_SGIS_generate_mipmap
1433 if (level == tobj->baseLevel && tobj->generateMipmap) {
1434 generate_mipmap(tobj, target);
1435 }
1436 else {
1437 tl->generateMipmap = GL_FALSE;
1438 }
1439#endif
1440
1441 DIRTY(tobj->dirty, g->neg_bitid);
1442 DIRTY(tobj->imageBit, g->neg_bitid);
1443 DIRTY(tl->dirty, g->neg_bitid);
1444 DIRTY(tb->dirty, g->neg_bitid);
1445}
1446
1447
1448void STATE_APIENTRY
1449crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
1450 GLint yoffset, GLsizei width,
1451 GLsizei height, GLenum format,
1452 GLsizei imageSize, const GLvoid * data)
1453{
1454 CRContext *g = GetCurrentContext();
1455 CRTextureState *t = &(g->texture);
1456 CRStateBits *sb = GetCurrentBits();
1457 CRTextureBits *tb = &(sb->texture);
1458 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1459 CRTextureObj *tobj = unit->currentTexture1D;
1460 CRTextureLevel *tl = tobj->level[0] + level;
1461
1462 FLUSH();
1463
1464 if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
1465 width, height, 1)) {
1466 return; /* GL error state already set */
1467 }
1468
1469#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1470 xoffset += tl->border;
1471 yoffset += tl->border;
1472
1473 if (xoffset == 0 && width == tl->width
1474 && yoffset == 0 && height == tl->height)
1475 {
1476 /* just memcpy */
1477 crMemcpy(tl->img, data, imageSize);
1478 }
1479 else {
1480 /* XXX this depends on the exact compression method */
1481 crWarning("Not implemented part crStateCompressedTexSubImage2DARB");
1482 }
1483#endif
1484
1485#ifdef CR_SGIS_generate_mipmap
1486 if (level == tobj->baseLevel && tobj->generateMipmap) {
1487 generate_mipmap(tobj, target);
1488 }
1489 else {
1490 tl->generateMipmap = GL_FALSE;
1491 }
1492#endif
1493
1494 DIRTY(tobj->dirty, g->neg_bitid);
1495 DIRTY(tobj->imageBit, g->neg_bitid);
1496 DIRTY(tl->dirty, g->neg_bitid);
1497 DIRTY(tb->dirty, g->neg_bitid);
1498}
1499
1500
1501void STATE_APIENTRY
1502crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
1503 GLint yoffset, GLint zoffset, GLsizei width,
1504 GLsizei height, GLsizei depth,
1505 GLenum format, GLsizei imageSize,
1506 const GLvoid * data)
1507{
1508 CRContext *g = GetCurrentContext();
1509 CRTextureState *t = &(g->texture);
1510 CRStateBits *sb = GetCurrentBits();
1511 CRTextureBits *tb = &(sb->texture);
1512 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1513 CRTextureObj *tobj = unit->currentTexture1D;
1514 CRTextureLevel *tl = tobj->level[0] + level;
1515
1516 FLUSH();
1517
1518 if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
1519 width, height, depth)) {
1520 return; /* GL error state already set */
1521 }
1522
1523#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1524 xoffset += tl->border;
1525 yoffset += tl->border;
1526 zoffset += tl->border;
1527
1528 if (xoffset == 0 && width == tl->width &&
1529 yoffset == 0 && height == tl->height &&
1530 zoffset == 0 && depth == tl->depth) {
1531 /* just memcpy */
1532 crMemcpy(tl->img, data, imageSize);
1533 }
1534 else {
1535 /* XXX this depends on the exact compression method */
1536 crWarning("Not implemented part crStateCompressedTexSubImage3DARB");
1537 }
1538#endif
1539
1540#ifdef CR_SGIS_generate_mipmap
1541 if (level == tobj->baseLevel && tobj->generateMipmap) {
1542 generate_mipmap(tobj, target);
1543 }
1544 else {
1545 tl->generateMipmap = GL_FALSE;
1546 }
1547#endif
1548
1549 DIRTY(tobj->dirty, g->neg_bitid);
1550 DIRTY(tobj->imageBit, g->neg_bitid);
1551 DIRTY(tl->dirty, g->neg_bitid);
1552 DIRTY(tb->dirty, g->neg_bitid);
1553}
1554
1555
1556void STATE_APIENTRY
1557crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
1558{
1559 CRContext *g = GetCurrentContext();
1560 CRTextureObj *tobj;
1561 CRTextureLevel *tl;
1562
1563 if (g->current.inBeginEnd)
1564 {
1565 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1566 "glGetCompressedTexImage called in begin/end");
1567 return;
1568 }
1569
1570 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1571 if (!tobj || !tl) {
1572 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1573 "glGetCompressedTexImage(invalid target or level)");
1574 return;
1575 }
1576
1577 if (!tl->compressed) {
1578 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1579 "glGetCompressedTexImage(not a compressed texture)");
1580 return;
1581 }
1582
1583#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1584 crMemcpy(img, tl->img, tl->bytes);
1585#else
1586 diff_api.GetCompressedTexImageARB(target, level, img);
1587#endif
1588}
1589
1590
1591void STATE_APIENTRY
1592crStateGetTexImage(GLenum target, GLint level, GLenum format,
1593 GLenum type, GLvoid * pixels)
1594{
1595 CRContext *g = GetCurrentContext();
1596 CRClientState *c = &(g->client);
1597 CRTextureObj *tobj;
1598 CRTextureLevel *tl;
1599
1600 if (g->current.inBeginEnd)
1601 {
1602 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1603 "glGetTexImage called in begin/end");
1604 return;
1605 }
1606
1607 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1608 if (!tobj || !tl) {
1609 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1610 "glGetTexImage(invalid target or level)");
1611 return;
1612 }
1613
1614 if (tl->compressed) {
1615 crWarning("glGetTexImage cannot decompress a compressed texture!");
1616 return;
1617 }
1618
1619 switch (format)
1620 {
1621 case GL_RED:
1622 case GL_GREEN:
1623 case GL_BLUE:
1624 case GL_ALPHA:
1625 case GL_RGB:
1626 case GL_RGBA:
1627 case GL_LUMINANCE:
1628 case GL_LUMINANCE_ALPHA:
1629 break;
1630 default:
1631 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1632 "glGetTexImage called with bogus format: %d", format);
1633 return;
1634 }
1635
1636 switch (type)
1637 {
1638 case GL_UNSIGNED_BYTE:
1639 case GL_BYTE:
1640 case GL_UNSIGNED_SHORT:
1641 case GL_SHORT:
1642 case GL_UNSIGNED_INT:
1643 case GL_INT:
1644 case GL_FLOAT:
1645 break;
1646 default:
1647 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1648 "glGetTexImage called with bogus type: %d", type);
1649 return;
1650 }
1651
1652#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1653#ifdef CR_OPENGL_VERSION_1_2
1654 if (target == GL_TEXTURE_3D)
1655 {
1656 crPixelCopy3D(tl->width, tl->height, tl->depth, (GLvoid *) pixels, format,
1657 type, NULL, (tl->img), format, type, &(c->pack));
1658 }
1659 else
1660#endif
1661 if ((target == GL_TEXTURE_1D) || (target == GL_TEXTURE_2D))
1662 {
1663 crPixelCopy2D(tl->width, tl->height, (GLvoid *) pixels, format, type, NULL, /* dst */
1664 tl->img, format, type, &(c->pack)); /* src */
1665 }
1666#else
1667 diff_api.GetTexImage(target, level, format, type, pixels);
1668#endif
1669}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette