Index: trunk/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h	(revision 25153)
+++ trunk/src/VBox/GuestHost/OpenGL/include/state/cr_texture.h	(revision 25154)
@@ -22,4 +22,6 @@
  */
 #define CR_STATE_NO_TEXTURE_IMAGE_STORE
+
+#define CR_MAX_MIPMAP_LEVELS 20
 
 typedef struct {
Index: trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 25153)
+++ trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c	(revision 25154)
@@ -54,7 +54,4 @@
  */
 
-/*@todo move with the one from state_texture.c to some header*/
-#define MAX_MIPMAP_LEVELS 20
-
 static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer)
 {
@@ -71,12 +68,14 @@
 {
     int32_t rc, face, i;
+    GLboolean bound = GL_FALSE;
     
     CRASSERT(pTexture && pSSM);
 
+    crDebug("crStateSaveTextureObjData %u. START", pTexture->name);
+
     for (face = 0; face < 6; face++) {
         CRASSERT(pTexture->level[face]);
 
-        /*@todo, check if safe to go till MAX_MIPMAP_LEVELS intead of TextureState->maxLevel*/
-        for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
+        for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
             CRTextureLevel *ptl = &(pTexture->level[face][i]);
             rc = SSMR3PutMem(pSSM, ptl, sizeof(*ptl));
@@ -98,10 +97,63 @@
             {
                 char *pImg;
-
+                GLenum target;
+
+                if (!bound)
+                {
+                    diff_api.BindTexture(pTexture->target, pTexture->name);
+                    bound = GL_TRUE;
+                }
+
+                if (pTexture->target!=GL_TEXTURE_CUBE_MAP_ARB)
+                {
+                    target = pTexture->target;
+                }
+                else
+                {
+                    target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+                }
+
+#ifdef DEBUG
+                pImg = crAlloc(ptl->bytes+4);
+#else
                 pImg = crAlloc(ptl->bytes);
+#endif
                 if (!pImg) return VERR_NO_MEMORY;
 
-                diff_api.BindTexture(pTexture->target, pTexture->name);
-                diff_api.GetTexImage(pTexture->target, i, ptl->format, ptl->type, pImg);
+#ifdef DEBUG
+                {
+                    GLint w,h=0;
+                    *(int*)((char*)pImg+ptl->bytes) = 0xDEADDEAD;
+                    crDebug("get image: compressed %i, face %i, level %i, width %i, height %i, bytes %i",
+                            ptl->compressed, face, i, ptl->width, ptl->height, ptl->bytes);
+                    diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_WIDTH, &w);
+                    diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_HEIGHT, &h);
+                    if (w!=ptl->width || h!=ptl->height)
+                    {
+                        crWarning("!!!tex size mismatch %i, %i!!!", w, h);
+                    }
+                }
+#endif
+
+                /*@todo: ugly workaround for crashes inside ati driver,
+                 *       they overwrite their own allocated memory in cases where texlevel >=4
+                         and width or height <=2.
+                 */
+                if (i<4 || (ptl->width>2 && ptl->height>2))
+                    if (!ptl->compressed)
+                    {
+                        diff_api.GetTexImage(target, i, ptl->format, ptl->type, pImg);
+                    }
+                    else
+                    {
+                        diff_api.GetCompressedTexImageARB(target, i, pImg);
+                    }
+
+#ifdef DEBUG
+                if (*(int*)((char*)pImg+ptl->bytes) != 0xDEADDEAD)
+                {
+                    crWarning("Texture is bigger than expected!!!");
+                }
+#endif
 
                 rc = SSMR3PutMem(pSSM, pImg, ptl->bytes);
@@ -113,4 +165,6 @@
     }
 
+    crDebug("crStateSaveTextureObjData %u. END", pTexture->name);
+
     return VINF_SUCCESS;
 }
@@ -125,5 +179,5 @@
         CRASSERT(pTexture->level[face]);
 
-        for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
+        for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
             CRTextureLevel *ptl = &(pTexture->level[face][i]);
             CRASSERT(!ptl->img);
@@ -1330,5 +1384,5 @@
         /*allocate actual memory*/
         for (i=0; i<6; ++i) {
-            pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * MAX_MIPMAP_LEVELS);
+            pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
             if (!pTexture->level[i]) return VERR_NO_MEMORY;
         }
Index: trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_special
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_special	(revision 25153)
+++ trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_special	(revision 25154)
@@ -375,2 +375,3 @@
 BindAttribLocation
 GetUniformLocation
+CopyTexImage2D
Index: trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c	(revision 25153)
+++ trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_teximage.c	(revision 25154)
@@ -15,4 +15,62 @@
 #include "state_internals.h"
 
+#ifndef IN_GUEST
+/*# define CR_DUMP_TEXTURES_2D*/
+#endif
+
+#ifdef CR_DUMP_TEXTURES_2D
+static int _tnum = 0;
+
+#pragma pack(1)
+typedef struct tgaheader_tag
+{
+    char  idlen;
+
+    char  colormap;
+
+    char  imagetype;
+
+    short cm_index;
+    short cm_len;
+    char  cm_entrysize;
+
+    short x, y, w, h;
+    char  depth;
+    char  imagedesc;
+    
+} tgaheader_t;
+#pragma pack()
+
+static crDumpTGA(short w, short h, char* data)
+{
+    char fname[200];
+    tgaheader_t header;
+    FILE *out;
+
+    if (!w || !h) return;
+
+    sprintf(fname, "tex%i.tga", _tnum++);
+    out = fopen(fname, "w");
+    if (!out) crError("can't create %s!", fname);
+
+    header.idlen = 0;
+    header.colormap = 0;
+    header.imagetype = 2;
+    header.cm_index = 0;
+    header.cm_len = 0;
+    header.cm_entrysize = 0;
+    header.x = 0;
+    header.y = 0;
+    header.w = w;
+    header.h = h;
+    header.depth = 32;
+    header.imagedesc = 0x08;
+    fwrite(&header, sizeof(header), 1, out);
+
+    fwrite(data, w*h*4, 1, out);
+
+    fclose(out);
+}
+#endif
 
 
@@ -593,4 +651,71 @@
 }
 
