DEADSOFTWARE

gl: implement texture filtering
[d2df-sdl.git] / src / game / renders / opengl / r_textures.pas
index b98c0d3507d98576d6ecafa23291bfd895280ce9..ae9d02afa6596d878453ffb7d1dc87e6f8e43485 100644 (file)
@@ -47,6 +47,7 @@ interface
     TGLAtlas = class (TAtlas)
       private
         mID: GLuint;
+        mFilter: Boolean;
 
       public
         constructor Create (ww, hh: Integer; id: GLuint);
@@ -56,6 +57,7 @@ interface
         function Alloc (ww, hh: Integer): TGLAtlasNode; overload;
 
         property id: GLuint read mID write mID default 0;
+        property filter: Boolean read mFilter write mFilter;
     end;
 
     TGLTexture = class
@@ -65,6 +67,7 @@ interface
         mCols: Integer;
         mTile: array of TGLAtlasNode;
         mHints: TGLHintsSet;
+        mFilter: Boolean;
 
       public
         destructor Destroy; override;
@@ -78,6 +81,7 @@ interface
         property cols: Integer read mCols;
         property lines: Integer read GetLines;
         property hints: TGLHintsSet read mHints;
+        property filter: Boolean read mFilter write mFilter;
     end;
 
     TGLMultiTexture = class
@@ -206,6 +210,7 @@ implementation
     ASSERT(hh > 0);
     inherited Create(ww, hh);
     self.mID := id;
+    self.mFilter := false;
   end;
 
   destructor TGLAtlas.Destroy;
@@ -378,6 +383,7 @@ implementation
       t.mCols := cols;
       // t.mLines := lines;
       t.mHints := hints;
+      t.mFilter := false;
       SetLength(t.mTile, cols * lines);
       for y := 0 to lines - 1 do
       begin
@@ -465,7 +471,8 @@ implementation
     begin
       // auto, max possible reccomended by driver
       glGetIntegerv(GL_MAX_TEXTURE_SIZE, @size);
-      if size < 1 then size := 64;
+      size := size div 2; (* hack: on some devices max size may produce invalid texture *)
+      if size < 64 then size := 64; (* at least 64x64 are guarantied by specification *)
     end
     else
     begin
@@ -482,7 +489,7 @@ implementation
   begin
     currentTexture2D := 0;
     maxTileSize := r_Textures_GetMaxHardwareSize();
-    e_LogWritefln('TEXTURE SIZE: %s', [maxTileSize]);
+    e_LogWritefln('Texture Tile Size: %s', [maxTileSize]);
   end;
 
   procedure r_Textures_Finalize;
@@ -492,9 +499,12 @@ implementation
     begin
       for i := 0 to High(atl) do
       begin
-        glDeleteTextures(1, @atl[i].id);
-        atl[i].id := 0;
-        r_Common_FreeAndNil(atl[i]);
+        if atl[i] <> nil then
+        begin
+          glDeleteTextures(1, @atl[i].id);
+          atl[i].id := 0;
+          r_Common_FreeAndNil(atl[i]);
+        end;
       end;
     end;
     SetLength(atl, 0);
@@ -503,9 +513,12 @@ implementation
     begin
       for i := 0 to High(ratl) do
       begin
-        glDeleteTextures(1, @ratl[i].id);
-        ratl[i].id := 0;
-        r_Common_FreeAndNil(ratl[i]);
+        if ratl[i] <> nil then
+        begin
+          glDeleteTextures(1, @ratl[i].id);
+          ratl[i].id := 0;
+          r_Common_FreeAndNil(ratl[i]);
+        end;
       end;
     end;
     SetLength(ratl, 0);
@@ -644,7 +657,7 @@ implementation
     end;
   end;
 
-  function r_Textures_LoadTextFromMemory (data: Pointer; size: LongInt; var txt: TAnimTextInfo): Boolean;
+  function r_Textures_LoadTextFromMemory (data: Pointer; size: LongInt; var text: TAnimTextInfo): Boolean;
     var cfg: TConfig;
   begin
     result := false;
@@ -653,15 +666,23 @@ implementation
       cfg := TConfig.CreateMem(data, size);
       if cfg <> nil then
       begin
-        txt.name := cfg.ReadStr('', 'resource', '');
-        txt.w := MAX(0, cfg.ReadInt('', 'framewidth', 0));
-        txt.h := MAX(0, cfg.ReadInt('', 'frameheight', 0));
-        txt.anim.loop := true;
-        txt.anim.delay := MAX(0, cfg.ReadInt('', 'waitcount', 0));
-        txt.anim.frames := MAX(0, cfg.ReadInt('', 'framecount', 0));
-        txt.anim.back := cfg.ReadBool('', 'backanim', false);
+        text.name := cfg.ReadStr('', 'resource', '');
+        text.w := cfg.ReadInt('', 'framewidth', 0);
+        text.h := cfg.ReadInt('', 'frameheight', 0);
+        text.anim.loop := true;
+        text.anim.delay := cfg.ReadInt('', 'waitcount', 0);
+        text.anim.frames := cfg.ReadInt('', 'framecount', 0);
+        text.anim.back := cfg.ReadBool('', 'backanim', false);
+        if text.w <= 0 then e_LogWritefln('Warning: bad animation width %s for %s', [text.w, text.name]);
+        if text.h <= 0 then e_LogWritefln('Warning: bad animation height %s for %s', [text.h, text.name]);
+        if text.anim.delay <= 0 then e_LogWritefln('Warning: bad animation delay %s for %s', [text.anim.delay, text.name]);
+        if text.anim.frames <= 0 then e_LogWritefln('Warning: bad animation frame count %s for %s', [text.anim.frames, text.name]);
+        text.w := MAX(0, text.w);
+        text.h := MAX(0, text.h);
+        text.anim.delay := MAX(1, text.anim.delay);
+        text.anim.frames := MAX(1, text.anim.frames);
         cfg.Free;
-        result := (txt.name <> '') and (txt.w > 0) and (txt.h > 0) and (txt.anim.delay > 0) and (txt.anim.frames > 0);
+        result := (text.name <> '') and (text.w > 0) and (text.h > 0) and (text.anim.delay > 0) and (text.anim.frames > 0);
       end;
     end;
   end;