Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi glDeleteTextures gibt Speicher nicht frei (https://www.delphipraxis.net/114309-gldeletetextures-gibt-speicher-nicht-frei.html)

EWeiss 23. Mai 2008 04:58


glDeleteTextures gibt Speicher nicht frei
 
trotz alledem das ich die texturen lösche wird der Speicher nicht freigegeben


Delphi-Quellcode:
    if assigned(quadTexture) then
    begin
      for I := 0 to QuadCount - 1 do
      begin
       glDeleteTextures(i, @quadTexture);
       quadTexture[i] := 0;
      end;
    end;

    glDeleteTextures(1, @BackTexture);    // Texture für Hintergrund
    glDeleteTextures(1, @GradientTex);    // Texture für DiskSpectrum
    glDeleteTextures(1, @MeterTexture);   // Texture für VUMeter
    glDeleteTextures(1, @PeaksTexture);   // Texture für Peaks
    glDeleteTextures(1, @SpectrumTexture); // Texture für Spectrum
    glDeleteTextures(1, @BarTexture);     // Texture für Slider
    glDeleteTextures(1, @PrivateTexture); // Texture für CDLabel
woran kann es liegen ?
Wüßte jetzt nicht was da falsch ist.

gruss Emil

marabu 23. Mai 2008 05:56

Re: glDeleteTextures gibt Speicher nicht frei
 
Moin Emil,

unabhängig von irgendwelchen Speicherfreigaben - müsste das nicht eher so aussehen?

Delphi-Quellcode:
begin
  if Assigned(QuadTexture) then
  begin
    glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
    SetLength(QuadTextures, 0);
  end;
  if Assigned(BackTexture) then
    // ...
end;
Ich habe jetzt mal dynamische Texture-Arrays angenommen.

Freundliche Grüße

Corpsman 23. Mai 2008 06:16

Re: glDeleteTextures gibt Speicher nicht frei
 
@EWeiss

dir ist aber schon klar das deine Texture Variablen Pointer sind, oder ?

Das heist.

Wenn du eine Varaible

Delphi-Quellcode:
var b:TBitmap;
hast. dann kannst du B.free machen , und gibst den speicher frei.


Die Abfrage

Delphi-Quellcode:
if assigned(b) then begin
end;
würde aber immer noch True ergeben, da b.free sich selbst nicht auf NIL setzt.

Genau das selbe ist es mit den OpenGL Texturen

als Test.

Gib deine Textur an einem Punkt frei nachdem du noch rendern kannst. ( also meinetwegen direkt wieder nach dem Laden )

dann stellst du fest das OpenGL dir stattdessen

1. Blödsinn
oder
2. eine weise Textur anzeigt

=> der speicher wurde freigegeben.

EWeiss 23. Mai 2008 09:36

Re: glDeleteTextures gibt Speicher nicht frei
 
@marabu
Dynamisches Array ist ok
hab dann wohl einen Denkfehler ;)
Hab nicht daran gedacht das ganze Array auf einmal zu löschen.


werd mal schaun ob es dann freigegeben wird.

Delphi-Quellcode:
begin
  if Assigned(QuadTexture) then
  begin
    glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
    SetLength(QuadTextures, 0);
  end;
  if Assigned(BackTexture) then
    // ...
end;
@Corpsman
Zitat:

dir ist aber schon klar das deine Texture Variablen Pointer sind, oder ?
Hmmm...
warum sollte es das nicht sein die Trexture ist ein Pointer auf GLUnit 'PGlUint'

Delphi-Quellcode:
quadTexture        : array of GLuint;
ist ein dynamisches array auf gluint da ist nix mit 'free'

EDIT:
Auch wenn ich das Array(Texturen) in einem zug frei gebe steigt die Speicherbelastung stetig..

gruss Emil

littleDave 23. Mai 2008 10:42

Re: glDeleteTextures gibt Speicher nicht frei
 
Woran erkennst du denn, dass die Texturen nicht freigegeben werden? Dem Arbeitsspeicher kannst du das eigentlich nicht ansehen, da die Texturen im Grafikkarten-RAM gespeichert werden. Wenn der Grafikkarten-Speicher voll ist, werden die Texturen dann in den Arbeitsspeicher geschoben, aber sonst nicht.

Noch was zu deinem Code
Delphi-Quellcode:
if assigned(quadTexture) then
begin
  for I := 0 to QuadCount - 1 do
  begin
    glDeleteTextures(i, @quadTexture);
    quadTexture[i] := 0;
  end;
