Only create textures for non-empty LandPixel chunks. This should save a fair amount of memory, especially on smaller maps, and eliminate a number of draws
authornemo
Sun, 03 Jun 2012 18:52:22 -0400
changeset 7170 84ac6c6d2d8e
parent 7168 8defaabce92e
child 7172 f68d62711a5c
Only create textures for non-empty LandPixel chunks. This should save a fair amount of memory, especially on smaller maps, and eliminate a number of draws
hedgewars/GSHandlers.inc
hedgewars/uLand.pas
hedgewars/uLandGraphics.pas
hedgewars/uLandTexture.pas
hedgewars/uStore.pas
--- a/hedgewars/GSHandlers.inc	Sun Jun 03 11:02:12 2012 -0400
+++ b/hedgewars/GSHandlers.inc	Sun Jun 03 18:52:22 2012 -0400
@@ -702,14 +702,14 @@
             //Land[py, px+1]:= lfBasic;
             
             if allpx then
-                UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w))
+                UpdateLandTexture(xx, Pred(s^.h), yy, Pred(s^.w), true)
             else
                 begin
                 UpdateLandTexture(
                     max(0, min(LAND_WIDTH, xx)),
                     min(LAND_WIDTH - xx, Pred(s^.w)),
                     max(0, min(LAND_WIDTH, yy)),
-                    min(LAND_HEIGHT - yy, Pred(s^.h))
+                    min(LAND_HEIGHT - yy, Pred(s^.h)), false // could this be true without unnecessarily creating blanks?
                 );
                 end;
 ////////////////////////////////// TODO - ASK UNC0RR FOR A GOOD HOME FOR THIS ////////////////////////////////////
--- a/hedgewars/uLand.pas	Sun Jun 03 11:02:12 2012 -0400
+++ b/hedgewars/uLand.pas	Sun Jun 03 18:52:22 2012 -0400
@@ -674,7 +674,7 @@
                 end
     end;
 
-UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT);
+UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false);
 end;
 
 procedure GenPreview(out Preview: TPreview);
--- a/hedgewars/uLandGraphics.pas	Sun Jun 03 11:02:12 2012 -0400
+++ b/hedgewars/uLandGraphics.pas	Sun Jun 03 18:52:22 2012 -0400
@@ -463,7 +463,7 @@
 dx:= Min(X + Radius + 1, LAND_WIDTH) - tx;
 ty:= Max(Y - Radius - 1, 0);
 dy:= Min(Y + Radius + 1, LAND_HEIGHT) - ty;
-UpdateLandTexture(tx, dx, ty, dy);
+UpdateLandTexture(tx, dx, ty, dy, false);
 DrawExplosion:= cnt
 end;
 
@@ -515,7 +515,7 @@
     end;
 
 
-UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT)
+UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false)
 end;
 
 //
@@ -665,7 +665,7 @@
 ddx:= Min(stX + HalfWidth * 2 + 4 + abs(hwRound(dX * ticks)), LAND_WIDTH) - tx;
 ddy:= Min(stY + HalfWidth * 2 + 4 + abs(hwRound(dY * ticks)), LAND_HEIGHT) - ty;
 
-UpdateLandTexture(tx, ddx, ty, ddy)
+UpdateLandTexture(tx, ddx, ty, ddy, false)
 end;
 
 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean; indestructible: boolean): boolean;
@@ -753,7 +753,7 @@
 w:= Min(cpX + Image^.w, LAND_WIDTH) - x;
 y:= Max(cpY, topY);
 h:= Min(cpY + Image^.h, LAND_HEIGHT) - y;
-UpdateLandTexture(x, w, y, h)
+UpdateLandTexture(x, w, y, h, true)
 end;
 
 function Despeckle(X, Y: LongInt): boolean;
@@ -955,7 +955,7 @@
                                 end;
                     end;
                 if updateBlock then
-                    UpdateLandTexture(tx, 32, ty, 32);
+                    UpdateLandTexture(tx, 32, ty, 32, false);
                 LandDirty[y, x]:= 2;
                 end;
             end;
--- a/hedgewars/uLandTexture.pas	Sun Jun 03 11:02:12 2012 -0400
+++ b/hedgewars/uLandTexture.pas	Sun Jun 03 18:52:22 2012 -0400
@@ -24,17 +24,17 @@
 
 procedure initModule;
 procedure freeModule;
-procedure UpdateLandTexture(X, Width, Y, Height: LongInt);
+procedure UpdateLandTexture(X, Width, Y, Height: LongInt; landAdded: boolean);
 procedure DrawLand(dX, dY: LongInt);
 procedure ResetLand;
 
 implementation
 uses uConsts, GLunit, uTypes, uVariables, uTextures, uDebug, uRender;
 
-const TEXSIZE = 512;
+const TEXSIZE = 256;
 
 type TLandRecord = record
-            shouldUpdate: boolean;
+            shouldUpdate, landAdded: boolean;
             tex: PTexture;
             end;
 
@@ -62,7 +62,7 @@
 Pixels2:= @tmpPixels
 end;
 
-procedure UpdateLandTexture(X, Width, Y, Height: LongInt);
+procedure UpdateLandTexture(X, Width, Y, Height: LongInt; landAdded: boolean);
 var tx, ty: Longword;
 begin
     if (Width <= 0) or (Height <= 0) then
