VirtualBox

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

Last change on this file since 68474 was 63199, checked in by vboxsync, 8 years ago

GuestHost/OpenGL: warnings (gcc).

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