end;
Dieser Code funktioniert nicht. glDeleteTextures erwartet zwei Parameter. Der erste Parameter sagt OGL, wieviele Texturen gelöscht werden sollen. Der zweite Parameter ist ein Pointer auf das erste Element eines glUint-arrays (wenn nur eine Textur gelöscht werden soll, dann muss es kein array sein).
Dein Code von oben müsste man also folgendermaßen umschreiben (nur wenn du ihn mit der for-schleife benutzen willst)
Delphi-Quellcode:
if assigned(quadTexture) then
begin
  for I := 0 to QuadCount - 1 do
  begin
    glDeleteTextures(1, @quadTexture[i]);
    quadTexture[i] := 0;
  end;
end;
//Edit:
Ach noch was: sind die anderen Variablen zufällig auch arrays? Wenn du den Pointer auf das erste Element eines arrays zurückgeben willst, würd ich das immer so machen:
Delphi-Quellcode:
@NameDesArrays[0]

EWeiss 23. Mai 2008 10:51

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Woran erkennst du denn, dass die Texturen nicht freigegeben werden? Dem Arbeitsspeicher kannst du das eigentlich nicht ansehen, da die Texturen im Grafikkarten-RAM gespeichert werden. Wenn der Grafikkarten-Speicher voll ist, werden die Texturen dann in den Arbeitsspeicher geschoben, aber sonst nicht.
Danke für deine Antwort ;)

Ich erkenne es daran das nach etwa 20 Titeln die Anwendung 150MB speicher belegt :)
Beim start sind es 30MB und es steigt stetig wenn das Album sich ändert
und die Texturen neu eingeladen werden.

Zitat:

Dieser Code funktioniert nicht. glDeleteTextures erwartet zwei Parameter. Der erste Parameter sagt OGL, wieviele Texturen gelöscht werden sollen. Der zweite Parameter ist ein Pointer auf das erste Element eines glUint-arrays (wenn nur eine Textur gelöscht werden soll, dann muss es kein array sein).
Ja hast du recht .. war ein flüchtigkeits fehler
Habe ja oben die einzelnen Texturen auch mit
Delphi-Quellcode:
glDeleteTextures(1, @BackTexture);    // Texture für Hintergrund
1 gelöscht.

Die schleife ansich macht das gleiche wie marabus vorschlag.
Nur seiner ist eleganter kann mir die schleife dann sparen.

EDIT:
Zitat:

Ach noch was: sind die anderen Variablen zufällig auch arrays? Wenn du den Pointer auf das erste Element eines arrays zurückgeben willst, würd ich das immer so machen:
Nein sind einzelne Texturen.

gruss Emil

littleDave 23. Mai 2008 11:26

Re: glDeleteTextures gibt Speicher nicht frei
 
Ich glaube, dass das Problem nicht bei glDeleteTextures liegt. Ich glaube, es liegt er daran, dass du die Texturdaten nach dem Laden nicht freigibst.

Normalerweise schaut das Laden einer Textur ungefähr so aus
Delphi-Quellcode:
glEnable(GL_TEXTURE_2D);
glGenTextures(1, @Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
// Textur mit Daten füllen
glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexData);
(die einzelnen Parameter sind jetzt mal beliebig gewählt)

In pTexData befinden sich jetzt die einzelnen RGB-Werte der Textur (in diesem Beispiel 768 KB). Diese Daten solltest du nach dem Laden wieder freigeben. Am besten mit FreeMem(pTexData);. Sonst spuken diese Daten im RAM herum, obwohl du sie nicht mehr brauchst.
Jetzt ist auch noch die Frage, wie du die Texturdaten aus der Datei in den Speicher bekommst (also pTexData mit RGB-Daten füllst). Wenn du z.B. TBitmap verwendest kann es noch sein, dass du die Instanz TBitmap nicht mehr freigibst.

Das ist jetzt alles nur eine Vermutung. Was du auch noch machen kannst: schau dir mal die Werte an, die die einzelnen Textur-Indizes haben (in meinem Beispiel den Wert von Texture). Soweit ich beobachtet habe sucht OpenGL den niedrigsten freien Wert und setzt ihn dann in die Variable. Wenn die Werte jetzt immer größer werden, werden die Texturen vielleicht nicht freigegeben. Ich bin mir da aber überhaupt nicht sicher, ob das überhaupt funktionierten kann.

EWeiss 23. Mai 2008 11:42

Re: glDeleteTextures gibt Speicher nicht frei
 
Ich lade sie so..

