VirtualBox

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

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

3D: Additional validation of glCopyTexImage2D arguments

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

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