retaining SDL surfaces in order to allow recreating atlases from scratch without
authorWolfgang Steffens <WolfgangSteff@gmail.com>
Mon, 25 Jun 2012 11:47:40 +0200
changeset 7291 ad4b6c2b09e8
parent 7288 5d0704f23a2a
child 7292 18430abfbcd2
retaining SDL surfaces in order to allow recreating atlases from scratch without reading back textures from the GL
hedgewars/options.inc
hedgewars/uChat.pas
hedgewars/uRenderUtils.pas
hedgewars/uScript.pas
hedgewars/uStore.pas
hedgewars/uTextures.pas
hedgewars/uTypes.pas
hedgewars/uWorld.pas
--- a/hedgewars/options.inc	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/options.inc	Mon Jun 25 11:47:40 2012 +0200
@@ -31,6 +31,7 @@
 
 
 {$DEFINE GL2}
+{$DEFINE RETAIN_SURFACES}
 
 {$IFDEF ANDROID}
     {$DEFINE MOBILE}
--- a/hedgewars/uChat.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uChat.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -96,9 +96,7 @@
 SDL_FreeSurface(strSurface);
 
 cl.Time:= RealTicks + 12500;
-cl.Tex:= Surface2Tex(resSurface, false);
-
-SDL_FreeSurface(resSurface)
+cl.Tex:= Surface2Atlas(resSurface, false);
 end;
 
 // For uStore texture recreation
--- a/hedgewars/uRenderUtils.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uRenderUtils.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -272,9 +272,7 @@
 
     TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
 
-    RenderStringTexLim:= Surface2Tex(finalSurface, false);
-
-    SDL_FreeSurface(finalSurface);
+    RenderStringTexLim:= Surface2Atlas(finalSurface, false);
 end;
 
 
@@ -459,10 +457,9 @@
         inc(pos);
         end;
 
-    RenderSpeechBubbleTex:= Surface2Tex(finalSurface, true);
+    RenderSpeechBubbleTex:= Surface2Atlas(finalSurface, true);
 
     SDL_FreeSurface(rotatedEdge);
-    SDL_FreeSurface(finalSurface);
 end;
 
 end.
--- a/hedgewars/uScript.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uScript.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -738,8 +738,7 @@
             DrawRoundRect(@rr, clan^.Color, clan^.Color, texsurf, false);
 
             FreeTexture(team^.HealthTex);
-            team^.HealthTex:= Surface2Tex(texsurf, false);
-            SDL_FreeSurface(texsurf);
+            team^.HealthTex:= Surface2Atlas(texsurf, false);
             MakeCrossHairs
             end
         end;
--- a/hedgewars/uStore.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uStore.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -155,8 +155,7 @@
         SDL_UnlockSurface(texsurf);
 
     FreeTexture(CrosshairTex);
-    CrosshairTex:= Surface2Tex(texsurf, false);
-    SDL_FreeSurface(texsurf)
+    CrosshairTex:= Surface2Atlas(texsurf, false);
     end;
 
 SDL_FreeSurface(tmpsurf)
@@ -189,8 +188,7 @@
         rr:= r;
         inc(rr.x, 2); dec(rr.w, 4); inc(rr.y, 2); dec(rr.h, 4);
         DrawRoundRect(@rr, Clan^.Color, Clan^.Color, texsurf, false);
-        HealthTex:= Surface2Tex(texsurf, false);
-        SDL_FreeSurface(texsurf);
+        HealthTex:= Surface2Atlas(texsurf, false);
 
         r.x:= 0;
         r.y:= 0;
@@ -230,8 +228,7 @@
         PLongwordArray(texsurf^.pixels)^[32 * 16 +  2]:= cNearBlackColor;
         PLongwordArray(texsurf^.pixels)^[32 * 16 + 23]:= cNearBlackColor;
 
-        FlagTex:= Surface2Tex(texsurf, false);
-        SDL_FreeSurface(texsurf);
+        FlagTex:= Surface2Atlas(texsurf, false);
         texsurf:= nil;
 
         AIKillsTex := RenderStringTex(inttostr(stats.AIKills), Clan^.Color, fnt16);