Delphi-Quellcode:
    if Assigned(QuadTexture) then
    begin
      glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
      SetLength(QuadTexture, 0);
    end;

    glDeleteTextures(1, @BackTexture);    // Texture für Hintergrund
    glDeleteTextures(1, @GradientTex);    // Texture für DiskSpectrum
    glDeleteTextures(1, @MeterTexture);   // Texture für VUMeter
    glDeleteTextures(1, @PeaksTexture);   // Texture für Peaks
    glDeleteTextures(1, @SpectrumTexture); // Texture für Spectrum
    glDeleteTextures(1, @BarTexture);     // Texture für Slider
    glDeleteTextures(1, @PrivateTexture); // Texture für CDLabel

    if assigned(aCovers) then
     aCovers.Free;

    // Lade Cover für Quader
    aCovers := TStringList.Create;
    if CoverPath <> '' then
    begin
      if CoverPath <> Path then
        ScanDirectory(CoverPath, 'bmp, tga, jpg', True);

      tmpC := 0;
      if (aCovers.count <= QuadCount) then
      begin
        for i := 0 to aCovers.count-1 do
        begin
          if (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'COVER')
            or (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'CDLABEL') then
            begin
              if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
                LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[i], False);
              dec(tmpC);
            end else
            begin
              LoadTexture(aCovers.Strings[i], quadTexture[tmpC], False);
            end;
            inc(tmpC);

        end;

        if (QuadCount >= (aCovers.count - 1)) then
        begin
          for q := (aCovers.count - 1) to QuadCount do
            if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
              LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[q-1], False);
        end;
        exit;
      end;


      tmpA := 0;
      if (aCovers.count >= QuadCount) then
      begin
        for i := 0 to aCovers.count-1 do
        begin
          if (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'COVER')
            or (ExtractFileName(AnsiLeftStr(aCovers.Strings[i], Length(aCovers.Strings[i]) - 4)) = 'CDLABEL') then
            begin
              if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
                LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[i], False);
              dec(tmpA);
            end else
            begin
              if (tmpA) <= QuadCount-1 then
                LoadTexture(aCovers.Strings[i], quadTexture[tmpA], False);
            end;
            inc(tmpA);
          end;

          if (QuadCount >= (aCovers.count - 1)) then
          begin
          for q := (aCovers.count - 1) to QuadCount do
            if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
              LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', quadTexture[q-1], False);
          end;
      end;
    end;
aCovers ist ne TStringList

Ok kann man besser machen ;)
Das laden funktioniert ja lediglich das freigeben nicht

Zum laden benutze ich den Textureloader von Sulaco

gruss Emil

littleDave 23. Mai 2008 12:21

Re: glDeleteTextures gibt Speicher nicht frei
 
Ok, der Texturloader vom Jan Horn sollte nicht das Problem sein, den hab ich früher auch verwendet.
Ich glaube, du lädst die Texturen doppelt. Die if-Abfragen
Delphi-Quellcode:
if (aCovers.count <= QuadCount) then
// ...
if (aCovers.count >= QuadCount) then
überlagern sich, falls aCovers.Count = QuadCount ist. Außerdem: kann es ein, dass du aCovers nicht mehr freigibst (oder hast du das aCovers.Free einfach nur nicht mit in den Post kopiert)?

Ich würd die Lade-Routine mal umschreiben, im Moment ist die noch relativ umständlich:

Delphi-Quellcode:
if FileExists(Path + UpperCase('Data\images\CompDisk\Default\NoCover.jpg')) then
   LoadTexture(Path + 'Data\images\CompDisk\Default\NoCover.jpg', NoCoverTexture, False)
else
   NoCoverTexture := 0;

aCovers := TStringList.Create;
try
  if CoverPath <> Path then
     ScanDirectory(CoverPath, 'bmp, tga, jpg', True);

  aFilledQuads := 0;
  for i:=0 to aCovers.Count-1 do
  begin
    // den Dateinamen extrahieren
    aFileName := ExtractFileName(aCovers[i]);
    // die Dateiendung abscheiden
    aFileName := Copy(aFileName, 1, length(aFileName) - length(ExtractFileExt(aFileName)));
    // Upper-Case machen
    aFileName := AnsiUpperCase(aFileName);

    if (aFileName = 'COVER') or (aFileName = 'CDLABEL') then
    begin
      LoadTexture(aCovers[i], quadTexture[i], False);
    end else
      QuadTexture[i] := NoCoverTexture;

    inc(aFilledQuads);
   
    // Schleife beenden, falls alle Elemente von quadTexture gefüllt sind
    if i >= High(quadTexture) then
       break;
  end;
 
  // Falls noch ein paar ungefüllte Quads übrig sind, werden die auch noch mit der
  // NoCoverTexture gefüllt
  for i:=aFilledQuads to High(quadTexture) do
    QuadTexture[i] := NoCoverTexture;
finally
  aCovers.Free;
end;
Keine Garantie auf Korrektheit, hab den Quelltext ohne offene IDE geschrieben

EWeiss 23. Mai 2008 12:30

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

überlagern sich, falls aCovers.Count = QuadCount ist. Außerdem: kann es ein, dass du aCovers nicht mehr freigibst (oder hast du das aCovers.Free einfach nur nicht mit in den Post kopiert)?
Steht oben ;)
Zitat:

