- Added ref counting to TMaterial

- Added cache growing to TCacheManager
- Fixed ImagingOptions.inc to not include JPEG support
- Fixed TfrmRadar to save the radar map to the correct location
- Fixed statics using the wrong hue when being painted
- Removed obsolete TLandTextureManager.GetFlatLandMaterial (and the according cache)
This commit is contained in:
Andreas Schneider 2009-12-10 21:40:14 +01:00
parent 59ab7046c4
commit 5c3de09d10
6 changed files with 113 additions and 46 deletions

View File

@ -43,11 +43,13 @@ type
PRadarBlock = ^TRadarBlock; PRadarBlock = ^TRadarBlock;
TRadarBlock = array[0..7, 0..7] of Word; TRadarBlock = array[0..7, 0..7] of Word;
{ TMaterial } //TODO : add ref counting { TMaterial }
TMaterial = class TMaterial = class(ICacheable)
constructor Create;
destructor Destroy; override; destructor Destroy; override;
protected protected
FRefCount: Integer;
FWidth: Integer; FWidth: Integer;
FHeight: Integer; FHeight: Integer;
FRealWidth: Integer; FRealWidth: Integer;
@ -64,7 +66,13 @@ type
property RealHeight: Integer read FRealHeight; property RealHeight: Integer read FRealHeight;
property Texture: GLuint read GetTexture; property Texture: GLuint read GetTexture;
procedure AddRef;
procedure DelRef;
function HitTest(AX, AY: Integer): Boolean; function HitTest(AX, AY: Integer): Boolean;
{ICacheable}
function CanBeRemoved: Boolean;
procedure RemoveFromCache;
end; end;
{ TSimpleMaterial } { TSimpleMaterial }
@ -100,7 +108,6 @@ type
destructor Destroy; override; destructor Destroy; override;
protected protected
FArtCache: TMaterialCache; FArtCache: TMaterialCache;
FFlatLandArtCache: TMaterialCache;
FTexCache: TMaterialCache; FTexCache: TMaterialCache;
FAnimCache: TMaterialCache; FAnimCache: TMaterialCache;
FUseAnims: Boolean; FUseAnims: Boolean;
@ -109,7 +116,6 @@ type
function GetArtMaterial(ATileID: Word): TMaterial; overload; function GetArtMaterial(ATileID: Word): TMaterial; overload;
function GetArtMaterial(ATileID: Word; AHue: THue; function GetArtMaterial(ATileID: Word; AHue: THue;
APartialHue: Boolean): TMaterial; overload; APartialHue: Boolean): TMaterial; overload;
function GetFlatLandMaterial(ATileID: Word): TMaterial;
function GetStaticMaterial(AStaticItem: TStaticItem; function GetStaticMaterial(AStaticItem: TStaticItem;
AOverrideHue: Integer = -1): TMaterial; AOverrideHue: Integer = -1): TMaterial;
function GetTexMaterial(ATileID: Word): TMaterial; function GetTexMaterial(ATileID: Word): TMaterial;
@ -309,7 +315,6 @@ constructor TLandTextureManager.Create;
begin begin
inherited Create; inherited Create;
FArtCache := TMaterialCache.Create(1024); FArtCache := TMaterialCache.Create(1024);
FFlatLandArtCache := TMaterialCache.Create(128);
FTexCache := TMaterialCache.Create(128); FTexCache := TMaterialCache.Create(128);
FAnimCache := TMaterialCache.Create(128); FAnimCache := TMaterialCache.Create(128);
FUseAnims := True; FUseAnims := True;
@ -318,7 +323,6 @@ end;
destructor TLandTextureManager.Destroy; destructor TLandTextureManager.Destroy;
begin begin
FreeAndNil(FArtCache); FreeAndNil(FArtCache);
FreeAndNil(FFlatLandArtCache);
FreeAndNil(FTexCache); FreeAndNil(FTexCache);
FreeAndNil(FAnimCache); FreeAndNil(FAnimCache);
inherited Destroy; inherited Destroy;
@ -351,6 +355,8 @@ begin
artEntry.Free; artEntry.Free;
end; end;
Result.AddRef;
end; end;
function TLandTextureManager.GetArtMaterial(ATileID: Word; AHue: THue; function TLandTextureManager.GetArtMaterial(ATileID: Word; AHue: THue;
@ -388,21 +394,7 @@ begin
artEntry.Free; artEntry.Free;
end; end;
end; Result.AddRef;
end;
function TLandTextureManager.GetFlatLandMaterial(ATileID: Word): TMaterial;
var
artEntry: TArt;
begin
if not FFlatLandArtCache.QueryID(ATileID, Result) then
begin
artEntry := ResMan.Art.GetFlatLand(ATileID);
Result := TSimpleMaterial.Create(artEntry.Graphic);
FFlatLandArtCache.StoreID(ATileID, Result);
artEntry.Free;
end; end;
end; end;
@ -417,7 +409,7 @@ begin
AOverrideHue := AStaticItem.Hue; AOverrideHue := AStaticItem.Hue;
if AOverrideHue > 0 then if AOverrideHue > 0 then
hue := ResMan.Hue.Hues[AOverrideHue] hue := ResMan.Hue.Hues[AOverrideHue - 1]
else else
hue := nil; hue := nil;
@ -444,6 +436,9 @@ begin
end else end else
Result := nil; Result := nil;
end; end;
if Result <> nil then
Result.AddRef;
end; end;
{ TSeperatedStaticBlock } { TSeperatedStaticBlock }
@ -1197,6 +1192,11 @@ end;
{ TMaterial } { TMaterial }
constructor TMaterial.Create;
begin
FRefCount := 1;
end;
destructor TMaterial.Destroy; destructor TMaterial.Destroy;
begin begin
FreeAndNil(FGraphic); FreeAndNil(FGraphic);
@ -1234,6 +1234,18 @@ begin
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
end; end;
procedure TMaterial.AddRef;
begin
Inc(FRefCount);
end;
procedure TMaterial.DelRef;
begin
Dec(FRefCount);
if FRefCount < 1 then
Free;
end;
function TMaterial.HitTest(AX, AY: Integer): Boolean; function TMaterial.HitTest(AX, AY: Integer): Boolean;
var var
pixel: TColor32Rec; pixel: TColor32Rec;
@ -1248,6 +1260,16 @@ begin
end; end;
end; end;
function TMaterial.CanBeRemoved: Boolean;
begin
Result := FRefCount <= 1;
end;
procedure TMaterial.RemoveFromCache;
begin
DelRef;
end;
{ TScreenBuffer } { TScreenBuffer }
constructor TScreenBuffer.Create; constructor TScreenBuffer.Create;
@ -1303,6 +1325,8 @@ begin
current^.Item.Locked := False; current^.Item.Locked := False;
current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved); current^.Item.OnDestroy.UnregisterEvent(@OnTileRemoved);
if current^.Normals <> nil then Dispose(current^.Normals); if current^.Normals <> nil then Dispose(current^.Normals);
if current^.HighRes <> nil then current^.HighRes.DelRef;
if current^.LowRes <> nil then current^.LowRes.DelRef;
current^.Text.Free; current^.Text.Free;
Dispose(current); Dispose(current);
current := next; current := next;
@ -1331,6 +1355,8 @@ begin
if last <> nil then last^.Next := current^.Next; if last <> nil then last^.Next := current^.Next;
if current^.Normals <> nil then Dispose(current^.Normals); if current^.Normals <> nil then Dispose(current^.Normals);
if current^.HighRes <> nil then current^.HighRes.DelRef;
if current^.LowRes <> nil then current^.LowRes.DelRef;
current^.Text.Free; current^.Text.Free;
Dispose(current); Dispose(current);
@ -1616,6 +1642,8 @@ var
art: array of TArt; art: array of TArt;
caps: TGLTextureCaps; caps: TGLTextureCaps;
begin begin
inherited Create;
FAnimData := AAnimData; FAnimData := AAnimData;
FRealWidth := 0; FRealWidth := 0;

View File

@ -1000,7 +1000,8 @@ end;
procedure TfrmMain.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean); procedure TfrmMain.ApplicationProperties1Idle(Sender: TObject; var Done: Boolean);
begin begin
if (FScreenBufferState <> CScreenBufferValid) or if (FScreenBufferState <> CScreenBufferValid) or
({FRepaintNeeded and }(MilliSecondsBetween(Now, FLastDraw) > 50)) then ((FRepaintNeeded or mnuShowAnimations.Checked) and
(MilliSecondsBetween(Now, FLastDraw) > 50)) then
begin begin
//Logger.Send([lcClient, lcDebug], 'Repainting Game Window'); //Logger.Send([lcClient, lcDebug], 'Repainting Game Window');
oglGameWindow.Repaint; oglGameWindow.Repaint;
@ -1895,11 +1896,9 @@ procedure TfrmMain.InitSize;
begin begin
glViewport(0, 0, oglGameWindow.Width, oglGameWindow.Height); glViewport(0, 0, oglGameWindow.Width, oglGameWindow.Height);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix;
glLoadIdentity; glLoadIdentity;
gluOrtho2D(0, oglGameWindow.Width, oglGameWindow.Height, 0); gluOrtho2D(0, oglGameWindow.Width, oglGameWindow.Height, 0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix;
glLoadIdentity; glLoadIdentity;
end; end;
@ -1999,6 +1998,9 @@ begin
rawZ := item.RawZ; rawZ := item.RawZ;
end; end;
if ABlockInfo^.HighRes <> nil then ABlockInfo^.HighRes.DelRef;
if ABlockInfo^.LowRes <> nil then ABlockInfo^.LowRes.DelRef;
ABlockInfo^.HighRes := nil; ABlockInfo^.HighRes := nil;
ABlockInfo^.CheckRealQuad := False; ABlockInfo^.CheckRealQuad := False;
ABlockInfo^.Text.Free; ABlockInfo^.Text.Free;
@ -2181,7 +2183,6 @@ begin
if not highlight then if not highlight then
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glLoadName(PtrInt(item));
glBegin(GL_QUADS); glBegin(GL_QUADS);
glNormal3fv(@blockInfo^.Normals^[0]); glNormal3fv(@blockInfo^.Normals^[0]);
glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]); glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]);
@ -2198,7 +2199,6 @@ begin
end else end else
begin begin
glBindTexture(GL_TEXTURE_2D, blockInfo^.LowRes.Texture); glBindTexture(GL_TEXTURE_2D, blockInfo^.LowRes.Texture);
glLoadName(PtrInt(item));
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]); glTexCoord2i(0, 0); glVertex2iv(@blockInfo^.DrawQuad[0]);
glTexCoord2i(1, 0); glVertex2iv(@blockInfo^.DrawQuad[1]); glTexCoord2i(1, 0); glVertex2iv(@blockInfo^.DrawQuad[1]);