@@ -263,8 +260,7 @@
         r.w:= 28;
         r.h:= 28;
         DrawRoundRect(@r, cWhiteColor, cNearBlackColor, iconsurf, true);
-        ropeIconTex:= Surface2Tex(iconsurf, false);
-        SDL_FreeSurface(iconsurf);
+        ropeIconTex:= Surface2Atlas(iconsurf, false);
         iconsurf:= nil;
         end;
 end;
@@ -299,8 +295,7 @@
                 texsurf:= LoadImage(UserPathz[ptGraves] + '/Statue', ifTransparent);
             if texsurf = nil then
                 texsurf:= LoadImage(Pathz[ptGraves] + '/Statue', ifCritical or ifTransparent);
-            GraveTex:= Surface2Tex(texsurf, false);
-            SDL_FreeSurface(texsurf)
+            GraveTex:= Surface2Atlas(texsurf, false);
             end
 end;
 
@@ -397,12 +392,12 @@
                     end;
                 if (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]) then
                     begin
-                    Texture:= Surface2Tex(tmpsurf, true);
+                    Texture:= Surface2Atlas(tmpsurf, true);
                     Texture^.Scale:= 2
                     end
                 else
                     begin
-                    Texture:= Surface2Tex(tmpsurf, false);
+                    Texture:= Surface2Atlas(tmpsurf, false);
                     // HACK: We should include some sprite attribute to define the texture wrap directions
                     if ((ii = sprWater) or (ii = sprSDWater)) and ((cReducedQuality and (rq2DWater or rqClampLess)) = 0) then
                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -416,8 +411,8 @@
 {$ELSE}
                     if saveSurf then
                         Surface:= tmpsurf
-                    else
-                        SDL_FreeSurface(tmpsurf)
+                    //else
+                    //    SDL_FreeSurface(tmpsurf) released by FreeTexture
 {$ENDIF}
                     end
                 end
@@ -432,8 +427,7 @@
 if tmpsurf = nil then
     tmpsurf:= LoadImage(Pathz[ptGraphics] + '/' + cHHFileName, ifAlpha or ifCritical or ifTransparent);
     
-HHTexture:= Surface2Tex(tmpsurf, false);
-SDL_FreeSurface(tmpsurf);
+HHTexture:= Surface2Atlas(tmpsurf, false);
 
 InitHealth;
 
@@ -453,8 +447,7 @@
         TryDo(tmpsurf <> nil,'Name-texture creation for ammo type #' + intToStr(ord(ai)) + ' failed!',true);
         tmpsurf:= doSurfaceConversion(tmpsurf);
         FreeTexture(NameTex);
-        NameTex:= Surface2Tex(tmpsurf, false);
-        SDL_FreeSurface(tmpsurf)
+        NameTex:= Surface2Atlas(tmpsurf, false);
         end;
 
 // number of weapons in ammo menu
@@ -463,8 +456,7 @@
     tmpsurf:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(IntToStr(i) + 'x'), cWhiteColorChannels);
     tmpsurf:= doSurfaceConversion(tmpsurf);
     FreeTexture(CountTexz[i]);
-    CountTexz[i]:= Surface2Tex(tmpsurf, false);
-    SDL_FreeSurface(tmpsurf)
+    CountTexz[i]:= Surface2Atlas(tmpsurf, false);
     end;
 
 if not reload then
@@ -616,10 +608,7 @@
         FreeTexture(HHGear^.Hedgehog^.HatTex);
 
         // assign new hat to hedgehog
-        HHGear^.Hedgehog^.HatTex:= Surface2Tex(texsurf, true);
-
-        // cleanup: free temporary surface mem
-        SDL_FreeSurface(texsurf)
+        HHGear^.Hedgehog^.HatTex:= Surface2Atlas(texsurf, true);
         end;
 end;
 