if assigned(aCovers) then
aCovers.Free;
Werde deine Routine mal testen.
Danke!

aCovers.free darf in Finaly nicht freigegeben werden da später im Code noch verwendet
Erst bei erneuten aufruf wenn neue Cover eingeladen werden.

gruss Emil

EWeiss 16. Jul 2008 22:10

Re: glDeleteTextures gibt Speicher nicht frei
 
Muss das nochmal aufgreifen

Delphi-Quellcode:
    if Assigned(QuadTexture) then
    begin
      glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
      SetLength(QuadTexture, 0);
    end;
Das hatten wir schon.
Warum wird der Speicher nicht freigegeben wenn die Texturen geöscht werden ?

Solange wie ich Cover aktiviere die innerhalb des Albumkreis schon vorhanden sind gibt es keine probleme
Lade ich neue addiert der speicher jedesmal um 10 MB ??
Das kann es irgendwo nicht sein.

gruss Emil

littleDave 16. Jul 2008 22:19

Re: glDeleteTextures gibt Speicher nicht frei
 
Ich glaube ja [immer noch], dass es nicht an glDeleteTextures liegt, sondern dass du beim Laden irgendwas nicht wieder freigibst. Mach mal folgendes: du hast doch sicherlich eine Funktion in der Art LoadCoverFromFile(...) (oder so). Jetzt schreibst du folgende Methode hinein:

Delphi-Quellcode:
procedure CreateTempTexture(var Target: cardinal);
var pTexData: Pointer;
begin
  GetMem(pTexData, 512*512*3);
 
  // Textur generieren und drauf zeigen
  glGenTextures(1, @Target);
  glBindTexture(GL_TEXTURE_2D, Target);
 
  // Daten in den Speicher, Lineares Filtering aktivieren
  glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexData);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
  // Freigeben
  FreeMem(pTexData);
end;
Jetzt rufst du anstatt deiner LoadCoverFromFile diese Funktion auf (vielleicht noch etwas anpassen!). Wenn dann der Speicher immernoch nicht wieder freigeräumt wird mit der glDeleteTextures - Methode, kann ich von hier auch nicht mehr groß helfen - ich hab dann überhaupt keine Ahnung woran es dann liegt.

EWeiss 16. Jul 2008 22:32

Re: glDeleteTextures gibt Speicher nicht frei
 
Danke das werd ich mal versuchen..
Ich gehe so vor

in acover befinden sich die Pfade zu den texturen
welche dann quadTexture : GLUint; zugewiesen werden abhängig vom CoverCount
also wieviele Cover zur laufzeit geladen werden sollen von 5 > Max 25.

Damit die Cover nicht immer wieder neu geladen werden wenn sie vorhanden sind
habe ich eine TStringList erstellt LstQuadTexture

Diese beinhaltet dann die quadTexture als Text
Damit vergleiche ich dann wenn ein neuer Titel abgespielt wird.
Ist die Texture vorhanden wird sich lediglich aktiviert nicht neu geladen.
LoadCover wird dann übersprungen.

Bei jeden aufruf von LoadCover werden (sollten) alle Cover gelöscht werden.
Aber anstelle zu löschen werden wie schon gesagt immer wieder so etwa 10 MB addiert.

Die LadeRoutine für die JPG, BMP ist die von Sulaco.
Da wird aber alles direkt wieder freigegeben.

EDIT:
Habe das jetzt mal versucht..
Anstelle von
LoadTexture(aCovers[i], quadTexture[i], False);
deine function zum testen genommen .. hoffe das ist richtig so ;)
So wie du sagst erstellt diese eine Temporäre Texture also alle Quader werden jetzt einfach
mit dieser gefüllt (alles schwartz)

Speicher wird einwandfrei freigegeben.
Delphi-Quellcode:
              if (aFileName = 'COVER') then
              begin
                CreateTempTexture(quadTexture[i]);
                //LoadTexture(aCovers[i], quadTexture[i], False);
                LstQuadTexture.Add(IntToStr(quadTexture[i]));
                LstCoverPath.Add(aCovers[i]);
                LastAddCover := Trunc(quadTexture[i]);
              end;
EDIT2:
Das ist der part des Textureloaders für JPG ohne von resource laden...
Da wird alles freigegeben.

