VirtualBox

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

最後變更 在這個檔案從76384是 73223,由 vboxsync 提交於 6 年 前

3D: texture unpacking reworked, bugref:9192. Merged r123597, r123598, r123600, r123601, r123755.

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

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