@@ -1052,11 +1041,10 @@
         if texsurf = nil then
             texsurf:= LoadImage(Pathz[ptGraphics] + '/Progress', ifCritical or ifTransparent);
 
-        ProgrTex:= Surface2Tex(texsurf, false);
+        ProgrTex:= Surface2Atlas(texsurf, false);
 
         squaresize:= texsurf^.w shr 1;
         numsquares:= texsurf^.h div squaresize;
-        SDL_FreeSurface(texsurf);
 
         uMobile.GameLoading();
         end;
@@ -1201,8 +1189,7 @@
 SDL_FillRect(tmpsurf, @r, $ffffffff);
 SDL_UpperBlit(iconsurf, iconrect, tmpsurf, @r);
 
-RenderHelpWindow:=  Surface2Tex(tmpsurf, true);
-SDL_FreeSurface(tmpsurf)
+RenderHelpWindow:=  Surface2Atlas(tmpsurf, true);
 end;
 
 procedure RenderWeaponTooltip(atype: TAmmoType);
--- a/hedgewars/uTextures.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uTextures.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -24,7 +24,7 @@
 
 function  NewTexture(width, height: Longword; buf: Pointer): PTexture;
 procedure Surface2GrayScale(surf: PSDL_Surface);
-function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+function  Surface2Atlas(surf: PSDL_Surface; enableClamp: boolean): PTexture;
 procedure FreeTexture(tex: PTexture);
 procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
 
@@ -32,7 +32,7 @@
 procedure freeModule;
 
 implementation
-uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole;
+uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole, uAtlas;
 
 var TextureList: PTexture;
 
@@ -159,42 +159,45 @@
 end;
 
 
-function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+function Surface2Atlas(surf: PSDL_Surface; enableClamp: boolean): PTexture;
 var tw, th, x, y: Longword;
     tmpp: pointer;
     fromP4, toP4: PLongWordArray;
 begin
-new(Surface2Tex);
-Surface2Tex^.PrevTexture:= nil;
-Surface2Tex^.NextTexture:= nil;
+    if (surf^.w <= 128) and (surf^.h <= 128) then
+        Surface2Tex_(surf, enableClamp); // run the atlas side by side for debugging
+new(Surface2Atlas);
+Surface2Atlas^.PrevTexture:= nil;
+Surface2Atlas^.NextTexture:= nil;
 if TextureList <> nil then
     begin
-    TextureList^.PrevTexture:= Surface2Tex;
-    Surface2Tex^.NextTexture:= TextureList
+    TextureList^.PrevTexture:= Surface2Atlas;
+    Surface2Atlas^.NextTexture:= TextureList
     end;
-TextureList:= Surface2Tex;
+TextureList:= Surface2Atlas;
 
 // Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
-new(Surface2Tex^.atlas);
+new(Surface2Atlas^.atlas);
 
-Surface2Tex^.w:= surf^.w;
-Surface2Tex^.h:= surf^.h;
-Surface2Tex^.x:=0;
-Surface2Tex^.y:=0;
-Surface2Tex^.isRotated:=false;
+Surface2Atlas^.w:= surf^.w;
+Surface2Atlas^.h:= surf^.h;
+Surface2Atlas^.x:=0;
+Surface2Atlas^.y:=0;
+Surface2Atlas^.isRotated:=false;
+Surface2Atlas^.surface:= surf;
 
 
 if (surf^.format^.BytesPerPixel <> 4) then
     begin
     TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
-    Surface2Tex^.atlas^.id:= 0;
+    Surface2Atlas^.atlas^.id:= 0;
     exit
     end;
 
 
-glGenTextures(1, @Surface2Tex^.atlas^.id);
+glGenTextures(1, @Surface2Atlas^.atlas^.id);
 
-glBindTexture(GL_TEXTURE_2D, Surface2Tex^.atlas^.id);
+glBindTexture(GL_TEXTURE_2D, Surface2Atlas^.atlas^.id);
 
 if SDL_MustLock(surf) then
     SDLTry(SDL_LockSurface(surf) >= 0, true);