Delphi-Quellcode:
  end
  else
  begin
    try
      JPG.LoadFromFile(Filename);
    except
      MessageBox(0, PChar('Couldn''t load JPG - "'+ Filename +'"'), PChar('BMP Unit'), MB_OK);
      Exit;
    end;
  end;

  // Create Bitmap
  BMP:=TBitmap.Create;
  try
  BMP.pixelformat:=pf32bit;
  BMP.width:=JPG.width;
  BMP.height:=JPG.height;
  BMP.canvas.draw(0,0,JPG);       // Copy the JPEG onto the Bitmap

  MStream := TMemoryStream.Create;
    try
      BMP.TransparentMode := tmAuto;
      BMP.PixelFormat := pf24bit; // just because this format works!
      BMP.Dormant;                 // make it so!
      BMP.SaveToStream(MStream);
      MStream.Seek(0,soFromBeginning);
      LoadBMPTextureFromStream(MStream, Texture);
    finally
      MStream.free;
    end;
  finally
    BMP.Free;
  end;
  result :=TRUE;
Gruss Emil

EWeiss 16. Jul 2008 22:57

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Zitat von EWeiss
Danke das werd ich mal versuchen..
Ich gehe so vor

in acover befinden sich die Pfade zu den texturen
welche dann quadTexture : GLUint; zugewiesen werden abhängig vom CoverCount
also wieviele Cover zur laufzeit geladen werden sollen von 5 > Max 25.

Damit die Cover nicht immer wieder neu geladen werden wenn sie vorhanden sind
habe ich eine TStringList erstellt LstQuadTexture

Diese beinhaltet dann die quadTexture als Text
Damit vergleiche ich dann wenn ein neuer Titel abgespielt wird.
Ist die Texture vorhanden wird sich lediglich aktiviert nicht neu geladen.
LoadCover wird dann übersprungen.

Bei jeden aufruf von LoadCover werden (sollten) alle Cover gelöscht werden.
Aber anstelle zu löschen werden wie schon gesagt immer wieder so etwa 10 MB addiert.

Die LadeRoutine für die JPG, BMP ist die von Sulaco.
Da wird aber alles direkt wieder freigegeben.

EDIT:
Habe das jetzt mal versucht..
Anstelle von
LoadTexture(aCovers[i], quadTexture[i], False);
deine function zum testen genommen .. hoffe das ist richtig so ;)
So wie du sagst erstellt diese eine Temporäre Texture also alle Quader werden jetzt einfach
mit dieser gefüllt (alles schwartz)

Speicher wird einwandfrei freigegeben.
Delphi-Quellcode:
              if (aFileName = 'COVER') then
              begin
                CreateTempTexture(quadTexture[i]);
                //LoadTexture(aCovers[i], quadTexture[i], False);
                LstQuadTexture.Add(IntToStr(quadTexture[i]));
                LstCoverPath.Add(aCovers[i]);
                LastAddCover := Trunc(quadTexture[i]);
              end;
EDIT2:
Das ist der part des Textureloaders für JPG ohne von resource laden...
Da wird alles freigegeben.

Delphi-Quellcode:
  end
  else
  begin
    try
      JPG.LoadFromFile(Filename);
    except
      MessageBox(0, PChar('Couldn''t load JPG - "'+ Filename +'"'), PChar('BMP Unit'), MB_OK);
      Exit;
    end;
  end;

  // Create Bitmap
  BMP:=TBitmap.Create;
  try
  BMP.pixelformat:=pf32bit;
  BMP.width:=JPG.width;
  BMP.height:=JPG.height;
  BMP.canvas.draw(0,0,JPG);       // Copy the JPEG onto the Bitmap

  MStream := TMemoryStream.Create;
    try
      BMP.TransparentMode := tmAuto;
      BMP.PixelFormat := pf24bit; // just because this format works!
      BMP.Dormant;                 // make it so!
      BMP.SaveToStream(MStream);
      MStream.Seek(0,soFromBeginning);
      LoadBMPTextureFromStream(MStream, Texture);
    finally
      MStream.free;
    end;
  finally
    BMP.Free;
  end;
  result :=TRUE;
Gruss Emil


littleDave 16. Jul 2008 23:16

Re: glDeleteTextures gibt Speicher nicht frei
 
Hab gerade mal auf meiner Platte gewühlt und die alte Textures.pas gefunden. Der Abschnitt schaut bei mir etwas anders aus:

Delphi-Quellcode:
// ... rest abgeschnitten
  begin
    try
      JPG.LoadFromFile(Filename);
    except
      MessageBox(0, PChar('Couldn''t load JPG - "'+ Filename +'"'), PChar('BMP Unit'), MB_OK);
      Exit;
    end;
  end;

  // Create Bitmap
  BMP:=TBitmap.Create;
  BMP.pixelformat:=pf32bit;
  BMP.width:=JPG.width;
  BMP.height:=JPG.height;
  BMP.canvas.draw(0,0,JPG);       // Copy the JPEG onto the Bitmap

  //  BMP.SaveToFile('D:\test.bmp');
  Width :=BMP.Width;
  Height :=BMP.Height;
  SetLength(Data, Width*Height);

  For H:=0 to Height-1 do
  Begin
    Line :=BMP.scanline[Height-H-1];  // flip JPEG
    For W:=0 to Width-1 do
    Begin
      c:=Line^ and $FFFFFF; // Need to do a color swap
      Data[W+(H*Width)] :=(((c and $FF) shl 16)+(c shr 16)+(c and $FF00)) or $FF000000; // 4 channel.
      inc(Line);
    End;
  End;

  BMP.free;
  JPG.free;

  Texture :=CreateTexture(Width, Height, GL_RGBA, addr(Data[0]));
  result :=TRUE;
