VirtualBox

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

Last change on this file since 78105 was 78105, checked in by vboxsync, 6 years ago

GuestHost/OpenGL,HostServices/SharedOpenGL: Updates bugref:9407

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

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