VirtualBox

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

Last change on this file since 61571 was 46235, checked in by vboxsync, 12 years ago

crOpenGL: TexImagestate fixes + debugging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 51.5 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 crWarning("unexpected texTarget 0x%x", texTarget);
312 *obj = NULL;
313 *img = NULL;
314}
315
316
317/**
318 * Do parameter error checking for glTexImagexD functions.
319 * We'll call crStateError if we detect any errors, unless it's a proxy target.
320 * Return GL_TRUE if any errors, GL_FALSE if no errors.
321 */
322static GLboolean
323ErrorCheckTexImage(GLuint dims, GLenum target, GLint level,
324 GLsizei width, GLsizei height, GLsizei depth, GLint border)
325{
326 CRContext *g = GetCurrentContext();
327
328 if (g->current.inBeginEnd)
329 {
330 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
331 "glTexImage%uD called in Begin/End", dims);
332 return GL_TRUE;
333 }
334
335 /*
336 * Test target
337 */
338 switch (target)
339 {
340 case GL_TEXTURE_1D:
341 case GL_PROXY_TEXTURE_1D:
342 if (dims != 1) {
343 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
344 "glTexImage(invalid target=0x%x)", target);
345 return GL_TRUE;
346 }
347 break;
348 case GL_TEXTURE_2D:
349 case GL_PROXY_TEXTURE_2D:
350 if (dims != 2) {
351 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
352 "glTexImage(invalid target=0x%x)", target);
353 return GL_TRUE;
354 }
355 break;
356 case GL_TEXTURE_3D:
357 case GL_PROXY_TEXTURE_3D:
358 if (dims != 3) {
359 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
360 "glTexImage(invalid target=0x%x)", target);
361 return GL_TRUE;
362 }
363 break;
364#ifdef CR_NV_texture_rectangle
365 case GL_TEXTURE_RECTANGLE_NV:
366 case GL_PROXY_TEXTURE_RECTANGLE_NV:
367 if (dims != 2 || !g->extensions.NV_texture_rectangle) {
368 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
369 "glTexImage2D(invalid target=0x%x)", target);
370 return GL_TRUE;
371 }
372 break;
373#endif
374#ifdef CR_ARB_texture_cube_map
375 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
376 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
377 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
378 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
379 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
380 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
381 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
382 if (dims != 2 || !g->extensions.ARB_texture_cube_map) {
383 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
384 "glTexImage2D(invalid target=0x%x)", target);
385 return GL_TRUE;
386 }
387 break;
388#endif
389 default:
390 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
391 "glTexImage%uD(invalid target=0x%x)", dims, target);
392 return GL_TRUE;
393 }
394
395 /*
396 * Test level
397 */
398 if (level < 0 || level > MaxTextureLevel(g, target)) {
399 if (!IsProxyTarget(target))
400 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
401 "glTexImage%uD(level=%d)", dims, level);
402 return GL_TRUE;
403 }
404
405 /*
406 * Test border
407 */
408 if (border != 0 && border != 1) {
409 if (!IsProxyTarget(target))
410 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
411 "glTexImage%uD(border=%d)", dims, border);
412 return GL_TRUE;
413 }
414
415 if ((target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
416 target == GL_TEXTURE_RECTANGLE_NV) && border != 0) {
417 if (!IsProxyTarget(target))
418 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
419 "glTexImage2D(border=%d)", border);
420 return GL_TRUE;
421 }
422
423 /*
424 * Test width, height, depth
425 */
426 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
427 if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize)) {
428 if (!IsProxyTarget(target))
429 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
430 "glTexImage1D(width=%d)", width);
431 return GL_TRUE;
432 }
433 }
434 else if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
435 if (!isLegalSize(g, width - 2 * border, g->limits.maxTextureSize) ||
436 !isLegalSize(g, height - 2 * border, g->limits.maxTextureSize)) {
437 if (!IsProxyTarget(target))
438 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
439 "glTexImage2D(width=%d, height=%d)", width, height);
440 return GL_TRUE;
441 }
442 }
443 else if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
444 if (!isLegalSize(g, width - 2 * border, g->limits.max3DTextureSize) ||
445 !isLegalSize(g, height - 2 * border, g->limits.max3DTextureSize) ||
446 !isLegalSize(g, depth - 2 * border, g->limits.max3DTextureSize)) {
447 if (!IsProxyTarget(target))
448 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
449 "glTexImage3D(width=%d, height=%d, depth=%d)",
450 width, height, depth);
451 return GL_TRUE;
452 }
453 }
454 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
455 target == GL_TEXTURE_RECTANGLE_NV) {
456 if (width < 0 || width > (int) g->limits.maxRectTextureSize ||
457 height < 0 || height > (int) g->limits.maxRectTextureSize) {
458 if (!IsProxyTarget(target))
459 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
460 "glTexImage2D(width=%d, height=%d)", width, height);
461 return GL_TRUE;
462 }
463 }
464 else {
465 /* cube map */
466 if (!isLegalSize(g, width - 2*border, g->limits.maxCubeMapTextureSize) ||
467 !isLegalSize(g, height - 2*border, g->limits.maxCubeMapTextureSize) ||
468 width != height) {
469 if (!IsProxyTarget(target))
470 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
471 "glTexImage2D(width=%d, height=%d)", width, height);
472 return GL_TRUE;
473 }
474 }
475
476 /* OK, no errors */
477 return GL_FALSE;
478}
479
480
481/**
482 * Do error check for glTexSubImage() functions.
483 * We'll call crStateError if we detect any errors.
484 * Return GL_TRUE if any errors, GL_FALSE if no errors.
485 */
486static GLboolean
487ErrorCheckTexSubImage(GLuint dims, GLenum target, GLint level,
488 GLint xoffset, GLint yoffset, GLint zoffset,
489 GLsizei width, GLsizei height, GLsizei depth)
490{
491 CRContext *g = GetCurrentContext();
492 CRTextureObj *tobj;
493 CRTextureLevel *tl;
494
495 if (g->current.inBeginEnd) {
496 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
497 "glTexSubImage%uD called in Begin/End", dims);
498 return GL_TRUE;
499 }
500
501 if (dims == 1) {
502 if (target != GL_TEXTURE_1D) {
503 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
504 "glTexSubImage1D(target=0x%x)", target);
505 return GL_TRUE;
506 }
507 }
508 else if (dims == 2) {
509 if (target != GL_TEXTURE_2D &&
510 target != GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
511 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB &&
512 target != GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB &&
513 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB &&
514 target != GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB &&
515 target != GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB &&
516 target != GL_TEXTURE_RECTANGLE_NV) {
517 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
518 "glTexSubImage2D(target=0x%x)", target);
519 return GL_TRUE;
520 }
521 }
522 else if (dims == 3) {
523 if (target != GL_TEXTURE_3D) {
524 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
525 "glTexSubImage3D(target=0x%x)", target);
526 return GL_TRUE;
527 }
528 }
529
530 /* test level */
531 if (level < 0 || level > MaxTextureLevel(g, target)) {
532 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
533 "glTexSubImage%uD(level=%d)", dims, level);
534 return GL_TRUE;
535 }
536
537 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
538 if (!tobj || !tl) {
539 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
540 "glTexSubImage%uD(target or level)", dims);
541 return GL_TRUE;
542 }
543
544 /* test x/y/zoffset and size */
545 if (xoffset < -tl->border || xoffset + width > tl->width) {
546 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
547 "glTexSubImage%uD(xoffset=%d + width=%d > %d)",
548 dims, xoffset, width, tl->width);
549 return GL_TRUE;
550 }
551 if (dims > 1 && (yoffset < -tl->border || yoffset + height > tl->height)) {
552 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
553 "glTexSubImage%uD(yoffset=%d + height=%d > %d)",
554 dims, yoffset, height, tl->height);
555 return GL_TRUE;
556 }
557 if (dims > 2 && (zoffset < -tl->border || zoffset + depth > tl->depth)) {
558 crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
559 "glTexSubImage%uD(zoffset=%d and/or depth=%d)",
560 dims, zoffset, depth);
561 return GL_TRUE;
562 }
563
564 /* OK, no errors */
565 return GL_FALSE;
566}
567
568
569
570void STATE_APIENTRY
571crStateTexImage1D(GLenum target, GLint level, GLint internalFormat,
572 GLsizei width, GLint border, GLenum format,
573 GLenum type, const GLvoid * pixels)
574{
575 CRContext *g = GetCurrentContext();
576 CRTextureState *t = &(g->texture);
577 CRClientState *c = &(g->client);
578 CRTextureObj *tobj;
579 CRTextureLevel *tl;
580 CRStateBits *sb = GetCurrentBits();
581 CRTextureBits *tb = &(sb->texture);
582
583 FLUSH();
584
585 if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
586 if (IsProxyTarget(target)) {
587 /* clear all state, but don't generate error */
588 crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
589 }
590 else {
591 /* error was already recorded */
592 }
593 return;
594 }
595
596 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
597 CRASSERT(tobj);
598 CRASSERT(tl);
599
600 if (IsProxyTarget(target))
601 tl->bytes = 0;
602 else
603 tl->bytes = crImageSize(format, type, width, 1);
604
605#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
606 if (tl->bytes)
607 {
608 /* this is not a proxy texture target so alloc storage */
609 if (tl->img)
610 crFree(tl->img);
611 tl->img = (GLubyte *) crAlloc(tl->bytes);
612 if (!tl->img)
613 {
614 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
615 "glTexImage1D out of memory");
616 return;
617 }
618 if (pixels)
619 crPixelCopy1D((GLvoid *) tl->img, format, type,
620 pixels, format, type, width, &(c->unpack));
621 }
622#endif
623
624 tl->width = width;
625 tl->height = 1;
626 tl->depth = 1;
627 tl->format = format;
628 tl->border = border;
629 tl->internalFormat = internalFormat;
630 crStateTextureInitTextureFormat(tl, internalFormat);
631 tl->type = type;
632 tl->compressed = GL_FALSE;
633 if (width)
634 tl->bytesPerPixel = tl->bytes / width;
635 else
636 tl->bytesPerPixel = 0;
637
638#ifdef CR_SGIS_generate_mipmap
639 if (level == tobj->baseLevel && tobj->generateMipmap) {
640 generate_mipmap(tobj, target);
641 }
642 else {
643 tl->generateMipmap = GL_FALSE;
644 }
645#endif
646
647 /* XXX may need to do some fine-tuning here for proxy textures */
648 DIRTY(tobj->dirty, g->neg_bitid);
649 DIRTY(tobj->imageBit, g->neg_bitid);
650 DIRTY(tl->dirty, g->neg_bitid);
651 DIRTY(tb->dirty, g->neg_bitid);
652}
653
654static void crStateNukeMipmaps(CRTextureObj *tobj)
655{
656 int i, face;
657
658 for (face = 0; face < 6; face++)
659 {
660 CRTextureLevel *levels = tobj->level[face];
661
662 if (levels)
663 {
664 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++)
665 {
666 if (levels[i].img)
667 {
668 crFree(levels[i].img);
669 }
670 levels[i].img = NULL;
671 levels[i].bytes = 0;
672 levels[i].internalFormat = GL_ONE;
673 levels[i].format = GL_RGBA;
674 levels[i].type = GL_UNSIGNED_BYTE;
675
676 }
677 }
678 }
679}
680
681void STATE_APIENTRY
682crStateCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
683{
684 CRContext *g = GetCurrentContext();
685 CRTextureObj *tobj = NULL;
686 CRTextureLevel *tl = NULL;
687
688 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
689 CRASSERT(tobj);
690 CRASSERT(tl);
691
692 crStateNukeMipmaps(tobj);
693
694 tl->bytes = crImageSize(GL_RGBA, GL_UNSIGNED_BYTE, width, height);
695
696 tl->width = width;
697 tl->height = height;
698 tl->depth = 1;
699 tl->format = GL_RGBA;
700 tl->internalFormat = internalFormat;
701 crStateTextureInitTextureFormat(tl, internalFormat);
702 tl->border = border;
703 tl->type = GL_UNSIGNED_BYTE;
704 tl->compressed = GL_FALSE;
705 if (width && height)
706 {
707 tl->bytesPerPixel = tl->bytes / (width * height);
708 }
709 else
710 tl->bytesPerPixel = 0;
711
712#ifdef CR_SGIS_generate_mipmap
713 if (level == tobj->baseLevel && tobj->generateMipmap) {
714 generate_mipmap(tobj, target);
715 }
716 else {
717 tl->generateMipmap = GL_FALSE;
718 }
719#endif
720}
721
722void STATE_APIENTRY
723crStateTexImage2D(GLenum target, GLint level, GLint internalFormat,
724 GLsizei width, GLsizei height, GLint border,
725 GLenum format, GLenum type, const GLvoid * pixels)
726{
727 CRContext *g = GetCurrentContext();
728 CRTextureState *t = &(g->texture);
729 CRClientState *c = &(g->client);
730 CRTextureObj *tobj = NULL;
731 CRTextureLevel *tl = NULL;
732 CRStateBits *sb = GetCurrentBits();
733 CRTextureBits *tb = &(sb->texture);
734 const int is_distrib = ((type == GL_TRUE) || (type == GL_FALSE));
735
736 FLUSH();
737
738 /* NOTE: we skip parameter error checking if this is a distributed
739 * texture! The user better provide correct parameters!!!
740 */
741 if (!is_distrib
742 && ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
743 if (IsProxyTarget(target)) {
744 /* clear all state, but don't generate error */
745 crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
746 }
747 else {
748 /* error was already recorded */
749 }
750 return;
751 }
752
753 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
754 CRASSERT(tobj);
755 CRASSERT(tl);
756
757 if (level==tobj->baseLevel && (tl->width!=width || tl->height!=height))
758 {
759 crStateNukeMipmaps(tobj);
760 }
761
762 /* compute size of image buffer */
763 if (is_distrib) {
764 tl->bytes = crStrlen((char *) pixels) + 1;
765 tl->bytes += crImageSize(format, GL_UNSIGNED_BYTE, width, height);
766 }
767 else if (IsProxyTarget(target)) {
768 tl->bytes = 0;
769 }
770 else {
771 tl->bytes = crImageSize(format, type, width, height);
772 }
773
774#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
775 /* allocate the image buffer and fill it */
776 if (tl->bytes)
777 {
778 /* this is not a proxy texture target so alloc storage */
779 if (tl->img)
780 crFree(tl->img);
781 tl->img = (GLubyte *) crAlloc(tl->bytes);
782 if (!tl->img)
783 {
784 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
785 "glTexImage2D out of memory");
786 return;
787 }
788 if (pixels)
789 {
790 if (is_distrib)
791 {
792 crMemcpy((void *) tl->img, (void *) pixels, tl->bytes);
793 }
794 else
795 {
796 crPixelCopy2D(width, height,
797 (GLvoid *) tl->img, format, type, NULL, /* dst */
798 pixels, format, type, &(c->unpack)); /* src */
799 }
800 }
801 }
802#endif
803
804 tl->width = width;
805 tl->height = height;
806 tl->depth = 1;
807 tl->format = format;
808 tl->internalFormat = internalFormat;
809 crStateTextureInitTextureFormat(tl, internalFormat);
810 tl->border = border;
811 tl->type = type;
812 tl->compressed = GL_FALSE;
813 if (width && height)
814 {
815 if (is_distrib)
816 tl->bytesPerPixel = 3; /* only support GL_RGB */
817 else
818 tl->bytesPerPixel = tl->bytes / (width * height);
819 }
820 else
821 tl->bytesPerPixel = 0;
822
823#ifdef CR_SGIS_generate_mipmap
824 if (level == tobj->baseLevel && tobj->generateMipmap) {
825 generate_mipmap(tobj, target);
826 }
827 else {
828 tl->generateMipmap = GL_FALSE;
829 }
830#endif
831
832 /* XXX may need to do some fine-tuning here for proxy textures */
833 DIRTY(tobj->dirty, g->neg_bitid);
834 DIRTY(tobj->imageBit, g->neg_bitid);
835 DIRTY(tl->dirty, g->neg_bitid);
836 DIRTY(tb->dirty, g->neg_bitid);
837
838#ifdef CR_DUMP_TEXTURES_2D
839 if (pixels)
840 {
841 GLint w,h;
842 char *data;
843
844 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
845 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
846
847 data = crAlloc(w*h*4);
848 if (!data) crError("no memory!");
849 diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
850 crDumpTGA(w, h, data);
851 crFree(data);
852 }
853#endif
854}
855
856#if defined( CR_OPENGL_VERSION_1_2 ) || defined( GL_EXT_texture3D )
857void STATE_APIENTRY
858crStateTexImage3D(GLenum target, GLint level,
859 GLint internalFormat,
860 GLsizei width, GLsizei height,
861 GLsizei depth, GLint border,
862 GLenum format, GLenum type, const GLvoid * pixels)
863{
864 CRContext *g = GetCurrentContext();
865 CRTextureState *t = &(g->texture);
866 CRClientState *c = &(g->client);
867 CRTextureObj *tobj = NULL;
868 CRTextureLevel *tl = NULL;
869 CRStateBits *sb = GetCurrentBits();
870 CRTextureBits *tb = &(sb->texture);
871
872 FLUSH();
873
874 if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
875 if (IsProxyTarget(target)) {
876 /* clear all state, but don't generate error */
877 crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
878 }
879 else {
880 /* error was already recorded */
881 }
882 return;
883 }
884
885 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
886 CRASSERT(tobj);
887 CRASSERT(tl);
888
889 if (IsProxyTarget(target))
890 tl->bytes = 0;
891 else
892 tl->bytes = crTextureSize(format, type, width, height, depth);
893
894#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
895 if (tl->bytes)
896 {
897 /* this is not a proxy texture target so alloc storage */
898 if (tl->img)
899 crFree(tl->img);
900 tl->img = (GLubyte *) crAlloc(tl->bytes);
901 if (!tl->img)
902 {
903 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
904 "glTexImage3D out of memory");
905 return;
906 }
907 if (pixels)
908 crPixelCopy3D(width, height, depth, (GLvoid *) (tl->img), format, type,
909 NULL, pixels, format, type, &(c->unpack));
910 }
911#endif
912
913 tl->internalFormat = internalFormat;
914 tl->border = border;
915 tl->width = width;
916 tl->height = height;
917 tl->depth = depth;
918 tl->format = format;
919 tl->type = type;
920 tl->compressed = GL_FALSE;
921
922#ifdef CR_SGIS_generate_mipmap
923 if (level == tobj->baseLevel && tobj->generateMipmap) {
924 generate_mipmap(tobj, target);
925 }
926 else {
927 tl->generateMipmap = GL_FALSE;
928 }
929#endif
930
931 /* XXX may need to do some fine-tuning here for proxy textures */
932 DIRTY(tobj->dirty, g->neg_bitid);
933 DIRTY(tobj->imageBit, g->neg_bitid);
934 DIRTY(tl->dirty, g->neg_bitid);
935 DIRTY(tb->dirty, g->neg_bitid);
936}
937#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
938
939
940#ifdef GL_EXT_texture3D
941void STATE_APIENTRY
942crStateTexImage3DEXT(GLenum target, GLint level,
943 GLenum internalFormat,
944 GLsizei width, GLsizei height, GLsizei depth,
945 GLint border, GLenum format, GLenum type,
946 const GLvoid * pixels)
947{
948 crStateTexImage3D(target, level, (GLint) internalFormat, width, height,
949 depth, border, format, type, pixels);
950}
951#endif /* GL_EXT_texture3D */
952
953
954void STATE_APIENTRY
955crStateTexSubImage1D(GLenum target, GLint level, GLint xoffset,
956 GLsizei width, GLenum format,
957 GLenum type, const GLvoid * pixels)
958{
959 CRContext *g = GetCurrentContext();
960 CRTextureState *t = &(g->texture);
961 CRClientState *c = &(g->client);
962 CRStateBits *sb = GetCurrentBits();
963 CRTextureBits *tb = &(sb->texture);
964 CRTextureUnit *unit = t->unit + t->curTextureUnit;
965 CRTextureObj *tobj = unit->currentTexture1D;
966 CRTextureLevel *tl = tobj->level[0] + level;
967
968 FLUSH();
969
970 if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0,
971 width, 1, 1)) {
972 return; /* GL error state already set */
973 }
974
975#ifdef DEBUG_misha
976 CRASSERT(tl->bytes);
977 CRASSERT(tl->height);
978 CRASSERT(tl->width);
979 CRASSERT(tl->depth);
980#endif
981
982#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
983 xoffset += tl->border;
984
985 crPixelCopy1D((void *) (tl->img + xoffset * tl->bytesPerPixel),
986 tl->format, tl->type,
987 pixels, format, type, width, &(c->unpack));
988#endif
989
990#ifdef CR_SGIS_generate_mipmap
991 if (level == tobj->baseLevel && tobj->generateMipmap) {
992 generate_mipmap(tobj, target);
993 }
994 else {
995 tl->generateMipmap = GL_FALSE;
996 }
997#endif
998
999 DIRTY(tobj->dirty, g->neg_bitid);
1000 DIRTY(tobj->imageBit, g->neg_bitid);
1001 DIRTY(tl->dirty, g->neg_bitid);
1002 DIRTY(tb->dirty, g->neg_bitid);
1003}
1004
1005
1006void STATE_APIENTRY
1007crStateTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
1008 GLsizei width, GLsizei height,
1009 GLenum format, GLenum type, const GLvoid * pixels)
1010{
1011 CRContext *g = GetCurrentContext();
1012 CRClientState *c = &(g->client);
1013 CRStateBits *sb = GetCurrentBits();
1014 CRTextureBits *tb = &(sb->texture);
1015 CRTextureObj *tobj;
1016 CRTextureLevel *tl;
1017 GLubyte *subimg = NULL;
1018 GLubyte *img = NULL;
1019#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1020 GLubyte *src;
1021 int i;
1022#endif
1023
1024 FLUSH();
1025
1026 if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
1027 width, height, 1)) {
1028 return; /* GL error state already set */
1029 }
1030
1031 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1032 CRASSERT(tobj);
1033 CRASSERT(tl);
1034
1035#ifdef DEBUG_misha
1036 CRASSERT(tl->bytes);
1037 CRASSERT(tl->height);
1038 CRASSERT(tl->width);
1039 CRASSERT(tl->depth);
1040#endif
1041
1042#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1043 xoffset += tl->border;
1044 yoffset += tl->border;
1045
1046 subimg = (GLubyte *) crAlloc(crImageSize(tl->format, tl->type, width, height));
1047
1048 crPixelCopy2D(width, height, subimg, tl->format, tl->type, NULL, /* dst */
1049 pixels, format, type, &(c->unpack)); /* src */
1050
1051 img = tl->img +
1052 xoffset * tl->bytesPerPixel + yoffset * tl->width * tl->bytesPerPixel;
1053
1054 src = subimg;
1055
1056 /* Copy the data into the texture */
1057 for (i = 0; i < height; i++)
1058 {
1059 crMemcpy(img, src, tl->bytesPerPixel * width);
1060 img += tl->width * tl->bytesPerPixel;
1061 src += width * tl->bytesPerPixel;
1062 }
1063
1064 crFree(subimg);
1065#endif
1066
1067#ifdef CR_SGIS_generate_mipmap
1068 if (level == tobj->baseLevel && tobj->generateMipmap) {
1069 generate_mipmap(tobj, target);
1070 }
1071 else {
1072 tl->generateMipmap = GL_FALSE;
1073 }
1074#endif
1075
1076 DIRTY(tobj->dirty, g->neg_bitid);
1077 DIRTY(tobj->imageBit, g->neg_bitid);
1078 DIRTY(tl->dirty, g->neg_bitid);
1079 DIRTY(tb->dirty, g->neg_bitid);
1080
1081#ifdef CR_DUMP_TEXTURES_2D
1082 {
1083 GLint w,h;
1084 char *data;
1085
1086 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
1087 diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
1088
1089 data = crAlloc(w*h*4);
1090 if (!data) crError("no memory!");
1091 diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
1092 crDumpTGA(w, h, data);
1093 crFree(data);
1094 }
1095#endif
1096}
1097
1098#if defined( CR_OPENGL_VERSION_1_2 )
1099void STATE_APIENTRY
1100crStateTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
1101 GLint zoffset, GLsizei width, GLsizei height,
1102 GLsizei depth, GLenum format, GLenum type,
1103 const GLvoid * pixels)
1104{
1105 CRContext *g = GetCurrentContext();
1106 CRTextureState *t = &(g->texture);
1107 CRClientState *c = &(g->client);
1108 CRStateBits *sb = GetCurrentBits();
1109 CRTextureBits *tb = &(sb->texture);
1110 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1111 CRTextureObj *tobj = unit->currentTexture3D;
1112 CRTextureLevel *tl = tobj->level[0] + level;
1113 GLubyte *subimg = NULL;
1114 GLubyte *img = NULL;
1115#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1116 GLubyte *src;
1117 int i;
1118#endif
1119
1120 FLUSH();
1121
1122 if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
1123 width, height, depth)) {
1124 return; /* GL error state already set */
1125 }
1126
1127#ifdef DEBUG_misha
1128 CRASSERT(target == GL_TEXTURE_3D);
1129 CRASSERT(tl->bytes);
1130 CRASSERT(tl->height);
1131 CRASSERT(tl->width);
1132 CRASSERT(tl->depth);
1133#endif
1134
1135#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1136 xoffset += tl->border;
1137 yoffset += tl->border;
1138 zoffset += tl->border;
1139
1140 subimg =
1141 (GLubyte *)
1142 crAlloc(crTextureSize(tl->format, tl->type, width, height, depth));
1143
1144 crPixelCopy3D(width, height, depth, subimg, tl->format, tl->type, NULL,
1145 pixels, format, type, &(c->unpack));
1146
1147 img = tl->img + xoffset * tl->bytesPerPixel +
1148 yoffset * tl->width * tl->bytesPerPixel +
1149 zoffset * tl->width * tl->height * tl->bytesPerPixel;
1150
1151 src = subimg;
1152
1153 /* Copy the data into the texture */
1154 for (i = 0; i < depth; i++)
1155 {
1156 crMemcpy(img, src, tl->bytesPerPixel * width * height);
1157 img += tl->width * tl->height * tl->bytesPerPixel;
1158 src += width * height * tl->bytesPerPixel;
1159 }
1160
1161 crFree(subimg);
1162#endif
1163
1164#ifdef CR_SGIS_generate_mipmap
1165 if (level == tobj->baseLevel && tobj->generateMipmap) {
1166 generate_mipmap(tobj, target);
1167 }
1168 else {
1169 tl->generateMipmap = GL_FALSE;
1170 }
1171#endif
1172
1173 DIRTY(tobj->dirty, g->neg_bitid);
1174 DIRTY(tobj->imageBit, g->neg_bitid);
1175 DIRTY(tl->dirty, g->neg_bitid);
1176 DIRTY(tb->dirty, g->neg_bitid);
1177}
1178#endif /* CR_OPENGL_VERSION_1_2 || GL_EXT_texture3D */
1179
1180
1181void STATE_APIENTRY
1182crStateCompressedTexImage1DARB(GLenum target, GLint level,
1183 GLenum internalFormat, GLsizei width,
1184 GLint border, GLsizei imageSize,
1185 const GLvoid * data)
1186{
1187 CRContext *g = GetCurrentContext();
1188 CRTextureState *t = &(g->texture);
1189 CRTextureObj *tobj;
1190 CRTextureLevel *tl;
1191 CRStateBits *sb = GetCurrentBits();
1192 CRTextureBits *tb = &(sb->texture);
1193
1194 FLUSH();
1195
1196 if (ErrorCheckTexImage(1, target, level, width, 1, 1, border)) {
1197 if (IsProxyTarget(target)) {
1198 /* clear all state, but don't generate error */
1199 crStateTextureInitTextureObj(g, &(t->proxy1D), 0, GL_TEXTURE_1D);
1200 }
1201 else {
1202 /* error was already recorded */
1203 }
1204 return;
1205 }
1206
1207 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1208 CRASSERT(tobj);
1209 CRASSERT(tl);
1210
1211 if (IsProxyTarget(target))
1212 tl->bytes = 0;
1213 else
1214 tl->bytes = imageSize;
1215
1216#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1217 if (tl->bytes)
1218 {
1219 /* this is not a proxy texture target so alloc storage */
1220 if (tl->img)
1221 crFree(tl->img);
1222 tl->img = (GLubyte *) crAlloc(tl->bytes);
1223 if (!tl->img)
1224 {
1225 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1226 "glTexImage1D out of memory");
1227 return;
1228 }
1229 if (data)
1230 crMemcpy(tl->img, data, imageSize);
1231 }
1232#endif
1233
1234 tl->width = width;
1235 tl->height = 1;
1236 tl->depth = 1;
1237 tl->border = border;
1238 tl->format = GL_NONE;
1239 tl->type = GL_NONE;
1240 tl->internalFormat = internalFormat;
1241 crStateTextureInitTextureFormat(tl, internalFormat);
1242 tl->compressed = GL_TRUE;
1243 tl->bytesPerPixel = 0; /* n/a */
1244
1245#ifdef CR_SGIS_generate_mipmap
1246 if (level == tobj->baseLevel && tobj->generateMipmap) {
1247 generate_mipmap(tobj, target);
1248 }
1249 else {
1250 tl->generateMipmap = GL_FALSE;
1251 }
1252#endif
1253
1254 DIRTY(tobj->dirty, g->neg_bitid);
1255 DIRTY(tobj->imageBit, g->neg_bitid);
1256 DIRTY(tl->dirty, g->neg_bitid);
1257 DIRTY(tb->dirty, g->neg_bitid);
1258}
1259
1260
1261void STATE_APIENTRY
1262crStateCompressedTexImage2DARB(GLenum target, GLint level,
1263 GLenum internalFormat, GLsizei width,
1264 GLsizei height, GLint border,
1265 GLsizei imageSize, const GLvoid * data)
1266{
1267 CRContext *g = GetCurrentContext();
1268 CRTextureState *t = &(g->texture);
1269 CRTextureObj *tobj = NULL;
1270 CRTextureLevel *tl = NULL;
1271 CRStateBits *sb = GetCurrentBits();
1272 CRTextureBits *tb = &(sb->texture);
1273
1274 FLUSH();
1275
1276 if (ErrorCheckTexImage(2, target, level, width, height, 1, border)) {
1277 if (IsProxyTarget(target)) {
1278 /* clear all state, but don't generate error */
1279 crStateTextureInitTextureObj(g, &(t->proxy2D), 0, GL_TEXTURE_2D);
1280 }
1281 else {
1282 /* error was already recorded */
1283 }
1284 return;
1285 }
1286
1287 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1288 CRASSERT(tobj);
1289 CRASSERT(tl);
1290
1291 if (IsProxyTarget(target))
1292 tl->bytes = 0;
1293 else
1294 tl->bytes = imageSize;
1295
1296#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1297 if (tl->bytes)
1298 {
1299 /* this is not a proxy texture target so alloc storage */
1300 if (tl->img)
1301 crFree(tl->img);
1302 tl->img = (GLubyte *) crAlloc(tl->bytes);
1303 if (!tl->img)
1304 {
1305 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1306 "glTexImage2D out of memory");
1307 return;
1308 }
1309 if (data)
1310 crMemcpy(tl->img, data, imageSize);
1311 }
1312#endif
1313
1314 tl->width = width;
1315 tl->height = height;
1316 tl->depth = 1;
1317 tl->border = border;
1318 tl->format = GL_NONE;
1319 tl->type = GL_NONE;
1320 tl->internalFormat = internalFormat;
1321 crStateTextureInitTextureFormat(tl, internalFormat);
1322 tl->compressed = GL_TRUE;
1323 tl->bytesPerPixel = 0; /* n/a */
1324
1325#ifdef CR_SGIS_generate_mipmap
1326 if (level == tobj->baseLevel && tobj->generateMipmap) {
1327 generate_mipmap(tobj, target);
1328 }
1329 else {
1330 tl->generateMipmap = GL_FALSE;
1331 }
1332#endif
1333
1334 /* XXX may need to do some fine-tuning here for proxy textures */
1335 DIRTY(tobj->dirty, g->neg_bitid);
1336 DIRTY(tobj->imageBit, g->neg_bitid);
1337 DIRTY(tl->dirty, g->neg_bitid);
1338 DIRTY(tb->dirty, g->neg_bitid);
1339}
1340
1341
1342void STATE_APIENTRY
1343crStateCompressedTexImage3DARB(GLenum target, GLint level,
1344 GLenum internalFormat, GLsizei width,
1345 GLsizei height, GLsizei depth, GLint border,
1346 GLsizei imageSize, const GLvoid * data)
1347{
1348 CRContext *g = GetCurrentContext();
1349 CRTextureState *t = &(g->texture);
1350 CRTextureObj *tobj = NULL;
1351 CRTextureLevel *tl = NULL;
1352 CRStateBits *sb = GetCurrentBits();
1353 CRTextureBits *tb = &(sb->texture);
1354
1355 FLUSH();
1356
1357 if (ErrorCheckTexImage(3, target, level, width, height, depth, border)) {
1358 if (IsProxyTarget(target)) {
1359 /* clear all state, but don't generate error */
1360 crStateTextureInitTextureObj(g, &(t->proxy3D), 0, GL_TEXTURE_3D);
1361 }
1362 else {
1363 /* error was already recorded */
1364 }
1365 return;
1366 }
1367
1368 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1369 CRASSERT(tobj);
1370 CRASSERT(tl);
1371
1372 if (IsProxyTarget(target))
1373 tl->bytes = 0;
1374 else
1375 tl->bytes = imageSize;
1376
1377#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1378 if (tl->bytes)
1379 {
1380 /* this is not a proxy texture target so alloc storage */
1381 if (tl->img)
1382 crFree(tl->img);
1383 tl->img = (GLubyte *) crAlloc(tl->bytes);
1384 if (!tl->img)
1385 {
1386 crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY,
1387 "glCompressedTexImage3D out of memory");
1388 return;
1389 }
1390 if (data)
1391 crMemcpy(tl->img, data, imageSize);
1392 }
1393#endif
1394
1395 tl->width = width;
1396 tl->height = height;
1397 tl->depth = depth;
1398 tl->border = border;
1399 tl->format = GL_NONE;
1400 tl->type = GL_NONE;
1401 tl->internalFormat = internalFormat;
1402 crStateTextureInitTextureFormat(tl, internalFormat);
1403 tl->compressed = GL_TRUE;
1404 tl->bytesPerPixel = 0; /* n/a */
1405
1406#ifdef CR_SGIS_generate_mipmap
1407 if (level == tobj->baseLevel && tobj->generateMipmap) {
1408 generate_mipmap(tobj, target);
1409 }
1410 else {
1411 tl->generateMipmap = GL_FALSE;
1412 }
1413#endif
1414
1415 /* XXX may need to do some fine-tuning here for proxy textures */
1416 DIRTY(tobj->dirty, g->neg_bitid);
1417 DIRTY(tobj->imageBit, g->neg_bitid);
1418 DIRTY(tl->dirty, g->neg_bitid);
1419 DIRTY(tb->dirty, g->neg_bitid);
1420}
1421
1422
1423void STATE_APIENTRY
1424crStateCompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
1425 GLsizei width, GLenum format,
1426 GLsizei imageSize, const GLvoid * data)
1427{
1428 CRContext *g = GetCurrentContext();
1429 CRTextureState *t = &(g->texture);
1430 CRStateBits *sb = GetCurrentBits();
1431 CRTextureBits *tb = &(sb->texture);
1432 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1433 CRTextureObj *tobj = unit->currentTexture1D;
1434 CRTextureLevel *tl = tobj->level[0] + level;
1435
1436 FLUSH();
1437
1438 if (ErrorCheckTexSubImage(1, target, level, xoffset, 0, 0, width, 1, 1)) {
1439 return; /* GL error state already set */
1440 }
1441
1442#ifdef DEBUG_misha
1443 CRASSERT(target == GL_TEXTURE_1D);
1444 CRASSERT(tl->bytes);
1445 CRASSERT(tl->height);
1446 CRASSERT(tl->width);
1447 CRASSERT(tl->depth);
1448#endif
1449
1450#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1451 xoffset += tl->border;
1452
1453 if (xoffset == 0 && width == tl->width) {
1454 /* just memcpy */
1455 crMemcpy(tl->img, data, imageSize);
1456 }
1457 else {
1458 /* XXX this depends on the exact compression method */
1459 crWarning("Not implemented part crStateCompressedTexSubImage1DARB");
1460 }
1461#endif
1462
1463#ifdef CR_SGIS_generate_mipmap
1464 if (level == tobj->baseLevel && tobj->generateMipmap) {
1465 generate_mipmap(tobj, target);
1466 }
1467 else {
1468 tl->generateMipmap = GL_FALSE;
1469 }
1470#endif
1471
1472 DIRTY(tobj->dirty, g->neg_bitid);
1473 DIRTY(tobj->imageBit, g->neg_bitid);
1474 DIRTY(tl->dirty, g->neg_bitid);
1475 DIRTY(tb->dirty, g->neg_bitid);
1476}
1477
1478
1479void STATE_APIENTRY
1480crStateCompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
1481 GLint yoffset, GLsizei width,
1482 GLsizei height, GLenum format,
1483 GLsizei imageSize, const GLvoid * data)
1484{
1485 CRContext *g = GetCurrentContext();
1486 CRTextureState *t = &(g->texture);
1487 CRStateBits *sb = GetCurrentBits();
1488 CRTextureBits *tb = &(sb->texture);
1489 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1490 CRTextureObj *tobj = unit->currentTexture2D;
1491 CRTextureLevel *tl = tobj->level[0] + level;
1492
1493 FLUSH();
1494
1495#ifdef DEBUG_misha
1496 CRASSERT(target == GL_TEXTURE_2D);
1497 CRASSERT(tl->bytes);
1498 CRASSERT(tl->height);
1499 CRASSERT(tl->width);
1500 CRASSERT(tl->depth);
1501#endif
1502
1503 if (ErrorCheckTexSubImage(2, target, level, xoffset, yoffset, 0,
1504 width, height, 1)) {
1505 return; /* GL error state already set */
1506 }
1507
1508#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1509 xoffset += tl->border;
1510 yoffset += tl->border;
1511
1512 if (xoffset == 0 && width == tl->width
1513 && yoffset == 0 && height == tl->height)
1514 {
1515 /* just memcpy */
1516 crMemcpy(tl->img, data, imageSize);
1517 }
1518 else {
1519 /* XXX this depends on the exact compression method */
1520 crWarning("Not implemented part crStateCompressedTexSubImage2DARB");
1521 }
1522#endif
1523
1524#ifdef CR_SGIS_generate_mipmap
1525 if (level == tobj->baseLevel && tobj->generateMipmap) {
1526 generate_mipmap(tobj, target);
1527 }
1528 else {
1529 tl->generateMipmap = GL_FALSE;
1530 }
1531#endif
1532
1533 DIRTY(tobj->dirty, g->neg_bitid);
1534 DIRTY(tobj->imageBit, g->neg_bitid);
1535 DIRTY(tl->dirty, g->neg_bitid);
1536 DIRTY(tb->dirty, g->neg_bitid);
1537}
1538
1539
1540void STATE_APIENTRY
1541crStateCompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
1542 GLint yoffset, GLint zoffset, GLsizei width,
1543 GLsizei height, GLsizei depth,
1544 GLenum format, GLsizei imageSize,
1545 const GLvoid * data)
1546{
1547 CRContext *g = GetCurrentContext();
1548 CRTextureState *t = &(g->texture);
1549 CRStateBits *sb = GetCurrentBits();
1550 CRTextureBits *tb = &(sb->texture);
1551 CRTextureUnit *unit = t->unit + t->curTextureUnit;
1552 CRTextureObj *tobj = unit->currentTexture3D;
1553 CRTextureLevel *tl = tobj->level[0] + level;
1554
1555 FLUSH();
1556
1557#ifdef DEBUG_misha
1558 CRASSERT(target == GL_TEXTURE_3D);
1559 CRASSERT(tl->bytes);
1560 CRASSERT(tl->height);
1561 CRASSERT(tl->width);
1562 CRASSERT(tl->depth);
1563#endif
1564
1565 if (ErrorCheckTexSubImage(3, target, level, xoffset, yoffset, zoffset,
1566 width, height, depth)) {
1567 return; /* GL error state already set */
1568 }
1569
1570#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1571 xoffset += tl->border;
1572 yoffset += tl->border;
1573 zoffset += tl->border;
1574
1575 if (xoffset == 0 && width == tl->width &&
1576 yoffset == 0 && height == tl->height &&
1577 zoffset == 0 && depth == tl->depth) {
1578 /* just memcpy */
1579 crMemcpy(tl->img, data, imageSize);
1580 }
1581 else {
1582 /* XXX this depends on the exact compression method */
1583 crWarning("Not implemented part crStateCompressedTexSubImage3DARB");
1584 }
1585#endif
1586
1587#ifdef CR_SGIS_generate_mipmap
1588 if (level == tobj->baseLevel && tobj->generateMipmap) {
1589 generate_mipmap(tobj, target);
1590 }
1591 else {
1592 tl->generateMipmap = GL_FALSE;
1593 }
1594#endif
1595
1596 DIRTY(tobj->dirty, g->neg_bitid);
1597 DIRTY(tobj->imageBit, g->neg_bitid);
1598 DIRTY(tl->dirty, g->neg_bitid);
1599 DIRTY(tb->dirty, g->neg_bitid);
1600}
1601
1602
1603void STATE_APIENTRY
1604crStateGetCompressedTexImageARB(GLenum target, GLint level, GLvoid * img)
1605{
1606 CRContext *g = GetCurrentContext();
1607 CRTextureObj *tobj;
1608 CRTextureLevel *tl;
1609
1610 if (g->current.inBeginEnd)
1611 {
1612 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1613 "glGetCompressedTexImage called in begin/end");
1614 return;
1615 }
1616
1617 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1618 if (!tobj || !tl) {
1619 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1620 "glGetCompressedTexImage(invalid target or level)");
1621 return;
1622 }
1623
1624 if (!tl->compressed) {
1625 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1626 "glGetCompressedTexImage(not a compressed texture)");
1627 return;
1628 }
1629
1630#ifdef DEBUG_misha
1631 CRASSERT(tl->bytes);
1632 CRASSERT(tl->height);
1633 CRASSERT(tl->width);
1634 CRASSERT(tl->depth);
1635#endif
1636
1637#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1638 crMemcpy(img, tl->img, tl->bytes);
1639#else
1640 diff_api.GetCompressedTexImageARB(target, level, img);
1641#endif
1642}
1643
1644
1645void STATE_APIENTRY
1646crStateGetTexImage(GLenum target, GLint level, GLenum format,
1647 GLenum type, GLvoid * pixels)
1648{
1649 CRContext *g = GetCurrentContext();
1650 CRClientState *c = &(g->client);
1651 CRTextureObj *tobj;
1652 CRTextureLevel *tl;
1653
1654 if (g->current.inBeginEnd)
1655 {
1656 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
1657 "glGetTexImage called in begin/end");
1658 return;
1659 }
1660
1661 crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
1662 if (!tobj || !tl) {
1663 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1664 "glGetTexImage(invalid target or level)");
1665 return;
1666 }
1667
1668 if (tl->compressed) {
1669 crWarning("glGetTexImage cannot decompress a compressed texture!");
1670 return;
1671 }
1672
1673#ifdef DEBUG_misha
1674 CRASSERT(tl->bytes);
1675 CRASSERT(tl->height);
1676 CRASSERT(tl->width);
1677 CRASSERT(tl->depth);
1678#endif
1679
1680 switch (format)
1681 {
1682 case GL_RED:
1683 case GL_GREEN:
1684 case GL_BLUE:
1685 case GL_ALPHA:
1686 case GL_RGB:
1687 case GL_RGBA:
1688 case GL_LUMINANCE:
1689 case GL_LUMINANCE_ALPHA:
1690 break;
1691 default:
1692 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1693 "glGetTexImage called with bogus format: %d", format);
1694 return;
1695 }
1696
1697 switch (type)
1698 {
1699 case GL_UNSIGNED_BYTE:
1700 case GL_BYTE:
1701 case GL_UNSIGNED_SHORT:
1702 case GL_SHORT:
1703 case GL_UNSIGNED_INT:
1704 case GL_INT:
1705 case GL_FLOAT:
1706 break;
1707 default:
1708 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
1709 "glGetTexImage called with bogus type: %d", type);
1710 return;
1711 }
1712
1713#ifndef CR_STATE_NO_TEXTURE_IMAGE_STORE
1714#ifdef CR_OPENGL_VERSION_1_2
1715 if (target == GL_TEXTURE_3D)
1716 {
1717 crPixelCopy3D(tl->width, tl->height, tl->depth, (GLvoid *) pixels, format,
1718 type, NULL, (tl->img), format, type, &(c->pack));
1719 }
1720 else
1721#endif
1722 if ((target == GL_TEXTURE_1D) || (target == GL_TEXTURE_2D))
1723 {
1724 crPixelCopy2D(tl->width, tl->height, (GLvoid *) pixels, format, type, NULL, /* dst */
1725 tl->img, format, type, &(c->pack)); /* src */
1726 }
1727#else
1728 diff_api.GetTexImage(target, level, format, type, pixels);
1729#endif
1730}
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