@@ -75,16 +75,24 @@
     if (cReducedQuality and rqBlurryLand) = 0 then
         for ty:= Y div TEXSIZE to (Y + Height - 1) div TEXSIZE do
             for tx:= X div TEXSIZE to (X + Width - 1) div TEXSIZE do
-                LandTextures[tx, ty].shouldUpdate:= true
+                begin
+                LandTextures[tx, ty].shouldUpdate:= true;
+                LandTextures[tx, ty].landAdded:= landAdded
+                end
     else
         for ty:= (Y div TEXSIZE) div 2 to ((Y + Height - 1) div TEXSIZE) div 2 do
             for tx:= (X div TEXSIZE) div 2 to ((X + Width - 1) div TEXSIZE) div 2 do
+                begin
                 LandTextures[tx, ty].shouldUpdate:= true;
+                LandTextures[tx, ty].landAdded:= landAdded
+                end
 end;
 
 procedure RealLandTexUpdate;
-var x, y: LongWord;
+var x, y, ty, tx, lx, ly : LongWord;
+    isEmpty: boolean;
 begin
+(*
 if LandTextures[0, 0].tex = nil then
     for x:= 0 to LANDTEXARW -1 do
         for y:= 0 to LANDTEXARH - 1 do
@@ -95,14 +103,67 @@
                 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, tpHigh);
                 end
 else
+*)
     for x:= 0 to LANDTEXARW -1 do
         for y:= 0 to LANDTEXARH - 1 do
             with LandTextures[x, y] do
                 if shouldUpdate then
                     begin
                     shouldUpdate:= false;
-                    glBindTexture(GL_TEXTURE_2D, tex^.id);
-                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y));
+                    isEmpty:= not landAdded;
+                    landAdded:= false;
+                    ty:= 0;
+                    tx:= 1;
+                    ly:= y * TEXSIZE;
+                    lx:= x * TEXSIZE;
+                    // first check edges
+                    while isEmpty and (ty < TEXSIZE) do
+                        begin
+                        isEmpty:= LandPixels[ly + ty, lx] and AMask = 0;
+                        if isEmpty then isEmpty:= LandPixels[ly + ty, lx + TEXSIZE-1] and AMask = 0;
+                        inc(ty)
+                        end;
+                    while isEmpty and (tx < TEXSIZE-1) do
+                        begin
+                        isEmpty:= LandPixels[ly, lx + tx] and AMask = 0;
+                        if isEmpty then isEmpty:= LandPixels[ly + TEXSIZE-1, lx + tx] and AMask = 0;
+                        inc(tx)
+                        end;
+                    // then search every other remaining. does this sort of stuff defeat compiler opts?
+                    ty:= 2;
+                    while isEmpty and (ty < TEXSIZE-1) do
+                        begin
+                        tx:= 2;
+                        while isEmpty and (tx < TEXSIZE-1) do
+                            begin
+                            isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0;
+                            inc(tx,2)
+                            end;
+                        inc(ty,2);
+                        end;
+                    // and repeat
+                    ty:= 1;
+                    while isEmpty and (ty < TEXSIZE-1) do
+                        begin
+                        tx:= 1;
+                        while isEmpty and (tx < TEXSIZE-1) do
+                            begin
+                            isEmpty:= LandPixels[ly + ty, lx + tx] and AMask = 0;
+                            inc(tx,2)
+                            end;
+                        inc(ty,2);
+                        end;
+                    if not isEmpty then
+                        begin
+                        if tex = nil then tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y));
+                        glBindTexture(GL_TEXTURE_2D, tex^.id);
+                        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y));
+                        end
+                    else if tex <> nil then
+                        begin
+                        FreeTexture(tex);
+                        tex:= nil
+                        end;
                     end
 end;
 
@@ -114,10 +175,11 @@
 for x:= 0 to LANDTEXARW -1 do
     for y:= 0 to LANDTEXARH - 1 do
         with LandTextures[x, y] do
-            if (cReducedQuality and rqBlurryLand) = 0 then
-                DrawTexture(dX + x * TEXSIZE, dY + y * TEXSIZE, tex)
-            else
-                DrawTexture(dX + x * TEXSIZE * 2, dY + y * TEXSIZE * 2, tex, 2.0)
+            if tex <> nil then
+                if (cReducedQuality and rqBlurryLand) = 0 then
+                    DrawTexture(dX + x * TEXSIZE, dY + y * TEXSIZE, tex)
+                else
+                    DrawTexture(dX + x * TEXSIZE * 2, dY + y * TEXSIZE * 2, tex, 2.0)
 
 end;
 
@@ -144,8 +206,11 @@
         for y:= 0 to LANDTEXARH - 1 do
             with LandTextures[x, y] do
                 begin
-                FreeTexture(tex);
-                tex:= nil;
+                if tex <> nil then
+                    begin
+                    FreeTexture(tex);
+                    tex:= nil
+                    end
                 end;
 end;
 
--- a/hedgewars/uStore.pas	Sun Jun 03 11:02:12 2012 -0400
+++ b/hedgewars/uStore.pas	Sun Jun 03 18:52:22 2012 -0400
@@ -1118,7 +1118,7 @@
         ReloadLines;
         StoreLoad(true);
         // redraw all land
-        UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT);
+        UpdateLandTexture(0, LAND_WIDTH, 0, LAND_HEIGHT, false);
         end;
 end;