+static void crStateNukeMipmaps(CRTextureObj *tobj)
+{
+    int i, face;
+
+    for (face = 0; face < 6; face++)
+    {
+        CRTextureLevel *levels = tobj->level[face];
+
+        if (levels) 
+        {
+            for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++)
+            {
+                if (levels[i].img) 
+                {
+                    crFree(levels[i].img);
+                }
+                levels[i].img = NULL;
+                levels[i].bytes = 0;
+                levels[i].internalFormat = GL_ONE;
+                levels[i].format = GL_RGBA;
+                levels[i].type = GL_UNSIGNED_BYTE;
+
+            }
+        }
+    }
+}
+
+void STATE_APIENTRY
+crStateCopyTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+    CRContext *g = GetCurrentContext();
+    CRTextureObj *tobj = NULL;
+    CRTextureLevel *tl = NULL;
+    
+    crStateGetTextureObjectAndImage(g, target, level, &tobj, &tl);
+    CRASSERT(tobj);
+    CRASSERT(tl);
+
+    crStateNukeMipmaps(tobj);
+
+    tl->bytes = crImageSize(GL_RGBA, GL_UNSIGNED_BYTE, width, height);
+
+    tl->width = width;
+    tl->height = height;
+    tl->depth = 1;
+    tl->format = GL_RGBA;
+    tl->internalFormat = internalFormat;
+    crStateTextureInitTextureFormat(tl, internalFormat);
+    tl->border = border;
+    tl->type = GL_UNSIGNED_BYTE;
+    tl->compressed = GL_FALSE;
+    if (width && height)
+    {
+        tl->bytesPerPixel = tl->bytes / (width * height);
+    }
+    else
+        tl->bytesPerPixel = 0;
+
+#ifdef CR_SGIS_generate_mipmap
+    if (level == tobj->baseLevel && tobj->generateMipmap) {
+        generate_mipmap(tobj, target);
+    }
+    else {
+        tl->generateMipmap = GL_FALSE;
+    }
+#endif
+}
 
 void STATE_APIENTRY
@@ -628,4 +753,9 @@
     CRASSERT(tobj);
     CRASSERT(tl);
+
+    if (level==tobj->baseLevel && (tl->width!=width || tl->height!=height))
+    {
+        crStateNukeMipmaps(tobj);
+    }
 
     /* compute size of image buffer */
@@ -704,6 +834,22 @@
     DIRTY(tl->dirty, g->neg_bitid);
     DIRTY(tb->dirty, g->neg_bitid);
-}
-
+
+#ifdef CR_DUMP_TEXTURES_2D
+    if (pixels)
+    {
+        GLint w,h;
+        char *data;
+
+        diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
+        diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
+
+        data = crAlloc(w*h*4);
+        if (!data) crError("no memory!");
+        diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
+        crDumpTGA(w, h, data);
+        crFree(data);
+    }
+#endif
+}
 
 #if defined( CR_OPENGL_VERSION_1_2 ) || defined( GL_EXT_texture3D )
@@ -917,4 +1063,20 @@
     DIRTY(tl->dirty, g->neg_bitid);
     DIRTY(tb->dirty, g->neg_bitid);
+
+#ifdef CR_DUMP_TEXTURES_2D
+    {
+        GLint w,h;
+        char *data;
+
+        diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_WIDTH, &w);
+        diff_api.GetTexLevelParameteriv(target, level, GL_TEXTURE_HEIGHT, &h);
+
+        data = crAlloc(w*h*4);
+        if (!data) crError("no memory!");
+        diff_api.GetTexImage(target, level, GL_RGBA, GL_UNSIGNED_BYTE, data);
+        crDumpTGA(w, h, data);
+        crFree(data);
+    }
+#endif
 }
 
Index: trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c
===================================================================
--- trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c	(revision 25153)
+++ trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_texture.c	(revision 25154)
@@ -13,8 +13,4 @@
 #include "cr_version.h"
 #include "state_internals.h"
-
-
-#define MAX_MIPMAP_LEVELS 20
-
 
 #define UNUSED(x) ((void) (x))
@@ -205,7 +201,7 @@
 	for (face = 0; face < 6; face++) {
 		/* allocate array of mipmap levels */
-		CRASSERT(t->maxLevel < MAX_MIPMAP_LEVELS);
+		CRASSERT(t->maxLevel < CR_MAX_MIPMAP_LEVELS);
 		tobj->level[face] = (CRTextureLevel *)
-			crCalloc(sizeof(CRTextureLevel) * MAX_MIPMAP_LEVELS);
+			crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
 
 		if (!tobj->level[face])
@@ -569,5 +565,5 @@
 		if (levels) {
 			/* free all mipmap levels for this face */
-			for (k = 0; k < MAX_MIPMAP_LEVELS; k++) {
+			for (k = 0; k < CR_MAX_MIPMAP_LEVELS; k++) {
 				CRTextureLevel *tl = levels + k;
 				if (tl->img) {
Index: trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_gentextures.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_gentextures.c	(revision 25153)
+++ trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_gentextures.c	(revision 25154)
@@ -101,4 +101,5 @@
     }
 
+    crStateCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
     cr_server.head_spu->dispatch_table.CopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
 }