end;
Was aber sicherlich niemals schaden wird ist am Schluss noch ( nach Texture := CreateTexture( ...)
Delphi-Quellcode:
SetLength(Data, 0);
aufzurufen

Der Loader von Sulaco ist zwar schön und gut, doch so ganz neu ist der ja nun auch nicht mehr ;-). Ich würd dir in der Hinsicht dringend empfehlen, einen anderen Texture-Loaded (z.B. glBitmap) zu verwenden. Bei glBitmap hast du sogar noch den Vorteil, dass fast nichts umschreiben musst - dort gibt es auch eine Funktion namens LoadTexture, die genauso aufgebaut ist wie die von Jan Horn. Ich persönlich arbeite noch mit Version 1.8.9 dieses Headers, daher weiß ich nicht, was sich seit dem genau verändert hat.
Falls du den Header verwendest, solltest du ihn natürlich vorher einstellen (die Defines am Anfang}

EWeiss 16. Jul 2008 23:20

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Falls du den Header verwendest, solltest du ihn natürlich vorher einstellen (die Defines am Anfang}
ja und da habe ich ein problem mit ;)
Habe nach dem Loader schon geschaut .. schäm. muss gestehen keine ahnung was ich da einstellen soll

EDIT:
Und zusätzlich dazu muss dann noch einige fremd DLL's mit einbauen freejpg und was weiss ich noch alles.
Die DLL soll eigentlich einzeln ausgegeben werden.

gruss Emil

littleDave 16. Jul 2008 23:28

Re: glDeleteTextures gibt Speicher nicht frei
 
Das ist nicht schwer - wirklich. Falls du den DelphiGL-Header (dglOpenGl.pas) benutzt, ist es sehr einfach. Du lädst dir hier die Version glBitmap_1.8.9.zip herunter. Dann extrahierst du die Datei in einen beliebigen Order und fügst den in den Such-Pfad von Delphi hinzu.
Jetzt öffnest du die Datei - Windows NotePad reicht dabei vollkommen. Ganz oben im Interface-Abschnitt findest du dann die Zeile
Delphi-Quellcode:
{.$define NO_NATIVE_GL}
Dort löscht du einfach den Punkt vor $define, speicherst und fertig!

Zitat:

Zitat von EWeiss
Und zusätzlich dazu muss dann noch einige fremd DLL's mit einbauen freejpg und was weiss ich noch alles.
Die DLL soll eigentlich einzeln ausgegeben werden.

Bei Version 1.8.9 brauchst du keine weiteren DLLs. Ab Version 2.0 (glaub ich) hat Lossy auf libJpeg umgestellt, aber die Versionen davor brauchen keine weiteren DLLs

EWeiss 16. Jul 2008 23:33

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Zitat von littleDave
Das ist nicht schwer - wirklich. Falls du den DelphiGL-Header (dglOpenGl.pas) benutzt, ist es sehr einfach. Du lädst dir hier die Version glBitmap_1.8.9.zip herunter. Dann extrahierst du die Datei in einen beliebigen Order und fügst den in den Such-Pfad von Delphi hinzu.
Jetzt öffnest du die Datei - Windows NotePad reicht dabei vollkommen. Ganz oben im Interface-Abschnitt findest du dann die Zeile
Delphi-Quellcode:
{.$define NO_NATIVE_GL}
Dort löscht du einfach den Punkt vor $define, speicherst und fertig!

Zitat:

Zitat von EWeiss
Und zusätzlich dazu muss dann noch einige fremd DLL's mit einbauen freejpg und was weiss ich noch alles.
Die DLL soll eigentlich einzeln ausgegeben werden.

Bei Version 1.8.9 brauchst du keine weiteren DLLs. Ab Version 2.0 (glaub ich) hat Lossy auf libJpeg umgestellt, aber die Versionen davor brauchen keine weiteren DLLs

Ahhh dann ist alles ok werde dann umstellen :)
Fehler lag nicht an glDeleteTextures :)

Schau mal hier ..

deine..
Delphi-Quellcode:
  End;

  BMP.free;
  JPG.free;

  Texture :=CreateTexture(Width, Height, GL_RGBA, addr(Data[0]));
  result :=TRUE;