@@ -209,8 +212,8 @@
     tw:= toPowerOf2(Surf^.w);
     th:= toPowerOf2(Surf^.h);
 
-    Surface2Tex^.atlas^.w:=tw;
-    Surface2Tex^.atlas^.h:=th;
+    Surface2Atlas^.atlas^.w:=tw;
+    Surface2Atlas^.atlas^.h:=th;
 
     tmpp:= GetMem(tw * th * surf^.format^.BytesPerPixel);
 
@@ -240,23 +243,28 @@
     end
 else
     begin
-    Surface2Tex^.atlas^.w:=Surf^.w;
-    Surface2Tex^.atlas^.h:=Surf^.h;
+    Surface2Atlas^.atlas^.w:=Surf^.w;
+    Surface2Atlas^.atlas^.h:=Surf^.h;
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
     end;
 
-ResetVertexArrays(Surface2Tex);
+ResetVertexArrays(Surface2Atlas);
 
 if SDL_MustLock(surf) then
     SDL_UnlockSurface(surf);
 
 SetTextureParameters(enableClamp);
+
+    {$IFNDEF RETAIN_SURFACES}
+    SDL_FreeSurface(surf);
+    {$ENDIF}
 end;
 
 // deletes texture and frees the memory allocated for it.
 // if nil is passed nothing is done
 procedure FreeTexture(tex: PTexture);
 begin
+    FreeTexture_(tex); // run atlas side by side for debugging
 if tex <> nil then
     begin
     // Atlas cleanup happens here later on. For now we just free as each sprite has one atlas
@@ -269,12 +277,18 @@
     else
         TextureList:= tex^.NextTexture;
     glDeleteTextures(1, @tex^.atlas^.id);
+
+    {$IFDEF RETAIN_SURFACES}
+    SDL_FreeSurface(tex^.surface);
+    {$ENDIF}
+
     Dispose(tex);
     end
 end;
 
 procedure initModule;
 begin
+uAtlas.initModule;
 TextureList:= nil;
 end;
 
--- a/hedgewars/uTypes.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uTypes.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -221,6 +221,8 @@
             x, y: LongInt; // Offset in the texture atlas
             isRotated: boolean; // if true sprite is flipped in the atlas taking w pixels along the y and h pixels along the x axis
 
+            surface: PSDL_Surface; // retained in memory surface
+
             // Cached values for texel coordinates and vertex coordinates            
             vb, tb: TVertexRect;
 
--- a/hedgewars/uWorld.pas	Mon Jun 25 10:44:27 2012 +0200
+++ b/hedgewars/uWorld.pas	Mon Jun 25 11:47:40 2012 +0200
@@ -494,8 +494,7 @@
 DrawLine2Surf(amSurface, AMRect.w+BORDERSIZE+i, BORDERSIZE, AMRect.w + BORDERSIZE+i, AMRect.h + BORDERSIZE, 160,160,160);//right
 end;
 
-GetAmmoMenuTexture:= Surface2Tex(amSurface, false);
-if amSurface <> nil then SDL_FreeSurface(amSurface);
+GetAmmoMenuTexture:= Surface2Atlas(amSurface, false);
 end;
 
 procedure ShowAmmoMenu;
@@ -1461,8 +1460,7 @@
         tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
         tmpSurface:= doSurfaceConversion(tmpSurface);
         FreeTexture(timeTexture);
-        timeTexture:= Surface2Tex(tmpSurface, false);
-        SDL_FreeSurface(tmpSurface)
+        timeTexture:= Surface2Atlas(tmpSurface, false);
         end;
 
     if timeTexture <> nil then
@@ -1479,8 +1477,7 @@
             tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
             tmpSurface:= doSurfaceConversion(tmpSurface);
             FreeTexture(fpsTexture);
-            fpsTexture:= Surface2Tex(tmpSurface, false);
-            SDL_FreeSurface(tmpSurface)
+            fpsTexture:= Surface2Atlas(tmpSurface, false);
             end;
         if fpsTexture <> nil then
             DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture);