* refactored LoadDDS
authorBergmann89 <bergmann89@muo-game.de>
Sun, 10 Nov 2013 16:30:24 +0000 (17:30 +0100)
committerBergmann89 <bergmann89@muo-game.de>
Sun, 10 Nov 2013 16:30:24 +0000 (17:30 +0100)
glBitmap.pas

index 88724cf..72c81e0 100644 (file)
@@ -645,7 +645,11 @@ type
 
     tfDepth16,
     tfDepth24,
-    tfDepth32
+    tfDepth32,
+
+    tfS3tcDtx1RGBA,
+    tfS3tcDtx3RGBA,
+    tfS3tcDtx5RGBA
   );
 
   TglBitmapFileType = (
@@ -1054,7 +1058,9 @@ type
     fWithAlpha: TglBitmapFormat;
     fWithoutAlpha: TglBitmapFormat;
     fRGBInverted: TglBitmapFormat;
+    fUncompressed: TglBitmapFormat;
     fPixelSize: Single;
+    fIsCompressed: Boolean;
 
     fRange: TglBitmapColorRec;
     fShift: TShiftRec;
@@ -1071,6 +1077,7 @@ type
     property RGBInverted:  TglBitmapFormat read fRGBInverted;
     property Components:   Integer         read GetComponents;
     property PixelSize:    Single          read fPixelSize;
+    property IsCompressed: Boolean         read fIsCompressed;
 
     property glFormat:         Cardinal read fglFormat;
     property glInternalFormat: Cardinal read fglInternalFormat;
@@ -1413,6 +1420,24 @@ type
     constructor Create; override;
   end;
 
+  TfdS3tcDtx1RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
+  TfdS3tcDtx3RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
+  TfdS3tcDtx5RGBA = class(TFormatDescriptor)
+    procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override;
+    procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override;
+    constructor Create; override;
+  end;
+
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   TbmpBitfieldFormat = class(TFormatDescriptor)
   private
@@ -1526,7 +1551,11 @@ const
 
     TfdDepth16,
     TfdDepth24,
-    TfdDepth32
+    TfdDepth32,
+
+    TfdS3tcDtx1RGBA,
+    TfdS3tcDtx3RGBA,
+    TfdS3tcDtx5RGBA
   );
 
 var
@@ -2236,7 +2265,9 @@ begin
   fWithAlpha    := tfEmpty;
   fWithoutAlpha := tfEmpty;
   fRGBInverted  := tfEmpty;
+  fUncompressed := tfEmpty;
   fPixelSize    := 0.0;
+  fIsCompressed := false;
 
   fglFormat         := 0;
   fglInternalFormat := 0;
@@ -3401,6 +3432,84 @@ begin
 end;
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx1RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx1RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx1RGBA;
+  fWithAlpha        := tfS3tcDtx1RGBA;
+  fUncompressed     := tfRGB5A1;
+  fPixelSize        := 0.5;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx3RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx3RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx3RGBA;
+  fWithAlpha        := tfS3tcDtx3RGBA;
+  fUncompressed     := tfRGBA8;
+  fPixelSize        := 1.0;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TfdS3tcDtx5RGBA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer);
+begin
+  raise EglBitmapException.Create('mapping for compressed formats is not supported');
+end;
+
+constructor TfdS3tcDtx5RGBA.Create;
+begin
+  inherited Create;
+  fFormat           := tfS3tcDtx3RGBA;
+  fWithAlpha        := tfS3tcDtx3RGBA;
+  fUncompressed     := tfRGBA8;
+  fPixelSize        := 1.0;
+  fIsCompressed     := true;
+  fglFormat         := GL_COMPRESSED_RGBA;
+  fglInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+  fglDataFormat     := GL_UNSIGNED_BYTE;
+end;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //TFormatDescriptor///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 class procedure TFormatDescriptor.Init;
@@ -6882,6 +6991,7 @@ const
   DDPF_FOURCC                 = $00000004;
   DDPF_INDEXED                = $00000020;
   DDPF_RGB                    = $00000040;
+  DDPF_LUMINANCE              = $00020000;
 
   // DDS_header.sCaps.dwCaps1
   DDSCAPS_COMPLEX             = $00000008;
@@ -6940,84 +7050,70 @@ type
 function TglBitmap.LoadDDS(const aStream: TStream): Boolean;
 var
   Header: TDDSHeader;
-  StreamPos: Int64;
-  Y, LineSize: Cardinal;
-  RowSize: Cardinal;
-  NewImage, pData: pByte;
-  ddsFormat: TglBitmapFormat;
-
-  function RaiseEx : Exception;
-  begin
-    result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
-  end;
 
   function GetDDSFormat: TglBitmapFormat;
   begin
+    result := tfEmpty;
     with Header.PixelFormat do begin
       // Compresses
-      if (dwFlags and DDPF_FOURCC) > 0 then begin
-        (* TODO
+      if ((dwFlags and DDPF_FOURCC) > 0) then begin
         case Header.PixelFormat.dwFourCC of
-          D3DFMT_DXT1: result := ifDXT1;
-          D3DFMT_DXT3: result := ifDXT3;
-          D3DFMT_DXT5: result := ifDXT5;
-        else
-          raise RaiseEx;
+          D3DFMT_DXT1: result := tfS3tcDtx1RGBA;
+          D3DFMT_DXT3: result := tfS3tcDtx3RGBA;
+          D3DFMT_DXT5: result := tfS3tcDtx5RGBA;
         end;
-        *)
-        raise RaiseEx;
       end else
 
       // RGB
-      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
+      if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
         case dwRGBBitCount of
           8: begin
-            (* TODO if dwFlags and DDPF_ALPHAPIXELS > 0 then
-              result := tfAlpha
-            else
-            *)
+            if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then
+              result := tfAlpha8
+            else if ((dwFlags and DDPF_LUMINANCE) > 0) then
               result := tfLuminance8;
           end;
+
           16: begin
-            if dwFlags and DDPF_ALPHAPIXELS > 0 then begin
-              // Alpha
+            if ((dwFlags and DDPF_ALPHAPIXELS) > 0) then begin
               case CountSetBits(dwRBitMask) of
                 5: result := tfRGB5A1;
-                //TODO 4: result := tfRGBA4;
+                4: result := tfRGBA4;
               else
                 result := tfLuminance8Alpha8;
               end;
-            end else begin
-              // no Alpha
-              //TODO result := ifR5G6B5;
-              raise RaiseEx;
-            end;
+            end else if (CountSetBits(dwGBitMask) = 6) then
+              result := tfR5G6B5
+            else
+              result := tfRGB5;
           end;
+
           24: begin
-            if dwRBitMask > dwBBitMask then
-              result := tfBGR8
-            else
-              result := tfRGB8;
+            result := tfRGB8;
           end;
-        32: begin
-            if CountSetBits(dwRBitMask) = 10 then
-              //TODO result := tfRGB10A2
-              raise RaiseEx
-            else
 
-            if dwRBitMask > dwBBitMask then
-              result := tfBGRA8
+          32: begin
+            if CountSetBits(dwRBitMask) = 10 then
+              result := tfRGB10A2
             else
               result := tfRGBA8;
           end;
-        else
-          raise RaiseEx;
         end;
-      end else
-        raise RaiseEx;
+
+        if (dwRBitMask <> 0) and (dwBBitMask <> 0) and (dwRBitMask > dwBBitMask) then
+          result := TFormatDescriptor.Get(result).RGBInverted;
+      end;
     end;
   end;
 
+var
+  StreamPos: Int64;
+  Y, LineSize: Cardinal;
+  RowSize: Cardinal;
+  NewImage, TmpData: PByte;
+  ddsFormat: TglBitmapFormat;
+  FormatDesc: TFormatDescriptor;
+
 begin
   result := false;
 
@@ -7025,37 +7121,45 @@ begin
   StreamPos := aStream.Position;
   aStream.Read(Header, sizeof(Header));
 
-  if ((Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
-     ((Header.dwFlags and DDSD_PIXELFORMAT) = 0) or ((Header.dwFlags and DDSD_CAPS) = 0)) then begin
+  if (Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or
+     ((Header.dwFlags and (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) <>
+        (DDSD_PIXELFORMAT or DDSD_CAPS or DDSD_WIDTH or DDSD_HEIGHT)) then
+  begin
     aStream.Position := StreamPos;
     exit;
   end;
 
+  if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then
+    raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported');
+
   ddsFormat := GetDDSFormat;
-  LineSize  := Trunc(Header.dwWidth * TFormatDescriptor.Get(ddsFormat).PixelSize);
+  if (ddsFormat = tfEmpty) then
+    raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
+
+  FormatDesc := TFormatDescriptor.Get(ddsFormat);
+  LineSize   := Trunc(Header.dwWidth * FormatDesc.PixelSize);
   GetMem(NewImage, Header.dwHeight * LineSize);
   try
-    pData := NewImage;
+    TmpData := NewImage;
 
     // Compressed
-    if (Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0 then begin
+    if ((Header.PixelFormat.dwFlags and DDPF_FOURCC) > 0) then begin
       RowSize := Header.dwPitchOrLinearSize div Header.dwWidth;
-      for Y := 0 to Header.dwHeight -1 do begin
-        aStream.Read(pData^, RowSize);
-        Inc(pData, LineSize);
+      for Y := 0 to Header.dwHeight-1 do begin
+        aStream.Read(TmpData^, RowSize);
+        Inc(TmpData, LineSize);
       end;
     end else
 
-    // RGB(A)
-    if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin
-      RowSize := Header.dwPitchOrLinearSize;
-
-      for Y := 0 to Header.dwHeight -1 do begin
-        aStream.Read(pData^, RowSize);
-        Inc(pData, LineSize);
+    // Uncompressed
+    if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin
+      RowSize := (Header.PixelFormat.dwRGBBitCount * Header.dwWidth) shr 3;
+      for Y := 0 to Header.dwHeight-1 do begin
+        aStream.Read(TmpData^, RowSize);
+        Inc(TmpData, LineSize);
       end;
     end else
-      raise RaiseEx;
+      raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.');
 
     SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight);
     result := true;
@@ -7141,8 +7245,7 @@ var
 begin
   inherited SetDataPointer(aData, aFormat, aWidth, aHeight);
 
-  //TODO compression
-  if {FormatIsUncompressed(Format)} true then begin
+  if not TFormatDescriptor.Get(aFormat).IsCompressed then begin
     (* TODO PixelFuncs
     fGetPixelFunc := GetPixel2DUnmap;
     fSetPixelFunc := SetPixel2DUnmap;
@@ -7159,9 +7262,8 @@ begin
     end
       else SetLength(fLines, 0);
   end else begin
-    (*
     SetLength(fLines, 0);
-
+    (*
     fSetPixelFunc := nil;
 
     case Format of
@@ -7185,19 +7287,16 @@ var
 begin
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-  (* TODO compression
-  if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then
-    glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data)
-  else
-  *)
-
   FormatDesc := TFormatDescriptor.Get(Format);
-  if aBuildWithGlu then
+  if FormatDesc.IsCompressed then begin
+    glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data)
+  end else if aBuildWithGlu then begin
     gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height,
       FormatDesc.glFormat, FormatDesc.glDataFormat, Data)
-  else
+  end else begin
     glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0,
       FormatDesc.glFormat, FormatDesc.glDataFormat, Data);
+  end;
 
   // Freigeben
   if (FreeDataAfterGenTexture) then
@@ -7218,15 +7317,13 @@ var
   Size, w, h: Integer;
   FormatDesc: TFormatDescriptor;
 begin
-  (* TODO compression
-  if not FormatIsUncompressed(Format) then
+  FormatDesc := TFormatDescriptor.Get(Format);
+  if FormatDesc.IsCompressed then
     raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT);
-  *)
 
-  w := aRight  - aLeft;
-  h := aBottom - aTop;
-  FormatDesc   := TFormatDescriptor.Get(Format);
-  Size         := FormatDesc.GetSize(w, h);
+  w    := aRight  - aLeft;
+  h    := aBottom - aTop;
+  Size := FormatDesc.GetSize(w, h);
   GetMem(Temp, Size);
   try
     glPixelStorei(GL_PACK_ALIGNMENT, 1);
@@ -7266,12 +7363,10 @@ begin
   FormatDesc := TFormatDescriptor.Get(IntFormat);
   GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight));
   try
-    (* TODO Compression
-    if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then
+    if FormatDesc.IsCompressed then
       glGetCompressedTexImage(Target, 0, Temp)
     else
-    *)
-    glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
+     glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp);
     SetDataPointer(Temp, IntFormat, TempWidth, TempHeight);
   except
     FreeMem(Temp);