end;
meine..
Delphi-Quellcode:
    end;
  finally
    BMP.Free;
  end;
  result :=TRUE;
definitiv fehlt da was ;)
Kein wunder das nach 10 25x JPG Cover laden der speicher bei 80MB und drüber liegt.
Die größte leistung waren 1023 MB Speicher nur wegen der Vis ;)

Danke für den Tip werd es mal umändern.

gruss Emil

littleDave 16. Jul 2008 23:37

Re: glDeleteTextures gibt Speicher nicht frei
 
Hihi, stimmt - hätt ich jetzt nicht sofort gesehen - naja, bei der Uhrzeit auch verständlich ;-)

Falls es jetzt dann gehen sollte - bedenke: Never change a running system :zwinker:

Grüße und gute Nacht
Dave

EWeiss 16. Jul 2008 23:41

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Zitat von littleDave
Hihi, stimmt - hätt ich jetzt nicht sofort gesehen - naja, bei der Uhrzeit auch verständlich ;-)

Falls es jetzt dann gehen sollte - bedenke: Never change a running system :zwinker:

Grüße und gute Nacht
Dave

ja stimmt schon.
Aber die glBitmap wird wohl einige optimierungen haben werd es mir mal anschauen.
Vielleicht bringt es mir geschwindigkeits vorteile

danke nochmal

gruss Emil

turboPASCAL 17. Jul 2008 03:22

Re: glDeleteTextures gibt Speicher nicht frei
 
Mal so nebenbei, ich lösche die geladenen OpenGL-Texturen mit einem Einzeiler:

Delphi-Quellcode:
glDeleteTextures(TEXTURE_COUNT, @glTextures[0]);
glTextures kann ein statyisches oder dyn. Array sein, welches die Texturen (die Adresse(n) derer) enthält.

Beispiel:

Delphi-Quellcode:
var
  glTextures: Array [0.. TEXTURE_COUNT - 1] of gluInt;

const
  TEXTURE_COUNT = 1;

  TEX_WHITE = 0;
  TEX_BLACK = 1;

//...
begin
  LoadTexture(TexturePath + 'Image1.jpg', glTextures[TEX_WHITE]);
  LoadTexture(TexturePath + 'Image2.jpg', glTextures[TEX_BLACK]);
end;

EWeiss 17. Jul 2008 03:39

Re: glDeleteTextures gibt Speicher nicht frei
 
Ich auch im normal fall

Delphi-Quellcode:
    if Assigned(QuadTexture) then
    begin
      glDeleteTextures(Length(QuadTexture), @QuadTexture[Low(QuadTexture)]);
      SetLength(QuadTexture, 0);
    end;
Das geht aber nicht in meiner LoadCover function
Dort dürfen nur Texturen gelöscht werden die <> wie NoCoverTexture beinhalten.
Daher das löschen in einer schleife.

Ist also Programm abhängig

EDIT:
Das hätte zur folge das meine NoCoverTexturen die nur einmal beim start geladen werden
als weiße leere Texture zurück bliebe ;)

gruss Emil

Lossy eX 17. Jul 2008 09:38

Re: glDeleteTextures gibt Speicher nicht frei
 
Ich glaube glDeleteTextures wird innerhlab des Treibers sowieso in einzelne Texturlöschbefehle verwandeln weswegen es da vermutlich kaum einen Unterschied geben sollte.

Zur glBitmap. Ja ab der 2.0 habe ich einiges umgestellt. Also unter anderem eine Linuxkompatibilität, die Unterstützung für SDL, SDL_image, libJPEG und libPNG. Allerdings wird die pngimage und die JPEG Implementation von Delphi weiterhin unterstützt. Die glBitmap ist ab der 2.0 von Hause aus relativ nackt. Es werden nur DDS, TGA und BMP (mittlerweile vollkommen intern geladen) unterstützt. Die Unterstützung für alle anderen Schnittstellen muss man zusätzlich aktivieren.

EWeiss: Für deinen Fall musst du folgende Defines aktivieren.
- GLB_DELPHI um die Unterstützung von Delphi TBitmaps zu aktivieren.
- GLB_DELPHI_JPEG um die JPEG Implementation von Delphi zu aktivieren
und evtl. noch folgendes define
- GLB_PNGIMAGE um die native delphipng/pngimage implementation zu aktivieren.
bzw das folgende define kannst du evtl auch noch aktivieren
- GLB_NO_NATIVE_GL deaktiviert den internen Header und benutzt dafür die dglOpenGL.pas