View File

@ -30,7 +30,7 @@ object frmRadarMap: TfrmRadarMap
Left = 8 Left = 8
Height = 21 Height = 21
Top = 0 Top = 0
Width = 39 Width = 41
Align = alLeft Align = alLeft
BorderSpacing.Left = 8 BorderSpacing.Left = 8
Layout = tlCenter Layout = tlCenter

View File

@ -115,8 +115,8 @@ begin
for y := 0 to FRadar.Height - 1 do for y := 0 to FRadar.Height - 1 do
radarMap[x * FRadar.Height + y] := EncodeUOColor(PInteger(FRadar.PixelPointers[x, y])^); radarMap[x * FRadar.Height + y] := EncodeUOColor(PInteger(FRadar.PixelPointers[x, y])^);
radarMapFile := TFileStream.Create(IncludeTrailingPathDelimiter( radarMapFile := TFileStream.Create(GetAppConfigDir(False) + 'RadarMap.cache',
ExtractFilePath(Application.ExeName)) + 'RadarMap.cache', fmCreate); fmCreate);
radarMapFile.Write(radarMap[0], Length(radarMap) * SizeOf(Word)); radarMapFile.Write(radarMap[0], Length(radarMap) * SizeOf(Word));
radarMapFile.Free; radarMapFile.Free;

View File

@ -27,10 +27,10 @@
Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line Example: If you want to disable JPEG support just uncomment //{$DEFINE DONT_LINK_JPEG} line
*) *)
//{$DEFINE DONT_LINK_JPEG} // link support for Jpeg images {$DEFINE DONT_LINK_JPEG} // link support for Jpeg images
//{$DEFINE DONT_LINK_PNG} // link support for PNG images {.$DEFINE DONT_LINK_PNG} // link support for PNG images
//{$DEFINE DONT_LINK_TARGA} // link support for Targa images {.$DEFINE DONT_LINK_TARGA} // link support for Targa images
//{$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images {.$DEFINE DONT_LINK_BITMAP} // link support for Windows Bitmap images
{$DEFINE DONT_LINK_DDS} // link support for DDS images {$DEFINE DONT_LINK_DDS} // link support for DDS images
{$DEFINE DONT_LINK_GIF} // link support for GIF images {$DEFINE DONT_LINK_GIF} // link support for GIF images
{$DEFINE DONT_LINK_MNG} // link support for MNG images {$DEFINE DONT_LINK_MNG} // link support for MNG images

View File

@ -26,6 +26,7 @@
unit UCacheManager; unit UCacheManager;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
{$interfaces corba}
interface interface
@ -34,6 +35,11 @@ uses
type type
ICacheable = interface['{0ABAA4DE-8128-47B3-ABFE-5250A74A0428}']
function CanBeRemoved: Boolean;
procedure RemoveFromCache;
end;
{ TCacheManager } { TCacheManager }
generic TCacheManager<T> = class generic TCacheManager<T> = class
@ -53,6 +59,7 @@ type
FFirst: PCacheEntry; FFirst: PCacheEntry;
FLast: PCacheEntry; FLast: PCacheEntry;
FOnRemoveObject: TRemoveObjectEvent; FOnRemoveObject: TRemoveObjectEvent;
procedure DoRemoveObject(var AObject: T; ANotify: Boolean = True);
public public
constructor Create(ASize: Integer); constructor Create(ASize: Integer);
destructor Destroy; override; destructor Destroy; override;
@ -73,8 +80,24 @@ type
implementation implementation
uses
Logging;
{ TCacheManager } { TCacheManager }
procedure TCacheManager.DoRemoveObject(var AObject: T; ANotify: Boolean = True);
var
cacheable: ICacheable;
begin
if ANotify and Assigned(FOnRemoveObject) then FOnRemoveObject(AObject);
if TObject(AObject).GetInterface(ICacheable, cacheable) then
cacheable.RemoveFromCache
else
TObject(AObject).Free;
TObject(AObject) := nil;
end;
constructor TCacheManager.Create(ASize: Integer); constructor TCacheManager.Create(ASize: Integer);
var var
i: Integer; i: Integer;
@ -109,10 +132,7 @@ begin
for i := 1 to FSize do for i := 1 to FSize do
begin begin
if Pointer(current^.Obj) <> nil then if Pointer(current^.Obj) <> nil then
begin DoRemoveObject(current^.Obj);
if Assigned(FOnRemoveObject) then FOnRemoveObject(current^.Obj);
FreeAndNil(current^.Obj);
end;
last := current; last := current;
current := current^.Next; current := current^.Next;
Dispose(last); Dispose(last);
@ -166,7 +186,7 @@ begin
begin begin
current^.ID := LongInt($FFFFFFFF); current^.ID := LongInt($FFFFFFFF);
if Pointer(current^.Obj) <> nil then if Pointer(current^.Obj) <> nil then
FreeAndNil(current^.Obj); DoRemoveObject(current^.Obj, False);
end; end;
if (current^.Next <> nil) then if (current^.Next <> nil) then
FLast := current; FLast := current;
@ -184,8 +204,7 @@ begin
if Pointer(current^.Obj) <> nil then if Pointer(current^.Obj) <> nil then
begin begin
current^.ID := LongInt($FFFFFFFF); current^.ID := LongInt($FFFFFFFF);
if Assigned(FOnRemoveObject) then FOnRemoveObject(current^.Obj); DoRemoveObject(current^.Obj);
FreeAndNil(current^.Obj);
end; end;
current := current^.Next; current := current^.Next;
end; end;
@ -230,17 +249,37 @@ end;
procedure TCacheManager.StoreID(AID: Integer; AObj: T); procedure TCacheManager.StoreID(AID: Integer; AObj: T);
var var
current: PCacheEntry; current: PCacheEntry;
cacheable: ICacheable;
i: Integer;
begin begin
current := FLast^.Next; //well, FLast is not really the last, but the one before the last ;) current := FLast^.Next; //well, FLast is not really the last, but the one before the last ;)
FLast^.Next := nil; FLast^.Next := nil;
current^.Next := FFirst; current^.Next := FFirst;
FFirst := current; FFirst := current;
FFirst^.ID := AID; if Pointer(FFirst^.Obj) <> nil then //if the last cache entry did contain an object, remove it now or grow
if Pointer(FFirst^.Obj) <> nil then //if the last cache entry did contain an object, remove it now
begin begin
if Assigned(FOnRemoveObject) then FOnRemoveObject(FFirst^.Obj); if TObject(FFirst^.Obj).GetInterface(ICacheable, cacheable) and
FreeAndNil(FFirst^.Obj); not cacheable.CanBeRemoved then
begin
Logger.Send([lcInfo], 'Cache growing (%s)', [ClassName]);
New(FLast^.Next);
current := FLast^.Next;
current^.ID := FFirst^.ID;
current^.Obj := FFirst^.Obj;
for i := 2 to FSize do
begin
New(current^.Next);
FLast := current;
current := current^.Next;
current^.ID := LongInt($FFFFFFFF);
current^.Obj := nil;
end; end;
current^.Next := nil;
FSize := FSize * 2;
end else
DoRemoveObject(current^.Obj);
end;
FFirst^.ID := AID;
FFirst^.Obj := AObj; FFirst^.Obj := AObj;
end; end;