Vorteile durch die glBitmap: Auch wenn ich mir damit selber ein bisschen den Boden unter den Füßen wegziehe. Ich denke nicht, dass das Laden von JPEGs durch die glBitmap schneller sein wird. Denn die Delphi Implementation ist und bleibt langsam und nur weil jemand anders sie benutzt wird es nicht schneller gehen. Die libJPEG ist aber um einiges schneller als die Delphivariante. Nichts desto trotz dürfte die glBitmap einige Vorteile haben. Alleine dadurch, dass alles ausreichend getestet wurde und eine entsprechende Kompatibilität aufweist.
Wobei ich aber in jedem Fall zu den glBitmap eigenen Objekten raten würde. Dadurch, dass man die Objekte benutzt hat man viel mehr Kontrolle über die Texturen. Jetzt laden. Später eine Textur erstellen. Und es stehen einfach viel viel mehr features zur Verfügung. Ich habe es schon häufiger bereuht, dass ich die Methoden überhaupt eingebaut hatte. :wall:

littleDave: Ich würde dir evtl auch empfehlen die glBitmap auf den neusten Stand zu bringen. In der letzten Version habe ich TGAs noch mal erheblich beschleunigt. Bzw in der Version 1.8.11 hatte ich noch einen Fehler innerhalb der TGAs korrigiert. Der taucht aber nur bei recht wenigen Programmen auf.

EWeiss 17. Jul 2008 09:58

Re: glDeleteTextures gibt Speicher nicht frei
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

EWeiss: Für deinen Fall musst du folgende Defines aktivieren.
- GLB_DELPHI um die Unterstützung von Delphi TBitmaps zu aktivieren.
- GLB_DELPHI_JPEG um die JPEG Implementation von Delphi zu aktivieren
und evtl. noch folgendes define
- GLB_PNGIMAGE um die native delphipng/pngimage implementation zu aktivieren.
bzw das folgende define kannst du evtl auch noch aktivieren
- GLB_NO_NATIVE_GL deaktiviert den internen Header und benutzt dafür die dglOpenGL.pas
Werde es auf jedenfall mal versuchen und schauen welche vorteile es bringt.
Zumindest sieht das teil jetzt schon mal so aus.

Extra BIG in *.png Format für die Feinheiten.
Der Font kann während der laufzeit geändert werden.

gruss Emil

EWeiss 21. Jul 2008 14:47

Re: glDeleteTextures gibt Speicher nicht frei
 
Liste der Anhänge anzeigen (Anzahl: 3)
Denke vorerst mal fertig

Lade es mal hoch zum testen und spielen wenn jemand interesse hat.

Vorraussetzung:
Im Album Ordner müssen zwei Bitmaps (zumindest das Cover) vorhanden sein damit der Covermode funktioniert
Cover und CDLabel *.jpg, oder *.bmp am besten im Format 512x512

Das Archiv nach Winamp extrahieren
Winamp starten das Plugin wählen und fertig.
Konfiguriert wird es mit einem rechten Mausklick auf der Vis
dann sollte sich ein Preferences Dialog öffnen da nachschauen was es so gibt.

Denke wohl das ihr damit klar kommt wenn es denn läuft ;)

Klick auf ein Cover wenn vorhanden öffnet ein Album Info Fenster.
Aber nur wenn auch ein reales Cover vorhanden ist ansonsten geht nix auf.
Auf das Image klicken dann gibt es Infos von dem aktuell spielenden Album
Klickt man auf Play wird die Playliste von Winamp geleert und alle Titel vom aktuellen Album zur Playliste addiert.
So kann man sein lieblings Album hören.

Der nicht Covermode ermöglicht eine art slideshow abzuspielen
Alle Bilder im Screenmode Format bsp:640x480, 1024x768 usw.. die sich im CompDisk Ordner befinden
werden dann bei jeden neuen Titel überblendet und ein neues Bild angezeigt.

getestet mit Winamp 5.54

PS: Quelltext schicke ich später mal.

gruss Emil

turboPASCAL 21. Jul 2008 15:28

Re: glDeleteTextures gibt Speicher nicht frei
 
:gruebel:

Das hat doch jetzt nichts mit diesem Thread zu schaffen ?
Wenn es sich um ein Softwaretest im allgemeinen handelt mache dies bitte im Freewarethread bzw. Forum.

Gruss...

EWeiss 21. Jul 2008 16:03

Re: glDeleteTextures gibt Speicher nicht frei
 
Zitat:

Zitat von turboPASCAL
:gruebel:

Das hat doch jetzt nichts mit diesem Thread zu schaffen ?
Wenn es sich um ein Softwaretest im allgemeinen handelt mache dies bitte im Freewarethread bzw. Forum.

Gruss...

Wer diktiert das ?
Für mich ist der Thread gut sagt aus das mein problem mit dem Speicher behoben ist und das ergebniss getestet werden kann.
Ob es jetzt hier steht oder sonst wo ..
Ich sehe hier einen zusammenhang.

gruss Emil


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz