From 40c2e1a73048b33c1a9f238748a3dd14b98099a1 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 22 Oct 2013 17:13:07 +0200 Subject: [PATCH 01/38] * initial Commit --- glBitmap.pas | 6825 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 6825 insertions(+) create mode 100644 glBitmap.pas diff --git a/glBitmap.pas b/glBitmap.pas new file mode 100644 index 0000000..1198bda --- /dev/null +++ b/glBitmap.pas @@ -0,0 +1,6825 @@ +{*********************************************************** +glBitmap by Steffen Xonna aka Lossy eX (2003-2008) +http://www.opengl24.de/index.php?cat=header&file=glbitmap +------------------------------------------------------------ +The contents of this file are used with permission, subject to +the Mozilla Public License Version 1.1 (the "License"); you may +not use this file except in compliance with the License. You may +obtain a copy of the License at +http://www.mozilla.org/MPL/MPL-1.1.html +------------------------------------------------------------ +Version 2.0.3 +------------------------------------------------------------ +History +21-03-2010 +- The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi + then it's your problem if that isn't true. This prevents the unit for incompatibility + with newer versions of Delphi. +- Problems with D2009+ resolved (Thanks noeska and all i forgot) +- GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson) +10-08-2008 +- AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson) +- Additional Datapointer for functioninterface now has the name CustomData +24-07-2008 +- AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson) +- If you load an texture from an file the property Filename will be set to the name of the file +- Three new properties to attach custom data to the Texture objects + - CustomName (free for use string) + - CustomNameW (free for use widestring) + - CustomDataPointer (free for use pointer to attach other objects or complex structures) +27-05-2008 +- RLE TGAs loaded much faster +26-05-2008 +- fixed some problem with reading RLE TGAs. +21-05-2008 +- function clone now only copys data if it's assigned and now it also copies the ID +- it seems that lazarus dont like comments in comments. +01-05-2008 +- It's possible to set the id of the texture +- define GLB_NO_NATIVE_GL deactivated by default +27-04-2008 +- Now supports the following libraries + - SDL and SDL_image + - libPNG + - libJPEG +- Linux compatibillity via free pascal compatibility (delphi sources optional) +- BMPs now loaded manuel +- Large restructuring +- Property DataPtr now has the name Data +- Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR +- Unused Depth removed +- Function FreeData to freeing image data added +24-10-2007 +- ImageID flag of TGAs was ignored. (Thanks Zwoetzen) +15-11-2006 +- Function SetBorderColor implemented (only used by opengl if wrap is set to GL_CLAMP_TO_BORDER) +- Function AddAlphaFromValue implemented to use an fixed Value as Alphachannel +- Function ReadOpenGLExtension is now only intern +29-06-2006 +- pngimage now disabled by default like all other versions. +26-06-2006 +- Setting up an anisotropic filter of 0 isnt allowed by nvidia (Thanks Ogridi) +22-06-2006 +- Fixed some Problem with Delphi 5 +- Now uses the newest version of pngimage. Makes saving pngs much easier. +22-03-2006 +- Property IsCompressed and Size removed. Not really supported by Spec (Thanks Ogridi) +09-03-2006 +- Internal Format ifDepth8 added +- function GrabScreen now supports all uncompressed formats +31-01-2006 +- AddAlphaFromglBitmap implemented +29-12-2005 +- LoadFromResource and LoadFromResourceId now needs an Instance and an ResourceType (for ID) +28-12-2005 +- Width, Height and Depth internal changed to TglBitmapPixelPosition. + property Width, Height, Depth are still existing and new property Dimension are avail +11-12-2005 +- Added native OpenGL Support. Breaking the dglOpenGL "barrier". +19-10-2005 +- Added function GrabScreen to class TglBitmap2D +18-10-2005 +- Added support to Save images +- Added function Clone to Clone Instance +11-10-2005 +- Functions now works with Cardinals for each channel. Up to 32 Bits per channel. + Usefull for Future +- Several speed optimizations +09-10-2005 +- Internal structure change. Loading of TGA, PNG and DDS improved. + Data, format and size will now set directly with SetDataPtr. +- AddFunc now works with all Types of Images and Formats +- Some Funtions moved to Baseclass TglBitmap +06-10-2005 +- Added Support to decompress DXT3 and DXT5 compressed Images. +- Added Mapping to convert data from one format into an other. +05-10-2005 +- Added method ConvertTo in Class TglBitmap2D. Method allows to convert every + supported Input format (supported by GetPixel) into any uncompresed Format +- Added Support to decompress DXT1 compressed Images. +- SwapColors replaced by ConvertTo +04-10-2005 +- Added Support for compressed DDSs +- Added new internal formats (DXT1, DXT3, DXT5) +29-09-2005 +- Parameter Components renamed to InternalFormat +23-09-2005 +- Some AllocMem replaced with GetMem (little speed change) +- better exception handling. Better protection from memory leaks. +22-09-2005 +- Added support for Direct Draw Surfaces (.DDS) (uncompressed images only) +- Added new internal formats (RGB8, RGBA8, RGBA4, RGB5A1, RGB10A2, R5G6B5) +07-09-2005 +- Added support for Grayscale textures +- Added internal formats (Alpha, Luminance, LuminanceAlpha, BGR8, BGRA8) +10-07-2005 +- Added support for GL_VERSION_2_0 +- Added support for GL_EXT_texture_filter_anisotropic +04-07-2005 +- Function FillWithColor fills the Image with one Color +- Function LoadNormalMap added +30-06-2005 +- ToNormalMap allows to Create an NormalMap from the Alphachannel +- ToNormalMap now supports Sobel (nmSobel) function. +29-06-2005 +- support for RLE Compressed RGB TGAs added +28-06-2005 +- Class TglBitmapNormalMap added to support Normalmap generation +- Added function ToNormalMap in class TglBitmap2D to genereate normal maps from textures. + 3 Filters are supported. (4 Samples, 3x3 and 5x5) +16-06-2005 +- Method LoadCubeMapClass removed +- LoadCubeMap returnvalue is now the Texture paramter. Such as LoadTextures +- virtual abstract method GenTexture in class TglBitmap now is protected +12-06-2005 +- now support DescriptionFlag in LoadTga. Allows vertical flipped images to be loaded as normal +10-06-2005 +- little enhancement for IsPowerOfTwo +- TglBitmap1D.GenTexture now tests NPOT Textures +06-06-2005 +- some little name changes. All properties or function with Texture in name are + now without texture in name. We have allways texture so we dosn't name it. +03-06-2005 +- GenTexture now tests if texture is NPOT and NPOT-Texture are supported or + TextureTarget is GL_TEXTURE_RECTANGLE. Else it raised an exception. +02-06-2005 +- added support for GL_ARB_texture_rectangle, GL_EXT_texture_rectangle and GL_NV_texture_rectangle +25-04-2005 +- Function Unbind added +- call of SetFilter or SetTextureWrap if TextureID exists results in setting properties to opengl texture. +21-04-2005 +- class TglBitmapCubeMap added (allows to Create Cubemaps) +29-03-2005 +- Added Support for PNG Images. (http://pngdelphi.sourceforge.net/) + To Enable png's use the define pngimage +22-03-2005 +- New Functioninterface added +- Function GetPixel added +27-11-2004 +- Property BuildMipMaps renamed to MipMap +21-11-2004 +- property Name removed. +- BuildMipMaps is now a set of 3 values. None, GluBuildMipmaps and SGIS_generate_mipmap +22-05-2004 +- property name added. Only used in glForms! +26-11-2003 +- property FreeDataAfterGenTexture is now available as default (default = true) +- BuildMipmaps now implemented in TglBitmap1D (i've forgotten it) +- function MoveMemory replaced with function Move (little speed change) +- several calculations stored in variables (little speed change) +29-09-2003 +- property BuildMipsMaps added (default = True) + if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps +- property FreeDataAfterGenTexture added (default = True) + if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated. +- parameter DisableOtherTextureUnits of Bind removed +- parameter FreeDataAfterGeneration of GenTextures removed +12-09-2003 +- TglBitmap dosn't delete data if class was destroyed (fixed) +09-09-2003 +- Bind now enables TextureUnits (by params) +- GenTextures can leave data (by param) +- LoadTextures now optimal +03-09-2003 +- Performance optimization in AddFunc +- procedure Bind moved to subclasses +- Added new Class TglBitmap1D to support real OpenGL 1D Textures +19-08-2003 +- Texturefilter and texturewrap now also as defaults + Minfilter = GL_LINEAR_MIPMAP_LINEAR + Magfilter = GL_LINEAR + Wrap(str) = GL_CLAMP_TO_EDGE +- Added new format tfCompressed to create a compressed texture. +- propertys IsCompressed, TextureSize and IsResident added + IsCompressed and TextureSize only contains data from level 0 +18-08-2003 +- Added function AddFunc to add PerPixelEffects to Image +- LoadFromFunc now based on AddFunc +- Invert now based on AddFunc +- SwapColors now based on AddFunc +16-08-2003 +- Added function FlipHorz +15-08-2003 +- Added function LaodFromFunc to create images with function +- Added function FlipVert +- Added internal format RGB(A) if GL_EXT_bgra or OpenGL 1.2 isn't supported +29-07-2003 +- Added Alphafunctions to calculate alpha per function +- Added Alpha from ColorKey using alphafunctions +28-07-2003 +- First full functionally Version of glBitmap +- Support for 24Bit and 32Bit TGA Pictures added +25-07-2003 +- begin of programming +***********************************************************} +unit glBitmap; + +{$message warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} +// Please uncomment the defines below to configure the glBitmap to your preferences. +// If you have configured the unit you can uncomment the warning above. + + +// ###### Start of preferences ################################################ + +{.$define GLB_NO_NATIVE_GL} +// To enable the dglOpenGL.pas Header +// With native GL then bindings are staticlly declared to support other headers +// or use the glBitmap inside of DLLs (minimize codesize). + + +{.$define GLB_SDL} +// To enable the support for SDL_surfaces + +{.$define GLB_DELPHI} +// To enable the support for TBitmap from Delphi (not lazarus) + + +// *** image libs *** + +{.$define GLB_SDL_IMAGE} +// To enable the support of SDL_image to load files. (READ ONLY) +// If you enable SDL_image all other libraries will be ignored! + + +{.$define GLB_PNGIMAGE} +// to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ +// if you enable pngimage the libPNG will be ignored + +{.$define GLB_LIB_PNG} +// to use the libPNG http://www.libpng.org/ +// You will need an aditional header. +// http://www.opengl24.de/index.php?cat=header&file=libpng + +{.$define GLB_DELPHI_JPEG} +// if you enable delphi jpegs the libJPEG will be ignored + +{.$define GLB_LIB_JPEG} +// to use the libJPEG http://www.ijg.org/ +// You will need an aditional header. +// http://www.opengl24.de/index.php?cat=header&file=libjpeg + +// ###### End of preferences ################################################## + + +// ###### PRIVATE. Do not change anything. #################################### +// *** old defines for compatibility *** +{$ifdef NO_NATIVE_GL} + {$define GLB_NO_NATIVE_GL} +{$endif} +{$ifdef pngimage} + {$definde GLB_PNGIMAGE} +{$endif} + + +// *** Delphi Versions *** +{$ifdef fpc} + {$MODE Delphi} + + {$ifdef CPUI386} + {$define CPU386} + {$asmmode INTEL} + {$endif} + + {$ifndef WIN32} + {$linklib c} + {$endif} +{$endif} + +// *** checking define combinations *** +{$ifdef GLB_SDL_IMAGE} + {$ifndef GLB_SDL} + {$message warn 'SDL_image won''t work without SDL. SDL will be activated.'} + {$define GLB_SDL} + {$endif} + {$ifdef GLB_PNGIMAGE} + {$message warn 'The unit pngimage will be ignored because you are using SDL_image.'} + {$undef GLB_PNGIMAGE} + {$endif} + {$ifdef GLB_DELPHI_JPEG} + {$message warn 'The unit JPEG will be ignored because you are using SDL_image.'} + {$undef GLB_DELPHI_JPEG} + {$endif} + {$ifdef GLB_LIB_PNG} + {$message warn 'The library libPNG will be ignored because you are using SDL_image.'} + {$undef GLB_LIB_PNG} + {$endif} + {$ifdef GLB_LIB_JPEG} + {$message warn 'The library libJPEG will be ignored because you are using SDL_image.'} + {$undef GLB_LIB_JPEG} + {$endif} + + {$define GLB_SUPPORT_PNG_READ} + {$define GLB_SUPPORT_JPEG_READ} +{$endif} + +{$ifdef GLB_PNGIMAGE} + {$ifdef GLB_LIB_PNG} + {$message warn 'The library libPNG will be ignored if you are using pngimage.'} + {$undef GLB_LIB_PNG} + {$endif} + + {$define GLB_SUPPORT_PNG_READ} + {$define GLB_SUPPORT_PNG_WRITE} +{$endif} + +{$ifdef GLB_LIB_PNG} + {$define GLB_SUPPORT_PNG_READ} + {$define GLB_SUPPORT_PNG_WRITE} +{$endif} + + +{$ifdef GLB_DELPHI_JPEG} + {$ifdef GLB_LIB_JPEG} + {$message warn 'The library libJPEG will be ignored if you are using the unit JPEG.'} + {$undef GLB_LIB_JPEG} + {$endif} + + {$define GLB_SUPPORT_JPEG_READ} + {$define GLB_SUPPORT_JPEG_WRITE} +{$endif} + +{$ifdef GLB_LIB_JPEG} + {$define GLB_SUPPORT_JPEG_READ} + {$define GLB_SUPPORT_JPEG_WRITE} +{$endif} + +// *** general options *** +{$EXTENDEDSYNTAX ON} +{$LONGSTRINGS ON} +{$ALIGN ON} +{$ifndef fpc} + {$OPTIMIZATION ON} +{$endif} + + +interface + + +uses + {$ifdef GLB_NO_NATIVE_GL} dglOpenGL, {$endif} + + {$ifdef GLB_SDL} SDL, {$endif} + {$ifdef GLB_DELPHI} Dialogs, Windows, Graphics, {$endif} + + {$ifdef GLB_SDL_IMAGE} SDL_image, {$endif} + + {$ifdef GLB_PNGIMAGE} pngimage, {$endif} + {$ifdef GLB_LIB_PNG} libPNG, {$endif} + + {$ifdef GLB_DELPHI_JPEG} JPEG, {$endif} + {$ifdef GLB_LIB_JPEG} libJPEG, {$endif} + Classes, SysUtils; + + + +{$ifndef GLB_DELPHI} +type + HGLRC = Cardinal; + DWORD = Cardinal; + PDWORD = ^DWORD; + + TRGBQuad = packed record + rgbBlue: Byte; + rgbGreen: Byte; + rgbRed: Byte; + rgbReserved: Byte; + end; +{$endif} + + +{$ifndef GLB_NO_NATIVE_GL} +// Native OpenGL Implementation +type + PByteBool = ^ByteBool; + +{$ifdef GLB_DELPHI} +var + gLastContext: HGLRC; +{$endif} + +const + // Generell + GL_VERSION = $1F02; + GL_EXTENSIONS = $1F03; + + GL_TRUE = 1; + GL_FALSE = 0; + + GL_TEXTURE_1D = $0DE0; + GL_TEXTURE_2D = $0DE1; + + GL_MAX_TEXTURE_SIZE = $0D33; + GL_PACK_ALIGNMENT = $0D05; + GL_UNPACK_ALIGNMENT = $0CF5; + + // Textureformats + GL_RGB = $1907; + GL_RGB4 = $804F; + GL_RGB8 = $8051; + GL_RGBA = $1908; + GL_RGBA4 = $8056; + GL_RGBA8 = $8058; + GL_BGR = $80E0; + GL_BGRA = $80E1; + GL_ALPHA4 = $803B; + GL_ALPHA8 = $803C; + GL_LUMINANCE4 = $803F; + GL_LUMINANCE8 = $8040; + GL_LUMINANCE4_ALPHA4 = $8043; + GL_LUMINANCE8_ALPHA8 = $8045; + GL_DEPTH_COMPONENT = $1902; + + GL_UNSIGNED_BYTE = $1401; + GL_ALPHA = $1906; + GL_LUMINANCE = $1909; + GL_LUMINANCE_ALPHA = $190A; + + GL_TEXTURE_WIDTH = $1000; + GL_TEXTURE_HEIGHT = $1001; + GL_TEXTURE_INTERNAL_FORMAT = $1003; + GL_TEXTURE_RED_SIZE = $805C; + GL_TEXTURE_GREEN_SIZE = $805D; + GL_TEXTURE_BLUE_SIZE = $805E; + GL_TEXTURE_ALPHA_SIZE = $805F; + GL_TEXTURE_LUMINANCE_SIZE = $8060; + + // Dataformats + GL_UNSIGNED_SHORT_5_6_5 = $8363; + GL_UNSIGNED_SHORT_5_6_5_REV = $8364; + GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365; + GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366; + GL_UNSIGNED_INT_2_10_10_10_REV = $8368; + + // Filter + GL_NEAREST = $2600; + GL_LINEAR = $2601; + GL_NEAREST_MIPMAP_NEAREST = $2700; + GL_LINEAR_MIPMAP_NEAREST = $2701; + GL_NEAREST_MIPMAP_LINEAR = $2702; + GL_LINEAR_MIPMAP_LINEAR = $2703; + GL_TEXTURE_MAG_FILTER = $2800; + GL_TEXTURE_MIN_FILTER = $2801; + + // Wrapmodes + GL_TEXTURE_WRAP_S = $2802; + GL_TEXTURE_WRAP_T = $2803; + GL_CLAMP = $2900; + GL_REPEAT = $2901; + GL_CLAMP_TO_EDGE = $812F; + GL_CLAMP_TO_BORDER = $812D; + GL_TEXTURE_WRAP_R = $8072; + + GL_MIRRORED_REPEAT = $8370; + + // Border Color + GL_TEXTURE_BORDER_COLOR = $1004; + + // Texgen + GL_NORMAL_MAP = $8511; + GL_REFLECTION_MAP = $8512; + GL_S = $2000; + GL_T = $2001; + GL_R = $2002; + GL_TEXTURE_GEN_MODE = $2500; + GL_TEXTURE_GEN_S = $0C60; + GL_TEXTURE_GEN_T = $0C61; + GL_TEXTURE_GEN_R = $0C62; + + // Cubemaps + GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C; + GL_TEXTURE_CUBE_MAP = $8513; + GL_TEXTURE_BINDING_CUBE_MAP = $8514; + GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515; + GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516; + GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517; + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518; + GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519; + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A; + + GL_TEXTURE_RECTANGLE_ARB = $84F5; + + // GL_SGIS_generate_mipmap + GL_GENERATE_MIPMAP = $8191; + + // GL_EXT_texture_compression_s3tc + GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0; + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1; + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2; + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3; + + // GL_EXT_texture_filter_anisotropic + GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; + + // GL_ARB_texture_compression + GL_COMPRESSED_RGB = $84ED; + GL_COMPRESSED_RGBA = $84EE; + GL_COMPRESSED_ALPHA = $84E9; + GL_COMPRESSED_LUMINANCE = $84EA; + GL_COMPRESSED_LUMINANCE_ALPHA = $84EB; + + // Extensions +var + GL_VERSION_1_2, + GL_VERSION_1_3, + GL_VERSION_1_4, + GL_VERSION_2_0, + + GL_ARB_texture_border_clamp, + GL_ARB_texture_cube_map, + GL_ARB_texture_compression, + GL_ARB_texture_non_power_of_two, + GL_ARB_texture_rectangle, + GL_ARB_texture_mirrored_repeat, + GL_EXT_bgra, + GL_EXT_texture_edge_clamp, + GL_EXT_texture_cube_map, + GL_EXT_texture_compression_s3tc, + GL_EXT_texture_filter_anisotropic, + GL_EXT_texture_rectangle, + GL_NV_texture_rectangle, + GL_IBM_texture_mirrored_repeat, + GL_SGIS_generate_mipmap: Boolean; + + // Funtions +const + +{$ifdef LINUX} + libglu = 'libGLU.so.1'; + libopengl = 'libGL.so.1'; +{$else} + libglu = 'glu32.dll'; + libopengl = 'opengl32.dll'; +{$endif} + + +{$ifdef LINUX} + function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl; +{$else} + function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl; +{$endif} + + function glGetString(name: Cardinal): PAnsiChar; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + procedure glEnable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glDisable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + procedure glGenTextures(n: Integer; Textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glPixelStorei(pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + + function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu; + function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu; + +var + glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} + glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} + glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} +{$endif} + + +type + // Exception + EglBitmapException = Exception; + EglBitmapSizeToLargeException = EglBitmapException; + EglBitmapNonPowerOfTwoException = EglBitmapException; + EglBitmapUnsupportedInternalFormat = EglBitmapException; + + // Functions + TglBitmapPixelDesc = packed record + RedRange: Cardinal; + RedShift: Shortint; + GreenRange: Cardinal; + GreenShift: Shortint; + BlueRange: Cardinal; + BlueShift: Shortint; + AlphaRange: Cardinal; + AlphaShift: Shortint; + end; + + TglBitmapPixelData = packed record + Red: Cardinal; + Green: Cardinal; + Blue: Cardinal; + Alpha: Cardinal; + + PixelDesc: TglBitmapPixelDesc; + end; + + TglBitmapPixelPositionFields = set of (ffX, ffY); + TglBitmapPixelPosition = record + Fields : TglBitmapPixelPositionFields; + X : Word; + Y : Word; + end; + +const + cNullSize : TglBitmapPixelPosition = (Fields : []; X: 0; Y: 0); + +type + TglBitmap = class; + + TglBitmapFunctionRec = record + Sender : TglBitmap; + Size: TglBitmapPixelPosition; + Position: TglBitmapPixelPosition; + Source: TglBitmapPixelData; + Dest: TglBitmapPixelData; + CustomData: Pointer; + end; + + TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); + + TglBitmapGetPixel = procedure ( + const Pos: TglBitmapPixelPosition; + var Pixel: TglBitmapPixelData) of object; + + TglBitmapSetPixel = procedure ( + const Pos: TglBitmapPixelPosition; + const Pixel: TglBitmapPixelData) of object; + + // Settings + TglBitmapFileType = ( + {$ifdef GLB_SUPPORT_PNG_WRITE} ftPNG, {$endif} + {$ifdef GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$endif} + ftDDS, + ftTGA, + ftBMP); + TglBitmapFileTypes = set of TglBitmapFileType; + + TglBitmapFormat = (tfDefault, tf4BitsPerChanel, tf8BitsPerChanel, tfCompressed); + TglBitmapMipMap = (mmNone, mmMipmap, mmMipmapGlu); + TglBitmapNormalMapFunc = (nm4Samples, nmSobel, nm3x3, nm5x5); + TglBitmapInternalFormat = ( + ifEmpty, + // 4 Bit + ifDXT1, + // 8 Bit + ifDXT3, + ifDXT5, + ifAlpha, + ifLuminance, + ifDepth8, + // 16 Bit + ifLuminanceAlpha, + ifRGBA4, + ifR5G6B5, + ifRGB5A1, + // 24 Bit + ifBGR8, + ifRGB8, + // 32 Bit + ifBGRA8, + ifRGBA8, + ifRGB10A2 + ); + + // Pixelmapping + TglBitmapMapFunc = procedure (const Pixel: TglBitmapPixelData; var pDest: pByte); + TglBitmapUnMapFunc = procedure (var pData: pByte; var Pixel: TglBitmapPixelData); + + // Base Class + TglBitmap = class + protected + fID: Cardinal; + fTarget: Cardinal; + fFormat: TglBitmapFormat; + fMipMap: TglBitmapMipMap; + fAnisotropic: Integer; + fBorderColor: array [0..3] of single; + + fDeleteTextureOnFree: Boolean; + fFreeDataAfterGenTexture: Boolean; + + // Propertys + fData: pByte; + fInternalFormat: TglBitmapInternalFormat; + fDimension: TglBitmapPixelPosition; + + fIsResident: Boolean; + + // Mapping + fPixelSize: Integer; + fRowSize: Integer; + fUnmapFunc: TglBitmapUnMapFunc; + fMapFunc: TglBitmapMapFunc; + + // Filtering + fFilterMin: Integer; + fFilterMag: Integer; + + // Texturwarp + fWrapS: Integer; + fWrapT: Integer; + fWrapR: Integer; + + fGetPixelFunc: TglBitmapGetPixel; + fSetPixelFunc: TglBitmapSetPixel; + + // custom data + fFilename: String; + fCustomName: String; + fCustomNameW: WideString; + fCustomDataPointer: Pointer; + + + procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual; + + {$ifdef GLB_SUPPORT_PNG_READ} + function LoadPNG(Stream: TStream): Boolean; virtual; + {$endif} + {$ifdef GLB_SUPPORT_JPEG_READ} + function LoadJPEG(Stream: TStream): Boolean; virtual; + {$endif} + function LoadDDS(Stream: TStream): Boolean; virtual; + function LoadTGA(Stream: TStream): Boolean; virtual; + function LoadBMP(Stream: TStream): Boolean; virtual; + + + {$ifdef GLB_SUPPORT_PNG_WRITE} + procedure SavePNG(Stream: TStream); virtual; + {$endif} + {$ifdef GLB_SUPPORT_JPEG_WRITE} + procedure SaveJPEG(Stream: TStream); virtual; + {$endif} + procedure SaveDDS(Stream: TStream); virtual; + procedure SaveTGA(Stream: TStream); virtual; + procedure SaveBMP(Stream: TStream); virtual; + + + procedure CreateID; + procedure SetupParameters(var BuildWithGlu: Boolean); + procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True); + + procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract; + + procedure SetAnisotropic(const Value: Integer); + procedure SetInternalFormat(const Value: TglBitmapInternalFormat); + + function FlipHorz: Boolean; virtual; + function FlipVert: Boolean; virtual; + + function GetHeight: Integer; + function GetWidth: Integer; + + function GetFileHeight: Integer; + function GetFileWidth: Integer; + + property Width: Integer read GetWidth; + property Height: Integer read GetHeight; + + property FileWidth: Integer read GetFileWidth; + property FileHeight: Integer read GetFileHeight; + public + // propertys + property ID: Cardinal read fID write fID; + property Target: Cardinal read fTarget write fTarget; + property Format: TglBitmapFormat read fFormat write fFormat; + property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat; + property Dimension: TglBitmapPixelPosition read fDimension; + + property Data: pByte read fData; + + property MipMap: TglBitmapMipMap read fMipMap write fMipMap; + property Anisotropic: Integer read fAnisotropic write SetAnisotropic; + + property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write fDeleteTextureOnFree; + property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write fFreeDataAfterGenTexture; + + property IsResident: boolean read fIsResident; + + // propertys for custom data + property Filename: String read fFilename; + property CustomName: String read fCustomName write fCustomName; + property CustomNameW: WideString read fCustomNameW write fCustomNameW; + property CustomDataPointer: Pointer read fCustomDataPointer write fCustomDataPointer; + + // Construction and Destructions Methods + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + constructor Create(); overload; + constructor Create(FileName: String); overload; + constructor Create(Stream: TStream); overload; + {$ifdef GLB_DELPHI} + constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil); + constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload; + constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload; + {$endif} + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload; + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; + + function Clone: TglBitmap; + + procedure FreeData; + + // Loading Methods + procedure LoadFromFile(FileName: String); + procedure LoadFromStream(Stream: TStream); virtual; + {$ifdef GLB_DELPHI} + procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil); + procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); + {$endif} + procedure LoadFromFunc(Size: TglBitmapPixelPosition; Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer = nil); + + procedure SaveToFile(FileName: String; FileType: TglBitmapFileType); + procedure SaveToStream(Stream: TStream; FileType: TglBitmapFileType); virtual; + + function AddFunc(Source: TglBitmap; Func: TglBitmapFunction; CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload; + function AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload; + + {$ifdef GLB_SDL} + function AssignToSurface(out Surface: PSDL_Surface): boolean; + function AssignFromSurface(const Surface: PSDL_Surface): boolean; + function AssignAlphaToSurface(out Surface: PSDL_Surface): boolean; + + function AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + {$endif} + {$ifdef GLB_DELPHI} + function AssignToBitmap(const Bitmap: TBitmap): boolean; + function AssignFromBitmap(const Bitmap: TBitmap): boolean; + function AssignAlphaToBitmap(const Bitmap: TBitmap): boolean; + + function AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + {$endif} + + function AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer = nil): boolean; virtual; + function AddAlphaFromFile(FileName: String; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + function AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + {$ifdef GLB_DELPHI} + function AddAlphaFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + function AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + {$endif} + function AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; + + function AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte = 0): Boolean; + function AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean; + function AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean; + + function AddAlphaFromValue(Alpha: Byte): Boolean; + function AddAlphaFromValueRange(Alpha: Cardinal): Boolean; + function AddAlphaFromValueFloat(Alpha: Single): Boolean; + + function RemoveAlpha: Boolean; virtual; + + function ConvertTo(NewFormat: TglBitmapInternalFormat): boolean; virtual; + + // Other + procedure FillWithColor(Red, Green, Blue: Byte; Alpha : Byte = 255); + procedure FillWithColorRange(Red, Green, Blue: Cardinal; Alpha : Cardinal = $FFFFFFFF); + procedure FillWithColorFloat(Red, Green, Blue: Single; Alpha : Single = 1); + + procedure Invert(UseRGB: Boolean = true; UseAlpha: Boolean = false); + + procedure SetFilter(Min, Mag : Integer); + procedure SetWrap(S: Integer = GL_CLAMP_TO_EDGE; + T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE); + + procedure SetBorderColor(Red, Green, Blue, Alpha: Single); + + procedure GetPixel (const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual; + procedure SetPixel (const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual; + + // Generation + procedure Unbind(DisableTextureUnit: Boolean = True); virtual; + procedure Bind(EnableTextureUnit: Boolean = True); virtual; + end; + + + TglBitmap2D = class(TglBitmap) + protected + // Bildeinstellungen + fLines: array of PByte; + + procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData); + procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + + procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); + + function GetScanline(Index: Integer): Pointer; + + procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override; + procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); + public + // propertys + property Width; + property Height; + + property Scanline[Index: Integer]: Pointer read GetScanline; + + procedure AfterConstruction; override; + + procedure GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat); + procedure GetDataFromTexture; + + // Other + function FlipHorz: Boolean; override; + function FlipVert: Boolean; override; + + procedure ToNormalMap(Func: TglBitmapNormalMapFunc = nm3x3; Scale: Single = 2; UseAlpha: Boolean = False); + + // Generation + procedure GenTexture(TestTextureSize: Boolean = True); override; + end; + + + TglBitmapCubeMap = class(TglBitmap2D) + protected + fGenMode: Integer; + + // Hide GenTexture + procedure GenTexture(TestTextureSize: Boolean = True); reintroduce; + public + procedure AfterConstruction; override; + + procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true); + + procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual; + procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual; + end; + + + TglBitmapNormalMap = class(TglBitmapCubeMap) + public + procedure AfterConstruction; override; + + procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true); + end; + + + TglBitmap1D = class(TglBitmap) + protected + procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + + procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override; + procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); + public + // propertys + property Width; + + procedure AfterConstruction; override; + + // Other + function FlipHorz: Boolean; override; + + // Generation + procedure GenTexture(TestTextureSize: Boolean = True); override; + end; + + +// methods and vars for Defaults +procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat); +procedure glBitmapSetDefaultFilter(Min, Mag: Integer); +procedure glBitmapSetDefaultWrap(S: Integer = GL_CLAMP_TO_EDGE; T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE); + +procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean); +procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean); + +function glBitmapGetDefaultFormat: TglBitmapFormat; +procedure glBitmapGetDefaultFilter(var Min, Mag: Integer); +procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer); + +function glBitmapGetDefaultDeleteTextureOnFree: Boolean; +function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; + +// position / size +function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; + +// Formatfunctions +function FormatGetSize (Format: TglBitmapInternalFormat): Single; + +function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; +function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; +function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean; +function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean; + +procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat); + +function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; +function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; + +function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean; + + +// Call LoadingMethods +function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean; + +function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean; + +function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; + + +var + glBitmapDefaultFormat: TglBitmapFormat; + glBitmapDefaultFilterMin: Integer; + glBitmapDefaultFilterMag: Integer; + glBitmapDefaultWrapS: Integer; + glBitmapDefaultWrapT: Integer; + glBitmapDefaultWrapR: Integer; + + glBitmapDefaultDeleteTextureOnFree: Boolean; + glBitmapDefaultFreeDataAfterGenTextures: Boolean; + +{$ifdef GLB_DELPHI} +function CreateGrayPalette: HPALETTE; +{$endif} + + +implementation + +uses + Math; + + +{$ifndef GLB_NO_NATIVE_GL} +procedure ReadOpenGLExtensions; +var + {$ifdef GLB_DELPHI} + Context: HGLRC; + {$endif} + Buffer: AnsiString; + MajorVersion, MinorVersion: Integer; + + + procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer); + var + Separator: Integer; + begin + Minor := 0; + Major := 0; + + Separator := Pos(AnsiString('.'), Buffer); + + if (Separator > 1) and (Separator < Length(Buffer)) and + (Buffer[Separator - 1] in ['0'..'9']) and + (Buffer[Separator + 1] in ['0'..'9']) then begin + + Dec(Separator); + while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do + Dec(Separator); + + Delete(Buffer, 1, Separator); + Separator := Pos(AnsiString('.'), Buffer) + 1; + + while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do + Inc(Separator); + + Delete(Buffer, Separator, 255); + Separator := Pos(AnsiString('.'), Buffer); + + Major := StrToInt(Copy(String(Buffer), 1, Separator - 1)); + Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1)); + end; + end; + + + function CheckExtension(const Extension: AnsiString): Boolean; + var + ExtPos: Integer; + begin + ExtPos := Pos(Extension, Buffer); + Result := ExtPos > 0; + + if Result then + Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']); + end; + + + function glLoad (aFunc: pAnsiChar): pointer; + begin + {$ifdef LINUX} + Result := glXGetProcAddress(aFunc); + {$else} + Result := wglGetProcAddress(aFunc); + {$endif} + end; + + +begin + {$ifdef GLB_DELPHI} + Context := wglGetCurrentContext; + + if Context <> gLastContext then begin + gLastContext := Context; + {$endif} + + // Version + Buffer := glGetString(GL_VERSION); + TrimVersionString(Buffer, MajorVersion, MinorVersion); + + GL_VERSION_1_2 := False; + GL_VERSION_1_3 := False; + GL_VERSION_1_4 := False; + GL_VERSION_2_0 := False; + + if MajorVersion = 1 then begin + if MinorVersion >= 1 then begin + if MinorVersion >= 2 then + GL_VERSION_1_2 := True; + + if MinorVersion >= 3 then + GL_VERSION_1_3 := True; + + if MinorVersion >= 4 then + GL_VERSION_1_4 := True; + end; + end; + + if MajorVersion >= 2 then begin + GL_VERSION_1_2 := True; + GL_VERSION_1_3 := True; + GL_VERSION_1_4 := True; + GL_VERSION_2_0 := True; + end; + + // Extensions + Buffer := glGetString(GL_EXTENSIONS); + GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp'); + GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map'); + GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression'); + GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two'); + GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle'); + GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat'); + GL_EXT_bgra := CheckExtension('GL_EXT_bgra'); + GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp'); + GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map'); + GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc'); + GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic'); + GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle'); + GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle'); + GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat'); + GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap'); + + // Funtions + if GL_VERSION_1_3 then begin + // Loading Core + glCompressedTexImage1D := glLoad('glCompressedTexImage1D'); + glCompressedTexImage2D := glLoad('glCompressedTexImage2D'); + glGetCompressedTexImage := glLoad('glGetCompressedTexImage'); + end else + + begin + // Try loading Extension + glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB'); + glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB'); + glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB'); + end; + {$ifdef GLB_DELPHI} + end; + {$endif} +end; +{$endif} + + +function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; +begin + Result.Fields := []; + + if X >= 0 then + Result.Fields := Result.Fields + [ffX]; + if Y >= 0 then + Result.Fields := Result.Fields + [ffY]; + + Result.X := Max(0, X); + Result.Y := Max(0, Y); +end; + + +const + UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.'; + + PIXEL_DESC_ALPHA : TglBitmapPixelDesc = ( + RedRange : $00; RedShift : 0; + GreenRange : $00; GreenShift : 0; + BlueRange : $00; BlueShift : 0; + AlphaRange : $FF; AlphaShift : 0 ); + + PIXEL_DESC_LUMINANCE : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 0; + GreenRange : $FF; GreenShift : 0; + BlueRange : $FF; BlueShift : 0; + AlphaRange : $00; AlphaShift : 0 ); + + PIXEL_DESC_DEPTH8 : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 0; + GreenRange : $FF; GreenShift : 0; + BlueRange : $FF; BlueShift : 0; + AlphaRange : $00; AlphaShift : 0 ); + + PIXEL_DESC_LUMINANCEALPHA : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 0; + GreenRange : $FF; GreenShift : 0; + BlueRange : $FF; BlueShift : 0; + AlphaRange : $FF; AlphaShift : 8 ); + + PIXEL_DESC_RGBA4 : TglBitmapPixelDesc = ( + RedRange : $0F; RedShift : 8; + GreenRange : $0F; GreenShift : 4; + BlueRange : $0F; BlueShift : 0; + AlphaRange : $0F; AlphaShift : 12 ); + + PIXEL_DESC_R5G6B5 : TglBitmapPixelDesc = ( + RedRange : $1F; RedShift : 11; + GreenRange : $3F; GreenShift : 5; + BlueRange : $1F; BlueShift : 0; + AlphaRange : $00; AlphaShift : 0 ); + + PIXEL_DESC_RGB5A1 : TglBitmapPixelDesc = ( + RedRange : $1F; RedShift : 10; + GreenRange : $1F; GreenShift : 5; + BlueRange : $1F; BlueShift : 0; + AlphaRange : $01; AlphaShift : 15 ); + + PIXEL_DESC_RGB8 : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 0; + GreenRange : $FF; GreenShift : 8; + BlueRange : $FF; BlueShift : 16; + AlphaRange : $00; AlphaShift : 0 ); + + PIXEL_DESC_RGBA8 : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 0; + GreenRange : $FF; GreenShift : 8; + BlueRange : $FF; BlueShift : 16; + AlphaRange : $FF; AlphaShift : 24 ); + + PIXEL_DESC_BGR8 : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 16; + GreenRange : $FF; GreenShift : 8; + BlueRange : $FF; BlueShift : 0; + AlphaRange : $00; AlphaShift : 0 ); + + PIXEL_DESC_BGRA8 : TglBitmapPixelDesc = ( + RedRange : $FF; RedShift : 16; + GreenRange : $FF; GreenShift : 8; + BlueRange : $FF; BlueShift : 0; + AlphaRange : $FF; AlphaShift : 24 ); + + PIXEL_DESC_RGB10A2 : TglBitmapPixelDesc = ( + RedRange : $3FF; RedShift : 20; + GreenRange : $3FF; GreenShift : 10; + BlueRange : $3FF; BlueShift : 0; + AlphaRange : $003; AlphaShift : 30 ); + +{* +** Mapping +*} + +procedure MapAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := Pixel.Alpha; + Inc(pDest); +end; + + +procedure MapLuminance(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11); + Inc(pDest); +end; + + +procedure MapDepth8(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := (Pixel.Red + Pixel.Green + Pixel.Blue) div 3; + Inc(pDest); +end; + + +procedure MapLuminanceAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11); + Inc(pDest); + + pDest^ := Pixel.Alpha; + Inc(pDest); +end; + + +procedure MapRGBA4(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pWord(pDest)^ := + Pixel.Alpha shl PIXEL_DESC_RGBA4.AlphaShift or + Pixel.Red shl PIXEL_DESC_RGBA4.RedShift or + Pixel.Green shl PIXEL_DESC_RGBA4.GreenShift or + Pixel.Blue; + + Inc(pDest, 2); +end; + + +procedure MapR5G6B5(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pWord(pDest)^ := + Pixel.Red shl PIXEL_DESC_R5G6B5.RedShift or + Pixel.Green shl PIXEL_DESC_R5G6B5.GreenShift or + Pixel.Blue; + + Inc(pDest, 2); +end; + + +procedure MapRGB5A1(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pWord(pDest)^ := + Pixel.Alpha shl PIXEL_DESC_RGB5A1.AlphaShift or + Pixel.Red shl PIXEL_DESC_RGB5A1.RedShift or + Pixel.Green shl PIXEL_DESC_RGB5A1.GreenShift or + Pixel.Blue; + + Inc(pDest, 2); +end; + + +procedure MapRGB8(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := Pixel.Red; + Inc(pDest); + + pDest^ := Pixel.Green; + Inc(pDest); + + pDest^ := Pixel.Blue; + Inc(pDest); +end; + + +procedure MapBGR8(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDest^ := Pixel.Blue; + Inc(pDest); + + pDest^ := Pixel.Green; + Inc(pDest); + + pDest^ := Pixel.Red; + Inc(pDest); +end; + + +procedure MapRGBA8(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDWord(pDest)^ := + Pixel.Alpha shl PIXEL_DESC_RGBA8.AlphaShift or + Pixel.Blue shl PIXEL_DESC_RGBA8.BlueShift or + Pixel.Green shl PIXEL_DESC_RGBA8.GreenShift or + Pixel.Red; + + Inc(pDest, 4); +end; + + +procedure MapBGRA8(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDWord(pDest)^ := + Pixel.Alpha shl PIXEL_DESC_BGRA8.AlphaShift or + Pixel.Red shl PIXEL_DESC_BGRA8.RedShift or + Pixel.Green shl PIXEL_DESC_BGRA8.GreenShift or + Pixel.Blue; + + Inc(pDest, 4); +end; + + +procedure MapRGB10A2(const Pixel: TglBitmapPixelData; var pDest: pByte); +begin + pDWord(pDest)^ := + Pixel.Alpha shl PIXEL_DESC_RGB10A2.AlphaShift or + Pixel.Red shl PIXEL_DESC_RGB10A2.RedShift or + Pixel.Green shl PIXEL_DESC_RGB10A2.GreenShift or + Pixel.Blue; + + Inc(pDest, 4); +end; + + +function FormatGetMapFunc(Format: TglBitmapInternalFormat): TglBitmapMapFunc; +begin + case Format of + ifAlpha: Result := MapAlpha; + ifLuminance: Result := MapLuminance; + ifDepth8: Result := MapDepth8; + ifLuminanceAlpha: Result := MapLuminanceAlpha; + ifRGBA4: Result := MapRGBA4; + ifR5G6B5: Result := MapR5G6B5; + ifRGB5A1: Result := MapRGB5A1; + ifRGB8: Result := MapRGB8; + ifBGR8: Result := MapBGR8; + ifRGBA8: Result := MapRGBA8; + ifBGRA8: Result := MapBGRA8; + ifRGB10A2: Result := MapRGB10A2; + else + raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; +end; + + +{* +** Unmapping +*} +procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Alpha := pData^; + Pixel.Red := Pixel.PixelDesc.RedRange; + Pixel.Green := Pixel.PixelDesc.GreenRange; + Pixel.Blue := Pixel.PixelDesc.BlueRange; + + Inc(pData); +end; + + +procedure UnMapLuminance(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Alpha := 255; + Pixel.Red := pData^; + Pixel.Green := pData^; + Pixel.Blue := pData^; + + Inc(pData); +end; + + +procedure UnMapDepth8(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Alpha := 255; + Pixel.Red := pData^; + Pixel.Green := pData^; + Pixel.Blue := pData^; + + Inc(pData); +end; + + +procedure UnMapLuminanceAlpha(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Red := pData^; + Pixel.Green := pData^; + Pixel.Blue := pData^; + Inc(pData); + + Pixel.Alpha := pData^; + Inc(pData); +end; + + +procedure UnMapRGBA4(var pData: pByte; var Pixel: TglBitmapPixelData); +var + Temp: Word; +begin + Temp := pWord(pData)^; + + Pixel.Alpha := Temp shr PIXEL_DESC_RGBA4.AlphaShift and PIXEL_DESC_RGBA4.AlphaRange; + Pixel.Red := Temp shr PIXEL_DESC_RGBA4.RedShift and PIXEL_DESC_RGBA4.RedRange; + Pixel.Green := Temp shr PIXEL_DESC_RGBA4.GreenShift and PIXEL_DESC_RGBA4.GreenRange; + Pixel.Blue := Temp and PIXEL_DESC_RGBA4.BlueRange; + + Inc(pData, 2); +end; + + +procedure UnMapR5G6B5(var pData: pByte; var Pixel: TglBitmapPixelData); +var + Temp: Word; +begin + Temp := pWord(pData)^; + + Pixel.Alpha := Pixel.PixelDesc.AlphaRange; + Pixel.Red := Temp shr PIXEL_DESC_R5G6B5.RedShift and PIXEL_DESC_R5G6B5.RedRange; + Pixel.Green := Temp shr PIXEL_DESC_R5G6B5.GreenShift and PIXEL_DESC_R5G6B5.GreenRange; + Pixel.Blue := Temp and PIXEL_DESC_R5G6B5.BlueRange; + + Inc(pData, 2); +end; + + +procedure UnMapRGB5A1(var pData: pByte; var Pixel: TglBitmapPixelData); +var + Temp: Word; +begin + Temp := pWord(pData)^; + + Pixel.Alpha := Temp shr PIXEL_DESC_RGB5A1.AlphaShift and PIXEL_DESC_RGB5A1.AlphaRange; + Pixel.Red := Temp shr PIXEL_DESC_RGB5A1.RedShift and PIXEL_DESC_RGB5A1.RedRange; + Pixel.Green := Temp shr PIXEL_DESC_RGB5A1.GreenShift and PIXEL_DESC_RGB5A1.GreenRange; + Pixel.Blue := Temp and PIXEL_DESC_RGB5A1.BlueRange; + + Inc(pData, 2); +end; + + +procedure UnMapRGB8(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Alpha := Pixel.PixelDesc.AlphaRange; + + Pixel.Red := pData^; + Inc(pData); + + Pixel.Green := pData^; + Inc(pData); + + Pixel.Blue := pData^; + Inc(pData); +end; + + +procedure UnMapBGR8(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Alpha := Pixel.PixelDesc.AlphaRange; + + Pixel.Blue := pData^; + Inc(pData); + + Pixel.Green := pData^; + Inc(pData); + + Pixel.Red := pData^; + Inc(pData); +end; + + +procedure UnMapRGBA8(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Red := pData^; + Inc(pData); + + Pixel.Green := pData^; + Inc(pData); + + Pixel.Blue := pData^; + Inc(pData); + + Pixel.Alpha := pData^; + Inc(pData); +end; + + +procedure UnMapBGRA8(var pData: pByte; var Pixel: TglBitmapPixelData); +begin + Pixel.Blue := pData^; + Inc(pData); + + Pixel.Green := pData^; + Inc(pData); + + Pixel.Red := pData^; + Inc(pData); + + Pixel.Alpha := pData^; + Inc(pData); +end; + + +procedure UnMapRGB10A2(var pData: pByte; var Pixel: TglBitmapPixelData); +var + Temp: DWord; +begin + Temp := pDWord(pData)^; + + Pixel.Alpha := Temp shr PIXEL_DESC_RGB10A2.AlphaShift and PIXEL_DESC_RGB10A2.AlphaRange; + Pixel.Red := Temp shr PIXEL_DESC_RGB10A2.RedShift and PIXEL_DESC_RGB10A2.RedRange; + Pixel.Green := Temp shr PIXEL_DESC_RGB10A2.GreenShift and PIXEL_DESC_RGB10A2.GreenRange; + Pixel.Blue := Temp and PIXEL_DESC_RGB10A2.BlueRange; + + Inc(pData, 4); +end; + + +function FormatGetUnMapFunc(Format: TglBitmapInternalFormat): TglBitmapUnMapFunc; +begin + case Format of + ifAlpha: Result := UnmapAlpha; + ifLuminance: Result := UnMapLuminance; + ifDepth8: Result := UnMapDepth8; + ifLuminanceAlpha: Result := UnMapLuminanceAlpha; + ifRGBA4: Result := UnMapRGBA4; + ifR5G6B5: Result := UnMapR5G6B5; + ifRGB5A1: Result := UnMapRGB5A1; + ifRGB8: Result := UnMapRGB8; + ifBGR8: Result := UnMapBGR8; + ifRGBA8: Result := UnMapRGBA8; + ifBGRA8: Result := UnMapBGRA8; + ifRGB10A2: Result := UnMapRGB10A2; + else + raise EglBitmapUnsupportedInternalFormat.Create('FormatGetUnMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; +end; + +{* +** Tools +*} +function FormatGetSize (Format: TglBitmapInternalFormat): Single; +begin + case Format of + ifEmpty: + Result := 0; + ifDXT1: + Result := 0.5; + ifAlpha, ifLuminance, ifDepth8, ifDXT3, ifDXT5: + Result := 1; + ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5: + Result := 2; + ifBGR8, ifRGB8: + Result := 3; + ifBGRA8, ifRGBA8, ifRGB10A2: + Result := 4; + else + raise EglBitmapUnsupportedInternalFormat.Create('FormatGetSize - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; +end; + + +function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; +begin + Result := Format in [ifDXT1, ifDXT3, ifDXT5]; +end; + + +function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; +begin + Result := Format in [ifAlpha, ifLuminance, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8, ifRGB10A2]; +end; + + +function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean; +begin + Result := Format = ifEmpty; +end; + + +function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean; +begin + Result := Format in [ifDXT1, ifDXT3, ifDXT5 ,ifAlpha, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifBGRA8, ifRGBA8, ifRGB10A2]; +end; + + +procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat); +begin + FillChar(Pixel, SizeOf(Pixel), #0); + + case Format of + ifAlpha: + Pixel.PixelDesc := PIXEL_DESC_ALPHA; + ifLuminance: + Pixel.PixelDesc := PIXEL_DESC_LUMINANCE; + ifDepth8: + Pixel.PixelDesc := PIXEL_DESC_DEPTH8; + ifLuminanceAlpha: + Pixel.PixelDesc := PIXEL_DESC_LUMINANCEALPHA; + ifRGBA4: + Pixel.PixelDesc := PIXEL_DESC_RGBA4; + ifR5G6B5: + Pixel.PixelDesc := PIXEL_DESC_R5G6B5; + ifRGB5A1: + Pixel.PixelDesc := PIXEL_DESC_RGB5A1; + ifDXT1, ifDXT3, ifDXT5, ifBGRA8: + Pixel.PixelDesc := PIXEL_DESC_BGRA8; + ifBGR8: + Pixel.PixelDesc := PIXEL_DESC_BGR8; + ifRGB8: + Pixel.PixelDesc := PIXEL_DESC_RGB8; + ifRGBA8: + Pixel.PixelDesc := PIXEL_DESC_RGBA8; + ifRGB10A2: + Pixel.PixelDesc := PIXEL_DESC_RGB10A2; + end; + + Pixel.Red := Pixel.PixelDesc.RedRange; + Pixel.Green := Pixel.PixelDesc.GreenRange; + Pixel.Blue := Pixel.PixelDesc.BlueRange; + Pixel.Alpha := Pixel.PixelDesc.AlphaRange; +end; + + +function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; +begin + case Format of + ifAlpha: + Result := ifLuminance; + ifLuminanceAlpha: + Result := ifLuminance; + ifRGBA4: + Result := ifR5G6B5; + ifRGB5A1: + Result := ifR5G6B5; + ifBGRA8: + Result := ifBGR8; + ifRGBA8: + Result := ifRGB8; + ifRGB10A2: + Result := ifRGB8; + else + Result := Format; + end; +end; + + +function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; +begin + case Format of + ifLuminance: + Result := ifLuminanceAlpha; + ifR5G6B5: + Result := ifRGB5A1; + ifBGR8: + Result := ifBGRA8; + ifRGB8: + Result := ifRGBA8; + else + Result := Format; + end; +end; + + +function FormatGetUncompressed(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; +begin + case Format of + ifDXT1: + Result := ifRGB5A1; + ifDXT3: + Result := ifRGBA8; + ifDXT5: + Result := ifRGBA8; + else + Result := Format; + end; +end; + + +function FormatGetImageSize(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat): Integer; +begin + if (Size.X = 0) and (Size.Y = 0) then + Result := 0 + else + Result := Trunc(Max(Size.Y, 1) * Max(Size.X, 1) * FormatGetSize(Format)); +end; + + +function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFileTypes; +begin + Result := []; + + {$ifdef GLB_SUPPORT_PNG_WRITE} + if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then + Result := Result + [ftPNG]; + {$endif} + + {$ifdef GLB_SUPPORT_JPEG_WRITE} + if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then + Result := Result + [ftJPEG]; + {$endif} + + Result := Result + [ftDDS]; + + if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8] then + Result := Result + [ftTGA]; + + if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifRGB8, ifBGR8, ifRGBA8, ifBGRA8, ifRGB10A2] then + Result := Result + [ftBMP]; +end; + + +function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean; +var + Pix: TglBitmapPixelData; +begin + Result := False; + + if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) and (AlphaMask = 0) then + raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); + + FormatPreparePixel(Pix, Format); + + with Pix.PixelDesc do begin + if RedMask <> 0 then + if (RedMask <> (RedRange shl RedShift)) then + Exit; + + if GreenMask <> 0 then + if (GreenMask <> (GreenRange shl GreenShift)) then + Exit; + + if BlueMask <> 0 then + if (BlueMask <> (BlueRange shl BlueShift)) then + Exit; + + if AlphaMask <> 0 then + if (AlphaMask <> (AlphaRange shl AlphaShift)) then + Exit; + + Result := True; + end; +end; + + +function IsPowerOfTwo(Number: Integer): Boolean; +begin + while Number and 1 = 0 do + Number := Number shr 1; + + Result := Number = 1; +end; + + +function GetBitSize(BitSet: Cardinal): Integer; +begin + Result := 0; + + while BitSet > 0 do begin + if (BitSet and $1) = 1 then + Inc(Result); + + BitSet := BitSet shr 1; + end; +end; + + +procedure SwapRGB(pData: pByte; Width: Integer; HasAlpha: Boolean); +type + PRGBPix = ^TRGBPix; + TRGBPix = array [0..2] of byte; +var + Temp: Byte; +begin + while Width > 0 do begin + Temp := pRGBPIX(pData)^[0]; + pRGBPIX(pData)^[0] := pRGBPIX(pData)^[2]; + pRGBPIX(pData)^[2] := Temp; + + if HasAlpha then + Inc(pData, 4) + else + Inc(pData, 3); + + Dec(Width); + end; +end; + + +{$ifdef GLB_DELPHI} +function CreateGrayPalette: HPALETTE; +var + Idx: Integer; + Pal: PLogPalette; +begin + GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256)); + + Pal.palVersion := $300; + Pal.palNumEntries := 256; + + {$IFOPT R+} + {$DEFINE GLB_TEMPRANGECHECK} + {$R-} + {$ENDIF} + + for Idx := 0 to 256 - 1 do begin + Pal.palPalEntry[Idx].peRed := Idx; + Pal.palPalEntry[Idx].peGreen := Idx; + Pal.palPalEntry[Idx].peBlue := Idx; + Pal.palPalEntry[Idx].peFlags := 0; + end; + + {$IFDEF GLB_TEMPRANGECHECK} + {$UNDEF GLB_TEMPRANGECHECK} + {$R+} + {$ENDIF} + + Result := CreatePalette(Pal^); + + FreeMem(Pal); +end; +{$endif} + + +{$ifdef GLB_SDL_IMAGE} +function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; +begin + Result := TStream(context^.unknown.data1).Seek(offset, whence); +end; + + +function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl; +begin + Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum); +end; + + +function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl; +begin + Result := TStream(context^.unknown.data1).Write(Ptr^, size * num); +end; + + +function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl; +begin + Result := 0; +end; + + +function glBitmapCreateRWops(Stream: TStream): PSDL_RWops; +begin + Result := SDL_AllocRW; + + if Result = nil then + raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.'); + + Result^.seek := glBitmapRWseek; + Result^.read := glBitmapRWread; + Result^.write := glBitmapRWwrite; + Result^.close := glBitmapRWclose; + Result^.unknown.data1 := Stream; +end; +{$endif} + + +{* +** Helper functions +*} +function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean; +var + glBitmap: TglBitmap2D; +begin + Result := false; + Texture := 0; + + {$ifdef GLB_DELPHI} + if Instance = 0 then + Instance := HInstance; + + if (LoadFromRes) then + glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName) + else + {$endif} + glBitmap := TglBitmap2D.Create(FileName); + + try + glBitmap.DeleteTextureOnFree := False; + glBitmap.FreeDataAfterGenTexture := False; + glBitmap.GenTexture(True); + if (glBitmap.ID > 0) then begin + Texture := glBitmap.ID; + Result := True; + end; + finally + glBitmap.Free; + end; +end; + + +function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean; +var + CM: TglBitmapCubeMap; +begin + Texture := 0; + + {$ifdef GLB_DELPHI} + if Instance = 0 then + Instance := HInstance; + {$endif} + + CM := TglBitmapCubeMap.Create; + try + CM.DeleteTextureOnFree := False; + + // Maps + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveX) + else + {$endif} + CM.LoadFromFile(PositiveX); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X); + + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeX) + else + {$endif} + CM.LoadFromFile(NegativeX); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); + + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveY) + else + {$endif} + CM.LoadFromFile(PositiveY); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); + + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeY) + else + {$endif} + CM.LoadFromFile(NegativeY); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); + + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveZ) + else + {$endif} + CM.LoadFromFile(PositiveZ); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); + + {$ifdef GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeZ) + else + {$endif} + CM.LoadFromFile(NegativeZ); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + + Texture := CM.ID; + Result := True; + finally + CM.Free; + end; +end; + + +function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; +var + NM: TglBitmapNormalMap; +begin + Texture := 0; + + NM := TglBitmapNormalMap.Create; + try + NM.DeleteTextureOnFree := False; + NM.GenerateNormalMap(Size); + + Texture := NM.ID; + Result := True; + finally + NM.Free; + end; +end; + + +{* +** Defaults +*} +procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat); +begin + glBitmapDefaultFormat := Format; +end; + + +procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean); +begin + glBitmapDefaultDeleteTextureOnFree := DeleteTextureOnFree; +end; + + +procedure glBitmapSetDefaultFilter(Min, Mag: Integer); +begin + glBitmapDefaultFilterMin := Min; + glBitmapDefaultFilterMag := Mag; +end; + + +procedure glBitmapSetDefaultWrap(S: Integer; T: Integer; R: Integer); +begin + glBitmapDefaultWrapS := S; + glBitmapDefaultWrapT := T; + glBitmapDefaultWrapR := R; +end; + + +procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean); +begin + glBitmapDefaultFreeDataAfterGenTextures := FreeData; +end; + + +function glBitmapGetDefaultFormat: TglBitmapFormat; +begin + Result := glBitmapDefaultFormat; +end; + + +function glBitmapGetDefaultDeleteTextureOnFree: Boolean; +begin + Result := glBitmapDefaultDeleteTextureOnFree; +end; + + +procedure glBitmapGetDefaultFilter(var Min, Mag: Integer); +begin + Min := glBitmapDefaultFilterMin; + Mag := glBitmapDefaultFilterMag; +end; + + +procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer); +begin + S := glBitmapDefaultWrapS; + T := glBitmapDefaultWrapT; + R := glBitmapDefaultWrapR; +end; + + +function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; +begin + Result := glBitmapDefaultFreeDataAfterGenTextures; +end; + + +{ TglBitmap } + +procedure TglBitmap.AfterConstruction; +begin + inherited; + + fID := 0; + fTarget := 0; + fMipMap := mmMipmap; + fIsResident := False; + + // get defaults + fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; + fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; + + fFormat := glBitmapGetDefaultFormat; + + glBitmapGetDefaultFilter(fFilterMin, fFilterMag); + glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); +end; + + +procedure TglBitmap.BeforeDestruction; +begin + SetDataPointer(nil, ifEmpty); + + if ((ID > 0) and (fDeleteTextureOnFree)) then + glDeleteTextures(1, @ID); + + inherited; +end; + + +constructor TglBitmap.Create; +begin + {$ifndef GLB_NO_NATIVE_GL} + ReadOpenGLExtensions; + {$endif} + + if (ClassType = TglBitmap) then + raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); + + inherited Create; +end; + + +constructor TglBitmap.Create(FileName: String); +begin + Create; + LoadFromFile(FileName); +end; + + +constructor TglBitmap.Create(Stream: TStream); +begin + Create; + LoadFromStream(Stream); +end; + + +{$ifdef GLB_DELPHI} +constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar); +begin + Create; + LoadFromResource(Instance, Resource, ResType); +end; + + +constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar); +begin + Create; + LoadFromResource(Instance, Resource, ResType); +end; + + + +constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); +begin + Create; + LoadFromResourceID(Instance, ResourceID, ResType); +end; +{$endif} + + +constructor TglBitmap.Create(Size: TglBitmapPixelPosition; + Format: TglBitmapInternalFormat); +var + Image: pByte; + ImageSize: Integer; +begin + Create; + + ImageSize := FormatGetImageSize(Size, Format); + GetMem(Image, ImageSize); + try + FillChar(Image^, ImageSize, #$FF); + + SetDataPointer(Image, Format, Size.X, Size.Y); + except + FreeMem(Image); + raise; + end; +end; + + +constructor TglBitmap.Create(Size: TglBitmapPixelPosition; + Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer); +begin + Create; + LoadFromFunc(Size, Func, Format, CustomData); +end; + + +function TglBitmap.Clone: TglBitmap; +var + Temp: TglBitmap; + TempPtr: pByte; + Size: Integer; +begin + Temp := ClassType.Create as TglBitmap; + try + // copy texture data if assigned + if Assigned(Data) then begin + Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat); + + GetMem(TempPtr, Size); + try + Move(Data^, TempPtr^, Size); + Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height); + except + FreeMem(TempPtr); + raise; + end; + end else + Temp.SetDataPointer(nil, InternalFormat, Width, Height); + + // copy properties + Temp.fID := ID; + Temp.fTarget := Target; + Temp.fFormat := Format; + Temp.fMipMap := MipMap; + Temp.fAnisotropic := Anisotropic; + Temp.fBorderColor := fBorderColor; + Temp.fDeleteTextureOnFree := DeleteTextureOnFree; + Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture; + Temp.fFilterMin := fFilterMin; + Temp.fFilterMag := fFilterMag; + Temp.fWrapS := fWrapS; + Temp.fWrapT := fWrapT; + Temp.fWrapR := fWrapR; + Temp.fFilename := fFilename; + Temp.fCustomName := fCustomName; + Temp.fCustomNameW := fCustomNameW; + Temp.fCustomDataPointer := fCustomDataPointer; + + Result := Temp; + except + FreeAndNil(Temp); + raise; + end; +end; + + +procedure TglBitmap.LoadFromFile(FileName: String); +var + FS: TFileStream; +begin + fFilename := FileName; + + FS := TFileStream.Create(FileName, fmOpenRead); + try + FS.Position := 0; + + LoadFromStream(FS); + finally + FS.Free; + end; +end; + + +procedure TglBitmap.LoadFromStream(Stream: TStream); +begin + {$ifdef GLB_SUPPORT_PNG_READ} + if not LoadPNG(Stream) then + {$endif} + {$ifdef GLB_SUPPORT_JPEG_READ} + if not LoadJPEG(Stream) then + {$endif} + if not LoadDDS(Stream) then + if not LoadTGA(Stream) then + if not LoadBMP(Stream) then + raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.'); +end; + + +{$ifdef GLB_DELPHI} +procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar); +var + RS: TResourceStream; + TempPos: Integer; + ResTypeStr: String; + TempResType: PChar; +begin + if Assigned(ResType) then + TempResType := ResType + else + begin + TempPos := Pos('.', Resource); + ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); + Resource := UpperCase(Copy(Resource, 0, TempPos -1)); + TempResType := PChar(ResTypeStr); + end; + + RS := TResourceStream.Create(Instance, Resource, TempResType); + try + LoadFromStream(RS); + finally + RS.Free; + end; +end; + + +procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); +var + RS: TResourceStream; +begin + RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType); + try + LoadFromStream(RS); + finally + RS.Free; + end; +end; +{$endif} + + + +procedure TglBitmap.LoadFromFunc(Size: TglBitmapPixelPosition; + Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer); +var + Image: pByte; + ImageSize: Integer; +begin + ImageSize := FormatGetImageSize(Size, Format); + GetMem(Image, ImageSize); + try + FillChar(Image^, ImageSize, #$FF); + + SetDataPointer(Image, Format, Size.X, Size.Y); + except + FreeMem(Image); + raise; + end; + + AddFunc(Self, Func, False, Format, CustomData) +end; + + +procedure TglBitmap.SaveToFile(FileName: String; FileType: TglBitmapFileType); +var + FS: TFileStream; +begin + FS := TFileStream.Create(FileName, fmCreate); + try + FS.Position := 0; + SaveToStream(FS, FileType); + finally + FS.Free; + end; +end; + + +procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType); +begin + case FileType of + {$ifdef GLB_SUPPORT_PNG_WRITE} + ftPNG: SavePng(Stream); + {$endif} + {$ifdef GLB_SUPPORT_JPEG_WRITE} + ftJPEG: SaveJPEG(Stream); + {$endif} + ftDDS: SaveDDS(Stream); + ftTGA: SaveTGA(Stream); + ftBMP: SaveBMP(Stream); + end; +end; + + +{$ifdef GLB_SDL} +function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean; +var + Row, RowSize: Integer; + pSource, pData: PByte; + TempDepth: Integer; + Pix: TglBitmapPixelData; + + function GetRowPointer(Row: Integer): pByte; + begin + Result := Surface.pixels; + Inc(Result, Row * RowSize); + end; + +begin + Result := False; + + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if Assigned(Data) then begin + case Trunc(FormatGetSize(InternalFormat)) of + 1: TempDepth := 8; + 2: TempDepth := 16; + 3: TempDepth := 24; + 4: TempDepth := 32; + else + raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + + FormatPreparePixel(Pix, InternalFormat); + + with Pix.PixelDesc do + Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift); + + pSource := Data; + RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat)); + + for Row := 0 to FileHeight -1 do begin + pData := GetRowPointer(Row); + + if Assigned(pData) then begin + Move(pSource^, pData^, RowSize); + Inc(pSource, RowSize); + end; + end; + + Result := True; + end; +end; + + +function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean; +var + pSource, pData, pTempData: PByte; + Row, RowSize, TempWidth, TempHeight: Integer; + IntFormat: TglBitmapInternalFormat; + + function GetRowPointer(Row: Integer): pByte; + begin + Result := Surface^.pixels; + Inc(Result, Row * RowSize); + end; + +begin + Result := False; + + if (Assigned(Surface)) then begin + with Surface^.format^ do begin + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then + IntFormat := ifLuminance + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then + IntFormat := ifLuminanceAlpha + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then + IntFormat := ifRGBA4 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then + IntFormat := ifR5G6B5 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then + IntFormat := ifRGB5A1 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then + IntFormat := ifBGR8 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then + IntFormat := ifRGB8 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then + IntFormat := ifBGRA8 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then + IntFormat := ifRGBA8 + else + + if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then + IntFormat := ifRGB10A2 + else + raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.'); + end; + + TempWidth := Surface^.w; + TempHeight := Surface^.h; + + RowSize := Trunc(TempWidth * FormatGetSize(IntFormat)); + + GetMem(pData, TempHeight * RowSize); + try + pTempData := pData; + + for Row := 0 to TempHeight -1 do begin + pSource := GetRowPointer(Row); + + if (Assigned(pSource)) then begin + Move(pSource^, pTempData^, RowSize); + Inc(pTempData, RowSize); + end; + end; + + SetDataPointer(pData, IntFormat, TempWidth, TempHeight); + + Result := True; + except + FreeMem(pData); + raise; + end; + end; +end; + + +function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean; +var + Row, Col, AlphaInterleave: Integer; + pSource, pDest: PByte; + + function GetRowPointer(Row: Integer): pByte; + begin + Result := Surface.pixels; + Inc(Result, Row * Width); + end; + +begin + Result := False; + + if Assigned(Data) then begin + if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin + Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0); + + case InternalFormat of + ifLuminanceAlpha: + AlphaInterleave := 1; + ifBGRA8, ifRGBA8: + AlphaInterleave := 3; + else + AlphaInterleave := 0; + end; + + // Copy Data + pSource := Data; + + for Row := 0 to Height -1 do begin + pDest := GetRowPointer(Row); + + if Assigned(pDest) then begin + for Col := 0 to Width -1 do begin + Inc(pSource, AlphaInterleave); + pDest^ := pSource^; + Inc(pDest); + Inc(pSource); + end; + end; + end; + + Result := True; + end; + end; +end; + + +function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + glBitmap: TglBitmap2D; +begin + glBitmap := TglBitmap2D.Create; + try + glBitmap.AssignFromSurface(Surface); + + Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); + finally + glBitmap.Free; + end; +end; +{$endif} + + +{$ifdef GLB_DELPHI} +function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean; +var + pSource, pData, pTempData: PByte; + Row, RowSize, TempWidth, TempHeight: Integer; + IntFormat: TglBitmapInternalFormat; +begin + Result := False; + + if (Assigned(Bitmap)) then begin + case Bitmap.PixelFormat of + pf8bit: + IntFormat := ifLuminance; + pf15bit: + IntFormat := ifRGB5A1; + pf16bit: + IntFormat := ifR5G6B5; + pf24bit: + IntFormat := ifBGR8; + pf32bit: + IntFormat := ifBGRA8; + else + raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.'); + end; + + TempWidth := Bitmap.Width; + TempHeight := Bitmap.Height; + + RowSize := Trunc(TempWidth * FormatGetSize(IntFormat)); + + GetMem(pData, TempHeight * RowSize); + try + pTempData := pData; + + for Row := 0 to TempHeight -1 do begin + pSource := Bitmap.Scanline[Row]; + + if (Assigned(pSource)) then begin + Move(pSource^, pTempData^, RowSize); + Inc(pTempData, RowSize); + end; + end; + + SetDataPointer(pData, IntFormat, TempWidth, TempHeight); + + Result := True; + except + FreeMem(pData); + raise; + end; + end; +end; + + +function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean; +var + Row: Integer; + pSource, pData: PByte; +begin + Result := False; + + if Assigned(Data) then begin + if Assigned(Bitmap) then begin + Bitmap.Width := Width; + Bitmap.Height := Height; + + case InternalFormat of + ifAlpha, ifLuminance, ifDepth8: + begin + Bitmap.PixelFormat := pf8bit; + Bitmap.Palette := CreateGrayPalette; + end; + ifRGB5A1: + Bitmap.PixelFormat := pf15bit; + ifR5G6B5: + Bitmap.PixelFormat := pf16bit; + ifRGB8, ifBGR8: + Bitmap.PixelFormat := pf24bit; + ifRGBA8, ifBGRA8: + Bitmap.PixelFormat := pf32bit; + else + raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); + end; + + pSource := Data; + for Row := 0 to FileHeight -1 do begin + pData := Bitmap.Scanline[Row]; + + Move(pSource^, pData^, fRowSize); + Inc(pSource, fRowSize); + + // swap RGB(A) to BGR(A) + if InternalFormat in [ifRGB8, ifRGBA8] then + SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8); + end; + + Result := True; + end; + end; +end; + + +function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean; +var + Row, Col, AlphaInterleave: Integer; + pSource, pDest: PByte; +begin + Result := False; + + if Assigned(Data) then begin + if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin + if Assigned(Bitmap) then begin + Bitmap.PixelFormat := pf8bit; + Bitmap.Palette := CreateGrayPalette; + Bitmap.Width := Width; + Bitmap.Height := Height; + + case InternalFormat of + ifLuminanceAlpha: + AlphaInterleave := 1; + ifRGBA8, ifBGRA8: + AlphaInterleave := 3; + else + AlphaInterleave := 0; + end; + + // Copy Data + pSource := Data; + + for Row := 0 to Height -1 do begin + pDest := Bitmap.Scanline[Row]; + + if Assigned(pDest) then begin + for Col := 0 to Width -1 do begin + Inc(pSource, AlphaInterleave); + pDest^ := pSource^; + Inc(pDest); + Inc(pSource); + end; + end; + end; + + Result := True; + end; + end; + end; +end; + + +function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + glBitmap: TglBitmap2D; +begin + glBitmap := TglBitmap2D.Create; + try + glBitmap.AssignFromBitmap(Bitmap); + + Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); + finally + glBitmap.Free; + end; +end; +{$endif} + + +function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + FS: TFileStream; +begin + FS := TFileStream.Create(FileName, fmOpenRead); + try + Result := AddAlphaFromStream(FS, Func, CustomData); + finally + FS.Free; + end; +end; + + +function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + glBitmap: TglBitmap2D; +begin + glBitmap := TglBitmap2D.Create(Stream); + try + Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); + finally + glBitmap.Free; + end; +end; + + +{$ifdef GLB_DELPHI} +function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String; + ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + RS: TResourceStream; + TempPos: Integer; + ResTypeStr: String; + TempResType: PChar; +begin + if Assigned(ResType) then + TempResType := ResType + else + begin + TempPos := Pos('.', Resource); + ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); + Resource := UpperCase(Copy(Resource, 0, TempPos -1)); + TempResType := PChar(ResTypeStr); + end; + + RS := TResourceStream.Create(Instance, Resource, TempResType); + try + Result := AddAlphaFromStream(RS, Func, CustomData); + finally + RS.Free; + end; +end; + + +function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer; + ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + RS: TResourceStream; +begin + RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType); + try + Result := AddAlphaFromStream(RS, Func, CustomData); + finally + RS.Free; + end; +end; +{$endif} + + +procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + + with TglBitmapPixelData(CustomData^) do + if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and + (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and + (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then + Dest.Alpha := 0 + else + Dest.Alpha := Dest.PixelDesc.AlphaRange; + end; +end; + + +function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue, Deviation: Byte): Boolean; +begin + Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF); +end; + + +function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean; +var + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + + Result := AddAlphaFromColorKeyFloat( + Red / PixelData.PixelDesc.RedRange, + Green / PixelData.PixelDesc.GreenRange, + Blue / PixelData.PixelDesc.BlueRange, + Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange))); +end; + + +function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean; +var + TempR, TempG, TempB: Cardinal; + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + + // Calculate Colorrange + with PixelData.PixelDesc do begin + TempR := Trunc(RedRange * Deviation); + TempG := Trunc(GreenRange * Deviation); + TempB := Trunc(BlueRange * Deviation); + + PixelData.Red := Min(RedRange, Trunc(RedRange * Red) + TempR); + RedRange := Max(0, Trunc(RedRange * Red) - TempR); + PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG); + GreenRange := Max(0, Trunc(GreenRange * Green) - TempG); + PixelData.Blue := Min(BlueRange, Trunc(BlueRange * Blue) + TempB); + BlueRange := Max(0, Trunc(BlueRange * Blue) - TempB); + PixelData.Alpha := 0; + AlphaRange := 0; + end; + + Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData); +end; + + +procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + + with TglBitmapPixelData(CustomData^) do + Dest.Alpha := Alpha; + end; +end; + + +function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean; +begin + Result := AddAlphaFromValueFloat(Alpha / $FF); +end; + + +function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean; +var + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + + with PixelData.PixelDesc do + PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha))); + + Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData); +end; + + +function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean; +var + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + + Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange); +end; + + +procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + Dest.Alpha := Source.Alpha; + + if (Integer(CustomData) and $1 > 0) then begin + Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange; + Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange; + Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange; + end; + + if (Integer(CustomData) and $2 > 0) then begin + Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange; + end; + end; +end; + + +procedure TglBitmap.Invert(UseRGB, UseAlpha: Boolean); +begin + if ((UseRGB) or (UseAlpha)) then + AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB))); +end; + + +procedure TglBitmap.SetFilter(Min, Mag: Integer); +begin + case Min of + GL_NEAREST: + fFilterMin := GL_NEAREST; + GL_LINEAR: + fFilterMin := GL_LINEAR; + GL_NEAREST_MIPMAP_NEAREST: + fFilterMin := GL_NEAREST_MIPMAP_NEAREST; + GL_LINEAR_MIPMAP_NEAREST: + fFilterMin := GL_LINEAR_MIPMAP_NEAREST; + GL_NEAREST_MIPMAP_LINEAR: + fFilterMin := GL_NEAREST_MIPMAP_LINEAR; + GL_LINEAR_MIPMAP_LINEAR: + fFilterMin := GL_LINEAR_MIPMAP_LINEAR; + else + raise EglBitmapException.Create('SetFilter - Unknow Minfilter.'); + end; + + case Mag of + GL_NEAREST: + fFilterMag := GL_NEAREST; + GL_LINEAR: + fFilterMag := GL_LINEAR; + else + raise EglBitmapException.Create('SetFilter - Unknow Magfilter.'); + end; + + // If texture is created then assign filter + if ID > 0 then begin + Bind(False); + + glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag); + + if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin + case fFilterMin of + GL_NEAREST, GL_LINEAR: + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin); + GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR: + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR: + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + end; + end else + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin); + end; +end; + + +procedure TglBitmap.SetWrap(S: Integer; T: Integer; R: Integer); +begin + case S of + GL_CLAMP: + fWrapS := GL_CLAMP; + GL_REPEAT: + fWrapS := GL_REPEAT; + GL_CLAMP_TO_EDGE: + begin + if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then + fWrapS := GL_CLAMP_TO_EDGE + else + fWrapS := GL_CLAMP; + end; + GL_CLAMP_TO_BORDER: + begin + if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then + fWrapS := GL_CLAMP_TO_BORDER + else + fWrapS := GL_CLAMP; + end; + GL_MIRRORED_REPEAT: + begin + if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then + fWrapS := GL_MIRRORED_REPEAT + else + raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).'); + end; + else + raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).'); + end; + + case T of + GL_CLAMP: + fWrapT := GL_CLAMP; + GL_REPEAT: + fWrapT := GL_REPEAT; + GL_CLAMP_TO_EDGE: + begin + if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then + fWrapT := GL_CLAMP_TO_EDGE + else + fWrapT := GL_CLAMP; + end; + GL_CLAMP_TO_BORDER: + begin + if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then + fWrapT := GL_CLAMP_TO_BORDER + else + fWrapT := GL_CLAMP; + end; + GL_MIRRORED_REPEAT: + begin + if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then + fWrapT := GL_MIRRORED_REPEAT + else + raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).'); + end; + else + raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).'); + end; + + case R of + GL_CLAMP: + fWrapR := GL_CLAMP; + GL_REPEAT: + fWrapR := GL_REPEAT; + GL_CLAMP_TO_EDGE: + begin + if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then + fWrapR := GL_CLAMP_TO_EDGE + else + fWrapR := GL_CLAMP; + end; + GL_CLAMP_TO_BORDER: + begin + if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then + fWrapR := GL_CLAMP_TO_BORDER + else + fWrapR := GL_CLAMP; + end; + GL_MIRRORED_REPEAT: + begin + if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then + fWrapR := GL_MIRRORED_REPEAT + else + raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).'); + end; + else + raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).'); + end; + + if ID > 0 then begin + Bind (False); + glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS); + glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT); + glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR); + end; +end; + + +procedure TglBitmap.SetDataPointer(NewData: PByte; Format: TglBitmapInternalFormat; Width, Height: Integer); +begin + // Data + if Data <> NewData then begin + if (Assigned(Data)) + then FreeMem(Data); + + fData := NewData; + end; + + if Data = nil then begin + fInternalFormat := ifEmpty; + fPixelSize := 0; + fRowSize := 0; + end else begin + if Width <> -1 then begin + fDimension.Fields := fDimension.Fields + [ffX]; + fDimension.X := Width; + end; + + if Height <> -1 then begin + fDimension.Fields := fDimension.Fields + [ffY]; + fDimension.Y := Height; + end; + + fInternalFormat := Format; + fPixelSize := Trunc(FormatGetSize(InternalFormat)); + fRowSize := Trunc(FormatGetSize(InternalFormat) * Self.Width); + end; +end; + +{$ifdef GLB_SUPPORT_PNG_READ} +{$ifdef GLB_LIB_PNG} +procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; +begin + TStream(png_get_io_ptr(png)).Read(buffer^, size); +end; +{$endif} + + +function TglBitmap.LoadPNG(Stream: TStream): Boolean; +{$ifdef GLB_SDL_IMAGE} +var + Surface: PSDL_Surface; + RWops: PSDL_RWops; +begin + Result := False; + + RWops := glBitmapCreateRWops(Stream); + try + if IMG_isPNG(RWops) > 0 then begin + Surface := IMG_LoadPNG_RW(RWops); + try + AssignFromSurface(Surface); + Result := True; + finally + SDL_FreeSurface(Surface); + end; + end; + finally + SDL_FreeRW(RWops); + end; +end; +{$endif} +{$ifdef GLB_LIB_PNG} +var + StreamPos: Int64; + signature: array [0..7] of byte; + png: png_structp; + png_info: png_infop; + + TempHeight, TempWidth: Integer; + Format: TglBitmapInternalFormat; + + png_data: pByte; + png_rows: array of pByte; + Row, LineSize: Integer; +begin + Result := False; + + if not init_libPNG then + raise Exception.Create('LoadPNG - unable to initialize libPNG.'); + + try + // signature + StreamPos := Stream.Position; + Stream.Read(signature, 8); + Stream.Position := StreamPos; + + if png_check_sig(@signature, 8) <> 0 then begin + // png read struct + png := png_create_read_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil); + if png = nil then + raise EglBitmapException.Create('LoadPng - couldn''t create read struct.'); + + // png info + png_info := png_create_info_struct(png); + if png_info = nil then begin + png_destroy_read_struct(@png, nil, nil); + raise EglBitmapException.Create('LoadPng - couldn''t create info struct.'); + end; + + // set read callback + png_set_read_fn(png, stream, glBitmap_libPNG_read_func); + + // read informations + png_read_info(png, png_info); + + // size + TempHeight := png_get_image_height(png, png_info); + TempWidth := png_get_image_width(png, png_info); + + // format + case png_get_color_type(png, png_info) of + PNG_COLOR_TYPE_GRAY: + Format := ifLuminance; + PNG_COLOR_TYPE_GRAY_ALPHA: + Format := ifLuminanceAlpha; + PNG_COLOR_TYPE_RGB: + Format := ifRGB8; + PNG_COLOR_TYPE_RGB_ALPHA: + Format := ifRGBA8; + else + raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); + end; + + // cut upper 8 bit from 16 bit formats + if png_get_bit_depth(png, png_info) > 8 then + png_set_strip_16(png); + + // expand bitdepth smaller than 8 + if png_get_bit_depth(png, png_info) < 8 then + png_set_expand(png); + + // allocating mem for scanlines + LineSize := png_get_rowbytes(png, png_info); + GetMem(png_data, TempHeight * LineSize); + try + SetLength(png_rows, TempHeight); + for Row := Low(png_rows) to High(png_rows) do begin + png_rows[Row] := png_data; + Inc(png_rows[Row], Row * LineSize); + end; + + // read complete image into scanlines + png_read_image(png, @png_rows[0]); + + // read end + png_read_end(png, png_info); + + // destroy read struct + png_destroy_read_struct(@png, @png_info, nil); + + SetLength(png_rows, 0); + + // set new data + SetDataPointer(png_data, Format, TempWidth, TempHeight); + + Result := True; + except + FreeMem(png_data); + raise; + end; + end; + finally + quit_libPNG; + end; +end; +{$endif} +{$ifdef GLB_PNGIMAGE} +var + StreamPos: Int64; + Png: TPNGObject; + Header: Array[0..7] of Byte; + Row, Col, PixSize, LineSize: Integer; + NewImage, pSource, pDest, pAlpha: pByte; + Format: TglBitmapInternalFormat; + +const + PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10); + +begin + Result := False; + + StreamPos := Stream.Position; + Stream.Read(Header[0], SizeOf(Header)); + Stream.Position := StreamPos; + + {Test if the header matches} + if Header = PngHeader then begin + Png := TPNGObject.Create; + try + Png.LoadFromStream(Stream); + + case Png.Header.ColorType of + COLOR_GRAYSCALE: + Format := ifLuminance; + COLOR_GRAYSCALEALPHA: + Format := ifLuminanceAlpha; + COLOR_RGB: + Format := ifBGR8; + COLOR_RGBALPHA: + Format := ifBGRA8; + else + raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); + end; + + PixSize := Trunc(FormatGetSize(Format)); + LineSize := Integer(Png.Header.Width) * PixSize; + + GetMem(NewImage, LineSize * Integer(Png.Header.Height)); + try + pDest := NewImage; + + case Png.Header.ColorType of + COLOR_RGB, COLOR_GRAYSCALE: + begin + for Row := 0 to Png.Height -1 do begin + Move (Png.Scanline[Row]^, pDest^, LineSize); + Inc(pDest, LineSize); + end; + end; + COLOR_RGBALPHA, COLOR_GRAYSCALEALPHA: + begin + PixSize := PixSize -1; + + for Row := 0 to Png.Height -1 do begin + pSource := Png.Scanline[Row]; + pAlpha := pByte(Png.AlphaScanline[Row]); + + for Col := 0 to Png.Width -1 do begin + Move (pSource^, pDest^, PixSize); + Inc(pSource, PixSize); + Inc(pDest, PixSize); + + pDest^ := pAlpha^; + inc(pAlpha); + Inc(pDest); + end; + end; + end; + else + raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); + end; + + SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height); + + Result := True; + except + FreeMem(NewImage); + raise; + end; + finally + Png.Free; + end; + end; +end; +{$endif} +{$endif} + + +{$ifdef GLB_LIB_JPEG} +type + glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr; + glBitmap_libJPEG_source_mgr = record + pub: jpeg_source_mgr; + + SrcStream: TStream; + SrcBuffer: array [1..4096] of byte; + end; + + + glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr; + glBitmap_libJPEG_dest_mgr = record + pub: jpeg_destination_mgr; + + DestStream: TStream; + DestBuffer: array [1..4096] of byte; + end; + + + +procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl; +//var +// Msg: String; +begin +// SetLength(Msg, 256); +// cinfo^.err^.format_message(cinfo, pChar(Msg)); + +// Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); + +// cinfo^.global_state := 0; + +// jpeg_abort(cinfo); +end; + + +procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl; +//var +// Msg: String; +begin +// SetLength(Msg, 256); +// cinfo^.err^.format_message(cinfo, pChar(Msg)); + +// Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); + +// cinfo^.global_state := 0; +end; + + +procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl; +begin +end; + + +function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl; +var + src: glBitmap_libJPEG_source_mgr_ptr; + bytes: integer; +begin + src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src); + + bytes := src^.SrcStream.Read(src^.SrcBuffer[1], 4096); + if (bytes <= 0) then begin + src^.SrcBuffer[1] := $FF; + src^.SrcBuffer[2] := JPEG_EOI; + bytes := 2; + end; + + src^.pub.next_input_byte := @(src^.SrcBuffer[1]); + src^.pub.bytes_in_buffer := bytes; + + result := true; +end; + + +procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl; +var + src: glBitmap_libJPEG_source_mgr_ptr; +begin + src := glBitmap_libJPEG_source_mgr_ptr(cinfo^.src); + + if num_bytes > 0 then begin + // wanted byte isn't in buffer so set stream position and read buffer + if num_bytes > src^.pub.bytes_in_buffer then begin + src^.SrcStream.Position := src^.SrcStream.Position + num_bytes - src^.pub.bytes_in_buffer; + src^.pub.fill_input_buffer(cinfo); + end else begin + // wanted byte is in buffer so only skip + inc(src^.pub.next_input_byte, num_bytes); + dec(src^.pub.bytes_in_buffer, num_bytes); + end; + end; +end; + + +procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl; +begin +end; + + +procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl; +begin +end; + + +function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl; +var + dest: glBitmap_libJPEG_dest_mgr_ptr; +begin + dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest); + + if dest^.pub.free_in_buffer < Cardinal(Length(dest^.DestBuffer)) then begin + // write complete buffer + dest^.DestStream.Write(dest^.DestBuffer[1], SizeOf(dest^.DestBuffer)); + + // reset buffer + dest^.pub.next_output_byte := @dest^.DestBuffer[1]; + dest^.pub.free_in_buffer := Length(dest^.DestBuffer); + end; + + Result := True; +end; + + +procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl; +var + Idx: Integer; + dest: glBitmap_libJPEG_dest_mgr_ptr; +begin + dest := glBitmap_libJPEG_dest_mgr_ptr(cinfo^.dest); + + for Idx := Low(dest^.DestBuffer) to High(dest^.DestBuffer) do begin + // check for endblock + if (Idx < High(dest^.DestBuffer)) and (dest^.DestBuffer[Idx] = $FF) and (dest^.DestBuffer[Idx +1] = JPEG_EOI) then begin + // write endblock + dest^.DestStream.Write(dest^.DestBuffer[Idx], 2); + + // leave + Break; + end else + dest^.DestStream.Write(dest^.DestBuffer[Idx], 1); + end; +end; +{$endif} + + +{$ifdef GLB_SUPPORT_JPEG_READ} +function TglBitmap.LoadJPEG(Stream: TStream): Boolean; +{$ifdef GLB_SDL_IMAGE} +var + Surface: PSDL_Surface; + RWops: PSDL_RWops; +begin + Result := False; + + RWops := glBitmapCreateRWops(Stream); + try + if IMG_isJPG(RWops) > 0 then begin + Surface := IMG_LoadJPG_RW(RWops); + try + AssignFromSurface(Surface); + Result := True; + finally + SDL_FreeSurface(Surface); + end; + end; + finally + SDL_FreeRW(RWops); + end; +end; +{$endif} +{$ifdef GLB_LIB_JPEG} +var + StreamPos: Int64; + Temp: array[0..1]of Byte; + + jpeg: jpeg_decompress_struct; + jpeg_err: jpeg_error_mgr; + + IntFormat: TglBitmapInternalFormat; + pImage: pByte; + TempHeight, TempWidth: Integer; + + pTemp: pByte; + Row: Integer; +begin + Result := False; + + if not init_libJPEG then + raise Exception.Create('LoadJPG - unable to initialize libJPEG.'); + + try + // reading first two bytes to test file and set cursor back to begin + StreamPos := Stream.Position; + Stream.Read(Temp[0], 2); + Stream.Position := StreamPos; + + // if Bitmap then read file. + if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin + FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00); + FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); + + // error managment + jpeg.err := jpeg_std_error(@jpeg_err); + jpeg_err.error_exit := glBitmap_libJPEG_error_exit; + jpeg_err.output_message := glBitmap_libJPEG_output_message; + + // decompression struct + jpeg_create_decompress(@jpeg); + + // allocation space for streaming methods + jpeg.src := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_source_mgr)); + + // seeting up custom functions + with glBitmap_libJPEG_source_mgr_ptr(jpeg.src)^ do begin + pub.init_source := glBitmap_libJPEG_init_source; + pub.fill_input_buffer := glBitmap_libJPEG_fill_input_buffer; + pub.skip_input_data := glBitmap_libJPEG_skip_input_data; + pub.resync_to_restart := jpeg_resync_to_restart; // use default method + pub.term_source := glBitmap_libJPEG_term_source; + + pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read + pub.next_input_byte := nil; // until buffer loaded + + SrcStream := Stream; + end; + + // set global decoding state + jpeg.global_state := DSTATE_START; + + // read header of jpeg + jpeg_read_header(@jpeg, False); + + // setting output parameter + case jpeg.jpeg_color_space of + JCS_GRAYSCALE: + begin + jpeg.out_color_space := JCS_GRAYSCALE; + IntFormat := ifLuminance; + end; + else + jpeg.out_color_space := JCS_RGB; + IntFormat := ifRGB8; + end; + + // reading image + jpeg_start_decompress(@jpeg); + + TempHeight := jpeg.output_height; + TempWidth := jpeg.output_width; + + // creating new image + GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat)); + try + pTemp := pImage; + + for Row := 0 to TempHeight -1 do begin + jpeg_read_scanlines(@jpeg, @pTemp, 1); + Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth)); + end; + + // finish decompression + jpeg_finish_decompress(@jpeg); + + // destroy decompression + jpeg_destroy_decompress(@jpeg); + + SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); + + Result := True; + except + FreeMem(pImage); + raise; + end; + end; + finally + quit_libJPEG; + end; +end; +{$endif} +{$ifdef GLB_DELPHI_JPEG} +var + bmp: TBitmap; + jpg: TJPEGImage; + StreamPos: Int64; + Temp: array[0..1]of Byte; +begin + Result := False; + + // reading first two bytes to test file and set cursor back to begin + StreamPos := Stream.Position; + Stream.Read(Temp[0], 2); + Stream.Position := StreamPos; + + // if Bitmap then read file. + if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin + bmp := TBitmap.Create; + try + jpg := TJPEGImage.Create; + try + jpg.LoadFromStream(Stream); + bmp.Assign(jpg); + Result := AssignFromBitmap(bmp); + finally + jpg.Free; + end; + finally + bmp.Free; + end; + end; +end; +{$endif} +{$endif} + + +const + BMP_MAGIC = $4D42; + + BMP_COMP_RGB = 0; + BMP_COMP_RLE8 = 1; + BMP_COMP_RLE4 = 2; + BMP_COMP_BITFIELDS = 3; + +type + TBMPHeader = packed record + bfType: Word; + bfSize: Cardinal; + bfReserved1: Word; + bfReserved2: Word; + bfOffBits: Cardinal; + end; + + TBMPInfo = packed record + biSize: Cardinal; + biWidth: Longint; + biHeight: Longint; + biPlanes: Word; + biBitCount: Word; + biCompression: Cardinal; + biSizeImage: Cardinal; + biXPelsPerMeter: Longint; + biYPelsPerMeter: Longint; + biClrUsed: Cardinal; + biClrImportant: Cardinal; + end; + + TBMPInfoOS = packed record + biSize: Cardinal; + biWidth: Longint; + biHeight: Longint; + biPlanes: Word; + biBitCount: Word; + end; + +// TBMPPalette = record +// case Boolean of +// True : (Colors: array[Byte] of TRGBQUAD); +// False: (redMask, greenMask, blueMask: Cardinal); +// end; + +function TglBitmap.LoadBMP(Stream: TStream): Boolean; +var + StreamPos: Int64; + Header: TBMPHeader; + Info: TBMPInfo; + NewImage, pData: pByte; + + Format: TglBitmapInternalFormat; + LineSize, Padding, LineIdx: Integer; + RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; + + PaddingBuff: Cardinal; + + + function GetLineWidth : Integer; + begin + Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3; + end; + + +begin + Result := False; + + RedMask := 0; + GreenMask := 0; + BlueMask := 0; + Format := ifEmpty; + + // Header + StreamPos := Stream.Position; + Stream.Read(Header, SizeOf(Header)); + + if Header.bfType = BMP_MAGIC then begin + Stream.Read(Info, SizeOf(Info)); + + // Check for Compression + if Info.biCompression <> BMP_COMP_RGB then begin + if Info.biCompression = BMP_COMP_BITFIELDS then begin + // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!) + if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin + Stream.Read(RedMask, SizeOf(Cardinal)); + Stream.Read(GreenMask, SizeOf(Cardinal)); + Stream.Read(BlueMask, SizeOf(Cardinal)); + Stream.Read(AlphaMask, SizeOf(Cardinal)); + end; + end else begin + // RLE compression is unsupported + Stream.Position := StreamPos; + + Exit; + end; + end; + + // Skip palette + if Info.biBitCount < 16 then + Stream.Position := Stream.Position + Info.biClrUsed * 4; + + // Jump to the data + Stream.Position := StreamPos + Header.bfOffBits; + + // Select Format + case Info.biBitCount of + 8 : Format := ifLuminance; + 16: + begin + if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin + Format := ifRGB5A1; + end else begin + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then + Format := ifLuminanceAlpha; + + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA4) then + Format := ifRGBA4; + + if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifRGB5A1) then + Format := ifRGB5A1; + + if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then + Format := ifR5G6B5; + end; + end; + 24: Format := ifBGR8; + 32: + begin + if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin + Format := ifBGRA8; + end else begin + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA8) then + Format := ifRGBA8; + + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then + Format := ifBGRA8; + + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGB10A2) then + Format := ifRGB10A2; + end; + end; + end; + + if Format <> ifEmpty then begin + LineSize := Trunc(Info.biWidth * FormatGetSize(Format)); + Padding := GetLineWidth - LineSize; + + // copying data + GetMem(NewImage, Info.biHeight * LineSize); + try + FillChar(NewImage^, Info.biHeight * LineSize, $FF); + + // Set pData to last Line + pData := NewImage; + Inc(pData, LineSize * (Info.biHeight -1)); + + // Copy Image Data + for LineIdx := 0 to Info.biHeight - 1 do begin + Stream.Read(pData^, LineSize); + Dec(pData, LineSize); + + Stream.Read(PaddingBuff, Padding); + end; + + // Set new Image + SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight); + + Result := True; + except + FreeMem(NewImage); + raise; + end; + end; + end + else Stream.Position := StreamPos; +end; + + +const + DDS_MAGIC = $20534444; + + // DDS_header.dwFlags + DDSD_CAPS = $00000001; + DDSD_HEIGHT = $00000002; + DDSD_WIDTH = $00000004; + DDSD_PITCH = $00000008; + DDSD_PIXELFORMAT = $00001000; + DDSD_MIPMAPCOUNT = $00020000; + DDSD_LINEARSIZE = $00080000; + DDSD_DEPTH = $00800000; + + // DDS_header.sPixelFormat.dwFlags + DDPF_ALPHAPIXELS = $00000001; + DDPF_FOURCC = $00000004; + DDPF_INDEXED = $00000020; + DDPF_RGB = $00000040; + + // DDS_header.sCaps.dwCaps1 + DDSCAPS_COMPLEX = $00000008; + DDSCAPS_TEXTURE = $00001000; + DDSCAPS_MIPMAP = $00400000; + + // DDS_header.sCaps.dwCaps2 + DDSCAPS2_CUBEMAP = $00000200; + DDSCAPS2_CUBEMAP_POSITIVEX = $00000400; + DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800; + DDSCAPS2_CUBEMAP_POSITIVEY = $00001000; + DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000; + DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000; + DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000; + DDSCAPS2_VOLUME = $00200000; + + D3DFMT_DXT1 = $31545844; + D3DFMT_DXT3 = $33545844; + D3DFMT_DXT5 = $35545844; + +type + TDDSPixelFormat = packed record + dwSize: Cardinal; + dwFlags: Cardinal; + dwFourCC: Cardinal; + dwRGBBitCount: Cardinal; + dwRBitMask: Cardinal; + dwGBitMask: Cardinal; + dwBBitMask: Cardinal; + dwAlphaBitMask: Cardinal; + end; + + TDDSCaps = packed record + dwCaps1: Cardinal; + dwCaps2: Cardinal; + dwDDSX: Cardinal; + dwReserved: Cardinal; + end; + + TDDSHeader = packed record + dwMagic: Cardinal; + dwSize: Cardinal; + dwFlags: Cardinal; + dwHeight: Cardinal; + dwWidth: Cardinal; + dwPitchOrLinearSize: Cardinal; + dwDepth: Cardinal; + dwMipMapCount: Cardinal; + dwReserved: array[0..10] of Cardinal; + PixelFormat: TDDSPixelFormat; + Caps: TDDSCaps; + dwReserved2: Cardinal; + end; + + +function TglBitmap.LoadDDS(Stream: TStream): Boolean; +var + Header: TDDSHeader; + StreamPos: Int64; + Y, LineSize: Cardinal; + +// MipMapCount, X, Y, XSize, YSize: Cardinal; + RowSize: Cardinal; + NewImage, pData: pByte; + Format: TglBitmapInternalFormat; + + + function RaiseEx : Exception; + begin + Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + end; + + + function GetInternalFormat: TglBitmapInternalFormat; + begin + with Header.PixelFormat do begin + // Compresses + 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; + end; + end else + + // RGB + if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin + case dwRGBBitCount of + 8: + begin + if dwFlags and DDPF_ALPHAPIXELS > 0 then + Result := ifAlpha + else + Result := ifLuminance; + end; + 16: + begin + if dwFlags and DDPF_ALPHAPIXELS > 0 then begin + // Alpha + case GetBitSize(dwRBitMask) of + 5: Result := ifRGB5A1; + 4: Result := ifRGBA4; + else + Result := ifLuminanceAlpha; + end; + end else begin + // no Alpha + Result := ifR5G6B5; + end; + end; + 24: + begin + if dwRBitMask > dwBBitMask then + Result := ifBGR8 + else + Result := ifRGB8; + end; + 32: + begin + if GetBitSize(dwRBitMask) = 10 then + Result := ifRGB10A2 + else + + if dwRBitMask > dwBBitMask then + Result := ifBGRA8 + else + Result := ifRGBA8; + end; + else + raise RaiseEx; + end; + end else + raise RaiseEx; + end; + end; + +begin + Result := False; + + // Header + StreamPos := Stream.Position; + Stream.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 + Stream.Position := StreamPos; + Exit; + end; + + // Pixelformat +// if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0 +// then MipMapCount := Header.dwMipMapCount +// else MipMapCount := 1; + + Format := GetInternalFormat; + LineSize := Trunc(Header.dwWidth * FormatGetSize(Format)); + + GetMem(NewImage, Header.dwHeight * LineSize); + try + pData := NewImage; + + // Compressed + 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 + Stream.Read(pData^, RowSize); + Inc(pData, 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 + Stream.Read(pData^, RowSize); + Inc(pData, LineSize); + end; + end + else raise RaiseEx; + + SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight); + + Result := True; + except + FreeMem(NewImage); + raise; + end; +end; + + +type + TTGAHeader = packed record + ImageID: Byte; + ColorMapType: Byte; + ImageType: Byte; + ColorMapSpec: Array[0..4] of Byte; + OrigX: Word; + OrigY: Word; + Width: Word; + Height: Word; + Bpp: Byte; + ImageDes: Byte; + end; + +const + TGA_UNCOMPRESSED_RGB = 2; + TGA_UNCOMPRESSED_GRAY = 3; + TGA_COMPRESSED_RGB = 10; + TGA_COMPRESSED_GRAY = 11; + + + +function TglBitmap.LoadTGA(Stream: TStream): Boolean; +var + Header: TTGAHeader; + NewImage, pData: PByte; + StreamPos: Int64; + PixelSize, LineSize, YStart, YEnd, YInc: Integer; + Format: TglBitmapInternalFormat; + +const + CACHE_SIZE = $4000; + + procedure ReadUncompressed; + var + RowSize: Integer; + begin + RowSize := Header.Width * PixelSize; + + // copy line by line + while YStart <> YEnd + YInc do begin + pData := NewImage; + Inc(pData, YStart * LineSize); + + Stream.Read(pData^, RowSize); + Inc(YStart, YInc); + end; + end; + + + procedure ReadCompressed; + var + HeaderWidth, HeaderHeight: Integer; + LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer; + + Cache: PByte; + CacheSize, CachePos: Integer; + + Temp: Byte; + TempBuf: Array [0..15] of Byte; + + PixelRepeat: Boolean; + PixelToRead, TempPixels: Integer; + + + procedure CheckLine; + begin + if LinePixelsRead >= HeaderWidth then begin + LinePixelsRead := 0; + pData := NewImage; + Inc(YStart, YInc); + Inc(pData, YStart * LineSize); + end; + end; + + + procedure CachedRead(var Buffer; Count: Integer); + var + BytesRead: Integer; + begin + if (CachePos + Count) > CacheSize then begin + BytesRead := 0; + + // Read Data + if CacheSize - CachePos > 0 then begin + BytesRead := CacheSize - CachePos; + + Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead); + Inc(CachePos, BytesRead); + end; + + // Reload Data + CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position); + Stream.Read(Cache^, CacheSize); + CachePos := 0; + + // Read else + if Count - BytesRead > 0 then begin + Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead); + Inc(CachePos, Count - BytesRead); + end; + end else begin + Move(pByteArray(Cache)^[CachePos], Buffer, Count); + Inc(CachePos, Count); + end; + end; + + + begin + CacheSize := 0; + CachePos := 0; + + HeaderWidth := Header.Width; + HeaderHeight := Header.Height; + + GetMem(Cache, CACHE_SIZE); // 16K Buffer + try + ImgPixelsToRead := HeaderWidth * HeaderHeight; + ImgPixelsRead := 0; + LinePixelsRead := 0; + + pData := NewImage; + Inc(pData, YStart * LineSize); + + // Read until all Pixels + repeat + CachedRead(Temp, 1); + + PixelRepeat := Temp and $80 > 0; + PixelToRead := (Temp and $7F) + 1; + + Inc(ImgPixelsRead, PixelToRead); + + if PixelRepeat then begin + // repeat one pixel x times + CachedRead(TempBuf[0], PixelSize); + + // repeat Pixel + while PixelToRead > 0 do begin + CheckLine; + + TempPixels := HeaderWidth - LinePixelsRead; + if PixelToRead < TempPixels then + TempPixels := PixelToRead; + + Inc(LinePixelsRead, TempPixels); + Dec(PixelToRead, TempPixels); + + while TempPixels > 0 do begin + case PixelSize of + 1: + begin + pData^ := TempBuf[0]; + Inc(pData); + end; + 2: + begin + pWord(pData)^ := pWord(@TempBuf[0])^; + Inc(pData, 2); + end; + 3: + begin + pWord(pData)^ := pWord(@TempBuf[0])^; + Inc(pData, 2); + pData^ := TempBuf[2]; + Inc(pData); + end; + 4: + begin + pDWord(pData)^ := pDWord(@TempBuf[0])^; + Inc(pData, 4); + end; + end; + + Dec(TempPixels); + end; + end; + end else begin + // copy x pixels + while PixelToRead > 0 do begin + CheckLine; + + TempPixels := HeaderWidth - LinePixelsRead; + if PixelToRead < TempPixels then + TempPixels := PixelToRead; + + CachedRead(pData^, PixelSize * TempPixels); + Inc(pData, PixelSize * TempPixels); + + Inc(LinePixelsRead, TempPixels); + + Dec(PixelToRead, TempPixels); + end; + end; + until ImgPixelsRead >= ImgPixelsToRead; + finally + FreeMem(Cache) + end; + end; + +begin + Result := False; + + // reading header to test file and set cursor back to begin + StreamPos := Stream.Position; + Stream.Read(Header, SizeOf(Header)); + + // no colormapped files + if (Header.ColorMapType = 0) then begin + if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin + case Header.Bpp of + 8: Format := ifAlpha; + 16: Format := ifLuminanceAlpha; + 24: Format := ifBGR8; + 32: Format := ifBGRA8; + else + raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.'); + end; + + // skip image ID + if Header.ImageID <> 0 then + Stream.Position := Stream.Position + Header.ImageID; + + PixelSize := Trunc(FormatGetSize(Format)); + LineSize := Trunc(Header.Width * PixelSize); + + GetMem(NewImage, LineSize * Header.Height); + try + // Row direction + if (Header.ImageDes and $20 > 0) then begin + YStart := 0; + YEnd := Header.Height -1; + YInc := 1; + end else begin + YStart := Header.Height -1; + YEnd := 0; + YInc := -1; + end; + + // Read Image + case Header.ImageType of + TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY: + ReadUncompressed; + TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY: + ReadCompressed; + end; + + SetDataPointer(NewImage, Format, Header.Width, Header.Height); + + Result := True; + except + FreeMem(NewImage); + raise; + end; + end + else Stream.Position := StreamPos; + end + else Stream.Position := StreamPos; +end; + + +{$ifdef GLB_SUPPORT_PNG_WRITE} +{$ifdef GLB_LIB_PNG} +procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; +begin + TStream(png_get_io_ptr(png)).Write(buffer^, size); +end; +{$endif} + +procedure TglBitmap.SavePNG(Stream: TStream); +{$ifdef GLB_LIB_PNG} +var + png: png_structp; + png_info: png_infop; + png_rows: array of pByte; + LineSize: Integer; + ColorType: Integer; + Row: Integer; +begin + if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if not init_libPNG then + raise Exception.Create('SavePNG - unable to initialize libPNG.'); + + try + case FInternalFormat of + ifAlpha, ifLuminance, ifDepth8: + ColorType := PNG_COLOR_TYPE_GRAY; + ifLuminanceAlpha: + ColorType := PNG_COLOR_TYPE_GRAY_ALPHA; + ifBGR8, ifRGB8: + ColorType := PNG_COLOR_TYPE_RGB; + ifBGRA8, ifRGBA8: + ColorType := PNG_COLOR_TYPE_RGBA; + else + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + + LineSize := Trunc(FormatGetSize(FInternalFormat) * Width); + + // creating array for scanline + SetLength(png_rows, Height); + try + for Row := 0 to Height - 1 do begin + png_rows[Row] := Data; + Inc(png_rows[Row], Row * LineSize) + end; + + // write struct + png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil); + if png = nil then + raise EglBitmapException.Create('SavePng - couldn''t create write struct.'); + + // create png info + png_info := png_create_info_struct(png); + if png_info = nil then begin + png_destroy_write_struct(@png, nil); + raise EglBitmapException.Create('SavePng - couldn''t create info struct.'); + end; + + // set read callback + png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil); + + // set compression + png_set_compression_level(png, 6); + + if InternalFormat in [ifBGR8, ifBGRA8] then + png_set_bgr(png); + + // setup header + png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + // write info + png_write_info(png, png_info); + + // write image data + png_write_image(png, @png_rows[0]); + + // write end + png_write_end(png, png_info); + + // destroy write struct + png_destroy_write_struct(@png, @png_info); + finally + SetLength(png_rows, 0); + end; + finally + quit_libPNG; + end; +end; +{$endif} +{$ifdef GLB_PNGIMAGE} +var + Png: TPNGObject; + + pSource, pDest: pByte; + X, Y, PixSize: Integer; + ColorType: Cardinal; + Alpha: Boolean; + + pTemp: pByte; + Temp: Byte; +begin + if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + + case FInternalFormat of + ifAlpha, ifLuminance, ifDepth8: + begin + ColorType := COLOR_GRAYSCALE; + PixSize := 1; + Alpha := False; + end; + ifLuminanceAlpha: + begin + ColorType := COLOR_GRAYSCALEALPHA; + PixSize := 1; + Alpha := True; + end; + ifBGR8, ifRGB8: + begin + ColorType := COLOR_RGB; + PixSize := 3; + Alpha := False; + end; + ifBGRA8, ifRGBA8: + begin + ColorType := COLOR_RGBALPHA; + PixSize := 3; + Alpha := True + end; + else + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + + Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height); + try + // Copy ImageData + pSource := Data; + for Y := 0 to Height -1 do begin + pDest := png.ScanLine[Y]; + + for X := 0 to Width -1 do begin + Move(pSource^, pDest^, PixSize); + + Inc(pDest, PixSize); + Inc(pSource, PixSize); + + if Alpha then begin + png.AlphaScanline[Y]^[X] := pSource^; + Inc(pSource); + end; + end; + + // convert RGB line to BGR + if InternalFormat in [ifRGB8, ifRGBA8] then begin + pTemp := png.ScanLine[Y]; + + for X := 0 to Width -1 do begin + Temp := pByteArray(pTemp)^[0]; + pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2]; + pByteArray(pTemp)^[2] := Temp; + + Inc(pTemp, 3); + end; + end; + end; + + // Save to Stream + Png.CompressionLevel := 6; + Png.SaveToStream(Stream); + finally + FreeAndNil(Png); + end; +end; +{$endif} +{$endif} + + +procedure TglBitmap.SaveDDS(Stream: TStream); +var + Header: TDDSHeader; + Pix: TglBitmapPixelData; +begin + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if InternalFormat = ifAlpha then + FormatPreparePixel(Pix, ifLuminance) + else + FormatPreparePixel(Pix, InternalFormat); + + // Generell + FillChar(Header, SizeOf(Header), 0); + + Header.dwMagic := DDS_MAGIC; + Header.dwSize := 124; + Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT; + + if Width > 0 then begin + Header.dwWidth := Width; + Header.dwFlags := Header.dwFlags or DDSD_WIDTH; + end; + + if Height > 0 then begin + Header.dwHeight := Height; + Header.dwFlags := Header.dwFlags or DDSD_HEIGHT; + end; + + Header.dwPitchOrLinearSize := fRowSize; + Header.dwMipMapCount := 1; + + // Caps + Header.Caps.dwCaps1 := DDSCAPS_TEXTURE; + + // Pixelformat + Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat); + Header.PixelFormat.dwFlags := DDPF_RGB; + + if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha) + then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS; + + Header.PixelFormat.dwRGBBitCount := Trunc(FormatGetSize(InternalFormat) * 8); + Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift; + Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift; + Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift; + Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift; + + // Write + Stream.Write(Header, SizeOf(Header)); + + Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat)); +end; + + +procedure TglBitmap.SaveTGA(Stream: TStream); +var + Header: TTGAHeader; + Size: Integer; + pTemp: pByte; + + + procedure ConvertData(pTemp: pByte); + var + Idx, PixelSize: Integer; + Temp: byte; + begin + PixelSize := fPixelSize; + + for Idx := 0 to Height * Width do begin + Temp := pByteArray(pTemp)^[2]; + pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0]; + pByteArray(pTemp)^[0] := Temp; + + Inc(pTemp, PixelSize); + end; + end; + + +begin + if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); + + FillChar(Header, SizeOf(Header), 0); + + case InternalFormat of + ifAlpha, ifLuminance, ifDepth8: + begin + Header.ImageType := TGA_UNCOMPRESSED_GRAY; + Header.Bpp := 8; + end; + ifLuminanceAlpha: + begin + Header.ImageType := TGA_UNCOMPRESSED_GRAY; + Header.Bpp := 16; + end; + ifRGB8, ifBGR8: + begin + Header.ImageType := TGA_UNCOMPRESSED_RGB; + Header.Bpp := 24; + end; + ifRGBA8, ifBGRA8: + begin + Header.ImageType := TGA_UNCOMPRESSED_RGB; + Header.Bpp := 32; + end; + else + raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + + Header.Width := Width; + Header.Height := Height; + Header.ImageDes := $20; + + if FormatHasAlpha(InternalFormat) then + Header.ImageDes := Header.ImageDes or $08; + + Stream.Write(Header, SizeOf(Header)); + + // convert RGB(A) to BGR(A) + Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat); + if InternalFormat in [ifRGB8, ifRGBA8] then begin + GetMem(pTemp, Size); + end else + pTemp := Data; + + try + // convert data + if InternalFormat in [ifRGB8, ifRGBA8] then begin + Move(Data^, pTemp^, Size); + ConvertData(pTemp); + end; + + // write data + Stream.Write(pTemp^, Size); + finally + // free tempdata + if InternalFormat in [ifRGB8, ifRGBA8] then + FreeMem(pTemp); + end; +end; + + +{$ifdef GLB_SUPPORT_JPEG_WRITE} +procedure TglBitmap.SaveJPEG(Stream: TStream); +{$ifdef GLB_LIB_JPEG} +var + jpeg: jpeg_compress_struct; + jpeg_err: jpeg_error_mgr; + Row: Integer; + pTemp, pTemp2: pByte; + + + procedure CopyRow(pDest, pSource: pByte); + var + X: Integer; + begin + for X := 0 to Width - 1 do begin + pByteArray(pDest)^[0] := pByteArray(pSource)^[2]; + pByteArray(pDest)^[1] := pByteArray(pSource)^[1]; + pByteArray(pDest)^[2] := pByteArray(pSource)^[0]; + + Inc(pDest, 3); + Inc(pSource, 3); + end; + end; + +begin + if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if not init_libJPEG then + raise Exception.Create('SaveJPG - unable to initialize libJPEG.'); + + try + FillChar(jpeg, SizeOf(jpeg_compress_struct), $00); + FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); + + // error managment + jpeg.err := jpeg_std_error(@jpeg_err); + jpeg_err.error_exit := glBitmap_libJPEG_error_exit; + jpeg_err.output_message := glBitmap_libJPEG_output_message; + + // compression struct + jpeg_create_compress(@jpeg); + + // allocation space for streaming methods + jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr)); + + // seeting up custom functions + with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin + pub.init_destination := glBitmap_libJPEG_init_destination; + pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer; + pub.term_destination := glBitmap_libJPEG_term_destination; + + pub.next_output_byte := @DestBuffer[1]; + pub.free_in_buffer := Length(DestBuffer); + + DestStream := Stream; + end; + + // very important state + jpeg.global_state := CSTATE_START; + + jpeg.image_width := Width; + jpeg.image_height := Height; + case InternalFormat of + ifAlpha, ifLuminance, ifDepth8: + begin + jpeg.input_components := 1; + jpeg.in_color_space := JCS_GRAYSCALE; + end; + ifRGB8, ifBGR8: + begin + jpeg.input_components := 3; + jpeg.in_color_space := JCS_RGB; + end; + end; + + // setting defaults + jpeg_set_defaults(@jpeg); + + // compression quality + jpeg_set_quality(@jpeg, 95, True); + + // start compression + jpeg_start_compress(@jpeg, true); + + // write rows + pTemp := Data; + + // initialing row + if InternalFormat = ifBGR8 then + GetMem(pTemp2, fRowSize) + else + pTemp2 := pTemp; + + try + for Row := 0 to jpeg.image_height -1 do begin + // prepare row + if InternalFormat = ifBGR8 then + CopyRow(pTemp2, pTemp) + else + pTemp2 := pTemp; + + // write row + jpeg_write_scanlines(@jpeg, @pTemp2, 1); + inc(pTemp, fRowSize); + end; + finally + // free memory + if InternalFormat = ifBGR8 then + FreeMem(pTemp2); + end; + + // finish compression + jpeg_finish_compress(@jpeg); + + // destroy compression + jpeg_destroy_compress(@jpeg); + finally + quit_libJPEG; + end; +end; +{$endif} +{$ifdef GLB_DELPHI_JPEG} +var + Bmp: TBitmap; + Jpg: TJPEGImage; +begin + if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + + Bmp := TBitmap.Create; + try + Jpg := TJPEGImage.Create; + try + AssignToBitmap(Bmp); + + if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin + Jpg.Grayscale := True; + Jpg.PixelFormat := jf8Bit; + end; + + Jpg.Assign(Bmp); + + Jpg.SaveToStream(Stream); + finally + FreeAndNil(Jpg); + end; + finally + FreeAndNil(Bmp); + end; +end; +{$endif} +{$endif} + + +procedure TglBitmap.SaveBMP(Stream: TStream); +var + Header: TBMPHeader; + Info: TBMPInfo; + pData, pTemp: pByte; + + PixelFormat: TglBitmapPixelData; + ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer; + Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; + + PaddingBuff: Cardinal; + + + function GetLineWidth : Integer; + begin + Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3; + end; + + +begin + if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); + + ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat)); + + Header.bfType := BMP_MAGIC; + Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; + Header.bfReserved1 := 0; + Header.bfReserved2 := 0; + Header.bfOffBits := SizeOf(Header) + SizeOf(Info); + + FillChar(Info, SizeOf(Info), 0); + Info.biSize := SizeOf(Info); + Info.biWidth := Width; + Info.biHeight := Height; + Info.biPlanes := 1; + Info.biCompression := BMP_COMP_RGB; + Info.biSizeImage := ImageSize; + case InternalFormat of + ifAlpha, ifLuminance, ifDepth8: + begin + Info.biBitCount := 8; + + Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); + + Info.biClrUsed := 256; + Info.biClrImportant := 256; + end; + ifLuminanceAlpha, ifRGBA4, ifR5G6B5, ifRGB5A1: + begin + Info.biBitCount := 16; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + ifBGR8, ifRGB8: + Info.biBitCount := 24; + ifBGRA8, ifRGBA8, ifRGB10A2: + begin + Info.biBitCount := 32; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + else + raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + Info.biXPelsPerMeter := 2835; + Info.biYPelsPerMeter := 2835; + + // prepare bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + Info.biSize := Info.biSize + 4 * SizeOf(Cardinal); + Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); + + FormatPreparePixel(PixelFormat, InternalFormat); + + with PixelFormat.PixelDesc do begin + RedMask := RedRange shl RedShift; + GreenMask := GreenRange shl GreenShift; + BlueMask := BlueRange shl BlueShift; + AlphaMask := AlphaRange shl AlphaShift; + end; + end; + + // headers + Stream.Write(Header, SizeOf(Header)); + Stream.Write(Info, SizeOf(Info)); + + // colortable + if Info.biBitCount = 8 then begin + Temp := 0; + for ColorIdx := Low(Byte) to High(Byte) do begin + Stream.Write(Temp, 4); + Temp := Temp + $00010101; + end; + end; + + // bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + Stream.Write(RedMask, SizeOf(Cardinal)); + Stream.Write(GreenMask, SizeOf(Cardinal)); + Stream.Write(BlueMask, SizeOf(Cardinal)); + Stream.Write(AlphaMask, SizeOf(Cardinal)); + end; + + // image data + LineSize := Trunc(Width * FormatGetSize(InternalFormat)); + Padding := GetLineWidth - LineSize; + PaddingBuff := 0; + + pData := Data; + Inc(pData, (Height -1) * LineSize); + + // prepare row buffer. But only for RGB because RGBA supports color masks + // so it's possible to change color within the image. + if InternalFormat = ifRGB8 then + GetMem(pTemp, fRowSize) + else + pTemp := nil; + + try + // write image data + for LineIdx := 0 to Height - 1 do begin + // preparing row + if InternalFormat = ifRGB8 then begin + Move(pData^, pTemp^, fRowSize); + SwapRGB(pTemp, Width, False); + end else + pTemp := pData; + + Stream.Write(pTemp^, LineSize); + + Dec(pData, LineSize); + + if Padding > 0 then + Stream.Write(PaddingBuff, Padding); + end; + finally + // destroy row buffer + if InternalFormat = ifRGB8 then + FreeMem(pTemp); + end; +end; + + +procedure TglBitmap.Bind(EnableTextureUnit: Boolean); +begin + if EnableTextureUnit then + glEnable(Target); + + if ID > 0 then + glBindTexture(Target, ID); +end; + + +procedure TglBitmap.Unbind(DisableTextureUnit: Boolean); +begin + if DisableTextureUnit then + glDisable(Target); + + glBindTexture(Target, 0); +end; + + +procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition; + var Pixel: TglBitmapPixelData); +begin + if Assigned (fGetPixelFunc) then + fGetPixelFunc(Pos, Pixel); +end; + + +procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition; + const Pixel: TglBitmapPixelData); +begin + if Assigned (fSetPixelFunc) then + fSetPixelFunc(Pos, Pixel); +end; + + +procedure TglBitmap.CreateID; +begin + // Generate Texture + if ID <> 0 then + glDeleteTextures(1, @ID); + + glGenTextures(1, @ID); + + Bind(False); +end; + + +procedure TglBitmap.SetupParameters(var BuildWithGlu: Boolean); +begin + // Set up parameters + SetWrap(fWrapS, fWrapT, fWrapR); + SetFilter(fFilterMin, fFilterMag); + SetAnisotropic(fAnisotropic); + SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]); + + // Mip Maps generation Mode + BuildWithGlu := False; + + if (MipMap = mmMipmap) then begin + if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then + glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE) + else + BuildWithGlu := True; + end else + if (MipMap = mmMipmapGlu) then + BuildWithGlu := True; +end; + + +procedure TglBitmap.SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True); + + procedure Check12; + begin + if not GL_VERSION_1_2 then + raise EglBitmapUnsupportedInternalFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.'); + end; + +begin + glType := GL_UNSIGNED_BYTE; + + // selecting Format + case DataFormat of + ifAlpha: + glFormat := GL_ALPHA; + ifLuminance: + glFormat := GL_LUMINANCE; + ifDepth8: + glFormat := GL_DEPTH_COMPONENT; + ifLuminanceAlpha: + glFormat := GL_LUMINANCE_ALPHA; + ifBGR8: + begin + if (GL_VERSION_1_2 or GL_EXT_bgra) then begin + glFormat := GL_BGR; + end else begin + if CanConvertImage then + ConvertTo(ifRGB8); + glFormat := GL_RGB; + end; + end; + ifBGRA8: + begin + if (GL_VERSION_1_2 or GL_EXT_bgra) then begin + glFormat := GL_BGRA; + end else begin + if CanConvertImage then + ConvertTo(ifRGBA8); + glFormat := GL_RGBA; + end; + end; + ifRGB8: + glFormat := GL_RGB; + ifRGBA8: + glFormat := GL_RGBA; + ifRGBA4: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_SHORT_4_4_4_4_REV; + end; + ifRGB5A1: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_SHORT_1_5_5_5_REV; + end; + ifRGB10A2: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_INT_2_10_10_10_REV; + end; + ifR5G6B5: + begin + Check12; + glFormat := GL_RGB; + glType := GL_UNSIGNED_SHORT_5_6_5; + end; + else + glFormat := 0; + end; + + // Selecting InternalFormat + case DataFormat of + ifDXT1, ifDXT3, ifDXT5: + begin + if GL_EXT_texture_compression_s3tc then begin + case DataFormat of + ifDXT1: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + ifDXT3: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + ifDXT5: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + end; + end else begin + // Compression isn't supported so convert to RGBA + if CanConvertImage then + ConvertTo(ifRGBA8); + glFormat := GL_RGBA; + glInternalFormat := GL_RGBA8; + end; + end; + ifAlpha: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_ALPHA4; + tf8BitsPerChanel: + glInternalFormat := GL_ALPHA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_ALPHA + else + glInternalFormat := GL_ALPHA; + end; + else + glInternalFormat := GL_ALPHA; + end; + end; + ifLuminance: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_LUMINANCE4; + tf8BitsPerChanel: + glInternalFormat := GL_LUMINANCE8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_LUMINANCE + else + glInternalFormat := GL_LUMINANCE; + end; + else + glInternalFormat := GL_LUMINANCE; + end; + end; + ifDepth8: + begin + glInternalFormat := GL_DEPTH_COMPONENT; + end; + ifLuminanceAlpha: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_LUMINANCE4_ALPHA4; + tf8BitsPerChanel: + glInternalFormat := GL_LUMINANCE8_ALPHA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA + else + glInternalFormat := GL_LUMINANCE_ALPHA; + end; + else + glInternalFormat := GL_LUMINANCE_ALPHA; + end; + end; + ifBGR8, ifRGB8: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_RGB4; + tf8BitsPerChanel: + glInternalFormat := GL_RGB8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin + glInternalFormat := GL_COMPRESSED_RGB + end else begin + if (GL_EXT_texture_compression_s3tc) then + glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT + else + glInternalFormat := GL_RGB; + end; + end; + else + glInternalFormat := GL_RGB; + end; + end; + ifBGRA8, ifRGBA8, ifRGBA4, ifRGB5A1, ifRGB10A2, ifR5G6B5: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_RGBA4; + tf8BitsPerChanel: + glInternalFormat := GL_RGBA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin + glInternalFormat := GL_COMPRESSED_RGBA + end else begin + if (GL_EXT_texture_compression_s3tc) then + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + else + glInternalFormat := GL_RGBA; + end; + end; + else + glInternalFormat := GL_RGBA; + end; + end; + end; +end; + + +function TglBitmap.FlipHorz: Boolean; +begin + Result := False; +end; + + +function TglBitmap.FlipVert: Boolean; +begin + Result := False; +end; + + +procedure TglBitmap.FreeData; +begin + SetDataPointer(nil, ifEmpty); +end; + + +procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec); +type + PglBitmapPixelData = ^TglBitmapPixelData; +begin + with FuncRec do begin + Dest.Red := PglBitmapPixelData(CustomData)^.Red; + Dest.Green := PglBitmapPixelData(CustomData)^.Green; + Dest.Blue := PglBitmapPixelData(CustomData)^.Blue; + Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha; + end; +end; + + +procedure TglBitmap.FillWithColor(Red, Green, Blue, Alpha: Byte); +begin + FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF); +end; + + +procedure TglBitmap.FillWithColorFloat(Red, Green, Blue, Alpha: Single); +var + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, InternalFormat); + + PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * Red))); + PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green))); + PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * Blue))); + PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha))); + + AddFunc(glBitmapFillWithColorFunc, False, @PixelData); +end; + + +procedure TglBitmap.FillWithColorRange(Red, Green, Blue, Alpha: Cardinal); +var + PixelData: TglBitmapPixelData; +begin + FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + + FillWithColorFloat( + Red / PixelData.PixelDesc.RedRange, + Green / PixelData.PixelDesc.GreenRange, + Blue / PixelData.PixelDesc.BlueRange, + Alpha / PixelData.PixelDesc.AlphaRange); +end; + + +procedure TglBitmap.SetAnisotropic(const Value: Integer); +var + MaxAniso: Integer; +begin + fAnisotropic := Value; + + if (ID > 0) then begin + if GL_EXT_texture_filter_anisotropic then begin + if fAnisotropic > 0 then begin + Bind(False); + + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAniso); + + if Value > MaxAniso then + fAnisotropic := MaxAniso; + + glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic); + end; + end else begin + fAnisotropic := 0; + end; + end; +end; + + +procedure TglBitmap.SetInternalFormat(const Value: TglBitmapInternalFormat); +begin + if InternalFormat <> Value then begin + if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT); + + // Update whatever + SetDataPointer(Data, Value); + end; +end; + + +function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean; + CustomData: Pointer): boolean; +begin + Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData); +end; + + +function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction; + CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer): boolean; +var + pDest, NewImage, pSource: pByte; + TempHeight, TempWidth: Integer; + MapFunc: TglBitmapMapFunc; + UnMapFunc: TglBitmapUnMapFunc; + + FuncRec: TglBitmapFunctionRec; +begin + Assert(Assigned(Data)); + Assert(Assigned(Source)); + Assert(Assigned(Source.Data)); + + Result := False; + + if Assigned (Source.Data) and FormatIsUncompressed(Format) and + ((Source.Height > 0) or (Source.Width > 0)) then begin + + // inkompatible Formats so CreateTemp + if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then + CreateTemp := True; + + // Values + TempHeight := Max(1, Source.Height); + TempWidth := Max(1, Source.Width); + + FuncRec.Sender := Self; + FuncRec.CustomData := CustomData; + + NewImage := nil; + + if CreateTemp then begin + GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth)); + pDest := NewImage; + end + else pDest := Data; + + try + // Mapping + MapFunc := FormatGetMapFunc(Format); + FormatPreparePixel(FuncRec.Dest, Format); + FormatPreparePixel(FuncRec.Source, Source.InternalFormat); + + FuncRec.Size := Source.Dimension; + FuncRec.Position.Fields := FuncRec.Size.Fields; + + if FormatIsUncompressed(Source.InternalFormat) then begin + // Uncompressed Images + pSource := Source.Data; + UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat); + + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + // Get Data + UnMapFunc(pSource, FuncRec.Source); + // Func + Func(FuncRec); + // Set Data + MapFunc(FuncRec.Dest, pDest); + Inc(FuncRec.Position.X); + end; + Inc(FuncRec.Position.Y); + end; + end else begin + // Compressed Images + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + // Get Data + fGetPixelFunc(FuncRec.Position, FuncRec.Source); + // Func + Func(FuncRec); + // Set Data + MapFunc(FuncRec.Dest, pDest); + Inc(FuncRec.Position.X); + end; + Inc(FuncRec.Position.Y); + end; + end; + + // Updating Image or InternalFormat + if CreateTemp then + SetDataPointer(NewImage, Format) + else + + if Format <> InternalFormat then + SetInternalFormat(Format); + + Result := True; + except + if CreateTemp + then FreeMem(NewImage); + raise; + end; + end; +end; + + +procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do begin + if Source.PixelDesc.RedRange > 0 then + Dest.Red := Source.Red; + + if Source.PixelDesc.GreenRange > 0 then + Dest.Green := Source.Green; + + if Source.PixelDesc.BlueRange > 0 then + Dest.Blue := Source.Blue; + + if Source.PixelDesc.AlphaRange > 0 then + Dest.Alpha := Source.Alpha; + end; +end; + + +procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do begin + if Source.PixelDesc.RedRange > 0 then + Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange); + + if Source.PixelDesc.GreenRange > 0 then + Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange); + + if Source.PixelDesc.BlueRange > 0 then + Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange); + + if Source.PixelDesc.AlphaRange > 0 then + Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange); + end; +end; + + +procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do + with TglBitmapPixelDesc(CustomData^) do begin + if Source.PixelDesc.RedRange > 0 then + Dest.Red := Source.Red shr RedShift; + + if Source.PixelDesc.GreenRange > 0 then + Dest.Green := Source.Green shr GreenShift; + + if Source.PixelDesc.BlueRange > 0 then + Dest.Blue := Source.Blue shr BlueShift; + + if Source.PixelDesc.AlphaRange > 0 then + Dest.Alpha := Source.Alpha shr AlphaShift; + end; +end; + + +function TglBitmap.ConvertTo(NewFormat: TglBitmapInternalFormat): boolean; +var + Source, Dest: TglBitmapPixelData; + PixelDesc: TglBitmapPixelDesc; + + function CopyDirect: Boolean; + begin + Result := + ((Source.PixelDesc.RedRange = Dest.PixelDesc.RedRange) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and + ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and + ((Source.PixelDesc.BlueRange = Dest.PixelDesc.BlueRange) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and + ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0)); + end; + + function CanShift: Boolean; + begin + Result := + ((Source.PixelDesc.RedRange >= Dest.PixelDesc.RedRange ) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and + ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and + ((Source.PixelDesc.BlueRange >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and + ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0)); + end; + + function GetShift(Source, Dest: Cardinal) : ShortInt; + begin + Result := 0; + + while (Source > Dest) and (Source > 0) do begin + Inc(Result); + Source := Source shr 1; + end; + end; + +begin + if NewFormat <> InternalFormat then begin + FormatPreparePixel(Source, InternalFormat); + FormatPreparePixel(Dest, NewFormat); + + if CopyDirect then + Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat) + else + if CanShift then begin + PixelDesc.RedShift := GetShift(Source.PixelDesc.RedRange, Dest.PixelDesc.RedRange); + PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange); + PixelDesc.BlueShift := GetShift(Source.PixelDesc.BlueRange, Dest.PixelDesc.BlueRange); + PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange); + + Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc); + end + else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat); + end + else Result := True; +end; + + +function TglBitmap.RemoveAlpha: Boolean; +begin + Result := False; + + if (Assigned(Data)) then begin + if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT); + + Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat)); + end; +end; + + +function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean; +begin + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); + + Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData); +end; + + +function TglBitmap.GetHeight: Integer; +begin + if ffY in fDimension.Fields then + Result := fDimension.Y + else + Result := -1; +end; + + +function TglBitmap.GetWidth: Integer; +begin + if ffX in fDimension.Fields then + Result := fDimension.X + else + Result := -1; +end; + + +function TglBitmap.GetFileHeight: Integer; +begin + Result := Max(1, Height); +end; + + +function TglBitmap.GetFileWidth: Integer; +begin + Result := Max(1, Width); +end; + + +procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec); +var + Temp: Single; +begin + with FuncRec do begin + Temp := + Source.Red / Source.PixelDesc.RedRange * 0.3 + + Source.Green / Source.PixelDesc.GreenRange * 0.59 + + Source.Blue / Source.PixelDesc.BlueRange * 0.11; + + Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp); + end; +end; + + +function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean; +var + pDest, pDest2, pSource: pByte; + TempHeight, TempWidth: Integer; + MapFunc: TglBitmapMapFunc; + DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc; + + FuncRec: TglBitmapFunctionRec; +begin + Result := False; + + assert(Assigned(Data)); + assert(Assigned(glBitmap)); + assert(Assigned(glBitmap.Data)); + + if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin + // Convert to Data with Alpha + Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat))); + + if not Assigned(Func) then + Func := glBitmapAlphaFunc; + + // Values + TempHeight := glBitmap.FileHeight; + TempWidth := glBitmap.FileWidth; + + FuncRec.Sender := Self; + FuncRec.CustomData := CustomData; + + pDest := Data; + pDest2 := Data; + pSource := glBitmap.Data; + + // Mapping + FormatPreparePixel(FuncRec.Dest, InternalFormat); + FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat); + MapFunc := FormatGetMapFunc(InternalFormat); + DestUnMapFunc := FormatGetUnMapFunc(InternalFormat); + UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat); + + FuncRec.Size := Dimension; + FuncRec.Position.Fields := FuncRec.Size.Fields; + + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + // Get Data + UnMapFunc(pSource, FuncRec.Source); + DestUnMapFunc(pDest2, FuncRec.Dest); + // Func + Func(FuncRec); + // Set Data + MapFunc(FuncRec.Dest, pDest); + Inc(FuncRec.Position.X); + end; + Inc(FuncRec.Position.Y); + end; + end; +end; + + +procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single); +begin + fBorderColor[0] := Red; + fBorderColor[1] := Green; + fBorderColor[2] := Blue; + fBorderColor[3] := Alpha; + + if ID > 0 then begin + Bind (False); + + glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]); + end; +end; + + +{ TglBitmap2D } + +procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer); +var + Idx, LineWidth: Integer; +begin + inherited; + + // Format + if FormatIsUncompressed(Format) then begin + fUnmapFunc := FormatGetUnMapFunc(Format); + fGetPixelFunc := GetPixel2DUnmap; + + fMapFunc := FormatGetMapFunc(Format); + fSetPixelFunc := SetPixel2DUnmap; + + // Assigning Data + if Assigned(Data) then begin + SetLength(fLines, GetHeight); + + LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat)); + + for Idx := 0 to GetHeight -1 do begin + fLines[Idx] := Data; + Inc(fLines[Idx], Idx * LineWidth); + end; + end + else SetLength(fLines, 0); + end else begin + SetLength(fLines, 0); + + fSetPixelFunc := nil; + + case Format of + ifDXT1: + fGetPixelFunc := GetPixel2DDXT1; + ifDXT3: + fGetPixelFunc := GetPixel2DDXT3; + ifDXT5: + fGetPixelFunc := GetPixel2DDXT5; + else + fGetPixelFunc := nil; + end; + end; +end; + + +procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData); +type + PDXT1Chunk = ^TDXT1Chunk; + TDXT1Chunk = packed record + Color1: WORD; + Color2: WORD; + Pixels: array [0..3] of byte; + end; + +var + BasePtr: pDXT1Chunk; + PixPos: Integer; + Colors: array [0..3] of TRGBQuad; +begin + BasePtr := pDXT1Chunk(pData); + + PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3; + + if PixPos in [0, 2, 3] then begin + Colors[0].rgbRed := BasePtr^.Color1 and $F800 shr 8; + Colors[0].rgbGreen := BasePtr^.Color1 and $07E0 shr 3; + Colors[0].rgbBlue := BasePtr^.Color1 and $001F shl 3; + Colors[0].rgbReserved := 255; + end; + + if PixPos in [1, 2, 3] then begin + Colors[1].rgbRed := BasePtr^.Color2 and $F800 shr 8; + Colors[1].rgbGreen := BasePtr^.Color2 and $07E0 shr 3; + Colors[1].rgbBlue := BasePtr^.Color2 and $001F shl 3; + Colors[1].rgbReserved := 255; + end; + + if PixPos = 2 then begin + Colors[2].rgbRed := (Colors[0].rgbRed * 67 + Colors[1].rgbRed * 33) div 100; + Colors[2].rgbGreen := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100; + Colors[2].rgbBlue := (Colors[0].rgbBlue * 67 + Colors[1].rgbBlue * 33) div 100; + Colors[2].rgbReserved := 255; + end; + + if PixPos = 3 then begin + Colors[3].rgbRed := (Colors[0].rgbRed * 33 + Colors[1].rgbRed * 67) div 100; + Colors[3].rgbGreen := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100; + Colors[3].rgbBlue := (Colors[0].rgbBlue * 33 + Colors[1].rgbBlue * 67) div 100; + if BasePtr^.Color1 > BasePtr^.Color2 then + Colors[3].rgbReserved := 255 + else + Colors[3].rgbReserved := 0; + end; + + Pixel.Red := Colors[PixPos].rgbRed; + Pixel.Green := Colors[PixPos].rgbGreen; + Pixel.Blue := Colors[PixPos].rgbBlue; + Pixel.Alpha := Colors[PixPos].rgbReserved; +end; + + +procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); +var + BasePtr: pByte; + PosX, PosY: Integer; +begin + inherited; + + if (Pos.Y <= Height) and (Pos.X <= Width) then begin + PosX := Pos.X div 4; + PosY := Pos.Y div 4; + + BasePtr := Data; + Inc(BasePtr, (PosY * Width div 4 + PosX) * 8); + + GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel); + end; +end; + + +procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); +type + PDXT3AlphaChunk = ^TDXT3AlphaChunk; + TDXT3AlphaChunk = array [0..3] of WORD; + +var + ColorPtr: pByte; + AlphaPtr: PDXT3AlphaChunk; + PosX, PosY, relX, relY: Integer; +begin + inherited; + + if (Pos.Y <= Height) and (Pos.X <= Width) then begin + PosX := Pos.X div 4; + PosY := Pos.Y div 4; + relX := Pos.X - PosX * 4; + relY := Pos.Y - PosY * 4; + + // get color value + AlphaPtr := PDXT3AlphaChunk(Data); + Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2); + + ColorPtr := pByte(AlphaPtr); + Inc(ColorPtr, 8); + + GetDXTColorBlock(ColorPtr, relX, relY, Pixel); + + // extracting alpha + Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4; + end; +end; + + +procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); +var + ColorPtr: pByte; + AlphaPtr: PInt64; + PixPos, PosX, PosY, relX, relY: Integer; + Alpha0, Alpha1: Byte; +begin + inherited; + + if (Pos.Y <= Height) and (Pos.X <= Width) then begin + PosX := Pos.X div 4; + PosY := Pos.Y div 4; + relX := Pos.X - PosX * 4; + relY := Pos.Y - PosY * 4; + + // get color value + AlphaPtr := PInt64(Data); + Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2); + + ColorPtr := pByte(AlphaPtr); + Inc(ColorPtr, 8); + + GetDXTColorBlock(ColorPtr, relX, relY, Pixel); + + // extracting alpha + Alpha0 := AlphaPtr^ and $FF; + Alpha1 := AlphaPtr^ shr 8 and $FF; + + PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07; + + // use alpha 0 + if PixPos = 0 then begin + Pixel.Alpha := Alpha0; + end else + + // use alpha 1 + if PixPos = 1 then begin + Pixel.Alpha := Alpha1; + end else + + // alpha interpolate 7 Steps + if Alpha0 > Alpha1 then begin + Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7; + end else + + // alpha is 100% transparent or not transparent + if PixPos >= 6 then begin + if PixPos = 6 then + Pixel.Alpha := 0 + else + Pixel.Alpha := 255; + end else + + // alpha interpolate 5 Steps + begin + Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5; + end; + end; +end; + + +procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); +var + pTemp: pByte; +begin + pTemp := fLines[Pos.Y]; + Inc(pTemp, Pos.X * fPixelSize); + + fUnmapFunc(pTemp, Pixel); +end; + + +procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); +var + pTemp: pByte; +begin + pTemp := fLines[Pos.Y]; + Inc(pTemp, Pos.X * fPixelSize); + + fMapFunc(Pixel, pTemp); +end; + + +function TglBitmap2D.FlipHorz: Boolean; +var + Col, Row: Integer; + pTempDest, pDest, pSource: pByte; + ImgSize: Integer; +begin + Result := Inherited FlipHorz; + + if Assigned(Data) then begin + pSource := Data; + ImgSize := Height * fRowSize; + + GetMem(pDest, ImgSize); + try + pTempDest := pDest; + + Dec(pTempDest, fRowSize + fPixelSize); + for Row := 0 to Height -1 do begin + Inc(pTempDest, fRowSize * 2); + for Col := 0 to Width -1 do begin + Move(pSource^, pTempDest^, fPixelSize); + + Inc(pSource, fPixelSize); + Dec(pTempDest, fPixelSize); + end; + end; + + SetDataPointer(pDest, InternalFormat); + + Result := True; + except + FreeMem(pDest); + raise; + end; + end; +end; + + +function TglBitmap2D.FlipVert: Boolean; +var + Row: Integer; + pTempDest, pDest, pSource: pByte; +begin + Result := Inherited FlipVert; + + if Assigned(Data) then begin + pSource := Data; + GetMem(pDest, Height * fRowSize); + try + pTempDest := pDest; + + Inc(pTempDest, Width * (Height -1) * fPixelSize); + + for Row := 0 to Height -1 do begin + Move(pSource^, pTempDest^, fRowSize); + + Dec(pTempDest, fRowSize); + Inc(pSource, fRowSize); + end; + + SetDataPointer(pDest, InternalFormat); + + Result := True; + except + FreeMem(pDest); + raise; + end; + end; +end; + + +procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); +begin + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + // Upload data + if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then + glCompressedTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Trunc(Width * Height * FormatGetSize(Self.InternalFormat)), Data) + else + + if BuildWithGlu then + gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data) + else + glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data); + + // Freigeben + if (FreeDataAfterGenTexture) then + FreeData; +end; + + +procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean); +var + BuildWithGlu, PotTex, TexRec: Boolean; + glFormat, glInternalFormat, glType: Cardinal; + TexSize: Integer; +begin + if Assigned(Data) then begin + // Check Texture Size + if (TestTextureSize) then begin + glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); + + if ((Height > TexSize) or (Width > TexSize)) then + raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); + + PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width); + TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and + (Target = GL_TEXTURE_RECTANGLE_ARB); + + if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then + raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); + end; + + CreateId; + + SetupParameters(BuildWithGlu); + SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); + + UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu); + + // Infos sammeln + glAreTexturesResident(1, @ID, @fIsResident); + end; +end; + + +procedure TglBitmap2D.AfterConstruction; +begin + inherited; + + Target := GL_TEXTURE_2D; +end; + + +type + TMatrixItem = record + X, Y: Integer; + W: Single; + end; + + PglBitmapToNormalMapRec = ^TglBitmapToNormalMapRec; + TglBitmapToNormalMapRec = Record + Scale: Single; + Heights: array of Single; + MatrixU : array of TMatrixItem; + MatrixV : array of TMatrixItem; + end; + +const + oneover255 = 1 / 255; + +procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec); +var + Val: Single; +begin + with FuncRec do begin + Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11; + PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255; + end; +end; + + +procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec); +begin + with FuncRec do + PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255; +end; + + +procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec); +type + TVec = Array[0..2] of Single; +var + Idx: Integer; + du, dv: Double; + Len: Single; + Vec: TVec; + + function GetHeight(X, Y: Integer): Single; + begin + with FuncRec do begin + X := Max(0, Min(Size.X -1, X)); + Y := Max(0, Min(Size.Y -1, Y)); + + Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X]; + end; + end; + +begin + with FuncRec do begin + with PglBitmapToNormalMapRec (CustomData)^ do begin + du := 0; + for Idx := Low(MatrixU) to High(MatrixU) do + du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W; + + dv := 0; + for Idx := Low(MatrixU) to High(MatrixU) do + dv := dv + GetHeight(Position.X + MatrixV[Idx].X, Position.Y + MatrixV[Idx].Y) * MatrixV[Idx].W; + + Vec[0] := -du * Scale; + Vec[1] := -dv * Scale; + Vec[2] := 1; + end; + + // Normalize + Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2])); + if Len <> 0 then begin + Vec[0] := Vec[0] * Len; + Vec[1] := Vec[1] * Len; + Vec[2] := Vec[2] * Len; + end; + + // Farbe zuweisem + Dest.Red := Trunc((Vec[0] + 1) * 127.5); + Dest.Green := Trunc((Vec[1] + 1) * 127.5); + Dest.Blue := Trunc((Vec[2] + 1) * 127.5); + end; +end; + + +procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean); +var + Rec: TglBitmapToNormalMapRec; + + procedure SetEntry (var Matrix: array of TMatrixItem; Index, X, Y: Integer; W: Single); + begin + if (Index >= Low(Matrix)) and (Index <= High(Matrix)) then begin + Matrix[Index].X := X; + Matrix[Index].Y := Y; + Matrix[Index].W := W; + end; + end; + +begin + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if Scale > 100 then + Rec.Scale := 100 + else + if Scale < -100 then + Rec.Scale := -100 + else + Rec.Scale := Scale; + + SetLength(Rec.Heights, Width * Height); + try + case Func of + nm4Samples: + begin + SetLength(Rec.MatrixU, 2); + SetEntry(Rec.MatrixU, 0, -1, 0, -0.5); + SetEntry(Rec.MatrixU, 1, 1, 0, 0.5); + + SetLength(Rec.MatrixV, 2); + SetEntry(Rec.MatrixV, 0, 0, 1, 0.5); + SetEntry(Rec.MatrixV, 1, 0, -1, -0.5); + end; + nmSobel: + begin + SetLength(Rec.MatrixU, 6); + SetEntry(Rec.MatrixU, 0, -1, 1, -1.0); + SetEntry(Rec.MatrixU, 1, -1, 0, -2.0); + SetEntry(Rec.MatrixU, 2, -1, -1, -1.0); + SetEntry(Rec.MatrixU, 3, 1, 1, 1.0); + SetEntry(Rec.MatrixU, 4, 1, 0, 2.0); + SetEntry(Rec.MatrixU, 5, 1, -1, 1.0); + + SetLength(Rec.MatrixV, 6); + SetEntry(Rec.MatrixV, 0, -1, 1, 1.0); + SetEntry(Rec.MatrixV, 1, 0, 1, 2.0); + SetEntry(Rec.MatrixV, 2, 1, 1, 1.0); + SetEntry(Rec.MatrixV, 3, -1, -1, -1.0); + SetEntry(Rec.MatrixV, 4, 0, -1, -2.0); + SetEntry(Rec.MatrixV, 5, 1, -1, -1.0); + end; + nm3x3: + begin + SetLength(Rec.MatrixU, 6); + SetEntry(Rec.MatrixU, 0, -1, 1, -1/6); + SetEntry(Rec.MatrixU, 1, -1, 0, -1/6); + SetEntry(Rec.MatrixU, 2, -1, -1, -1/6); + SetEntry(Rec.MatrixU, 3, 1, 1, 1/6); + SetEntry(Rec.MatrixU, 4, 1, 0, 1/6); + SetEntry(Rec.MatrixU, 5, 1, -1, 1/6); + + SetLength(Rec.MatrixV, 6); + SetEntry(Rec.MatrixV, 0, -1, 1, 1/6); + SetEntry(Rec.MatrixV, 1, 0, 1, 1/6); + SetEntry(Rec.MatrixV, 2, 1, 1, 1/6); + SetEntry(Rec.MatrixV, 3, -1, -1, -1/6); + SetEntry(Rec.MatrixV, 4, 0, -1, -1/6); + SetEntry(Rec.MatrixV, 5, 1, -1, -1/6); + end; + nm5x5: + begin + SetLength(Rec.MatrixU, 20); + SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16); + SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10); + SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10); + SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16); + SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10); + SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8); + SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8); + SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10); + SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8); + SetEntry(Rec.MatrixU, 9, -1, 0, -0.5); + SetEntry(Rec.MatrixU, 10, 1, 0, 0.5); + SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8); + SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10); + SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8); + SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8); + SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10); + SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16); + SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10); + SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10); + SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16); + + SetLength(Rec.MatrixV, 20); + SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16); + SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10); + SetEntry(Rec.MatrixV, 2, 0, 2, 0.25); + SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10); + SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16); + SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10); + SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8); + SetEntry(Rec.MatrixV, 7, 0, 1, 0.5); + SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8); + SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16); + SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16); + SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8); + SetEntry(Rec.MatrixV, 12, 0, -1, -0.5); + SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8); + SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10); + SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16); + SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10); + SetEntry(Rec.MatrixV, 17, 0, -2, -0.25); + SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10); + SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16); + end; + end; + + // Daten Sammeln + if UseAlpha and FormatHasAlpha(InternalFormat) then + AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec) + else + AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec); + + // Neues Bild berechnen + AddFunc(glBitmapToNormalMapFunc, False, @Rec); + finally + SetLength(Rec.Heights, 0); + end; +end; + + +procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat); +var + Temp: pByte; + Size: Integer; + glFormat, glInternalFormat, glType: Cardinal; +begin + if not FormatIsUncompressed(Format) then + raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT); + + // Only to select Formats + SelectFormat(Format, glFormat, glInternalFormat, glType, False); + + Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format); + GetMem(Temp, Size); + try + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp); + + // Set Data + SetDataPointer(Temp, Format, Right - Left, Bottom - Top); + + // Flip + FlipVert; + except + FreeMem(Temp); + raise; + end; +end; + + +procedure TglBitmap2D.GetDataFromTexture; +var + Temp: pByte; + TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer; + TempType, TempIntFormat: Cardinal; + IntFormat: TglBitmapInternalFormat; +begin + Bind; + + // Request Data + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); + + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize); + + // Get glBitmapInternalFormat from TempIntFormat + TempType := GL_UNSIGNED_BYTE; + case TempIntFormat of + GL_ALPHA: + IntFormat := ifAlpha; + GL_LUMINANCE: + IntFormat := ifLuminance; + GL_LUMINANCE_ALPHA: + IntFormat := ifLuminanceAlpha; + GL_RGB4: + begin + IntFormat := ifR5G6B5; + TempIntFormat := GL_RGB; + TempType := GL_UNSIGNED_SHORT_5_6_5; + end; + GL_RGB, GL_RGB8: + IntFormat := ifRGB8; + GL_RGBA, GL_RGBA4, GL_RGBA8: + begin + if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin + IntFormat := ifRGBA4; + TempIntFormat := GL_BGRA; + TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV; + end else + if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin + IntFormat := ifRGB5A1; + TempIntFormat := GL_BGRA; + TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV; + end else begin + IntFormat := ifRGBA8; + end; + end; + GL_BGR: + IntFormat := ifBGR8; + GL_BGRA: + IntFormat := ifBGRA8; + GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + IntFormat := ifDXT1; + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + IntFormat := ifDXT1; + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + IntFormat := ifDXT3; + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + IntFormat := ifDXT5; + else + IntFormat := ifEmpty; + end; + + // Getting data from OpenGL + GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat)); + try + if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then + glGetCompressedTexImage(Target, 0, Temp) + else + glGetTexImage(Target, 0, TempIntFormat, TempType, Temp); + + SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); + except + FreeMem(Temp); + raise; + end; +end; + + +function TglBitmap2D.GetScanline(Index: Integer): Pointer; +begin + if (Index >= Low(fLines)) and (Index <= High(fLines)) then + Result := fLines[Index] + else + Result := nil; +end; + + +{ TglBitmap1D } + +procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer); +var + pTemp: pByte; + Size: Integer; +begin + if Height > 1 then begin + // extract first line of the data + Size := FormatGetImageSize(glBitmapPosition(Width), Format); + GetMem(pTemp, Size); + + Move(Data^, pTemp^, Size); + + FreeMem(Data); + end else + pTemp := Data; + + // set data pointer + inherited SetDataPointer(pTemp, Format, Width); + + if FormatIsUncompressed(Format) then begin + fUnmapFunc := FormatGetUnMapFunc(Format); + fGetPixelFunc := GetPixel1DUnmap; + end; +end; + + +procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); +var + pTemp: pByte; +begin + pTemp := Data; + Inc(pTemp, Pos.X * fPixelSize); + + fUnmapFunc(pTemp, Pixel); +end; + + +function TglBitmap1D.FlipHorz: Boolean; +var + Col: Integer; + pTempDest, pDest, pSource: pByte; +begin + Result := Inherited FlipHorz; + + if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin + pSource := Data; + + GetMem(pDest, fRowSize); + try + pTempDest := pDest; + + Inc(pTempDest, fRowSize); + for Col := 0 to Width -1 do begin + Move(pSource^, pTempDest^, fPixelSize); + + Inc(pSource, fPixelSize); + Dec(pTempDest, fPixelSize); + end; + + SetDataPointer(pDest, InternalFormat); + + Result := True; + finally + FreeMem(pDest); + end; + end; +end; + + +procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); +begin + // Upload data + if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then + glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data) + else + + // Upload data + if BuildWithGlu then + gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data) + else + glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data); + + // Freigeben + if (FreeDataAfterGenTexture) then + FreeData; +end; + + +procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean); +var + BuildWithGlu, TexRec: Boolean; + glFormat, glInternalFormat, glType: Cardinal; + TexSize: Integer; +begin + if Assigned(Data) then begin + // Check Texture Size + if (TestTextureSize) then begin + glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); + + if (Width > TexSize) then + raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); + + TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and + (Target = GL_TEXTURE_RECTANGLE_ARB); + + if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then + raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.'); + end; + + CreateId; + + SetupParameters(BuildWithGlu); + SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); + + UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu); + + // Infos sammeln + glAreTexturesResident(1, @ID, @fIsResident); + end; +end; + + +procedure TglBitmap1D.AfterConstruction; +begin + inherited; + + Target := GL_TEXTURE_1D; +end; + + +{ TglBitmapCubeMap } + +procedure TglBitmapCubeMap.AfterConstruction; +begin + inherited; + + if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then + raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.'); + + SetWrap; // set all to GL_CLAMP_TO_EDGE + Target := GL_TEXTURE_CUBE_MAP; + fGenMode := GL_REFLECTION_MAP; +end; + + +procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean); +begin + inherited Bind (EnableTextureUnit); + + if EnableTexCoordsGen then begin + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + end; +end; + + +procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean); +var + glFormat, glInternalFormat, glType: Cardinal; + BuildWithGlu: Boolean; + TexSize: Integer; +begin + // Check Texture Size + if (TestTextureSize) then begin + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize); + + if ((Height > TexSize) or (Width > TexSize)) then + raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.'); + + if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then + raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.'); + end; + + // create Texture + if ID = 0 then begin + CreateID; + SetupParameters(BuildWithGlu); + end; + + SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); + + UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu); +end; + + +procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean); +begin + Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.'); +end; + + +procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen, + DisableTextureUnit: Boolean); +begin + inherited Unbind (DisableTextureUnit); + + if DisableTexCoordsGen then begin + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + end; +end; + + +{ TglBitmapNormalMap } + +type + TVec = Array[0..2] of Single; + TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); + + PglBitmapNormalMapRec = ^TglBitmapNormalMapRec; + TglBitmapNormalMapRec = record + HalfSize : Integer; + Func: TglBitmapNormalMapGetVectorFunc; + end; + + +procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := HalfSize; + Vec[1] := - (Position.Y + 0.5 - HalfSize); + Vec[2] := - (Position.X + 0.5 - HalfSize); +end; + + +procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := - HalfSize; + Vec[1] := - (Position.Y + 0.5 - HalfSize); + Vec[2] := Position.X + 0.5 - HalfSize; +end; + + +procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := Position.X + 0.5 - HalfSize; + Vec[1] := HalfSize; + Vec[2] := Position.Y + 0.5 - HalfSize; +end; + + +procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := Position.X + 0.5 - HalfSize; + Vec[1] := - HalfSize; + Vec[2] := - (Position.Y + 0.5 - HalfSize); +end; + + +procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := Position.X + 0.5 - HalfSize; + Vec[1] := - (Position.Y + 0.5 - HalfSize); + Vec[2] := HalfSize; +end; + + +procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +begin + Vec[0] := - (Position.X + 0.5 - HalfSize); + Vec[1] := - (Position.Y + 0.5 - HalfSize); + Vec[2] := - HalfSize; +end; + + +procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec); +var + Vec : TVec; + Len: Single; +begin + with FuncRec do begin + with PglBitmapNormalMapRec (CustomData)^ do begin + Func(Vec, Position, HalfSize); + + // Normalize + Len := 1 / Sqrt(Sqr(Vec[0]) + Sqr(Vec[1]) + Sqr(Vec[2])); + if Len <> 0 then begin + Vec[0] := Vec[0] * Len; + Vec[1] := Vec[1] * Len; + Vec[2] := Vec[2] * Len; + end; + + // Scale Vector and AddVectro + Vec[0] := Vec[0] * 0.5 + 0.5; + Vec[1] := Vec[1] * 0.5 + 0.5; + Vec[2] := Vec[2] * 0.5 + 0.5; + end; + + // Set Color + Dest.Red := Round(Vec[0] * 255); + Dest.Green := Round(Vec[1] * 255); + Dest.Blue := Round(Vec[2] * 255); + end; +end; + + +procedure TglBitmapNormalMap.AfterConstruction; +begin + inherited; + + fGenMode := GL_NORMAL_MAP; +end; + + +procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer; + TestTextureSize: Boolean); +var + Rec: TglBitmapNormalMapRec; + SizeRec: TglBitmapPixelPosition; +begin + Rec.HalfSize := Size div 2; + + FreeDataAfterGenTexture := False; + + SizeRec.Fields := [ffX, ffY]; + SizeRec.X := Size; + SizeRec.Y := Size; + + // Positive X + Rec.Func := glBitmapNormalMapPosX; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize); + + // Negative X + Rec.Func := glBitmapNormalMapNegX; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize); + + // Positive Y + Rec.Func := glBitmapNormalMapPosY; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize); + + // Negative Y + Rec.Func := glBitmapNormalMapNegY; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize); + + // Positive Z + Rec.Func := glBitmapNormalMapPosZ; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize); + + // Negative Z + Rec.Func := glBitmapNormalMapNegZ; + LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize); +end; + + + +initialization + glBitmapSetDefaultFormat(tfDefault); + glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); + glBitmapSetDefaultWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + + glBitmapSetDefaultFreeDataAfterGenTexture(True); + glBitmapSetDefaultDeleteTextureOnFree(True); + +finalization + +end. From 669392448a38034e96a92fa3c8063b41d3ecae55 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 22 Oct 2013 17:28:34 +0200 Subject: [PATCH 02/38] * fixed bug: buffer overflow when exporting TGA files --- glBitmap.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glBitmap.pas b/glBitmap.pas index 1198bda..0641898 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -4630,7 +4630,7 @@ var begin PixelSize := fPixelSize; - for Idx := 0 to Height * Width do begin + for Idx := 1 to Height * Width do begin Temp := pByteArray(pTemp)^[2]; pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0]; pByteArray(pTemp)^[0] := Temp; From b44eb11a7e6cd1cb6eb36f290e184f53a6e6ec86 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 22 Oct 2013 20:31:38 +0200 Subject: [PATCH 03/38] * started refactoring (interface part, mapping functions) --- glBitmap.pas | 1785 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 1154 insertions(+), 631 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 0641898..1a21c20 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -214,46 +214,45 @@ History ***********************************************************} unit glBitmap; -{$message warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} +{.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} // Please uncomment the defines below to configure the glBitmap to your preferences. // If you have configured the unit you can uncomment the warning above. - // ###### Start of preferences ################################################ -{.$define GLB_NO_NATIVE_GL} +{$DEFINE GLB_NO_NATIVE_GL} // To enable the dglOpenGL.pas Header // With native GL then bindings are staticlly declared to support other headers // or use the glBitmap inside of DLLs (minimize codesize). -{.$define GLB_SDL} +{.$DEFINE GLB_SDL} // To enable the support for SDL_surfaces -{.$define GLB_DELPHI} +{.$DEFINE GLB_DELPHI} // To enable the support for TBitmap from Delphi (not lazarus) // *** image libs *** -{.$define GLB_SDL_IMAGE} +{.$DEFINE GLB_SDL_IMAGE} // To enable the support of SDL_image to load files. (READ ONLY) // If you enable SDL_image all other libraries will be ignored! -{.$define GLB_PNGIMAGE} +{.$DEFINE GLB_PNGIMAGE} // to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored -{.$define GLB_LIB_PNG} +{.$DEFINE GLB_LIB_PNG} // to use the libPNG http://www.libpng.org/ // You will need an aditional header. // http://www.opengl24.de/index.php?cat=header&file=libpng -{.$define GLB_DELPHI_JPEG} +{.$DEFINE GLB_DELPHI_JPEG} // if you enable delphi jpegs the libJPEG will be ignored -{.$define GLB_LIB_JPEG} +{.$DEFINE GLB_LIB_JPEG} // to use the libJPEG http://www.ijg.org/ // You will need an aditional header. // http://www.opengl24.de/index.php?cat=header&file=libjpeg @@ -263,116 +262,110 @@ unit glBitmap; // ###### PRIVATE. Do not change anything. #################################### // *** old defines for compatibility *** -{$ifdef NO_NATIVE_GL} - {$define GLB_NO_NATIVE_GL} -{$endif} -{$ifdef pngimage} +{$IFDEF NO_NATIVE_GL} + {$DEFINE GLB_NO_NATIVE_GL} +{$ENDIF} +{$IFDEF pngimage} {$definde GLB_PNGIMAGE} -{$endif} - +{$ENDIF} // *** Delphi Versions *** -{$ifdef fpc} +{$IFDEF fpc} {$MODE Delphi} - {$ifdef CPUI386} - {$define CPU386} - {$asmmode INTEL} - {$endif} + {$IFDEF CPUI386} + {$DEFINE CPU386} + {$ASMMODE INTEL} + {$ENDIF} - {$ifndef WIN32} + {$IFNDEF WINDOWS} {$linklib c} - {$endif} -{$endif} + {$ENDIF} +{$ENDIF} // *** checking define combinations *** -{$ifdef GLB_SDL_IMAGE} - {$ifndef GLB_SDL} - {$message warn 'SDL_image won''t work without SDL. SDL will be activated.'} - {$define GLB_SDL} - {$endif} - {$ifdef GLB_PNGIMAGE} - {$message warn 'The unit pngimage will be ignored because you are using SDL_image.'} +{$IFDEF GLB_SDL_IMAGE} + {$IFNDEF GLB_SDL} + {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'} + {$DEFINE GLB_SDL} + {$ENDIF} + {$IFDEF GLB_PNGIMAGE} + {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'} {$undef GLB_PNGIMAGE} - {$endif} - {$ifdef GLB_DELPHI_JPEG} - {$message warn 'The unit JPEG will be ignored because you are using SDL_image.'} + {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} + {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'} {$undef GLB_DELPHI_JPEG} - {$endif} - {$ifdef GLB_LIB_PNG} - {$message warn 'The library libPNG will be ignored because you are using SDL_image.'} + {$ENDIF} + {$IFDEF GLB_LIB_PNG} + {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'} {$undef GLB_LIB_PNG} - {$endif} - {$ifdef GLB_LIB_JPEG} - {$message warn 'The library libJPEG will be ignored because you are using SDL_image.'} + {$ENDIF} + {$IFDEF GLB_LIB_JPEG} + {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'} {$undef GLB_LIB_JPEG} - {$endif} + {$ENDIF} - {$define GLB_SUPPORT_PNG_READ} - {$define GLB_SUPPORT_JPEG_READ} -{$endif} + {$DEFINE GLB_SUPPORT_PNG_READ} + {$DEFINE GLB_SUPPORT_JPEG_READ} +{$ENDIF} -{$ifdef GLB_PNGIMAGE} - {$ifdef GLB_LIB_PNG} - {$message warn 'The library libPNG will be ignored if you are using pngimage.'} +{$IFDEF GLB_PNGIMAGE} + {$IFDEF GLB_LIB_PNG} + {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'} {$undef GLB_LIB_PNG} - {$endif} - - {$define GLB_SUPPORT_PNG_READ} - {$define GLB_SUPPORT_PNG_WRITE} -{$endif} + {$ENDIF} -{$ifdef GLB_LIB_PNG} - {$define GLB_SUPPORT_PNG_READ} - {$define GLB_SUPPORT_PNG_WRITE} -{$endif} + {$DEFINE GLB_SUPPORT_PNG_READ} + {$DEFINE GLB_SUPPORT_PNG_WRITE} +{$ENDIF} +{$IFDEF GLB_LIB_PNG} + {$DEFINE GLB_SUPPORT_PNG_READ} + {$DEFINE GLB_SUPPORT_PNG_WRITE} +{$ENDIF} -{$ifdef GLB_DELPHI_JPEG} - {$ifdef GLB_LIB_JPEG} - {$message warn 'The library libJPEG will be ignored if you are using the unit JPEG.'} +{$IFDEF GLB_DELPHI_JPEG} + {$IFDEF GLB_LIB_JPEG} + {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'} {$undef GLB_LIB_JPEG} - {$endif} + {$ENDIF} - {$define GLB_SUPPORT_JPEG_READ} - {$define GLB_SUPPORT_JPEG_WRITE} -{$endif} + {$DEFINE GLB_SUPPORT_JPEG_READ} + {$DEFINE GLB_SUPPORT_JPEG_WRITE} +{$ENDIF} -{$ifdef GLB_LIB_JPEG} - {$define GLB_SUPPORT_JPEG_READ} - {$define GLB_SUPPORT_JPEG_WRITE} -{$endif} +{$IFDEF GLB_LIB_JPEG} + {$DEFINE GLB_SUPPORT_JPEG_READ} + {$DEFINE GLB_SUPPORT_JPEG_WRITE} +{$ENDIF} // *** general options *** {$EXTENDEDSYNTAX ON} {$LONGSTRINGS ON} {$ALIGN ON} -{$ifndef fpc} +{$IFNDEF FPC} {$OPTIMIZATION ON} -{$endif} - +{$ENDIF} interface - uses - {$ifdef GLB_NO_NATIVE_GL} dglOpenGL, {$endif} + {$IFDEF GLB_NO_NATIVE_GL} dglOpenGL, {$ENDIF} - {$ifdef GLB_SDL} SDL, {$endif} - {$ifdef GLB_DELPHI} Dialogs, Windows, Graphics, {$endif} + {$IFDEF GLB_SDL} SDL, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Windows, Graphics, {$ENDIF} - {$ifdef GLB_SDL_IMAGE} SDL_image, {$endif} + {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} - {$ifdef GLB_PNGIMAGE} pngimage, {$endif} - {$ifdef GLB_LIB_PNG} libPNG, {$endif} + {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} + {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} - {$ifdef GLB_DELPHI_JPEG} JPEG, {$endif} - {$ifdef GLB_LIB_JPEG} libJPEG, {$endif} + {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} + {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} Classes, SysUtils; - - -{$ifndef GLB_DELPHI} +{$IFNDEF GLB_DELPHI} type HGLRC = Cardinal; DWORD = Cardinal; @@ -384,18 +377,18 @@ type rgbRed: Byte; rgbReserved: Byte; end; -{$endif} +{$ENDIF} - -{$ifndef GLB_NO_NATIVE_GL} +(* TODO dglOpenGL +{$IFNDEF GLB_NO_NATIVE_GL} // Native OpenGL Implementation type PByteBool = ^ByteBool; -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} var gLastContext: HGLRC; -{$endif} +{$ENDIF} const // Generell @@ -541,73 +534,69 @@ var GL_IBM_texture_mirrored_repeat, GL_SGIS_generate_mipmap: Boolean; - // Funtions const - -{$ifdef LINUX} +{$IFDEF LINUX} libglu = 'libGLU.so.1'; libopengl = 'libGL.so.1'; {$else} libglu = 'glu32.dll'; libopengl = 'opengl32.dll'; -{$endif} - +{$ENDIF} -{$ifdef LINUX} +{$IFDEF LINUX} function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl; {$else} function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl; -{$endif} +{$ENDIF} - function glGetString(name: Cardinal): PAnsiChar; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + function glGetString(name: Cardinal): PAnsiChar; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glEnable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glDisable(cap: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glEnable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glDisable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glGenTextures(n: Integer; Textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glGenTextures(n: Integer; Textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glPixelStorei(pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glPixelStorei(pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; - procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libopengl; + function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; + procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu; - function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$ifdef Win32}stdcall; {$else}cdecl; {$endif} external libglu; + function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu; + function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu; var - glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} - glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} - glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$ifdef Win32}stdcall; {$else}cdecl; {$endif} -{$endif} - + glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} + glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} + glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} +{$ENDIF} +*) type - // Exception - EglBitmapException = Exception; - EglBitmapSizeToLargeException = EglBitmapException; - EglBitmapNonPowerOfTwoException = EglBitmapException; - EglBitmapUnsupportedInternalFormat = EglBitmapException; + EglBitmapException = class(Exception); + EglBitmapSizeToLargeException = class(EglBitmapException); + EglBitmapNonPowerOfTwoException = class(EglBitmapException); + EglBitmapUnsupportedInternalFormat = class(EglBitmapException); - // Functions TglBitmapPixelDesc = packed record RedRange: Cardinal; - RedShift: Shortint; GreenRange: Cardinal; - GreenShift: Shortint; BlueRange: Cardinal; - BlueShift: Shortint; AlphaRange: Cardinal; + + RedShift: Shortint; + GreenShift: Shortint; + BlueShift: Shortint; AlphaShift: Shortint; end; @@ -616,7 +605,6 @@ type Green: Cardinal; Blue: Cardinal; Alpha: Cardinal; - PixelDesc: TglBitmapPixelDesc; end; @@ -628,7 +616,7 @@ type end; const - cNullSize : TglBitmapPixelPosition = (Fields : []; X: 0; Y: 0); + NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0); type TglBitmap = class; @@ -652,65 +640,94 @@ type const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData) of object; - // Settings TglBitmapFileType = ( - {$ifdef GLB_SUPPORT_PNG_WRITE} ftPNG, {$endif} - {$ifdef GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$endif} + {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} ftDDS, ftTGA, ftBMP); TglBitmapFileTypes = set of TglBitmapFileType; - TglBitmapFormat = (tfDefault, tf4BitsPerChanel, tf8BitsPerChanel, tfCompressed); - TglBitmapMipMap = (mmNone, mmMipmap, mmMipmapGlu); - TglBitmapNormalMapFunc = (nm4Samples, nmSobel, nm3x3, nm5x5); + TglBitmapMipMap = ( + mmNone, + mmMipmap, + mmMipmapGlu); + TglBitmapNormalMapFunc = ( + nm4Samples, + nmSobel, + nm3x3, + nm5x5); + TglBitmapFormat = ( + tfRed = GL_RED, + tfGreen = GL_GREEN, + tfBlue = GL_BLUE, + tfAlpha = GL_ALPHA, + tfRGB = GL_RGB, + tfBGR = GL_BGR, + tfRGBA = GL_RGBA, + tfBGRA = GL_BGRA, + tfLuminance = GL_LUMINANCE, + tfLuminanceAlpha = GL_LUMINANCE_ALPHA + ); TglBitmapInternalFormat = ( - ifEmpty, - // 4 Bit - ifDXT1, - // 8 Bit - ifDXT3, - ifDXT5, - ifAlpha, - ifLuminance, - ifDepth8, - // 16 Bit - ifLuminanceAlpha, - ifRGBA4, - ifR5G6B5, - ifRGB5A1, - // 24 Bit - ifBGR8, - ifRGB8, - // 32 Bit - ifBGRA8, - ifRGBA8, - ifRGB10A2 + ifAlpha4 = GL_ALPHA4, + ifAlpha8 = GL_ALPHA8, + ifAlpha12 = GL_ALPHA12, + ifAlpha16 = GL_ALPHA16, + + ifLuminance4 = GL_LUMINANCE4, + ifLuminance8 = GL_LUMINANCE8, + ifLuminance12 = GL_LUMINANCE12, + ifLuminance16 = GL_LUMINANCE16, + + ifLuminance4Alpha4 = GL_LUMINANCE4_ALPHA4, + ifLuminance6Alpha2 = GL_LUMINANCE6_ALPHA2, + ifLuminance8Alpha8 = GL_LUMINANCE8_ALPHA8, + ifLuminance12Alpha4 = GL_LUMINANCE12_ALPHA4, + ifLuminance12Alpha12 = GL_LUMINANCE12_ALPHA12, + ifLuminance16Alpha16 = GL_LUMINANCE16_ALPHA16, + + ifR3G3B2 = GL_R3_G3_B2, + ifRGB4 = GL_RGB4, + ifRGB5 = GL_RGB5, + ifRGB8 = GL_RGB8, + ifRGB10 = GL_RGB10, + ifRGB12 = GL_RGB12, + ifRGB16 = GL_RGB16, + + ifRGBA2 = GL_RGBA2, + ifRGBA4 = GL_RGBA4, + ifRGB5A1 = GL_RGB5_A1, + ifRGBA8 = GL_RGBA8, + ifRGB10A2 = GL_RGB10_A2, + ifRGBA12 = GL_RGBA12, + ifRGBA16 = GL_RGBA16, + + ifDepth16 = GL_DEPTH_COMPONENT16, + ifDepth24 = GL_DEPTH_COMPONENT24, + ifDepth32 = GL_DEPTH_COMPONENT32 ); // Pixelmapping - TglBitmapMapFunc = procedure (const Pixel: TglBitmapPixelData; var pDest: pByte); - TglBitmapUnMapFunc = procedure (var pData: pByte; var Pixel: TglBitmapPixelData); + TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); + TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); // Base Class TglBitmap = class protected fID: Cardinal; fTarget: Cardinal; - fFormat: TglBitmapFormat; - fMipMap: TglBitmapMipMap; fAnisotropic: Integer; - fBorderColor: array [0..3] of single; - fDeleteTextureOnFree: Boolean; fFreeDataAfterGenTexture: Boolean; + fData: PByte; + fIsResident: Boolean; + fBorderColor: array[0..3] of Single; - // Propertys - fData: pByte; - fInternalFormat: TglBitmapInternalFormat; fDimension: TglBitmapPixelPosition; - - fIsResident: Boolean; + fMipMap: TglBitmapMipMap; + fFormat: TglBitmapFormat; + fInternalFormat: TglBitmapInternalFormat; // Mapping fPixelSize: Integer; @@ -719,184 +736,182 @@ type fMapFunc: TglBitmapMapFunc; // Filtering - fFilterMin: Integer; - fFilterMag: Integer; + fFilterMin: Cardinal; + fFilterMag: Cardinal; - // Texturwarp - fWrapS: Integer; - fWrapT: Integer; - fWrapR: Integer; + // TexturWarp + fWrapS: Cardinal; + fWrapT: Cardinal; + fWrapR: Cardinal; fGetPixelFunc: TglBitmapGetPixel; fSetPixelFunc: TglBitmapSetPixel; - // custom data + // CustomData fFilename: String; fCustomName: String; fCustomNameW: WideString; - fCustomDataPointer: Pointer; - - - procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual; - - {$ifdef GLB_SUPPORT_PNG_READ} - function LoadPNG(Stream: TStream): Boolean; virtual; - {$endif} - {$ifdef GLB_SUPPORT_JPEG_READ} - function LoadJPEG(Stream: TStream): Boolean; virtual; - {$endif} + fCustomData: Pointer; + + //Getter + function GetHeight: Integer; virtual; + function GetWidth: Integer; virtual; + + //Setter + procedure SetCustomData(const aValue: Pointer); + procedure SetCustomName(const aValue: String); + procedure SetCustomNameW(const aValue: WideString); + procedure SetDeleteTextureOnFree(const aValue: Boolean); + procedure SetFormat(const aValue: TglBitmapFormat); + procedure SetFreeDataAfterGenTexture(const aValue: Boolean); + procedure SetID(const aValue: Cardinal); + procedure SetMipMap(const aValue: TglBitmapMipMap); + procedure SetTarget(const aValue: Cardinal); + procedure SetAnisotropic(const aValue: Integer); + procedure SetInternalFormat(const aValue: TglBitmapInternalFormat); + + //Load + {$IFDEF GLB_SUPPORT_PNG_READ} + function LoadPNG(Stream: TStream): Boolean; virtual; + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_READ} + function LoadJPEG(Stream: TStream): Boolean; virtual; + {$ENDIF} function LoadDDS(Stream: TStream): Boolean; virtual; function LoadTGA(Stream: TStream): Boolean; virtual; function LoadBMP(Stream: TStream): Boolean; virtual; - - {$ifdef GLB_SUPPORT_PNG_WRITE} - procedure SavePNG(Stream: TStream); virtual; - {$endif} - {$ifdef GLB_SUPPORT_JPEG_WRITE} - procedure SaveJPEG(Stream: TStream); virtual; - {$endif} + //Save + {$IFDEF GLB_SUPPORT_PNG_WRITE} + procedure SavePNG(Stream: TStream); virtual; + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_WRITE} + procedure SaveJPEG(Stream: TStream); virtual; + {$ENDIF} procedure SaveDDS(Stream: TStream); virtual; procedure SaveTGA(Stream: TStream); virtual; procedure SaveBMP(Stream: TStream); virtual; - procedure CreateID; procedure SetupParameters(var BuildWithGlu: Boolean); procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True); + procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual; procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract; - procedure SetAnisotropic(const Value: Integer); - procedure SetInternalFormat(const Value: TglBitmapInternalFormat); - function FlipHorz: Boolean; virtual; function FlipVert: Boolean; virtual; - function GetHeight: Integer; - function GetWidth: Integer; - - function GetFileHeight: Integer; - function GetFileWidth: Integer; - - property Width: Integer read GetWidth; + property Width: Integer read GetWidth; property Height: Integer read GetHeight; - - property FileWidth: Integer read GetFileWidth; - property FileHeight: Integer read GetFileHeight; public - // propertys - property ID: Cardinal read fID write fID; - property Target: Cardinal read fTarget write fTarget; - property Format: TglBitmapFormat read fFormat write fFormat; + property ID: Cardinal read fID write SetID; + property Target: Cardinal read fTarget write SetTarget; + property Format: TglBitmapFormat read fFormat write SetFormat; property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat; - property Dimension: TglBitmapPixelPosition read fDimension; + property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; + property Anisotropic: Integer read fAnisotropic write SetAnisotropic; - property Data: pByte read fData; + property Filename: String read fFilename; + property CustomName: String read fCustomName write SetCustomName; + property CustomNameW: WideString read fCustomNameW write SetCustomNameW; + property CustomData: Pointer read fCustomData write SetCustomData; - property MipMap: TglBitmapMipMap read fMipMap write fMipMap; - property Anisotropic: Integer read fAnisotropic write SetAnisotropic; + property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree; + property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture; - property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write fDeleteTextureOnFree; - property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write fFreeDataAfterGenTexture; + property Dimension: TglBitmapPixelPosition read fDimension; + property Data: PByte read fData; + property IsResident: Boolean read fIsResident; - property IsResident: boolean read fIsResident; - - // propertys for custom data - property Filename: String read fFilename; - property CustomName: String read fCustomName write fCustomName; - property CustomNameW: WideString read fCustomNameW write fCustomNameW; - property CustomDataPointer: Pointer read fCustomDataPointer write fCustomDataPointer; - - // Construction and Destructions Methods procedure AfterConstruction; override; procedure BeforeDestruction; override; - constructor Create(); overload; - constructor Create(FileName: String); overload; - constructor Create(Stream: TStream); overload; - {$ifdef GLB_DELPHI} - constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil); - constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload; - constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload; - {$endif} - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload; - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; + //Loading + procedure LoadFromFile(const aFileName: String); + procedure LoadFromStream(const aStream: TStream); virtual; + procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; + const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat; + const aArgs: PtrInt = 0); + {$IFDEF GLB_DELPHI} + procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil); + procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); + {$ENDIF} + + procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); + procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual; + + //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload; + //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload; +(* TODO + {$IFDEF GLB_SDL} + function AssignToSurface(out aSurface: PSDL_Surface): Boolean; + function AssignFromSurface(const aSurface: PSDL_Surface): Boolean; + function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean; + function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; + const aArgs: PtrInt = 0): Boolean; + {$ENDIF} + + {$IFDEF GLB_DELPHI} + function AssignToBitmap(const aBitmap: TBitmap): Boolean; + function AssignFromBitmap(const aBitmap: TBitmap): Boolean; + function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean; + function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; + const aArgs: PtrInt = 0): Boolean; + {$ENDIF} + + function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual; + function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + {$IFDEF GLB_DELPHI} + function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil; + const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; + const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + {$ENDIF} + + function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean; + function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean; + function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean; + + function AddAlphaFromValue(const aAlpha: Byte): Boolean; + function AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean; + function AddAlphaFromValueFloat(const aAlpha: Single): Boolean; + function RemoveAlpha: Boolean; virtual; function Clone: TglBitmap; - + function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat): Boolean; virtual; + procedure SetBorderColor(Red, Green, Blue, Alpha: Single); + procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false); procedure FreeData; - // Loading Methods - procedure LoadFromFile(FileName: String); - procedure LoadFromStream(Stream: TStream); virtual; - {$ifdef GLB_DELPHI} - procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil); - procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); - {$endif} - procedure LoadFromFunc(Size: TglBitmapPixelPosition; Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer = nil); - - procedure SaveToFile(FileName: String; FileType: TglBitmapFileType); - procedure SaveToStream(Stream: TStream; FileType: TglBitmapFileType); virtual; - - function AddFunc(Source: TglBitmap; Func: TglBitmapFunction; CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload; - function AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload; - - {$ifdef GLB_SDL} - function AssignToSurface(out Surface: PSDL_Surface): boolean; - function AssignFromSurface(const Surface: PSDL_Surface): boolean; - function AssignAlphaToSurface(out Surface: PSDL_Surface): boolean; - - function AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - {$endif} - {$ifdef GLB_DELPHI} - function AssignToBitmap(const Bitmap: TBitmap): boolean; - function AssignFromBitmap(const Bitmap: TBitmap): boolean; - function AssignAlphaToBitmap(const Bitmap: TBitmap): boolean; - - function AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - {$endif} - - function AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer = nil): boolean; virtual; - function AddAlphaFromFile(FileName: String; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - function AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - {$ifdef GLB_DELPHI} - function AddAlphaFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - function AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - {$endif} - function AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction = nil; CustomData: Pointer = nil): boolean; - - function AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte = 0): Boolean; - function AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean; - function AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean; - - function AddAlphaFromValue(Alpha: Byte): Boolean; - function AddAlphaFromValueRange(Alpha: Cardinal): Boolean; - function AddAlphaFromValueFloat(Alpha: Single): Boolean; - - function RemoveAlpha: Boolean; virtual; - - function ConvertTo(NewFormat: TglBitmapInternalFormat): boolean; virtual; - - // Other - procedure FillWithColor(Red, Green, Blue: Byte; Alpha : Byte = 255); - procedure FillWithColorRange(Red, Green, Blue: Cardinal; Alpha : Cardinal = $FFFFFFFF); - procedure FillWithColorFloat(Red, Green, Blue: Single; Alpha : Single = 1); - - procedure Invert(UseRGB: Boolean = true; UseAlpha: Boolean = false); + procedure FillWithColor(const aRed, aGreen, aBlue: aByte; Alpha: Byte = 255); + procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF); + procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1); +*) + procedure SetFilter(const aMin, aMag: Cardinal); + procedure SetWrap( + const S: Cardinal = GL_CLAMP_TO_EDGE; + const T: Cardinal = GL_CLAMP_TO_EDGE; + const R: Cardinal = GL_CLAMP_TO_EDGE); - procedure SetFilter(Min, Mag : Integer); - procedure SetWrap(S: Integer = GL_CLAMP_TO_EDGE; - T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE); + procedure GetPixel(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual; + procedure SetPixel(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual; - procedure SetBorderColor(Red, Green, Blue, Alpha: Single); - - procedure GetPixel (const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual; - procedure SetPixel (const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual; - - // Generation procedure Unbind(DisableTextureUnit: Boolean = True); virtual; procedure Bind(EnableTextureUnit: Boolean = True); virtual; + + constructor Create; overload; + constructor Create(FileName: String); overload; + constructor Create(Stream: TStream); overload; + {$IFDEF GLB_DELPHI} + constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil); + constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload; + constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload; + {$ENDIF} + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload; + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; end; @@ -910,36 +925,29 @@ type procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); + function GetScanline(Index: Integer): Pointer; procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); - function GetScanline(Index: Integer): Pointer; - procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override; procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); public - // propertys property Width; property Height; - property Scanline[Index: Integer]: Pointer read GetScanline; procedure AfterConstruction; override; - procedure GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat); + procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat); procedure GetDataFromTexture; + procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False); + procedure GenTexture(TestTextureSize: Boolean = True); override; - // Other function FlipHorz: Boolean; override; function FlipVert: Boolean; override; - - procedure ToNormalMap(Func: TglBitmapNormalMapFunc = nm3x3; Scale: Single = 2; UseAlpha: Boolean = False); - - // Generation - procedure GenTexture(TestTextureSize: Boolean = True); override; end; - +(* TODO TglBitmapCubeMap = class(TglBitmap2D) protected fGenMode: Integer; @@ -982,78 +990,73 @@ type // Generation procedure GenTexture(TestTextureSize: Boolean = True); override; end; +*) - -// methods and vars for Defaults -procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat); -procedure glBitmapSetDefaultFilter(Min, Mag: Integer); -procedure glBitmapSetDefaultWrap(S: Integer = GL_CLAMP_TO_EDGE; T: Integer = GL_CLAMP_TO_EDGE; R: Integer = GL_CLAMP_TO_EDGE); - -procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean); -procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean); - -function glBitmapGetDefaultFormat: TglBitmapFormat; -procedure glBitmapGetDefaultFilter(var Min, Mag: Integer); -procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer); +procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean); +procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean); +procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat); +procedure glBitmapSetDefaultInternalFormat(const aInternalFormat: TglBitmapInternalFormat); +procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer); +procedure glBitmapSetDefaultWrap( + const S: Cardinal = GL_CLAMP_TO_EDGE; + const T: Cardinal = GL_CLAMP_TO_EDGE; + const R: Cardinal = GL_CLAMP_TO_EDGE); function glBitmapGetDefaultDeleteTextureOnFree: Boolean; function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; +function glBitmapGetDefaultFormat: TglBitmapFormat; +function glBitmapGetDefaultInternalFormat: TglBitmapInternalFormat; +procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal); +procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); // position / size function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; // Formatfunctions -function FormatGetSize (Format: TglBitmapInternalFormat): Single; - +function FormatGetSize(Format: TglBitmapInternalFormat): Single; function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean; function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean; - procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat); - function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; - function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean; -// Call LoadingMethods -function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean; - -function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$endif}): Boolean; - +(* TODO +function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; +function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; - +*) var - glBitmapDefaultFormat: TglBitmapFormat; - glBitmapDefaultFilterMin: Integer; - glBitmapDefaultFilterMag: Integer; - glBitmapDefaultWrapS: Integer; - glBitmapDefaultWrapT: Integer; - glBitmapDefaultWrapR: Integer; - glBitmapDefaultDeleteTextureOnFree: Boolean; glBitmapDefaultFreeDataAfterGenTextures: Boolean; - -{$ifdef GLB_DELPHI} + glBitmapDefaultFormat: TglBitmapFormat; + glBitmapDefaultInternalFormat: TglBitmapInternalFormat; + glBitmapDefaultFilterMin: Cardinal; + glBitmapDefaultFilterMag: Cardinal; + glBitmapDefaultWrapS: Cardinal; + glBitmapDefaultWrapT: Cardinal; + glBitmapDefaultWrapR: Cardinal; + +{$IFDEF GLB_DELPHI} function CreateGrayPalette: HPALETTE; -{$endif} - +{$ENDIF} implementation uses Math; - -{$ifndef GLB_NO_NATIVE_GL} +(* TODO +{$IFNDEF GLB_NO_NATIVE_GL} procedure ReadOpenGLExtensions; var - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} Context: HGLRC; - {$endif} + {$ENDIF} Buffer: AnsiString; MajorVersion, MinorVersion: Integer; @@ -1104,21 +1107,21 @@ var function glLoad (aFunc: pAnsiChar): pointer; begin - {$ifdef LINUX} + {$IFDEF LINUX} Result := glXGetProcAddress(aFunc); {$else} Result := wglGetProcAddress(aFunc); - {$endif} + {$ENDIF} end; begin - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} Context := wglGetCurrentContext; if Context <> gLastContext then begin gLastContext := Context; - {$endif} + {$ENDIF} // Version Buffer := glGetString(GL_VERSION); @@ -1181,13 +1184,14 @@ begin glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB'); glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB'); end; - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} end; - {$endif} + {$ENDIF} end; -{$endif} - +{$ENDIF} +*) +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; begin Result.Fields := []; @@ -1203,236 +1207,677 @@ end; const + LUMINANCE_WEIGHT_R = 0.30; + LUMINANCE_WEIGHT_G = 0.59; + LUMINANCE_WEIGHT_B = 0.11; UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.'; - PIXEL_DESC_ALPHA : TglBitmapPixelDesc = ( - RedRange : $00; RedShift : 0; - GreenRange : $00; GreenShift : 0; - BlueRange : $00; BlueShift : 0; - AlphaRange : $FF; AlphaShift : 0 ); - - PIXEL_DESC_LUMINANCE : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 0; - GreenRange : $FF; GreenShift : 0; - BlueRange : $FF; BlueShift : 0; - AlphaRange : $00; AlphaShift : 0 ); - - PIXEL_DESC_DEPTH8 : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 0; - GreenRange : $FF; GreenShift : 0; - BlueRange : $FF; BlueShift : 0; - AlphaRange : $00; AlphaShift : 0 ); - - PIXEL_DESC_LUMINANCEALPHA : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 0; - GreenRange : $FF; GreenShift : 0; - BlueRange : $FF; BlueShift : 0; - AlphaRange : $FF; AlphaShift : 8 ); - - PIXEL_DESC_RGBA4 : TglBitmapPixelDesc = ( - RedRange : $0F; RedShift : 8; - GreenRange : $0F; GreenShift : 4; - BlueRange : $0F; BlueShift : 0; - AlphaRange : $0F; AlphaShift : 12 ); - - PIXEL_DESC_R5G6B5 : TglBitmapPixelDesc = ( - RedRange : $1F; RedShift : 11; - GreenRange : $3F; GreenShift : 5; - BlueRange : $1F; BlueShift : 0; - AlphaRange : $00; AlphaShift : 0 ); - - PIXEL_DESC_RGB5A1 : TglBitmapPixelDesc = ( - RedRange : $1F; RedShift : 10; - GreenRange : $1F; GreenShift : 5; - BlueRange : $1F; BlueShift : 0; - AlphaRange : $01; AlphaShift : 15 ); - - PIXEL_DESC_RGB8 : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 0; - GreenRange : $FF; GreenShift : 8; - BlueRange : $FF; BlueShift : 16; - AlphaRange : $00; AlphaShift : 0 ); - - PIXEL_DESC_RGBA8 : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 0; - GreenRange : $FF; GreenShift : 8; - BlueRange : $FF; BlueShift : 16; - AlphaRange : $FF; AlphaShift : 24 ); - - PIXEL_DESC_BGR8 : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 16; - GreenRange : $FF; GreenShift : 8; - BlueRange : $FF; BlueShift : 0; - AlphaRange : $00; AlphaShift : 0 ); - - PIXEL_DESC_BGRA8 : TglBitmapPixelDesc = ( - RedRange : $FF; RedShift : 16; - GreenRange : $FF; GreenShift : 8; - BlueRange : $FF; BlueShift : 0; - AlphaRange : $FF; AlphaShift : 24 ); - - PIXEL_DESC_RGB10A2 : TglBitmapPixelDesc = ( - RedRange : $3FF; RedShift : 20; - GreenRange : $3FF; GreenShift : 10; - BlueRange : $3FF; BlueShift : 0; - AlphaRange : $003; AlphaShift : 30 ); +{$REGION PixelDescription} +const + //ifAlpha4//////////////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_ALPHA4: TglBitmapPixelDesc = ( + RedRange: $00000000; RedShift: 0; + GreenRange: $00000000; GreenShift: 0; + BlueRange: $00000000; BlueShift: 0; + AlphaRange: $0000000F; AlphaShift: 0); + + //ifAlpha8 + PIXEL_DESC_ALPHA8: TglBitmapPixelDesc = ( + RedRange: $00000000; RedShift: 0; + GreenRange: $00000000; GreenShift: 0; + BlueRange: $00000000; BlueShift: 0; + AlphaRange: $000000FF; AlphaShift: 0); + + //ifAlpha12 + PIXEL_DESC_ALPHA12: TglBitmapPixelDesc = ( + RedRange: $00000000; RedShift: 0; + GreenRange: $00000000; GreenShift: 0; + BlueRange: $00000000; BlueShift: 0; + AlphaRange: $00000FFF; AlphaShift: 0); + + //ifAlpha16 + PIXEL_DESC_ALPHA16: TglBitmapPixelDesc = ( + RedRange: $00000000; RedShift: 0; + GreenRange: $00000000; GreenShift: 0; + BlueRange: $00000000; BlueShift: 0; + AlphaRange: $0000FFFF; AlphaShift: 0); + + //ifLuminance4//////////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_LUMINANCE4: TglBitmapPixelDesc = ( + RedRange: $0000000F; RedShift: 0; + GreenRange: $0000000F; GreenShift: 0; + BlueRange: $0000000F; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); + + //ifLuminance8 + PIXEL_DESC_LUMINANCE8: TglBitmapPixelDesc = ( + RedRange: $000000FF; RedShift: 0; + GreenRange: $000000FF; GreenShift: 0; + BlueRange: $000000FF; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); + + //ifLuminance12 + PIXEL_DESC_LUMINANCE12: TglBitmapPixelDesc = ( + RedRange: $00000FFF; RedShift: 0; + GreenRange: $00000FFF; GreenShift: 0; + BlueRange: $00000FFF; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); + + //ifLuminance16 + PIXEL_DESC_LUMINANCE16: TglBitmapPixelDesc = ( + RedRange: $0000FFFF; RedShift: 0; + GreenRange: $0000FFFF; GreenShift: 0; + BlueRange: $0000FFFF; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); + + //ifLuminance4Alpha4////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_LUMINANCE4_ALPHA4: TglBitmapPixelDesc = ( + RedRange: $0000000F; RedShift: 0; + GreenRange: $0000000F; GreenShift: 0; + BlueRange: $0000000F; BlueShift: 0; + AlphaRange: $0000000F; AlphaShift: 4); + //ifLuminance6Alpha2 + PIXEL_DESC_LUMINANCE6_ALPHA2: TglBitmapPixelDesc = ( + RedRange: $0000003F; RedShift: 0; + GreenRange: $0000003F; GreenShift: 0; + BlueRange: $0000003F; BlueShift: 0; + AlphaRange: $00000003; AlphaShift: 6); + + //ifLuminance8Alpha8 + PIXEL_DESC_LUMINANCE8_ALPHA8: TglBitmapPixelDesc = ( + RedRange: $000000FF; RedShift: 0; + GreenRange: $000000FF; GreenShift: 0; + BlueRange: $000000FF; BlueShift: 0; + AlphaRange: $000000FF; AlphaShift: 8); + + //ifLuminance12Alpha4 + PIXEL_DESC_LUMINANCE12_ALPHA4: TglBitmapPixelDesc = ( + RedRange: $00000FFF; RedShift: 0; + GreenRange: $00000FFF; GreenShift: 0; + BlueRange: $00000FFF; BlueShift: 0; + AlphaRange: $0000000F; AlphaShift: 12); + + //ifLuminance12Alpha12 + PIXEL_DESC_LUMINANCE12_ALPHA12: TglBitmapPixelDesc = ( + RedRange: $00000FFF; RedShift: 0; + GreenRange: $00000FFF; GreenShift: 0; + BlueRange: $00000FFF; BlueShift: 0; + AlphaRange: $00000FFF; AlphaShift: 12); + + //ifLuminance16Alpha16 + PIXEL_DESC_LUMINANCE16_ALPHA16: TglBitmapPixelDesc = ( + RedRange: $0000FFFF; RedShift: 0; + GreenRange: $0000FFFF; GreenShift: 0; + BlueRange: $0000FFFF; BlueShift: 0; + AlphaRange: $0000FFFF; AlphaShift: 16); + + //ifR3G3B2//////////////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_R3_G3_B2: TglBitmapPixelDesc = ( + RedRange: $00000007; RedShift: 0; + GreenRange: $00000007; GreenShift: 3; + BlueRange: $00000003; BlueShift: 6; + AlphaRange: $00000000; AlphaShift: 0); + + //ifRGB4 + PIXEL_DESC_RGB4: TglBitmapPixelDesc = ( + RedRange: $0000000F; RedShift: 0; + GreenRange: $0000000F; GreenShift: 4; + BlueRange: $0000000F; BlueShift: 8; + AlphaRange: $00000000; AlphaShift: 0); + + //ifRGB5 + PIXEL_DESC_RGB5: TglBitmapPixelDesc = ( + RedRange: $0000001F; RedShift: 0; + GreenRange: $0000001F; GreenShift: 5; + BlueRange: $0000001F; BlueShift: 10; + AlphaRange: $00000000; AlphaShift: 0); + + //ifRGB8 + PIXEL_DESC_RGB8: TglBitmapPixelDesc = ( + RedRange: $000000FF; RedShift: 0; + GreenRange: $000000FF; GreenShift: 8; + BlueRange: $000000FF; BlueShift: 16; + AlphaRange: $00000000; AlphaShift: 0); + + //ifRGB10 + PIXEL_DESC_RGB10: TglBitmapPixelDesc = ( + RedRange: $000003FF; RedShift: 0; + GreenRange: $000003FF; GreenShift: 10; + BlueRange: $000003FF; BlueShift: 20; + AlphaRange: $000003FF; AlphaShift: 0); + + //ifRGB12 + PIXEL_DESC_RGB12: TglBitmapPixelDesc = ( + RedRange: $00000000; RedShift: 0; + GreenRange: $00000000; GreenShift: 0; + BlueRange: $00000000; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); + + //ifRGB16 + PIXEL_DESC_RGB16: TglBitmapPixelDesc = ( + RedRange: $0000FFFF; RedShift: 0; + GreenRange: $0000FFFF; GreenShift: 16; + BlueRange: $0000FFFF; BlueShift: 32; + AlphaRange: $0000FFFF; AlphaShift: 0); + + //ifRGBA2///////////////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_RGBA2: TglBitmapPixelDesc = ( + RedRange: $00000003; RedShift: 0; + GreenRange: $00000003; GreenShift: 2; + BlueRange: $00000003; BlueShift: 4; + AlphaRange: $00000003; AlphaShift: 6); + + //ifRGBA4 + PIXEL_DESC_RGBA4: TglBitmapPixelDesc = ( + RedRange: $0000000F; RedShift: 0; + GreenRange: $0000000F; GreenShift: 4; + BlueRange: $0000000F; BlueShift: 8; + AlphaRange: $0000000F; AlphaShift: 12); + + //ifRGB5A1 + PIXEL_DESC_RGB5_A1: TglBitmapPixelDesc = ( + RedRange: $0000001F; RedShift: 0; + GreenRange: $0000001F; GreenShift: 5; + BlueRange: $0000001F; BlueShift: 10; + AlphaRange: $00000001; AlphaShift: 11); + + //ifRGBA8 + PIXEL_DESC_RGBA8: TglBitmapPixelDesc = ( + RedRange: $000000FF; RedShift: 0; + GreenRange: $000000FF; GreenShift: 8; + BlueRange: $000000FF; BlueShift: 16; + AlphaRange: $000000FF; AlphaShift: 24); + + //ifRGB10A2 + PIXEL_DESC_RGB10_A2: TglBitmapPixelDesc = ( + RedRange: $000003FF; RedShift: 0; + GreenRange: $000003FF; GreenShift: 10; + BlueRange: $000003FF; BlueShift: 20; + AlphaRange: $00000003; AlphaShift: 22); + + //ifRGBA12 + PIXEL_DESC_RGBA12: TglBitmapPixelDesc = ( + RedRange: $00000FFF; RedShift: 0; + GreenRange: $00000FFF; GreenShift: 12; + BlueRange: $00000FFF; BlueShift: 24; + AlphaRange: $00000FFF; AlphaShift: 36); + + //ifRGBA16 + PIXEL_DESC_RGBA16: TglBitmapPixelDesc = ( + RedRange: $0000FFFF; RedShift: 0; + GreenRange: $0000FFFF; GreenShift: 16; + BlueRange: $0000FFFF; BlueShift: 32; + AlphaRange: $0000FFFF; AlphaShift: 48); + + //ifDepthComponent16////////////////////////////////////////////////////////////////////////////// + PIXEL_DESC_DEPTH16: TglBitmapPixelDesc = ( + RedRange: $0000FFFF; RedShift: 0; + GreenRange: $0000FFFF; GreenShift: 0; + BlueRange: $0000FFFF; BlueShift: 0; + AlphaRange: $0000FFFF; AlphaShift: 0); -{* -** Mapping -*} + //ifDepthComponent24 + PIXEL_DESC_DEPTH24: TglBitmapPixelDesc = ( + RedRange: $00FFFFFF; RedShift: 0; + GreenRange: $00FFFFFF; GreenShift: 0; + BlueRange: $00FFFFFF; BlueShift: 0; + AlphaRange: $00FFFFFF; AlphaShift: 0); -procedure MapAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte); + //ifDepthComponent32 + PIXEL_DESC_DEPTH32: TglBitmapPixelDesc = ( + RedRange: $FFFFFFFF; RedShift: 0; + GreenRange: $FFFFFFFF; GreenShift: 0; + BlueRange: $FFFFFFFF; BlueShift: 0; + AlphaRange: $00000000; AlphaShift: 0); +{$ENDREGION} + +{$REGION MapFunctions} +//ALPHA///////////////////////////////////////////////////////////////////////////////////////////// +procedure MapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := Pixel.Alpha; - Inc(pDest); + //TODO end; +procedure MapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := aPixel.Alpha; + inc(aData); +end; -procedure MapLuminance(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11); - Inc(pDest); + //TODO end; +procedure MapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := aPixel.Alpha; + inc(aData, 2); +end; -procedure MapDepth8(const Pixel: TglBitmapPixelData; var pDest: pByte); +//LUMINANCE///////////////////////////////////////////////////////////////////////////////////////// +procedure MapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := (Pixel.Red + Pixel.Green + Pixel.Blue) div 3; - Inc(pDest); + //TODO end; +procedure MapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := Trunc( + aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B); + inc(aData); +end; -procedure MapLuminanceAlpha(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := Trunc(Pixel.Red * 0.3 + Pixel.Green * 0.59 + Pixel.Blue * 0.11); - Inc(pDest); + //TODO +end; - pDest^ := Pixel.Alpha; - Inc(pDest); +procedure MapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := Trunc( + aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B); + inc(aData, 2); end; +//LUMINANCE_ALPHA/////////////////////////////////////////////////////////////////////////////////// +procedure MapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := + ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B) and + aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; + inc(aData); +end; -procedure MapRGBA4(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pWord(pDest)^ := - Pixel.Alpha shl PIXEL_DESC_RGBA4.AlphaShift or - Pixel.Red shl PIXEL_DESC_RGBA4.RedShift or - Pixel.Green shl PIXEL_DESC_RGBA4.GreenShift or - Pixel.Blue; + MapLuminance4Alpha4(aPixel, aData, aBitOffset); +end; - Inc(pDest, 2); +procedure MapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := + ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B) and + aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; + inc(aData, 2); end; +procedure MapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + MapLuminance8Alpha8(aPixel, aData, aBitOffset); +end; -procedure MapR5G6B5(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pWord(pDest)^ := - Pixel.Red shl PIXEL_DESC_R5G6B5.RedShift or - Pixel.Green shl PIXEL_DESC_R5G6B5.GreenShift or - Pixel.Blue; + //TODO +end; - Inc(pDest, 2); +procedure MapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PCardinal(aData)^ := + ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B) and + aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; + inc(aData, 4); end; +//RGB/////////////////////////////////////////////////////////////////////////////////////////////// +procedure MapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); + inc(aData); +end; -procedure MapRGB5A1(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pWord(pDest)^ := - Pixel.Alpha shl PIXEL_DESC_RGB5A1.AlphaShift or - Pixel.Red shl PIXEL_DESC_RGB5A1.RedShift or - Pixel.Green shl PIXEL_DESC_RGB5A1.GreenShift or - Pixel.Blue; + //TODO +end; - Inc(pDest, 2); +procedure MapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO end; +procedure MapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PCardinal(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); + inc(aData, 3); +end; -procedure MapRGB8(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := Pixel.Red; - Inc(pDest); + //TODO +end; - pDest^ := Pixel.Green; - Inc(pDest); +procedure MapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; - pDest^ := Pixel.Blue; - Inc(pDest); +procedure MapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := aPixel.Red; + inc(aData, 2); + PWord(aData)^ := aPixel.Green; + inc(aData, 2); + PWord(aData)^ := aPixel.Blue; + inc(aData, 2); end; +//RGBA////////////////////////////////////////////////////////////////////////////////////////////// +procedure MapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData); +end; -procedure MapBGR8(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDest^ := Pixel.Blue; - Inc(pDest); + PWord(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData, 2); +end; - pDest^ := Pixel.Green; - Inc(pDest); +procedure MapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData, 2); +end; - pDest^ := Pixel.Red; - Inc(pDest); +procedure MapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PCardinal(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData, 4); end; +procedure MapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PCardinal(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData, 4); +end; -procedure MapRGBA8(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDWord(pDest)^ := - Pixel.Alpha shl PIXEL_DESC_RGBA8.AlphaShift or - Pixel.Blue shl PIXEL_DESC_RGBA8.BlueShift or - Pixel.Green shl PIXEL_DESC_RGBA8.GreenShift or - Pixel.Red; + //TODO +end; - Inc(pDest, 4); +procedure MapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := aPixel.Red; + inc(aData, 2); + PWord(aData)^ := aPixel.Green; + inc(aData, 2); + PWord(aData)^ := aPixel.Blue; + inc(aData, 2); + PWord(aData)^ := aPixel.Alpha; + inc(aData, 2); end; +//DEPTH///////////////////////////////////////////////////////////////////////////////////////////// +procedure MapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PWord(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3; + inc(aData, 2); +end; -procedure MapBGRA8(const Pixel: TglBitmapPixelData; var pDest: pByte); +procedure MapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDWord(pDest)^ := - Pixel.Alpha shl PIXEL_DESC_BGRA8.AlphaShift or - Pixel.Red shl PIXEL_DESC_BGRA8.RedShift or - Pixel.Green shl PIXEL_DESC_BGRA8.GreenShift or - Pixel.Blue; + //TODO +end; - Inc(pDest, 4); +procedure MapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + PCardinal(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3; + inc(aData, 4); end; +function FormatGetMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapMapFunc; +begin + case aInternalFormat of + ifAlpha4: result := MapAlpha4; + ifAlpha8: result := MapAlpha8; + ifAlpha12: result := MapAlpha12; + ifAlpha16: result := MapAlpha16; -procedure MapRGB10A2(const Pixel: TglBitmapPixelData; var pDest: pByte); + ifLuminance4: result := MapLuminance4; + ifLuminance8: result := MapLuminance8; + ifLuminance12: result := MapLuminance8; + ifLuminance16: result := MapLuminance8; + + ifLuminance4Alpha4: result := MapLuminance4Alpha4; + ifLuminance6Alpha2: result := MapLuminance6Alpha2; + ifLuminance8Alpha8: result := MapLuminance8Alpha8; + ifLuminance12Alpha4: result := MapLuminance12Alpha4; + ifLuminance12Alpha12: result := MapLuminance12Alpha12; + ifLuminance16Alpha16: result := MapLuminance16Alpha16; + + ifR3G3B2: result := MapR3G3B2; + ifRGB4: result := MapRGB4; + ifRGB5: result := MapRGB5; + ifRGB8: result := MapRGB8; + ifRGB10: result := MapRGB10; + ifRGB12: result := MapRGB12; + ifRGB16: result := MapRGB16; + + ifRGBA2: result := MapRGBA2; + ifRGBA4: result := MapRGBA4; + ifRGB5A1: result := MapRGB5A1; + ifRGBA8: result := MapRGBA8; + ifRGB10A2: result := MapRGB10A2; + ifRGBA12: result := MapRGBA12; + ifRGBA16: result := MapRGBA16; + + ifDepth16: result := MapDepth16; + ifDepth24: result := MapDepth24; + ifDepth32: result := MapDepth32; + else + raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; +end; +{$ENDREGION} + +{$REGION UnmapFunctions} +//ALPHA///////////////////////////////////////////////////////////////////////////////////////////// +procedure UnmapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - pDWord(pDest)^ := - Pixel.Alpha shl PIXEL_DESC_RGB10A2.AlphaShift or - Pixel.Red shl PIXEL_DESC_RGB10A2.RedShift or - Pixel.Green shl PIXEL_DESC_RGB10A2.GreenShift or - Pixel.Blue; - Inc(pDest, 4); end; +procedure UnmapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; -function FormatGetMapFunc(Format: TglBitmapInternalFormat): TglBitmapMapFunc; +procedure UnmapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - case Format of - ifAlpha: Result := MapAlpha; - ifLuminance: Result := MapLuminance; - ifDepth8: Result := MapDepth8; - ifLuminanceAlpha: Result := MapLuminanceAlpha; - ifRGBA4: Result := MapRGBA4; - ifR5G6B5: Result := MapR5G6B5; - ifRGB5A1: Result := MapRGB5A1; - ifRGB8: Result := MapRGB8; - ifBGR8: Result := MapBGR8; - ifRGBA8: Result := MapRGBA8; - ifBGRA8: Result := MapBGRA8; - ifRGB10A2: Result := MapRGB10A2; - else - raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; + end; +//LUMINANCE///////////////////////////////////////////////////////////////////////////////////////// +procedure UnmapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +//LUMINANCE_ALPHA/////////////////////////////////////////////////////////////////////////////////// +procedure UnmapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +//RGB/////////////////////////////////////////////////////////////////////////////////////////////// +procedure UnmapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +//RGBA////////////////////////////////////////////////////////////////////////////////////////////// +procedure UnmapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +//DEPTH///////////////////////////////////////////////////////////////////////////////////////////// +procedure UnmapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + +procedure UnmapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + //TODO +end; + +procedure UnmapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + +end; + + + -{* -** Unmapping -*} procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData); begin Pixel.Alpha := pData^; @@ -1600,25 +2045,50 @@ begin end; -function FormatGetUnMapFunc(Format: TglBitmapInternalFormat): TglBitmapUnMapFunc; -begin - case Format of - ifAlpha: Result := UnmapAlpha; - ifLuminance: Result := UnMapLuminance; - ifDepth8: Result := UnMapDepth8; - ifLuminanceAlpha: Result := UnMapLuminanceAlpha; - ifRGBA4: Result := UnMapRGBA4; - ifR5G6B5: Result := UnMapR5G6B5; - ifRGB5A1: Result := UnMapRGB5A1; - ifRGB8: Result := UnMapRGB8; - ifBGR8: Result := UnMapBGR8; - ifRGBA8: Result := UnMapRGBA8; - ifBGRA8: Result := UnMapBGRA8; - ifRGB10A2: Result := UnMapRGB10A2; - else - raise EglBitmapUnsupportedInternalFormat.Create('FormatGetUnMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); +function FormatGetUnMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapUnMapFunc; +begin + case aInternalFormat of + ifAlpha4: result := UnmapAlpha4; + ifAlpha8: result := UnmapAlpha8; + ifAlpha12: result := UnmapAlpha12; + ifAlpha16: result := UnmapAlpha16; + + ifLuminance4: result := UnmapLuminance4; + ifLuminance8: result := UnmapLuminance8; + ifLuminance12: result := UnmapLuminance8; + ifLuminance16: result := UnmapLuminance8; + + ifLuminance4Alpha4: result := UnmapLuminance4Alpha4; + ifLuminance6Alpha2: result := UnmapLuminance6Alpha2; + ifLuminance8Alpha8: result := UnmapLuminance8Alpha8; + ifLuminance12Alpha4: result := UnmapLuminance12Alpha4; + ifLuminance12Alpha12: result := UnmapLuminance12Alpha12; + ifLuminance16Alpha16: result := UnmapLuminance16Alpha16; + + ifR3G3B2: result := UnmapR3G3B2; + ifRGB4: result := UnmapRGB4; + ifRGB5: result := UnmapRGB5; + ifRGB8: result := UnmapRGB8; + ifRGB10: result := UnmapRGB10; + ifRGB12: result := UnmapRGB12; + ifRGB16: result := UnmapRGB16; + + ifRGBA2: result := UnmapRGBA2; + ifRGBA4: result := UnmapRGBA4; + ifRGB5A1: result := UnmapRGB5A1; + ifRGBA8: result := UnmapRGBA8; + ifRGB10A2: result := UnmapRGB10A2; + ifRGBA12: result := UnmapRGBA12; + ifRGBA16: result := UnmapRGBA16; + + ifDepth16: result := UnmapDepth16; + ifDepth24: result := UnmapDepth24; + ifDepth32: result := UnmapDepth32; + else + raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); end; end; +{$ENDREGION} {* ** Tools @@ -1774,15 +2244,15 @@ function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFile begin Result := []; - {$ifdef GLB_SUPPORT_PNG_WRITE} + {$IFDEF GLB_SUPPORT_PNG_WRITE} if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then Result := Result + [ftPNG]; - {$endif} + {$ENDIF} - {$ifdef GLB_SUPPORT_JPEG_WRITE} + {$IFDEF GLB_SUPPORT_JPEG_WRITE} if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then Result := Result + [ftJPEG]; - {$endif} + {$ENDIF} Result := Result + [ftDDS]; @@ -1871,7 +2341,7 @@ begin end; -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} function CreateGrayPalette: HPALETTE; var Idx: Integer; @@ -1903,10 +2373,10 @@ begin FreeMem(Pal); end; -{$endif} +{$ENDIF} -{$ifdef GLB_SDL_IMAGE} +{$IFDEF GLB_SDL_IMAGE} function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; begin Result := TStream(context^.unknown.data1).Seek(offset, whence); @@ -1944,27 +2414,27 @@ begin Result^.close := glBitmapRWclose; Result^.unknown.data1 := Stream; end; -{$endif} +{$ENDIF} {* ** Helper functions *} -function LoadTexture(Filename: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean; +function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; var glBitmap: TglBitmap2D; begin Result := false; Texture := 0; - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if Instance = 0 then Instance := HInstance; if (LoadFromRes) then glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName) else - {$endif} + {$ENDIF} glBitmap := TglBitmap2D.Create(FileName); try @@ -1981,67 +2451,67 @@ begin end; -function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$ifdef GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$endif}): Boolean; +function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; var CM: TglBitmapCubeMap; begin Texture := 0; - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if Instance = 0 then Instance := HInstance; - {$endif} + {$ENDIF} CM := TglBitmapCubeMap.Create; try CM.DeleteTextureOnFree := False; // Maps - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, PositiveX) else - {$endif} + {$ENDIF} CM.LoadFromFile(PositiveX); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X); - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, NegativeX) else - {$endif} + {$ENDIF} CM.LoadFromFile(NegativeX); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, PositiveY) else - {$endif} + {$ENDIF} CM.LoadFromFile(PositiveY); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, NegativeY) else - {$endif} + {$ENDIF} CM.LoadFromFile(NegativeY); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, PositiveZ) else - {$endif} + {$ENDIF} CM.LoadFromFile(PositiveZ); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); - {$ifdef GLB_DELPHI} + {$IFDEF GLB_DELPHI} if (LoadFromRes) then CM.LoadFromResource(Instance, NegativeZ) else - {$endif} + {$ENDIF} CM.LoadFromFile(NegativeZ); CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); @@ -2072,9 +2542,6 @@ begin end; -{* -** Defaults -*} procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat); begin glBitmapDefaultFormat := Format; @@ -2176,9 +2643,9 @@ end; constructor TglBitmap.Create; begin - {$ifndef GLB_NO_NATIVE_GL} + {$IFNDEF GLB_NO_NATIVE_GL} ReadOpenGLExtensions; - {$endif} + {$ENDIF} if (ClassType = TglBitmap) then raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); @@ -2201,7 +2668,7 @@ begin end; -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar); begin Create; @@ -2222,7 +2689,7 @@ begin Create; LoadFromResourceID(Instance, ResourceID, ResType); end; -{$endif} +{$ENDIF} constructor TglBitmap.Create(Size: TglBitmapPixelPosition; @@ -2323,12 +2790,12 @@ end; procedure TglBitmap.LoadFromStream(Stream: TStream); begin - {$ifdef GLB_SUPPORT_PNG_READ} + {$IFDEF GLB_SUPPORT_PNG_READ} if not LoadPNG(Stream) then - {$endif} - {$ifdef GLB_SUPPORT_JPEG_READ} + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_READ} if not LoadJPEG(Stream) then - {$endif} + {$ENDIF} if not LoadDDS(Stream) then if not LoadTGA(Stream) then if not LoadBMP(Stream) then @@ -2336,7 +2803,7 @@ begin end; -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar); var RS: TResourceStream; @@ -2374,7 +2841,7 @@ begin RS.Free; end; end; -{$endif} +{$ENDIF} @@ -2416,12 +2883,12 @@ end; procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType); begin case FileType of - {$ifdef GLB_SUPPORT_PNG_WRITE} + {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG: SavePng(Stream); - {$endif} - {$ifdef GLB_SUPPORT_JPEG_WRITE} + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_WRITE} ftJPEG: SaveJPEG(Stream); - {$endif} + {$ENDIF} ftDDS: SaveDDS(Stream); ftTGA: SaveTGA(Stream); ftBMP: SaveBMP(Stream); @@ -2429,7 +2896,7 @@ begin end; -{$ifdef GLB_SDL} +{$IFDEF GLB_SDL} function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean; var Row, RowSize: Integer; @@ -2631,10 +3098,10 @@ begin glBitmap.Free; end; end; -{$endif} +{$ENDIF} -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean; var pSource, pData, pTempData: PByte; @@ -2796,7 +3263,7 @@ begin glBitmap.Free; end; end; -{$endif} +{$ENDIF} function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean; @@ -2825,7 +3292,7 @@ begin end; -{$ifdef GLB_DELPHI} +{$IFDEF GLB_DELPHI} function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String; ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean; var @@ -2865,7 +3332,7 @@ begin RS.Free; end; end; -{$endif} +{$ENDIF} procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec); @@ -2886,7 +3353,8 @@ begin end; -function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue, Deviation: Byte): Boolean; +function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte + ): Boolean; begin Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF); end; @@ -2996,7 +3464,7 @@ begin end; -procedure TglBitmap.Invert(UseRGB, UseAlpha: Boolean); +procedure TglBitmap.Invert(UseRGB: Boolean; UseAlpha: Boolean); begin if ((UseRGB) or (UseAlpha)) then AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB))); @@ -3153,7 +3621,8 @@ begin end; -procedure TglBitmap.SetDataPointer(NewData: PByte; Format: TglBitmapInternalFormat; Width, Height: Integer); +procedure TglBitmap.SetDataPointer(NewData: pByte; + Format: TglBitmapInternalFormat; Width: Integer; Height: Integer); begin // Data if Data <> NewData then begin @@ -3184,17 +3653,17 @@ begin end; end; -{$ifdef GLB_SUPPORT_PNG_READ} -{$ifdef GLB_LIB_PNG} +{$IFDEF GLB_SUPPORT_PNG_READ} +{$IFDEF GLB_LIB_PNG} procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; begin TStream(png_get_io_ptr(png)).Read(buffer^, size); end; -{$endif} +{$ENDIF} function TglBitmap.LoadPNG(Stream: TStream): Boolean; -{$ifdef GLB_SDL_IMAGE} +{$IFDEF GLB_SDL_IMAGE} var Surface: PSDL_Surface; RWops: PSDL_RWops; @@ -3216,8 +3685,8 @@ begin SDL_FreeRW(RWops); end; end; -{$endif} -{$ifdef GLB_LIB_PNG} +{$ENDIF} +{$IFDEF GLB_LIB_PNG} var StreamPos: Int64; signature: array [0..7] of byte; @@ -3321,8 +3790,8 @@ begin quit_libPNG; end; end; -{$endif} -{$ifdef GLB_PNGIMAGE} +{$ENDIF} +{$IFDEF GLB_PNGIMAGE} var StreamPos: Int64; Png: TPNGObject; @@ -3410,11 +3879,11 @@ begin end; end; end; -{$endif} -{$endif} +{$ENDIF} +{$ENDIF} -{$ifdef GLB_LIB_JPEG} +{$IFDEF GLB_LIB_JPEG} type glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr; glBitmap_libJPEG_source_mgr = record @@ -3557,12 +4026,12 @@ begin dest^.DestStream.Write(dest^.DestBuffer[Idx], 1); end; end; -{$endif} +{$ENDIF} -{$ifdef GLB_SUPPORT_JPEG_READ} +{$IFDEF GLB_SUPPORT_JPEG_READ} function TglBitmap.LoadJPEG(Stream: TStream): Boolean; -{$ifdef GLB_SDL_IMAGE} +{$IFDEF GLB_SDL_IMAGE} var Surface: PSDL_Surface; RWops: PSDL_RWops; @@ -3584,8 +4053,8 @@ begin SDL_FreeRW(RWops); end; end; -{$endif} -{$ifdef GLB_LIB_JPEG} +{$ENDIF} +{$IFDEF GLB_LIB_JPEG} var StreamPos: Int64; Temp: array[0..1]of Byte; @@ -3693,8 +4162,8 @@ begin quit_libJPEG; end; end; -{$endif} -{$ifdef GLB_DELPHI_JPEG} +{$ENDIF} +{$IFDEF GLB_DELPHI_JPEG} var bmp: TBitmap; jpg: TJPEGImage; @@ -3725,8 +4194,8 @@ begin end; end; end; -{$endif} -{$endif} +{$ENDIF} +{$ENDIF} const @@ -3980,6 +4449,59 @@ type dwReserved2: Cardinal; end; +procedure TglBitmap.SetCustomData(const aValue: Pointer); +begin + if fCustomData = aValue then Exit; + fCustomData := aValue; +end; + +procedure TglBitmap.SetCustomName(const aValue: String); +begin + if fCustomName = aValue then Exit; + fCustomName := aValue; +end; + +procedure TglBitmap.SetCustomNameW(const aValue: WideString); +begin + if fCustomNameW = aValue then Exit; + fCustomNameW := aValue; +end; + +procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean); +begin + if fDeleteTextureOnFree = aValue then Exit; + fDeleteTextureOnFree := aValue; +end; + +procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat); +begin + if fFormat = aValue then Exit; + fFormat := aValue; +end; + +procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean); +begin + if fFreeDataAfterGenTexture = aValue then Exit; + fFreeDataAfterGenTexture := aValue; +end; + +procedure TglBitmap.SetID(const aValue: Cardinal); +begin + if fID = aValue then Exit; + fID := aValue; +end; + +procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap); +begin + if fMipMap = aValue then Exit; + fMipMap := aValue; +end; + +procedure TglBitmap.SetTarget(const aValue: Cardinal); +begin + if fTarget = aValue then Exit; + fTarget := aValue; +end; function TglBitmap.LoadDDS(Stream: TStream): Boolean; var @@ -4381,16 +4903,16 @@ begin end; -{$ifdef GLB_SUPPORT_PNG_WRITE} -{$ifdef GLB_LIB_PNG} +{$IFDEF GLB_SUPPORT_PNG_WRITE} +{$IFDEF GLB_LIB_PNG} procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; begin TStream(png_get_io_ptr(png)).Write(buffer^, size); end; -{$endif} +{$ENDIF} procedure TglBitmap.SavePNG(Stream: TStream); -{$ifdef GLB_LIB_PNG} +{$IFDEF GLB_LIB_PNG} var png: png_structp; png_info: png_infop; @@ -4471,8 +4993,8 @@ begin quit_libPNG; end; end; -{$endif} -{$ifdef GLB_PNGIMAGE} +{$ENDIF} +{$IFDEF GLB_PNGIMAGE} var Png: TPNGObject; @@ -4556,8 +5078,8 @@ begin FreeAndNil(Png); end; end; -{$endif} -{$endif} +{$ENDIF} +{$ENDIF} procedure TglBitmap.SaveDDS(Stream: TStream); @@ -4704,9 +5226,9 @@ begin end; -{$ifdef GLB_SUPPORT_JPEG_WRITE} +{$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure TglBitmap.SaveJPEG(Stream: TStream); -{$ifdef GLB_LIB_JPEG} +{$IFDEF GLB_LIB_JPEG} var jpeg: jpeg_compress_struct; jpeg_err: jpeg_error_mgr; @@ -4825,8 +5347,8 @@ begin quit_libJPEG; end; end; -{$endif} -{$ifdef GLB_DELPHI_JPEG} +{$ENDIF} +{$IFDEF GLB_DELPHI_JPEG} var Bmp: TBitmap; Jpg: TJPEGImage; @@ -4855,8 +5377,8 @@ begin FreeAndNil(Bmp); end; end; -{$endif} -{$endif} +{$ENDIF} +{$ENDIF} procedure TglBitmap.SaveBMP(Stream: TStream); @@ -5303,13 +5825,13 @@ begin end; -procedure TglBitmap.FillWithColor(Red, Green, Blue, Alpha: Byte); +procedure TglBitmap.FillWithColor(Red, Green, Blue: Byte; Alpha: Byte); begin FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF); end; -procedure TglBitmap.FillWithColorFloat(Red, Green, Blue, Alpha: Single); +procedure TglBitmap.FillWithColorFloat(Red, Green, Blue: Single; Alpha: Single); var PixelData: TglBitmapPixelData; begin @@ -5324,7 +5846,8 @@ begin end; -procedure TglBitmap.FillWithColorRange(Red, Green, Blue, Alpha: Cardinal); +procedure TglBitmap.FillWithColorRange(Red, Green, Blue: Cardinal; + Alpha: Cardinal); var PixelData: TglBitmapPixelData; begin @@ -5338,7 +5861,7 @@ begin end; -procedure TglBitmap.SetAnisotropic(const Value: Integer); +procedure TglBitmap.SetAnisotropic(const aValue: Integer); var MaxAniso: Integer; begin @@ -5363,7 +5886,7 @@ begin end; -procedure TglBitmap.SetInternalFormat(const Value: TglBitmapInternalFormat); +procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapInternalFormat); begin if InternalFormat <> Value then begin if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then From 13ac4110b1bb19f7799e5439411be7bde6639ef7 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 24 Oct 2013 18:50:00 +0200 Subject: [PATCH 04/38] * refactored FormatDescriptors --- glBitmap.pas | 2878 +++++++++++++++++++++----------------------------- 1 file changed, 1215 insertions(+), 1663 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 1a21c20..04f4a9f 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -583,23 +583,25 @@ var *) type - EglBitmapException = class(Exception); - EglBitmapSizeToLargeException = class(EglBitmapException); - EglBitmapNonPowerOfTwoException = class(EglBitmapException); - EglBitmapUnsupportedInternalFormat = class(EglBitmapException); +//////////////////////////////////////////////////////////////////////////////////////////////////// + EglBitmapException = class(Exception); + EglBitmapSizeToLargeException = class(EglBitmapException); + EglBitmapNonPowerOfTwoException = class(EglBitmapException); + EglBitmapUnsupportedFormatFormat = class(EglBitmapException); +//////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapPixelDesc = packed record RedRange: Cardinal; - GreenRange: Cardinal; - BlueRange: Cardinal; - AlphaRange: Cardinal; - RedShift: Shortint; + GreenRange: Cardinal; GreenShift: Shortint; + BlueRange: Cardinal; BlueShift: Shortint; + AlphaRange: Cardinal; AlphaShift: Shortint; end; +//////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapPixelData = packed record Red: Cardinal; Green: Cardinal; @@ -608,6 +610,14 @@ type PixelDesc: TglBitmapPixelDesc; end; +//////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmapFormatDesc = packed record + Format: Cardinal; + InternalFormat: Cardinal; + DataType: Cardinal; + end; + +//////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapPixelPositionFields = set of (ffX, ffY); TglBitmapPixelPosition = record Fields : TglBitmapPixelPositionFields; @@ -615,12 +625,8 @@ type Y : Word; end; -const - NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0); - -type +//////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class; - TglBitmapFunctionRec = record Sender : TglBitmap; Size: TglBitmapPixelPosition; @@ -629,17 +635,9 @@ type Dest: TglBitmapPixelData; CustomData: Pointer; end; - TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); - TglBitmapGetPixel = procedure ( - const Pos: TglBitmapPixelPosition; - var Pixel: TglBitmapPixelData) of object; - - TglBitmapSetPixel = procedure ( - const Pos: TglBitmapPixelPosition; - const Pixel: TglBitmapPixelData) of object; - +//////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapFileType = ( {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} @@ -652,66 +650,95 @@ type mmNone, mmMipmap, mmMipmapGlu); + TglBitmapNormalMapFunc = ( nm4Samples, nmSobel, nm3x3, nm5x5); + TglBitmapFormat = ( - tfRed = GL_RED, - tfGreen = GL_GREEN, - tfBlue = GL_BLUE, - tfAlpha = GL_ALPHA, - tfRGB = GL_RGB, - tfBGR = GL_BGR, - tfRGBA = GL_RGBA, - tfBGRA = GL_BGRA, - tfLuminance = GL_LUMINANCE, - tfLuminanceAlpha = GL_LUMINANCE_ALPHA - ); - TglBitmapInternalFormat = ( - ifAlpha4 = GL_ALPHA4, - ifAlpha8 = GL_ALPHA8, - ifAlpha12 = GL_ALPHA12, - ifAlpha16 = GL_ALPHA16, - - ifLuminance4 = GL_LUMINANCE4, - ifLuminance8 = GL_LUMINANCE8, - ifLuminance12 = GL_LUMINANCE12, - ifLuminance16 = GL_LUMINANCE16, - - ifLuminance4Alpha4 = GL_LUMINANCE4_ALPHA4, - ifLuminance6Alpha2 = GL_LUMINANCE6_ALPHA2, - ifLuminance8Alpha8 = GL_LUMINANCE8_ALPHA8, - ifLuminance12Alpha4 = GL_LUMINANCE12_ALPHA4, - ifLuminance12Alpha12 = GL_LUMINANCE12_ALPHA12, - ifLuminance16Alpha16 = GL_LUMINANCE16_ALPHA16, - - ifR3G3B2 = GL_R3_G3_B2, - ifRGB4 = GL_RGB4, - ifRGB5 = GL_RGB5, - ifRGB8 = GL_RGB8, - ifRGB10 = GL_RGB10, - ifRGB12 = GL_RGB12, - ifRGB16 = GL_RGB16, - - ifRGBA2 = GL_RGBA2, - ifRGBA4 = GL_RGBA4, - ifRGB5A1 = GL_RGB5_A1, - ifRGBA8 = GL_RGBA8, - ifRGB10A2 = GL_RGB10_A2, - ifRGBA12 = GL_RGBA12, - ifRGBA16 = GL_RGBA16, - - ifDepth16 = GL_DEPTH_COMPONENT16, - ifDepth24 = GL_DEPTH_COMPONENT24, - ifDepth32 = GL_DEPTH_COMPONENT32 + tfEmpty = 0, + { TODO + tfAlpha4, + tfAlpha8, + tfAlpha12, + tfAlpha16, + + tfLuminance4, } + tfLuminance8, +{ tfLuminance12, + tfLuminance16, + + tfuminance4Alpha4, + tfLuminance6Alpha2,} + tfLuminance8Alpha8, +{ tfLuminance12Alpha4, + tfLuminance12Alpha12, + tfLuminance16Alpha16, + + tfR3G3B2, + tfRGB4, + tfRGB5, } + tfRGB8, +{ tfRGB10, + tfRGB12, + tfRGB16, + + tfRGBA2, + tfRGBA4, + tfRGB5A1, } + tfRGBA8, +{ tfRGB10A2, + tfRGBA12, + tfRGBA16, + } + tfBGR8, + tfBGRA8, + { + tfDepth16, + tfDepth24, + tfDepth32 } ); - // Pixelmapping +//////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmapGetPixel = procedure(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData) of object; + TglBitmapSetPixel = procedure(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData) of object; + TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +//////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmapFormatDescriptor = class(TObject) + public + //virtual abstract + class function GetFormat: TglBitmapFormat; virtual; abstract; + class function GetPixelDesc: TglBitmapPixelDesc; virtual; abstract; + class function GetFormatDesc: TglBitmapFormatDesc; virtual; abstract; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); virtual; abstract; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); virtual; abstract; + + //virtual + class function WithoutAlpha: TglBitmapFormat; virtual; + class function WithAlpha: TglBitmapFormat; virtual; + + class function IsEmpty: Boolean; virtual; + class function HasAlpha: Boolean; virtual; + class function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; + + class procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual; + + (* TODO + function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; + function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; + function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; + function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; + function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; + *) + end; + TglBitmapFormatDescClass = class of TglBitmapFormatDescriptor; + // Base Class TglBitmap = class protected @@ -727,7 +754,6 @@ type fDimension: TglBitmapPixelPosition; fMipMap: TglBitmapMipMap; fFormat: TglBitmapFormat; - fInternalFormat: TglBitmapInternalFormat; // Mapping fPixelSize: Integer; @@ -768,7 +794,6 @@ type procedure SetMipMap(const aValue: TglBitmapMipMap); procedure SetTarget(const aValue: Cardinal); procedure SetAnisotropic(const aValue: Integer); - procedure SetInternalFormat(const aValue: TglBitmapInternalFormat); //Load {$IFDEF GLB_SUPPORT_PNG_READ} @@ -793,10 +818,10 @@ type procedure SaveBMP(Stream: TStream); virtual; procedure CreateID; - procedure SetupParameters(var BuildWithGlu: Boolean); - procedure SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True); + procedure SetupParameters(var aBuildWithGlu: Boolean); + procedure SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal); - procedure SetDataPointer(NewData: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); virtual; + procedure SetDataPointer(NewData: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); virtual; procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract; function FlipHorz: Boolean; virtual; @@ -805,12 +830,11 @@ type property Width: Integer read GetWidth; property Height: Integer read GetHeight; public - property ID: Cardinal read fID write SetID; - property Target: Cardinal read fTarget write SetTarget; - property Format: TglBitmapFormat read fFormat write SetFormat; - property InternalFormat: TglBitmapInternalFormat read fInternalFormat write SetInternalFormat; - property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; - property Anisotropic: Integer read fAnisotropic write SetAnisotropic; + property ID: Cardinal read fID write SetID; + property Target: Cardinal read fTarget write SetTarget; + property Format: TglBitmapFormat read fFormat write SetFormat; + property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; + property Anisotropic: Integer read fAnisotropic write SetAnisotropic; property Filename: String read fFilename; property CustomName: String read fCustomName write SetCustomName; @@ -831,17 +855,16 @@ type procedure LoadFromFile(const aFileName: String); procedure LoadFromStream(const aStream: TStream); virtual; procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; - const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat; - const aArgs: PtrInt = 0); + const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0); {$IFDEF GLB_DELPHI} - procedure LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar = nil); - procedure LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); + procedure LoadFromResource(const aInstance: Cardinal; aResource: String; const aResType: PChar = nil); + procedure LoadFromResourceID(const sInstance: Cardinal; aResourceID: Integer; const aResType: PChar); {$ENDIF} procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual; - //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer = nil): boolean; overload; + //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer = nil): boolean; overload; //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload; (* TODO {$IFDEF GLB_SDL} @@ -881,7 +904,7 @@ type function RemoveAlpha: Boolean; virtual; function Clone: TglBitmap; - function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat): Boolean; virtual; + function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapFormat): Boolean; virtual; procedure SetBorderColor(Red, Green, Blue, Alpha: Single); procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false); procedure FreeData; @@ -910,8 +933,8 @@ type constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload; constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload; {$ENDIF} - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat); overload; - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat); overload; + constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; end; @@ -929,7 +952,7 @@ type procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); - procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override; + procedure SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); override; procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); public property Width; @@ -938,7 +961,7 @@ type procedure AfterConstruction; override; - procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapInternalFormat); + procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat); procedure GetDataFromTexture; procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False); procedure GenTexture(TestTextureSize: Boolean = True); override; @@ -992,10 +1015,13 @@ type end; *) +const + NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0); + procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean); procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean); +procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap); procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat); -procedure glBitmapSetDefaultInternalFormat(const aInternalFormat: TglBitmapInternalFormat); procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer); procedure glBitmapSetDefaultWrap( const S: Cardinal = GL_CLAMP_TO_EDGE; @@ -1004,37 +1030,21 @@ procedure glBitmapSetDefaultWrap( function glBitmapGetDefaultDeleteTextureOnFree: Boolean; function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; +function glBitmapGetDefaultMipmap: TglBitmapMipMap; function glBitmapGetDefaultFormat: TglBitmapFormat; -function glBitmapGetDefaultInternalFormat: TglBitmapInternalFormat; procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal); procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); -// position / size function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; // Formatfunctions -function FormatGetSize(Format: TglBitmapInternalFormat): Single; -function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; -function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; -function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean; -function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean; -procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat); -function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; -function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; -function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean; - - -(* TODO -function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; -function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; -function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; -*) +function FormatGetSize(const aFormat: TglBitmapFormat): Single; var glBitmapDefaultDeleteTextureOnFree: Boolean; glBitmapDefaultFreeDataAfterGenTextures: Boolean; glBitmapDefaultFormat: TglBitmapFormat; - glBitmapDefaultInternalFormat: TglBitmapInternalFormat; + glBitmapDefaultMipmap: TglBitmapMipMap; glBitmapDefaultFilterMin: Cardinal; glBitmapDefaultFilterMag: Cardinal; glBitmapDefaultWrapS: Cardinal; @@ -1050,7 +1060,180 @@ implementation uses Math; -(* TODO +type +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdEmpty = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdLuminance8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdLuminance8Alpha8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithoutAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdRGB8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdRGBA8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithoutAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdBGR8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdBGRA8 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithoutAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; + class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + end; + +const + LUMINANCE_WEIGHT_R = 0.30; + LUMINANCE_WEIGHT_G = 0.59; + LUMINANCE_WEIGHT_B = 0.11; + UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.'; + +{$REGION Private Helper} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; +begin + Result.Fields := []; + + if X >= 0 then + Result.Fields := Result.Fields + [ffX]; + if Y >= 0 then + Result.Fields := Result.Fields + [ffY]; + + Result.X := Max(0, X); + Result.Y := Max(0, Y); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function FormatGetImageSize(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat): Integer; +begin + if (aSize.X = 0) and (aSize.Y = 0) then + Result := 0 + else + Result := Ceil(Max(aSize.Y, 1) * Max(aSize.X, 1) * FormatGetSize(aFormat)); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; +begin + //TODO check Formats! + result := []; + + {$IFDEF GLB_SUPPORT_PNG_WRITE} + if aFormat in [ + tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, + tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, + tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16, + tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, + tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16, + tfDepth16, tfDepth24, tfDepth32] + then + result := result + [ftPNG]; + {$ENDIF} + + {$IFDEF GLB_SUPPORT_JPEG_WRITE} + if Format in [ + tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, + tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, + tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, + tfDepth16, tfDepth24, tfDepth32] + then + result := result + [ftJPEG]; + {$ENDIF} + + if aFormat in [ + tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, + tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, + tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16, + tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, + tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16, + tfDepth16, tfDepth24, tfDepth32] + then + result := result + [ftDDS, ftTGA, ftBMP]; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function IsPowerOfTwo(aNumber: Integer): Boolean; +begin + while (aNumber and 1) = 0 do + aNumber := aNumber shr 1; + result := aNumber = 1; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function GetBitSize(aBitSet: Cardinal): Integer; +begin + result := 0; + while aBitSet > 0 do begin + if (aBitSet and 1) = 1 then + inc(result); + aBitSet := aBitSet shr 1; + end; +end; +{$ENDREGION} + +(* GLB_NO_NATIVE_GL {$IFNDEF GLB_NO_NATIVE_GL} procedure ReadOpenGLExtensions; var @@ -1191,1456 +1374,1146 @@ end; {$ENDIF} *) -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; +(* TODO GLB_DELPHI +{$IFDEF GLB_DELPHI} +function CreateGrayPalette: HPALETTE; +var + Idx: Integer; + Pal: PLogPalette; begin - Result.Fields := []; - - if X >= 0 then - Result.Fields := Result.Fields + [ffX]; - if Y >= 0 then - Result.Fields := Result.Fields + [ffY]; - - Result.X := Max(0, X); - Result.Y := Max(0, Y); -end; + GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256)); + Pal.palVersion := $300; + Pal.palNumEntries := 256; -const - LUMINANCE_WEIGHT_R = 0.30; - LUMINANCE_WEIGHT_G = 0.59; - LUMINANCE_WEIGHT_B = 0.11; - UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.'; + {$IFOPT R+} + {$DEFINE GLB_TEMPRANGECHECK} + {$R-} + {$ENDIF} -{$REGION PixelDescription} -const - //ifAlpha4//////////////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_ALPHA4: TglBitmapPixelDesc = ( - RedRange: $00000000; RedShift: 0; - GreenRange: $00000000; GreenShift: 0; - BlueRange: $00000000; BlueShift: 0; - AlphaRange: $0000000F; AlphaShift: 0); - - //ifAlpha8 - PIXEL_DESC_ALPHA8: TglBitmapPixelDesc = ( - RedRange: $00000000; RedShift: 0; - GreenRange: $00000000; GreenShift: 0; - BlueRange: $00000000; BlueShift: 0; - AlphaRange: $000000FF; AlphaShift: 0); - - //ifAlpha12 - PIXEL_DESC_ALPHA12: TglBitmapPixelDesc = ( - RedRange: $00000000; RedShift: 0; - GreenRange: $00000000; GreenShift: 0; - BlueRange: $00000000; BlueShift: 0; - AlphaRange: $00000FFF; AlphaShift: 0); - - //ifAlpha16 - PIXEL_DESC_ALPHA16: TglBitmapPixelDesc = ( - RedRange: $00000000; RedShift: 0; - GreenRange: $00000000; GreenShift: 0; - BlueRange: $00000000; BlueShift: 0; - AlphaRange: $0000FFFF; AlphaShift: 0); - - //ifLuminance4//////////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_LUMINANCE4: TglBitmapPixelDesc = ( - RedRange: $0000000F; RedShift: 0; - GreenRange: $0000000F; GreenShift: 0; - BlueRange: $0000000F; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); - - //ifLuminance8 - PIXEL_DESC_LUMINANCE8: TglBitmapPixelDesc = ( - RedRange: $000000FF; RedShift: 0; - GreenRange: $000000FF; GreenShift: 0; - BlueRange: $000000FF; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); - - //ifLuminance12 - PIXEL_DESC_LUMINANCE12: TglBitmapPixelDesc = ( - RedRange: $00000FFF; RedShift: 0; - GreenRange: $00000FFF; GreenShift: 0; - BlueRange: $00000FFF; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); - - //ifLuminance16 - PIXEL_DESC_LUMINANCE16: TglBitmapPixelDesc = ( - RedRange: $0000FFFF; RedShift: 0; - GreenRange: $0000FFFF; GreenShift: 0; - BlueRange: $0000FFFF; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); - - //ifLuminance4Alpha4////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_LUMINANCE4_ALPHA4: TglBitmapPixelDesc = ( - RedRange: $0000000F; RedShift: 0; - GreenRange: $0000000F; GreenShift: 0; - BlueRange: $0000000F; BlueShift: 0; - AlphaRange: $0000000F; AlphaShift: 4); - //ifLuminance6Alpha2 - PIXEL_DESC_LUMINANCE6_ALPHA2: TglBitmapPixelDesc = ( - RedRange: $0000003F; RedShift: 0; - GreenRange: $0000003F; GreenShift: 0; - BlueRange: $0000003F; BlueShift: 0; - AlphaRange: $00000003; AlphaShift: 6); - - //ifLuminance8Alpha8 - PIXEL_DESC_LUMINANCE8_ALPHA8: TglBitmapPixelDesc = ( - RedRange: $000000FF; RedShift: 0; - GreenRange: $000000FF; GreenShift: 0; - BlueRange: $000000FF; BlueShift: 0; - AlphaRange: $000000FF; AlphaShift: 8); - - //ifLuminance12Alpha4 - PIXEL_DESC_LUMINANCE12_ALPHA4: TglBitmapPixelDesc = ( - RedRange: $00000FFF; RedShift: 0; - GreenRange: $00000FFF; GreenShift: 0; - BlueRange: $00000FFF; BlueShift: 0; - AlphaRange: $0000000F; AlphaShift: 12); - - //ifLuminance12Alpha12 - PIXEL_DESC_LUMINANCE12_ALPHA12: TglBitmapPixelDesc = ( - RedRange: $00000FFF; RedShift: 0; - GreenRange: $00000FFF; GreenShift: 0; - BlueRange: $00000FFF; BlueShift: 0; - AlphaRange: $00000FFF; AlphaShift: 12); - - //ifLuminance16Alpha16 - PIXEL_DESC_LUMINANCE16_ALPHA16: TglBitmapPixelDesc = ( - RedRange: $0000FFFF; RedShift: 0; - GreenRange: $0000FFFF; GreenShift: 0; - BlueRange: $0000FFFF; BlueShift: 0; - AlphaRange: $0000FFFF; AlphaShift: 16); - - //ifR3G3B2//////////////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_R3_G3_B2: TglBitmapPixelDesc = ( - RedRange: $00000007; RedShift: 0; - GreenRange: $00000007; GreenShift: 3; - BlueRange: $00000003; BlueShift: 6; - AlphaRange: $00000000; AlphaShift: 0); - - //ifRGB4 - PIXEL_DESC_RGB4: TglBitmapPixelDesc = ( - RedRange: $0000000F; RedShift: 0; - GreenRange: $0000000F; GreenShift: 4; - BlueRange: $0000000F; BlueShift: 8; - AlphaRange: $00000000; AlphaShift: 0); - - //ifRGB5 - PIXEL_DESC_RGB5: TglBitmapPixelDesc = ( - RedRange: $0000001F; RedShift: 0; - GreenRange: $0000001F; GreenShift: 5; - BlueRange: $0000001F; BlueShift: 10; - AlphaRange: $00000000; AlphaShift: 0); - - //ifRGB8 - PIXEL_DESC_RGB8: TglBitmapPixelDesc = ( - RedRange: $000000FF; RedShift: 0; - GreenRange: $000000FF; GreenShift: 8; - BlueRange: $000000FF; BlueShift: 16; - AlphaRange: $00000000; AlphaShift: 0); - - //ifRGB10 - PIXEL_DESC_RGB10: TglBitmapPixelDesc = ( - RedRange: $000003FF; RedShift: 0; - GreenRange: $000003FF; GreenShift: 10; - BlueRange: $000003FF; BlueShift: 20; - AlphaRange: $000003FF; AlphaShift: 0); - - //ifRGB12 - PIXEL_DESC_RGB12: TglBitmapPixelDesc = ( - RedRange: $00000000; RedShift: 0; - GreenRange: $00000000; GreenShift: 0; - BlueRange: $00000000; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); - - //ifRGB16 - PIXEL_DESC_RGB16: TglBitmapPixelDesc = ( - RedRange: $0000FFFF; RedShift: 0; - GreenRange: $0000FFFF; GreenShift: 16; - BlueRange: $0000FFFF; BlueShift: 32; - AlphaRange: $0000FFFF; AlphaShift: 0); - - //ifRGBA2///////////////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_RGBA2: TglBitmapPixelDesc = ( - RedRange: $00000003; RedShift: 0; - GreenRange: $00000003; GreenShift: 2; - BlueRange: $00000003; BlueShift: 4; - AlphaRange: $00000003; AlphaShift: 6); - - //ifRGBA4 - PIXEL_DESC_RGBA4: TglBitmapPixelDesc = ( - RedRange: $0000000F; RedShift: 0; - GreenRange: $0000000F; GreenShift: 4; - BlueRange: $0000000F; BlueShift: 8; - AlphaRange: $0000000F; AlphaShift: 12); - - //ifRGB5A1 - PIXEL_DESC_RGB5_A1: TglBitmapPixelDesc = ( - RedRange: $0000001F; RedShift: 0; - GreenRange: $0000001F; GreenShift: 5; - BlueRange: $0000001F; BlueShift: 10; - AlphaRange: $00000001; AlphaShift: 11); - - //ifRGBA8 - PIXEL_DESC_RGBA8: TglBitmapPixelDesc = ( - RedRange: $000000FF; RedShift: 0; - GreenRange: $000000FF; GreenShift: 8; - BlueRange: $000000FF; BlueShift: 16; - AlphaRange: $000000FF; AlphaShift: 24); - - //ifRGB10A2 - PIXEL_DESC_RGB10_A2: TglBitmapPixelDesc = ( - RedRange: $000003FF; RedShift: 0; - GreenRange: $000003FF; GreenShift: 10; - BlueRange: $000003FF; BlueShift: 20; - AlphaRange: $00000003; AlphaShift: 22); - - //ifRGBA12 - PIXEL_DESC_RGBA12: TglBitmapPixelDesc = ( - RedRange: $00000FFF; RedShift: 0; - GreenRange: $00000FFF; GreenShift: 12; - BlueRange: $00000FFF; BlueShift: 24; - AlphaRange: $00000FFF; AlphaShift: 36); - - //ifRGBA16 - PIXEL_DESC_RGBA16: TglBitmapPixelDesc = ( - RedRange: $0000FFFF; RedShift: 0; - GreenRange: $0000FFFF; GreenShift: 16; - BlueRange: $0000FFFF; BlueShift: 32; - AlphaRange: $0000FFFF; AlphaShift: 48); - - //ifDepthComponent16////////////////////////////////////////////////////////////////////////////// - PIXEL_DESC_DEPTH16: TglBitmapPixelDesc = ( - RedRange: $0000FFFF; RedShift: 0; - GreenRange: $0000FFFF; GreenShift: 0; - BlueRange: $0000FFFF; BlueShift: 0; - AlphaRange: $0000FFFF; AlphaShift: 0); - - //ifDepthComponent24 - PIXEL_DESC_DEPTH24: TglBitmapPixelDesc = ( - RedRange: $00FFFFFF; RedShift: 0; - GreenRange: $00FFFFFF; GreenShift: 0; - BlueRange: $00FFFFFF; BlueShift: 0; - AlphaRange: $00FFFFFF; AlphaShift: 0); - - //ifDepthComponent32 - PIXEL_DESC_DEPTH32: TglBitmapPixelDesc = ( - RedRange: $FFFFFFFF; RedShift: 0; - GreenRange: $FFFFFFFF; GreenShift: 0; - BlueRange: $FFFFFFFF; BlueShift: 0; - AlphaRange: $00000000; AlphaShift: 0); -{$ENDREGION} + for Idx := 0 to 256 - 1 do begin + Pal.palPalEntry[Idx].peRed := Idx; + Pal.palPalEntry[Idx].peGreen := Idx; + Pal.palPalEntry[Idx].peBlue := Idx; + Pal.palPalEntry[Idx].peFlags := 0; + end; -{$REGION MapFunctions} -//ALPHA///////////////////////////////////////////////////////////////////////////////////////////// -procedure MapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO -end; + {$IFDEF GLB_TEMPRANGECHECK} + {$UNDEF GLB_TEMPRANGECHECK} + {$R+} + {$ENDIF} -procedure MapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - aData^ := aPixel.Alpha; - inc(aData); -end; + Result := CreatePalette(Pal^); -procedure MapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO + FreeMem(Pal); end; +{$ENDIF} +*) -procedure MapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +(* TODO GLB_SDL_IMAGE +{$IFDEF GLB_SDL_IMAGE} +function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; begin - PWord(aData)^ := aPixel.Alpha; - inc(aData, 2); + Result := TStream(context^.unknown.data1).Seek(offset, whence); end; -//LUMINANCE///////////////////////////////////////////////////////////////////////////////////////// -procedure MapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl; begin - //TODO + Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum); end; -procedure MapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl; begin - aData^ := Trunc( - aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B); - inc(aData); + Result := TStream(context^.unknown.data1).Write(Ptr^, size * num); end; -procedure MapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl; begin - //TODO + Result := 0; end; -procedure MapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function glBitmapCreateRWops(Stream: TStream): PSDL_RWops; begin - PWord(aData)^ := Trunc( - aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B); - inc(aData, 2); -end; + Result := SDL_AllocRW; -//LUMINANCE_ALPHA/////////////////////////////////////////////////////////////////////////////////// -procedure MapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - aData^ := - ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B) and - aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; - inc(aData); -end; + if Result = nil then + raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.'); -procedure MapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - MapLuminance4Alpha4(aPixel, aData, aBitOffset); + Result^.seek := glBitmapRWseek; + Result^.read := glBitmapRWread; + Result^.write := glBitmapRWwrite; + Result^.close := glBitmapRWclose; + Result^.unknown.data1 := Stream; end; +{$ENDIF} +*) -procedure MapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +(* TODO LoadFuncs +function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; +var + glBitmap: TglBitmap2D; begin - PWord(aData)^ := - ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B) and - aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; - inc(aData, 2); -end; + Result := false; + Texture := 0; -procedure MapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - MapLuminance8Alpha8(aPixel, aData, aBitOffset); -end; + {$IFDEF GLB_DELPHI} + if Instance = 0 then + Instance := HInstance; -procedure MapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO -end; + if (LoadFromRes) then + glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName) + else + {$ENDIF} + glBitmap := TglBitmap2D.Create(FileName); -procedure MapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - PCardinal(aData)^ := - ((Trunc(aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B) and - aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift; - inc(aData, 4); + try + glBitmap.DeleteTextureOnFree := False; + glBitmap.FreeDataAfterGenTexture := False; + glBitmap.GenTexture(True); + if (glBitmap.ID > 0) then begin + Texture := glBitmap.ID; + Result := True; + end; + finally + glBitmap.Free; + end; end; -//RGB/////////////////////////////////////////////////////////////////////////////////////////////// -procedure MapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; +var + CM: TglBitmapCubeMap; begin - aData^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); - inc(aData); -end; + Texture := 0; -procedure MapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO -end; + {$IFDEF GLB_DELPHI} + if Instance = 0 then + Instance := HInstance; + {$ENDIF} -procedure MapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO -end; + CM := TglBitmapCubeMap.Create; + try + CM.DeleteTextureOnFree := False; -procedure MapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - PCardinal(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); - inc(aData, 3); -end; + // Maps + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveX) + else + {$ENDIF} + CM.LoadFromFile(PositiveX); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X); -procedure MapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); -begin - //TODO + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeX) + else + {$ENDIF} + CM.LoadFromFile(NegativeX); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); + + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveY) + else + {$ENDIF} + CM.LoadFromFile(PositiveY); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); + + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeY) + else + {$ENDIF} + CM.LoadFromFile(NegativeY); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); + + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, PositiveZ) + else + {$ENDIF} + CM.LoadFromFile(PositiveZ); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); + + {$IFDEF GLB_DELPHI} + if (LoadFromRes) then + CM.LoadFromResource(Instance, NegativeZ) + else + {$ENDIF} + CM.LoadFromFile(NegativeZ); + CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + + Texture := CM.ID; + Result := True; + finally + CM.Free; + end; end; -procedure MapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; +var + NM: TglBitmapNormalMap; begin - //TODO + Texture := 0; + + NM := TglBitmapNormalMap.Create; + try + NM.DeleteTextureOnFree := False; + NM.GenerateNormalMap(Size); + + Texture := NM.ID; + Result := True; + finally + NM.Free; + end; end; +*) -procedure MapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION default Setter and Gettter} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean); begin - PWord(aData)^ := aPixel.Red; - inc(aData, 2); - PWord(aData)^ := aPixel.Green; - inc(aData, 2); - PWord(aData)^ := aPixel.Blue; - inc(aData, 2); + glBitmapDefaultDeleteTextureOnFree := aDeleteTextureOnFree; end; -//RGBA////////////////////////////////////////////////////////////////////////////////////////////// -procedure MapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultFreeDataAfterGenTexture(const aFreeData: Boolean); begin - aData^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); - inc(aData); + glBitmapDefaultFreeDataAfterGenTextures := aFreeData; end; -procedure MapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultMipmap(const aValue: TglBitmapMipMap); begin - PWord(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); - inc(aData, 2); + glBitmapDefaultMipmap := aValue; end; -procedure MapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultFormat(const aFormat: TglBitmapFormat); begin - PWord(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); - inc(aData, 2); + glBitmapDefaultFormat := aFormat; end; -procedure MapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultFilter(const aMin, aMag: Integer); begin - PCardinal(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); - inc(aData, 4); + glBitmapDefaultFilterMin := aMin; + glBitmapDefaultFilterMag := aMag; end; -procedure MapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultWrap(const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE); begin - PCardinal(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); - inc(aData, 4); + glBitmapDefaultWrapS := S; + glBitmapDefaultWrapT := T; + glBitmapDefaultWrapR := R; end; -procedure MapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapGetDefaultDeleteTextureOnFree: Boolean; begin - //TODO + result := glBitmapDefaultDeleteTextureOnFree; end; -procedure MapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; begin - PWord(aData)^ := aPixel.Red; - inc(aData, 2); - PWord(aData)^ := aPixel.Green; - inc(aData, 2); - PWord(aData)^ := aPixel.Blue; - inc(aData, 2); - PWord(aData)^ := aPixel.Alpha; - inc(aData, 2); + result := glBitmapDefaultFreeDataAfterGenTextures; end; -//DEPTH///////////////////////////////////////////////////////////////////////////////////////////// -procedure MapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapGetDefaultMipmap: TglBitmapMipMap; begin - PWord(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3; - inc(aData, 2); + result := glBitmapDefaultMipmap; end; -procedure MapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapGetDefaultFormat: TglBitmapFormat; begin - //TODO + result := glBitmapDefaultFormat; end; -procedure MapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal); begin - PCardinal(aData)^ := (aPixel.Red + aPixel.Green + aPixel.Blue) div 3; - inc(aData, 4); + aMin := glBitmapDefaultFilterMin; + aMag := glBitmapDefaultFilterMag; end; -function FormatGetMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapMapFunc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); begin - case aInternalFormat of - ifAlpha4: result := MapAlpha4; - ifAlpha8: result := MapAlpha8; - ifAlpha12: result := MapAlpha12; - ifAlpha16: result := MapAlpha16; - - ifLuminance4: result := MapLuminance4; - ifLuminance8: result := MapLuminance8; - ifLuminance12: result := MapLuminance8; - ifLuminance16: result := MapLuminance8; - - ifLuminance4Alpha4: result := MapLuminance4Alpha4; - ifLuminance6Alpha2: result := MapLuminance6Alpha2; - ifLuminance8Alpha8: result := MapLuminance8Alpha8; - ifLuminance12Alpha4: result := MapLuminance12Alpha4; - ifLuminance12Alpha12: result := MapLuminance12Alpha12; - ifLuminance16Alpha16: result := MapLuminance16Alpha16; - - ifR3G3B2: result := MapR3G3B2; - ifRGB4: result := MapRGB4; - ifRGB5: result := MapRGB5; - ifRGB8: result := MapRGB8; - ifRGB10: result := MapRGB10; - ifRGB12: result := MapRGB12; - ifRGB16: result := MapRGB16; - - ifRGBA2: result := MapRGBA2; - ifRGBA4: result := MapRGBA4; - ifRGB5A1: result := MapRGB5A1; - ifRGBA8: result := MapRGBA8; - ifRGB10A2: result := MapRGB10A2; - ifRGBA12: result := MapRGBA12; - ifRGBA16: result := MapRGBA16; - - ifDepth16: result := MapDepth16; - ifDepth24: result := MapDepth24; - ifDepth32: result := MapDepth32; - else - raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; + S := glBitmapDefaultWrapS; + T := glBitmapDefaultWrapT; + R := glBitmapDefaultWrapR; end; {$ENDREGION} -{$REGION UnmapFunctions} -//ALPHA///////////////////////////////////////////////////////////////////////////////////////////// -procedure UnmapAlpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TglBitmapFormatDescriptor} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.WithoutAlpha: TglBitmapFormat; begin - //TODO + if not HasAlpha then + result := GetFormat + else + result := tfEmpty; end; -procedure UnmapAlpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.WithAlpha: TglBitmapFormat; begin + if HasAlpha then + result := GetFormat + else + result := tfEmpty; +end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.IsEmpty: Boolean; +begin + result := (GetFormat = tfEmpty); end; -procedure UnmapAlpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.HasAlpha: Boolean; begin - //TODO + result := (GetPixelDesc.AlphaRange > 0); end; -procedure UnmapAlpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; +var + PixelDesc: TglBitmapPixelDesc; begin + result := False; + + if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then + raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); + PixelDesc := GetPixelDesc; + with PixelDesc do begin + if (aRedMask <> 0) and (aRedMask <> (RedRange shl RedShift)) then + exit; + if (aGreenMask <> 0) and (aGreenMask <> (GreenRange shl GreenShift)) then + exit; + if (aBlueMask <> 0) and (aBlueMask <> (BlueRange shl BlueShift)) then + exit; + if (aAlphaMask <> 0) and (aAlphaMask <> (AlphaRange shl AlphaShift)) then + exit; + end; + result := True; end; -//LUMINANCE///////////////////////////////////////////////////////////////////////////////////////// -procedure UnmapLuminance4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class procedure TglBitmapFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData); begin - //TODO + FillChar(aPixel, SizeOf(aPixel), 0); + with GetPixelDesc do begin + aPixel.Red := RedRange; + aPixel.Green := GreenRange; + aPixel.Blue := BlueRange; + aPixel.Alpha := AlphaRange; + end; end; +{$ENDREGION} -procedure UnmapLuminance8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TfdEmpty} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdEmpty//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdEmpty.GetFormat: TglBitmapFormat; begin - + result := tfEmpty; end; -procedure UnmapLuminance12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdEmpty.GetPixelDesc: TglBitmapPixelDesc; begin - //TODO + with result do begin + RedRange := $00000000; RedShift := 0; + GreenRange := $00000000; GreenShift := 0; + BlueRange := $00000000; BlueShift := 0; + AlphaRange := $00000000; AlphaShift := 0; + end; end; -procedure UnmapLuminance16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdEmpty.GetFormatDesc: TglBitmapFormatDesc; begin - + with result do begin + Format := 0; + InternalFormat := 0; + DataType := 0; + end; end; -//LUMINANCE_ALPHA/////////////////////////////////////////////////////////////////////////////////// -procedure UnmapLuminance4Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - + raise EglBitmapException.Create('format does not support mapping'); end; -procedure UnmapLuminance6Alpha2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdEmpty.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin - + raise EglBitmapException.Create('format does not support unmapping'); end; +{$ENDREGION} -procedure UnmapLuminance8Alpha8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TfdLuminance8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminance8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdLuminance8.GetFormat: TglBitmapFormat; begin - + result := tfEmpty; end; -procedure UnmapLuminance12Alpha4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8.GetPixelDesc: TglBitmapPixelDesc; begin - + with result do begin + RedRange := $000000FF; RedShift := 0; + GreenRange := $000000FF; GreenShift := 0; + BlueRange := $000000FF; BlueShift := 0; + AlphaRange := $00000000; AlphaShift := 0; + end; end; -procedure UnmapLuminance12Alpha12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8.GetFormatDesc: TglBitmapFormatDesc; begin - //TODO + with result do begin + Format := GL_LUMINANCE; + InternalFormat := GL_LUMINANCE8; + DataType := GL_UNSIGNED_BYTE; + end; end; -procedure UnmapLuminance16Alpha16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8.WithAlpha: TglBitmapFormat; begin - + result := tfLuminance8Alpha8; end; -//RGB/////////////////////////////////////////////////////////////////////////////////////////////// -procedure UnmapR3G3B2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - + aData^ := Trunc( + aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B); + inc(aData); end; -procedure UnmapRGB4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin - //TODO + aPixel.Red := aData^; + aPixel.Green := aData^; + aPixel.Blue := aData^; + aPixel.Alpha := 0; + inc(aData); end; +{$ENDREGION} -procedure UnmapRGB5(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TfdLuminance8Alpha8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminance8Alpha8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdLuminance8Alpha8.GetFormat: TglBitmapFormat; begin - //TODO + result := tfLuminance8Alpha8; end; -procedure UnmapRGB8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8Alpha8.GetPixelDesc: TglBitmapPixelDesc; begin - + with result do begin + RedRange := $000000FF; RedShift := 0; + GreenRange := $000000FF; GreenShift := 0; + BlueRange := $000000FF; BlueShift := 0; + AlphaRange := $000000FF; AlphaShift := 8; + end; end; -procedure UnmapRGB10(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8Alpha8.GetFormatDesc: TglBitmapFormatDesc; begin - //TODO + with result do begin + Format := GL_LUMINANCE_ALPHA; + InternalFormat := GL_LUMINANCE8_ALPHA8; + DataType := GL_UNSIGNED_BYTE; + end; end; -procedure UnmapRGB12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdLuminance8Alpha8.WithoutAlpha: TglBitmapFormat; begin - //TODO + result := tfLuminance8; end; -procedure UnmapRGB16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin + aData^ := Trunc( + aPixel.Red * LUMINANCE_WEIGHT_R + + aPixel.Green * LUMINANCE_WEIGHT_G + + aPixel.Blue * LUMINANCE_WEIGHT_B); + inc(aData); + aData^ := aPixel.Alpha; + inc(aData); end; -//RGBA////////////////////////////////////////////////////////////////////////////////////////////// -procedure UnmapRGBA2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin + aPixel.Red := aData^; + aPixel.Green := aData^; + aPixel.Blue := aData^; + inc(aData); + aPixel.Alpha := aData^; + inc(aData); end; +{$ENDREGION} -procedure UnmapRGBA4(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TfdRGB8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGB8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdRGB8.GetFormat: TglBitmapFormat; begin - + result := tfRGB8; end; -procedure UnmapRGB5A1(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdRGB8.GetPixelDesc: TglBitmapPixelDesc; begin - + with result do begin + RedRange := $000000FF; RedShift := 0; + GreenRange := $000000FF; GreenShift := 8; + BlueRange := $000000FF; BlueShift := 16; + AlphaRange := $00000000; AlphaShift := 0; + end; end; -procedure UnmapRGBA8(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdRGB8.GetFormatDesc: TglBitmapFormatDesc; begin - + with result do begin + Format := GL_LUMINANCE; + InternalFormat := GL_LUMINANCE8; + DataType := GL_UNSIGNED_BYTE; + end; end; -procedure UnmapRGB10A2(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdRGB8.WithAlpha: TglBitmapFormat; begin - + result := tfRGBA8; end; -procedure UnmapRGBA12(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - //TODO + aData^ := aPixel.Red; + inc(aData); + aData^ := aPixel.Green; + inc(aData); + aData^ := aPixel.Blue; + inc(aData); end; -procedure UnmapRGBA16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdRGB8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin - + aPixel.Red := aData^; + inc(aData); + aPixel.Green := aData^; + inc(aData); + aPixel.Blue := aData^; + inc(aData); + aPixel.Alpha := 0; end; +{$ENDREGION} -//DEPTH///////////////////////////////////////////////////////////////////////////////////////////// -procedure UnmapDepth16(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +{$REGION TfdRGBA8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGBA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdRGBA8.GetFormat: TglBitmapFormat; begin - + result := tfRGBA8; end; -procedure UnmapDepth24(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc; begin - //TODO + with result do begin + RedRange := $000000FF; RedShift := 0; + GreenRange := $000000FF; GreenShift := 8; + BlueRange := $000000FF; BlueShift := 16; + AlphaRange := $000000FF; AlphaShift := 24; + end; end; -procedure UnmapDepth32(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc; begin - + with result do begin + Format := GL_RGB; + InternalFormat := GL_RGB8; + DataType := GL_UNSIGNED_BYTE; + end; end; - - - -procedure UnMapAlpha(var pData: pByte; var Pixel: TglBitmapPixelData); +class function TfdRGBA8.WithoutAlpha: TglBitmapFormat; begin - Pixel.Alpha := pData^; - Pixel.Red := Pixel.PixelDesc.RedRange; - Pixel.Green := Pixel.PixelDesc.GreenRange; - Pixel.Blue := Pixel.PixelDesc.BlueRange; - - Inc(pData); + result := tfRGB8; end; - -procedure UnMapLuminance(var pData: pByte; var Pixel: TglBitmapPixelData); +class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - Pixel.Alpha := 255; - Pixel.Red := pData^; - Pixel.Green := pData^; - Pixel.Blue := pData^; - - Inc(pData); + aData^ := aPixel.Red; + inc(aData); + aData^ := aPixel.Green; + inc(aData); + aData^ := aPixel.Blue; + inc(aData); + aData^ := aPixel.Alpha; + inc(aData); end; - -procedure UnMapDepth8(var pData: pByte; var Pixel: TglBitmapPixelData); +class procedure TfdRGBA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin - Pixel.Alpha := 255; - Pixel.Red := pData^; - Pixel.Green := pData^; - Pixel.Blue := pData^; - - Inc(pData); + aPixel.Red := aData^; + inc(aData); + aPixel.Green := aData^; + inc(aData); + aPixel.Blue := aData^; + inc(aData); + aPixel.Alpha := aData^; + inc(aData); end; +{$ENDREGION} - -procedure UnMapLuminanceAlpha(var pData: pByte; var Pixel: TglBitmapPixelData); +{$REGION TfdBGR8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGR8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdBGR8.GetFormat: TglBitmapFormat; begin - Pixel.Red := pData^; - Pixel.Green := pData^; - Pixel.Blue := pData^; - Inc(pData); - - Pixel.Alpha := pData^; - Inc(pData); + result := tfBGR8; end; - -procedure UnMapRGBA4(var pData: pByte; var Pixel: TglBitmapPixelData); -var - Temp: Word; +class function TfdBGR8.GetPixelDesc: TglBitmapPixelDesc; begin - Temp := pWord(pData)^; - - Pixel.Alpha := Temp shr PIXEL_DESC_RGBA4.AlphaShift and PIXEL_DESC_RGBA4.AlphaRange; - Pixel.Red := Temp shr PIXEL_DESC_RGBA4.RedShift and PIXEL_DESC_RGBA4.RedRange; - Pixel.Green := Temp shr PIXEL_DESC_RGBA4.GreenShift and PIXEL_DESC_RGBA4.GreenRange; - Pixel.Blue := Temp and PIXEL_DESC_RGBA4.BlueRange; - - Inc(pData, 2); + with result do begin + RedRange := $000000FF; RedShift := 16; + GreenRange := $000000FF; GreenShift := 8; + BlueRange := $000000FF; BlueShift := 0; + AlphaRange := $00000000; AlphaShift := 0; + end; end; - -procedure UnMapR5G6B5(var pData: pByte; var Pixel: TglBitmapPixelData); -var - Temp: Word; +class function TfdBGR8.GetFormatDesc: TglBitmapFormatDesc; begin - Temp := pWord(pData)^; - - Pixel.Alpha := Pixel.PixelDesc.AlphaRange; - Pixel.Red := Temp shr PIXEL_DESC_R5G6B5.RedShift and PIXEL_DESC_R5G6B5.RedRange; - Pixel.Green := Temp shr PIXEL_DESC_R5G6B5.GreenShift and PIXEL_DESC_R5G6B5.GreenRange; - Pixel.Blue := Temp and PIXEL_DESC_R5G6B5.BlueRange; - - Inc(pData, 2); + with result do begin + Format := GL_BGR; + InternalFormat := GL_RGB8; + DataType := GL_UNSIGNED_BYTE; + end; end; - -procedure UnMapRGB5A1(var pData: pByte; var Pixel: TglBitmapPixelData); -var - Temp: Word; +class function TfdBGR8.WithAlpha: TglBitmapFormat; begin - Temp := pWord(pData)^; - - Pixel.Alpha := Temp shr PIXEL_DESC_RGB5A1.AlphaShift and PIXEL_DESC_RGB5A1.AlphaRange; - Pixel.Red := Temp shr PIXEL_DESC_RGB5A1.RedShift and PIXEL_DESC_RGB5A1.RedRange; - Pixel.Green := Temp shr PIXEL_DESC_RGB5A1.GreenShift and PIXEL_DESC_RGB5A1.GreenRange; - Pixel.Blue := Temp and PIXEL_DESC_RGB5A1.BlueRange; - - Inc(pData, 2); + result := tfBGRA8; end; - -procedure UnMapRGB8(var pData: pByte; var Pixel: TglBitmapPixelData); +class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); begin - Pixel.Alpha := Pixel.PixelDesc.AlphaRange; - - Pixel.Red := pData^; - Inc(pData); - - Pixel.Green := pData^; - Inc(pData); - - Pixel.Blue := pData^; - Inc(pData); + aData^ := aPixel.Blue; + inc(aData); + aData^ := aPixel.Green; + inc(aData); + aData^ := aPixel.Red; + inc(aData); end; - -procedure UnMapBGR8(var pData: pByte; var Pixel: TglBitmapPixelData); +class procedure TfdBGR8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); begin - Pixel.Alpha := Pixel.PixelDesc.AlphaRange; - - Pixel.Blue := pData^; - Inc(pData); - - Pixel.Green := pData^; - Inc(pData); - - Pixel.Red := pData^; - Inc(pData); + aPixel.Blue := aData^; + inc(aData); + aPixel.Green := aData^; + inc(aData); + aPixel.Red := aData^; + inc(aData); end; +{$ENDREGION} - -procedure UnMapRGBA8(var pData: pByte; var Pixel: TglBitmapPixelData); +{$REGION TfdBGRA8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGRA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdBGRA8.GetFormat: TglBitmapFormat; begin - Pixel.Red := pData^; - Inc(pData); - - Pixel.Green := pData^; - Inc(pData); - - Pixel.Blue := pData^; - Inc(pData); - - Pixel.Alpha := pData^; - Inc(pData); + result := tfBGRA8; end; - -procedure UnMapBGRA8(var pData: pByte; var Pixel: TglBitmapPixelData); +class function TfdBGRA8.GetPixelDesc: TglBitmapPixelDesc; begin - Pixel.Blue := pData^; - Inc(pData); - - Pixel.Green := pData^; - Inc(pData); + with result do begin + RedRange := $000000FF; RedShift := 16; + GreenRange := $000000FF; GreenShift := 8; + BlueRange := $000000FF; BlueShift := 0; + AlphaRange := $000000FF; AlphaShift := 24; + end; +end; - Pixel.Red := pData^; - Inc(pData); +class function TfdBGRA8.GetFormatDesc: TglBitmapFormatDesc; +begin + with result do begin + Format := GL_BGRA; + InternalFormat := GL_RGBA8; + DataType := GL_UNSIGNED_BYTE; + end; +end; - Pixel.Alpha := pData^; - Inc(pData); +class function TfdBGRA8.WithoutAlpha: TglBitmapFormat; +begin + result := tfBGR8; end; +class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +begin + aData^ := aPixel.Blue; + inc(aData); + aData^ := aPixel.Green; + inc(aData); + aData^ := aPixel.Red; + inc(aData); + aData^ := aPixel.Alpha; + inc(aData); +end; -procedure UnMapRGB10A2(var pData: pByte; var Pixel: TglBitmapPixelData); -var - Temp: DWord; -begin - Temp := pDWord(pData)^; - - Pixel.Alpha := Temp shr PIXEL_DESC_RGB10A2.AlphaShift and PIXEL_DESC_RGB10A2.AlphaRange; - Pixel.Red := Temp shr PIXEL_DESC_RGB10A2.RedShift and PIXEL_DESC_RGB10A2.RedRange; - Pixel.Green := Temp shr PIXEL_DESC_RGB10A2.GreenShift and PIXEL_DESC_RGB10A2.GreenRange; - Pixel.Blue := Temp and PIXEL_DESC_RGB10A2.BlueRange; - - Inc(pData, 4); -end; - - -function FormatGetUnMapFunc(const aInternalFormat: TglBitmapInternalFormat): TglBitmapUnMapFunc; -begin - case aInternalFormat of - ifAlpha4: result := UnmapAlpha4; - ifAlpha8: result := UnmapAlpha8; - ifAlpha12: result := UnmapAlpha12; - ifAlpha16: result := UnmapAlpha16; - - ifLuminance4: result := UnmapLuminance4; - ifLuminance8: result := UnmapLuminance8; - ifLuminance12: result := UnmapLuminance8; - ifLuminance16: result := UnmapLuminance8; - - ifLuminance4Alpha4: result := UnmapLuminance4Alpha4; - ifLuminance6Alpha2: result := UnmapLuminance6Alpha2; - ifLuminance8Alpha8: result := UnmapLuminance8Alpha8; - ifLuminance12Alpha4: result := UnmapLuminance12Alpha4; - ifLuminance12Alpha12: result := UnmapLuminance12Alpha12; - ifLuminance16Alpha16: result := UnmapLuminance16Alpha16; - - ifR3G3B2: result := UnmapR3G3B2; - ifRGB4: result := UnmapRGB4; - ifRGB5: result := UnmapRGB5; - ifRGB8: result := UnmapRGB8; - ifRGB10: result := UnmapRGB10; - ifRGB12: result := UnmapRGB12; - ifRGB16: result := UnmapRGB16; - - ifRGBA2: result := UnmapRGBA2; - ifRGBA4: result := UnmapRGBA4; - ifRGB5A1: result := UnmapRGB5A1; - ifRGBA8: result := UnmapRGBA8; - ifRGB10A2: result := UnmapRGB10A2; - ifRGBA12: result := UnmapRGBA12; - ifRGBA16: result := UnmapRGBA16; - - ifDepth16: result := UnmapDepth16; - ifDepth24: result := UnmapDepth24; - ifDepth32: result := UnmapDepth32; - else - raise EglBitmapUnsupportedInternalFormat.Create('FormatGetMapFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; +class procedure TfdBGRA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +begin + aPixel.Blue := aData^; + inc(aData); + aPixel.Green := aData^; + inc(aData); + aPixel.Red := aData^; + inc(aData); + aPixel.Alpha := aData^; + inc(aData); end; {$ENDREGION} -{* -** Tools -*} -function FormatGetSize (Format: TglBitmapInternalFormat): Single; -begin - case Format of - ifEmpty: - Result := 0; - ifDXT1: - Result := 0.5; - ifAlpha, ifLuminance, ifDepth8, ifDXT3, ifDXT5: - Result := 1; - ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5: - Result := 2; - ifBGR8, ifRGB8: - Result := 3; - ifBGRA8, ifRGBA8, ifRGB10A2: - Result := 4; - else - raise EglBitmapUnsupportedInternalFormat.Create('FormatGetSize - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; +{$REGION TglBitmap } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetHeight: Integer; +begin + if (ffY in fDimension.Fields) then + result := fDimension.Y + else + result := -1; end; - -function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetWidth: Integer; begin - Result := Format in [ifDXT1, ifDXT3, ifDXT5]; + if (ffX in fDimension.Fields) then + result := fDimension.X + else + result := -1; end; - -function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; +{$REGION Setter} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetCustomData(const aValue: Pointer); begin - Result := Format in [ifAlpha, ifLuminance, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8, ifRGB10A2]; + if fCustomData = aValue then + exit; + fCustomData := aValue; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetCustomName(const aValue: String); +begin + if fCustomName = aValue then + exit; + fCustomName := aValue; +end; -function FormatIsEmpty(Format: TglBitmapInternalFormat): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetCustomNameW(const aValue: WideString); begin - Result := Format = ifEmpty; + if fCustomNameW = aValue then + exit; + fCustomNameW := aValue; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean); +begin + if fDeleteTextureOnFree = aValue then + exit; + fDeleteTextureOnFree := aValue; +end; -function FormatHasAlpha(Format: TglBitmapInternalFormat): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat); begin - Result := Format in [ifDXT1, ifDXT3, ifDXT5 ,ifAlpha, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifBGRA8, ifRGBA8, ifRGB10A2]; + if fFormat = aValue then + exit; + fFormat := aValue; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean); +begin + if fFreeDataAfterGenTexture = aValue then + exit; + fFreeDataAfterGenTexture := aValue; +end; -procedure FormatPreparePixel(var Pixel: TglBitmapPixelData; Format: TglBitmapInternalFormat); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetID(const aValue: Cardinal); begin - FillChar(Pixel, SizeOf(Pixel), #0); + if fID = aValue then + exit; + fID := aValue; +end; - case Format of - ifAlpha: - Pixel.PixelDesc := PIXEL_DESC_ALPHA; - ifLuminance: - Pixel.PixelDesc := PIXEL_DESC_LUMINANCE; - ifDepth8: - Pixel.PixelDesc := PIXEL_DESC_DEPTH8; - ifLuminanceAlpha: - Pixel.PixelDesc := PIXEL_DESC_LUMINANCEALPHA; - ifRGBA4: - Pixel.PixelDesc := PIXEL_DESC_RGBA4; - ifR5G6B5: - Pixel.PixelDesc := PIXEL_DESC_R5G6B5; - ifRGB5A1: - Pixel.PixelDesc := PIXEL_DESC_RGB5A1; - ifDXT1, ifDXT3, ifDXT5, ifBGRA8: - Pixel.PixelDesc := PIXEL_DESC_BGRA8; - ifBGR8: - Pixel.PixelDesc := PIXEL_DESC_BGR8; - ifRGB8: - Pixel.PixelDesc := PIXEL_DESC_RGB8; - ifRGBA8: - Pixel.PixelDesc := PIXEL_DESC_RGBA8; - ifRGB10A2: - Pixel.PixelDesc := PIXEL_DESC_RGB10A2; - end; - - Pixel.Red := Pixel.PixelDesc.RedRange; - Pixel.Green := Pixel.PixelDesc.GreenRange; - Pixel.Blue := Pixel.PixelDesc.BlueRange; - Pixel.Alpha := Pixel.PixelDesc.AlphaRange; -end; - - -function FormatGetWithoutAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; -begin - case Format of - ifAlpha: - Result := ifLuminance; - ifLuminanceAlpha: - Result := ifLuminance; - ifRGBA4: - Result := ifR5G6B5; - ifRGB5A1: - Result := ifR5G6B5; - ifBGRA8: - Result := ifBGR8; - ifRGBA8: - Result := ifRGB8; - ifRGB10A2: - Result := ifRGB8; - else - Result := Format; - end; -end; - - -function FormatGetWithAlpha(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; -begin - case Format of - ifLuminance: - Result := ifLuminanceAlpha; - ifR5G6B5: - Result := ifRGB5A1; - ifBGR8: - Result := ifBGRA8; - ifRGB8: - Result := ifRGBA8; - else - Result := Format; - end; -end; - - -function FormatGetUncompressed(Format: TglBitmapInternalFormat): TglBitmapInternalFormat; -begin - case Format of - ifDXT1: - Result := ifRGB5A1; - ifDXT3: - Result := ifRGBA8; - ifDXT5: - Result := ifRGBA8; - else - Result := Format; - end; -end; - - -function FormatGetImageSize(Size: TglBitmapPixelPosition; Format: TglBitmapInternalFormat): Integer; -begin - if (Size.X = 0) and (Size.Y = 0) then - Result := 0 - else - Result := Trunc(Max(Size.Y, 1) * Max(Size.X, 1) * FormatGetSize(Format)); -end; - - -function FormatGetSupportedFiles(Format: TglBitmapInternalFormat): TglBitmapFileTypes; -begin - Result := []; - - {$IFDEF GLB_SUPPORT_PNG_WRITE} - if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifBGRA8, ifRGB8, ifRGBA8] then - Result := Result + [ftPNG]; - {$ENDIF} - - {$IFDEF GLB_SUPPORT_JPEG_WRITE} - if Format in [ifLuminance, ifAlpha, ifDepth8, ifRGB8, ifBGR8] then - Result := Result + [ftJPEG]; - {$ENDIF} - - Result := Result + [ftDDS]; - - if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifBGR8, ifRGB8, ifBGRA8, ifRGBA8] then - Result := Result + [ftTGA]; - - if Format in [ifLuminance, ifAlpha, ifDepth8, ifLuminanceAlpha, ifRGBA4, ifRGB5A1, ifR5G6B5, ifRGB8, ifBGR8, ifRGBA8, ifBGRA8, ifRGB10A2] then - Result := Result + [ftBMP]; -end; - - -function FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; Format: TglBitmapInternalFormat): boolean; -var - Pix: TglBitmapPixelData; -begin - Result := False; - - if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) and (AlphaMask = 0) then - raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); - - FormatPreparePixel(Pix, Format); - - with Pix.PixelDesc do begin - if RedMask <> 0 then - if (RedMask <> (RedRange shl RedShift)) then - Exit; - - if GreenMask <> 0 then - if (GreenMask <> (GreenRange shl GreenShift)) then - Exit; - - if BlueMask <> 0 then - if (BlueMask <> (BlueRange shl BlueShift)) then - Exit; - - if AlphaMask <> 0 then - if (AlphaMask <> (AlphaRange shl AlphaShift)) then - Exit; - - Result := True; - end; -end; - - -function IsPowerOfTwo(Number: Integer): Boolean; -begin - while Number and 1 = 0 do - Number := Number shr 1; - - Result := Number = 1; -end; - - -function GetBitSize(BitSet: Cardinal): Integer; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap); begin - Result := 0; - - while BitSet > 0 do begin - if (BitSet and $1) = 1 then - Inc(Result); - - BitSet := BitSet shr 1; - end; + if fMipMap = aValue then + exit; + fMipMap := aValue; end; - -procedure SwapRGB(pData: pByte; Width: Integer; HasAlpha: Boolean); -type - PRGBPix = ^TRGBPix; - TRGBPix = array [0..2] of byte; -var - Temp: Byte; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetTarget(const aValue: Cardinal); begin - while Width > 0 do begin - Temp := pRGBPIX(pData)^[0]; - pRGBPIX(pData)^[0] := pRGBPIX(pData)^[2]; - pRGBPIX(pData)^[2] := Temp; - - if HasAlpha then - Inc(pData, 4) - else - Inc(pData, 3); - - Dec(Width); - end; + if fTarget = aValue then + exit; + fTarget := aValue; end; - -{$IFDEF GLB_DELPHI} -function CreateGrayPalette: HPALETTE; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetAnisotropic(const aValue: Integer); var - Idx: Integer; - Pal: PLogPalette; + MaxAnisotropic: Integer; begin - GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256)); - - Pal.palVersion := $300; - Pal.palNumEntries := 256; - - {$IFOPT R+} - {$DEFINE GLB_TEMPRANGECHECK} - {$R-} - {$ENDIF} - - for Idx := 0 to 256 - 1 do begin - Pal.palPalEntry[Idx].peRed := Idx; - Pal.palPalEntry[Idx].peGreen := Idx; - Pal.palPalEntry[Idx].peBlue := Idx; - Pal.palPalEntry[Idx].peFlags := 0; + fAnisotropic := Value; + if (ID > 0) then begin + if GL_EXT_texture_filter_anisotropic then begin + if fAnisotropic > 0 then begin + Bind(False); + glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic); + if aValue > MaxAnisotropic then + fAnisotropic := MaxAnisotropic; + glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic); + end; + end else begin + fAnisotropic := 0; + end; end; - - {$IFDEF GLB_TEMPRANGECHECK} - {$UNDEF GLB_TEMPRANGECHECK} - {$R+} - {$ENDIF} - - Result := CreatePalette(Pal^); - - FreeMem(Pal); -end; -{$ENDIF} - - -{$IFDEF GLB_SDL_IMAGE} -function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; -begin - Result := TStream(context^.unknown.data1).Seek(offset, whence); end; +{$ENDREGION} - -function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl; +procedure TglBitmap.AfterConstruction; begin - Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum); -end; + inherited AfterConstruction; + fID := 0; + fTarget := 0; + fIsResident := False; -function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl; -begin - Result := TStream(context^.unknown.data1).Write(Ptr^, size * num); -end; - + fFormat := glBitmapGetDefaultFormat; + fMipMap := glBitmapDefaultMipmap; + fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; + fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; -function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl; -begin - Result := 0; + glBitmapGetDefaultFilter (fFilterMin, fFilterMag); + glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); end; - -function glBitmapCreateRWops(Stream: TStream): PSDL_RWops; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.BeforeDestruction; begin - Result := SDL_AllocRW; - - if Result = nil then - raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.'); - - Result^.seek := glBitmapRWseek; - Result^.read := glBitmapRWread; - Result^.write := glBitmapRWwrite; - Result^.close := glBitmapRWclose; - Result^.unknown.data1 := Stream; + SetDataPointer(nil, ifEmpty); + if (ID > 0) and fDeleteTextureOnFree then + glDeleteTextures(1, @ID); + inherited BeforeDestruction; end; -{$ENDIF} - -{* -** Helper functions -*} -function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; -var - glBitmap: TglBitmap2D; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.CreateID; begin - Result := false; - Texture := 0; - - {$IFDEF GLB_DELPHI} - if Instance = 0 then - Instance := HInstance; - - if (LoadFromRes) then - glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName) - else - {$ENDIF} - glBitmap := TglBitmap2D.Create(FileName); - - try - glBitmap.DeleteTextureOnFree := False; - glBitmap.FreeDataAfterGenTexture := False; - glBitmap.GenTexture(True); - if (glBitmap.ID > 0) then begin - Texture := glBitmap.ID; - Result := True; - end; - finally - glBitmap.Free; - end; + if ID <> 0 then + glDeleteTextures(1, @ID); + glGenTextures(1, @ID); + Bind(false); end; - -function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; -var - CM: TglBitmapCubeMap; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean); begin - Texture := 0; - - {$IFDEF GLB_DELPHI} - if Instance = 0 then - Instance := HInstance; - {$ENDIF} - - CM := TglBitmapCubeMap.Create; - try - CM.DeleteTextureOnFree := False; - - // Maps - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveX) - else - {$ENDIF} - CM.LoadFromFile(PositiveX); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeX) - else - {$ENDIF} - CM.LoadFromFile(NegativeX); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveY) - else - {$ENDIF} - CM.LoadFromFile(PositiveY); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeY) - else - {$ENDIF} - CM.LoadFromFile(NegativeY); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveZ) - else - {$ENDIF} - CM.LoadFromFile(PositiveZ); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); + // Set Up Parameters + SetWrap(fWrapS, fWrapT, fWrapR); + SetFilter(fFilterMin, fFilterMag); + SetAnisotropic(fAnisotropic); + SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]); - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeZ) + // Mip Maps Generation Mode + aBuildWithGlu := False; + if (MipMap = mmMipmap) then begin + if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then + glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE) else - {$ENDIF} - CM.LoadFromFile(NegativeZ); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); - - Texture := CM.ID; - Result := True; - finally - CM.Free; - end; + BuildWithGlu := True; + end else if (MipMap = mmMipmapGlu) then + BuildWithGlu := True; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal); -function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; -var - NM: TglBitmapNormalMap; -begin - Texture := 0; - - NM := TglBitmapNormalMap.Create; - try - NM.DeleteTextureOnFree := False; - NM.GenerateNormalMap(Size); - - Texture := NM.ID; - Result := True; - finally - NM.Free; + procedure Check12; + begin + if not GL_VERSION_1_2 then + raise EglBitmapUnsupportedFormatFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.'); end; -end; - - -procedure glBitmapSetDefaultFormat(Format: TglBitmapFormat); -begin - glBitmapDefaultFormat := Format; -end; - - -procedure glBitmapSetDefaultDeleteTextureOnFree(DeleteTextureOnFree: Boolean); -begin - glBitmapDefaultDeleteTextureOnFree := DeleteTextureOnFree; -end; - -procedure glBitmapSetDefaultFilter(Min, Mag: Integer); begin - glBitmapDefaultFilterMin := Min; - glBitmapDefaultFilterMag := Mag; -end; + PIXEL_DESC_ALPHA12; + glType := GL_UNSIGNED_BYTE; + glInternalFormat := Cardinal(aFormat); + case aFormat of + tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16: + glFormat := GL_ALPHA; -procedure glBitmapSetDefaultWrap(S: Integer; T: Integer; R: Integer); -begin - glBitmapDefaultWrapS := S; - glBitmapDefaultWrapT := T; - glBitmapDefaultWrapR := R; -end; + tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16: + glFormat := GL_LUMINANCE; + tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, + tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16: + glFormat := GL_LUMINANCE_ALPHA; -procedure glBitmapSetDefaultFreeDataAfterGenTexture(FreeData: Boolean); -begin - glBitmapDefaultFreeDataAfterGenTextures := FreeData; -end; + tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16: + glFormat := GL_RGB; + tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16: + glFormat := GL_RGBA; -function glBitmapGetDefaultFormat: TglBitmapFormat; -begin - Result := glBitmapDefaultFormat; -end; + tfDepth16, tfDepth24, tfDepth32: + glFormat := GL_DEPTH_COMPONENT; + else + glFormat := 0; + end; + case aFormat of + tfRGBA4: + glType := GL_UNSIGNED_SHORT_4_4_4_4; + tfRGB5A1: + glType := GL_UNSIGNED_SHORT_5_5_5_1; + tfRG + end; -function glBitmapGetDefaultDeleteTextureOnFree: Boolean; -begin - Result := glBitmapDefaultDeleteTextureOnFree; -end; + // selecting Format + case DataFormat of + ifAlpha: + glFormat := GL_ALPHA; + ifLuminance: + glFormat := GL_LUMINANCE; + ifDepth8: + glFormat := GL_DEPTH_COMPONENT; + ifLuminanceAlpha: + glFormat := GL_LUMINANCE_ALPHA; + ifBGR8: + begin + if (GL_VERSION_1_2 or GL_EXT_bgra) then begin + glFormat := GL_BGR; + end else begin + if CanConvertImage then + ConvertTo(tfRGB8); + glFormat := GL_RGB; + end; + end; + ifBGRA8: + begin + if (GL_VERSION_1_2 or GL_EXT_bgra) then begin + glFormat := GL_BGRA; + end else begin + if CanConvertImage then + ConvertTo(tfRGBA8); + glFormat := GL_RGBA; + end; + end; + tfRGB8: + glFormat := GL_RGB; + tfRGBA8: + glFormat := GL_RGBA; + tfRGBA4: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_SHORT_4_4_4_4_REV; + end; + tfRGB5A1: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_SHORT_1_5_5_5_REV; + end; + tfRGB10A2: + begin + Check12; + glFormat := GL_BGRA; + glType := GL_UNSIGNED_INT_2_10_10_10_REV; + end; + ifR5G6B5: + begin + Check12; + glFormat := GL_RGB; + glType := GL_UNSIGNED_SHORT_5_6_5; + end; + else + glFormat := 0; + end; -procedure glBitmapGetDefaultFilter(var Min, Mag: Integer); -begin - Min := glBitmapDefaultFilterMin; - Mag := glBitmapDefaultFilterMag; + // Selecting InternalFormat + case DataFormat of + ifDXT1, ifDXT3, ifDXT5: + begin + if GL_EXT_texture_compression_s3tc then begin + case DataFormat of + ifDXT1: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + ifDXT3: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + ifDXT5: + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + end; + end else begin + // Compression isn't supported so convert to RGBA + if CanConvertImage then + ConvertTo(tfRGBA8); + glFormat := GL_RGBA; + glInternalFormat := GL_RGBA8; + end; + end; + ifAlpha: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_ALPHA4; + tf8BitsPerChanel: + glInternalFormat := GL_ALPHA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_ALPHA + else + glInternalFormat := GL_ALPHA; + end; + else + glInternalFormat := GL_ALPHA; + end; + end; + ifLuminance: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_LUMINANCE4; + tf8BitsPerChanel: + glInternalFormat := GL_LUMINANCE8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_LUMINANCE + else + glInternalFormat := GL_LUMINANCE; + end; + else + glInternalFormat := GL_LUMINANCE; + end; + end; + ifDepth8: + begin + glInternalFormat := GL_DEPTH_COMPONENT; + end; + ifLuminanceAlpha: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_LUMINANCE4_ALPHA4; + tf8BitsPerChanel: + glInternalFormat := GL_LUMINANCE8_ALPHA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then + glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA + else + glInternalFormat := GL_LUMINANCE_ALPHA; + end; + else + glInternalFormat := GL_LUMINANCE_ALPHA; + end; + end; + ifBGR8, tfRGB8: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_RGB4; + tf8BitsPerChanel: + glInternalFormat := GL_RGB8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin + glInternalFormat := GL_COMPRESSED_RGB + end else begin + if (GL_EXT_texture_compression_s3tc) then + glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT + else + glInternalFormat := GL_RGB; + end; + end; + else + glInternalFormat := GL_RGB; + end; + end; + ifBGRA8, tfRGBA8, tfRGBA4, tfRGB5A1, tfRGB10A2, ifR5G6B5: + begin + case Format of + tf4BitsPerChanel: + glInternalFormat := GL_RGBA4; + tf8BitsPerChanel: + glInternalFormat := GL_RGBA8; + tfCompressed: + begin + if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin + glInternalFormat := GL_COMPRESSED_RGBA + end else begin + if (GL_EXT_texture_compression_s3tc) then + glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + else + glInternalFormat := GL_RGBA; + end; + end; + else + glInternalFormat := GL_RGBA; + end; + end; + end; end; -procedure glBitmapGetDefaultTextureWrap(var S, T, R: Integer); -begin - S := glBitmapDefaultWrapS; - T := glBitmapDefaultWrapT; - R := glBitmapDefaultWrapR; -end; -function glBitmapGetDefaultFreeDataAfterGenTexture: Boolean; -begin - Result := glBitmapDefaultFreeDataAfterGenTextures; -end; -{ TglBitmap } -procedure TglBitmap.AfterConstruction; -begin - inherited; - fID := 0; - fTarget := 0; - fMipMap := mmMipmap; - fIsResident := False; - // get defaults - fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; - fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; - fFormat := glBitmapGetDefaultFormat; - glBitmapGetDefaultFilter(fFilterMin, fFilterMag); - glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); -end; -procedure TglBitmap.BeforeDestruction; -begin - SetDataPointer(nil, ifEmpty); - if ((ID > 0) and (fDeleteTextureOnFree)) then - glDeleteTextures(1, @ID); - inherited; -end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TglBitmap.Create; begin {$IFNDEF GLB_NO_NATIVE_GL} @@ -2693,7 +2566,7 @@ end; constructor TglBitmap.Create(Size: TglBitmapPixelPosition; - Format: TglBitmapInternalFormat); + Format: TglBitmapFormat); var Image: pByte; ImageSize: Integer; @@ -2714,7 +2587,7 @@ end; constructor TglBitmap.Create(Size: TglBitmapPixelPosition; - Format: TglBitmapInternalFormat; Func: TglBitmapFunction; CustomData: Pointer); + Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer); begin Create; LoadFromFunc(Size, Func, Format, CustomData); @@ -2771,7 +2644,7 @@ begin end; -procedure TglBitmap.LoadFromFile(FileName: String); +procedure TglBitmap.LoadFromFile(const aFileName: String); var FS: TFileStream; begin @@ -2788,7 +2661,7 @@ begin end; -procedure TglBitmap.LoadFromStream(Stream: TStream); +procedure TglBitmap.LoadFromStream(const aStream: TStream); begin {$IFDEF GLB_SUPPORT_PNG_READ} if not LoadPNG(Stream) then @@ -2845,8 +2718,9 @@ end; -procedure TglBitmap.LoadFromFunc(Size: TglBitmapPixelPosition; - Func: TglBitmapFunction; Format: TglBitmapInternalFormat; CustomData: Pointer); +procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; + const aFunc: TglBitmapFunction; const aFormat: TglBitmapFormat; + const aArgs: PtrInt); var Image: pByte; ImageSize: Integer; @@ -2866,7 +2740,8 @@ begin end; -procedure TglBitmap.SaveToFile(FileName: String; FileType: TglBitmapFileType); +procedure TglBitmap.SaveToFile(const aFileName: String; + const aFileType: TglBitmapFileType); var FS: TFileStream; begin @@ -2880,7 +2755,8 @@ begin end; -procedure TglBitmap.SaveToStream(Stream: TStream; FileType: TglBitmapFileType); +procedure TglBitmap.SaveToStream(const aStream: TStream; + const aFileType: TglBitmapFileType); begin case FileType of {$IFDEF GLB_SUPPORT_PNG_WRITE} @@ -3471,7 +3347,7 @@ begin end; -procedure TglBitmap.SetFilter(Min, Mag: Integer); +procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal); begin case Min of GL_NEAREST: @@ -3520,7 +3396,8 @@ begin end; -procedure TglBitmap.SetWrap(S: Integer; T: Integer; R: Integer); +procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; + const R: Cardinal); begin case S of GL_CLAMP: @@ -3622,7 +3499,7 @@ end; procedure TglBitmap.SetDataPointer(NewData: pByte; - Format: TglBitmapInternalFormat; Width: Integer; Height: Integer); + Format: TglBitmapFormat; Width: Integer; Height: Integer); begin // Data if Data <> NewData then begin @@ -4250,7 +4127,7 @@ var Info: TBMPInfo; NewImage, pData: pByte; - Format: TglBitmapInternalFormat; + Format: TglBitmapFormat; LineSize, Padding, LineIdx: Integer; RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; @@ -4309,16 +4186,16 @@ begin 16: begin if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin - Format := ifRGB5A1; + Format := tfRGB5A1; end else begin if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then Format := ifLuminanceAlpha; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA4) then - Format := ifRGBA4; + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA4) then + Format := tfRGBA4; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifRGB5A1) then - Format := ifRGB5A1; + if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, tfRGB5A1) then + Format := tfRGB5A1; if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then Format := ifR5G6B5; @@ -4330,14 +4207,14 @@ begin if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin Format := ifBGRA8; end else begin - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGBA8) then - Format := ifRGBA8; + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA8) then + Format := tfRGBA8; if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then Format := ifBGRA8; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifRGB10A2) then - Format := ifRGB10A2; + if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGB10A2) then + Format := tfRGB10A2; end; end; end; @@ -4375,7 +4252,7 @@ begin end else Stream.Position := StreamPos; end; - +{$ENDREGION} const DDS_MAGIC = $20534444; @@ -4446,62 +4323,10 @@ type dwReserved: array[0..10] of Cardinal; PixelFormat: TDDSPixelFormat; Caps: TDDSCaps; - dwReserved2: Cardinal; - end; - -procedure TglBitmap.SetCustomData(const aValue: Pointer); -begin - if fCustomData = aValue then Exit; - fCustomData := aValue; -end; - -procedure TglBitmap.SetCustomName(const aValue: String); -begin - if fCustomName = aValue then Exit; - fCustomName := aValue; -end; - -procedure TglBitmap.SetCustomNameW(const aValue: WideString); -begin - if fCustomNameW = aValue then Exit; - fCustomNameW := aValue; -end; - -procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean); -begin - if fDeleteTextureOnFree = aValue then Exit; - fDeleteTextureOnFree := aValue; -end; - -procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat); -begin - if fFormat = aValue then Exit; - fFormat := aValue; -end; - -procedure TglBitmap.SetFreeDataAfterGenTexture(const aValue: Boolean); -begin - if fFreeDataAfterGenTexture = aValue then Exit; - fFreeDataAfterGenTexture := aValue; -end; - -procedure TglBitmap.SetID(const aValue: Cardinal); -begin - if fID = aValue then Exit; - fID := aValue; -end; - -procedure TglBitmap.SetMipMap(const aValue: TglBitmapMipMap); -begin - if fMipMap = aValue then Exit; - fMipMap := aValue; -end; + dwReserved2: Cardinal; + end; + -procedure TglBitmap.SetTarget(const aValue: Cardinal); -begin - if fTarget = aValue then Exit; - fTarget := aValue; -end; function TglBitmap.LoadDDS(Stream: TStream): Boolean; var @@ -4512,7 +4337,7 @@ var // MipMapCount, X, Y, XSize, YSize: Cardinal; RowSize: Cardinal; NewImage, pData: pByte; - Format: TglBitmapInternalFormat; + Format: TglBitmapFormat; function RaiseEx : Exception; @@ -4521,7 +4346,7 @@ var end; - function GetInternalFormat: TglBitmapInternalFormat; + function GetInternalFormat: TglBitmapFormat; begin with Header.PixelFormat do begin // Compresses @@ -4550,8 +4375,8 @@ var if dwFlags and DDPF_ALPHAPIXELS > 0 then begin // Alpha case GetBitSize(dwRBitMask) of - 5: Result := ifRGB5A1; - 4: Result := ifRGBA4; + 5: Result := tfRGB5A1; + 4: Result := tfRGBA4; else Result := ifLuminanceAlpha; end; @@ -4565,18 +4390,18 @@ var if dwRBitMask > dwBBitMask then Result := ifBGR8 else - Result := ifRGB8; + Result := tfRGB8; end; 32: begin if GetBitSize(dwRBitMask) = 10 then - Result := ifRGB10A2 + Result := tfRGB10A2 else if dwRBitMask > dwBBitMask then Result := ifBGRA8 else - Result := ifRGBA8; + Result := tfRGBA8; end; else raise RaiseEx; @@ -4670,7 +4495,7 @@ var NewImage, pData: PByte; StreamPos: Int64; PixelSize, LineSize, YStart, YEnd, YInc: Integer; - Format: TglBitmapInternalFormat; + Format: TglBitmapFormat; const CACHE_SIZE = $4000; @@ -5088,7 +4913,7 @@ var Pix: TglBitmapPixelData; begin if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT); if InternalFormat = ifAlpha then FormatPreparePixel(Pix, ifLuminance) @@ -5164,7 +4989,7 @@ var begin if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); FillChar(Header, SizeOf(Header), 0); @@ -5179,18 +5004,18 @@ begin Header.ImageType := TGA_UNCOMPRESSED_GRAY; Header.Bpp := 16; end; - ifRGB8, ifBGR8: + tfRGB8, ifBGR8: begin Header.ImageType := TGA_UNCOMPRESSED_RGB; Header.Bpp := 24; end; - ifRGBA8, ifBGRA8: + tfRGBA8, ifBGRA8: begin Header.ImageType := TGA_UNCOMPRESSED_RGB; Header.Bpp := 32; end; else - raise EglBitmapUnsupportedInternalFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); end; Header.Width := Width; @@ -5204,14 +5029,14 @@ begin // convert RGB(A) to BGR(A) Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat); - if InternalFormat in [ifRGB8, ifRGBA8] then begin + if InternalFormat in [tfRGB8, tfRGBA8] then begin GetMem(pTemp, Size); end else pTemp := Data; try // convert data - if InternalFormat in [ifRGB8, ifRGBA8] then begin + if InternalFormat in [tfRGB8, tfRGBA8] then begin Move(Data^, pTemp^, Size); ConvertData(pTemp); end; @@ -5220,7 +5045,7 @@ begin Stream.Write(pTemp^, Size); finally // free tempdata - if InternalFormat in [ifRGB8, ifRGBA8] then + if InternalFormat in [tfRGB8, tfRGBA8] then FreeMem(pTemp); end; end; @@ -5402,7 +5227,7 @@ var begin if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat)); @@ -5430,20 +5255,20 @@ begin Info.biClrUsed := 256; Info.biClrImportant := 256; end; - ifLuminanceAlpha, ifRGBA4, ifR5G6B5, ifRGB5A1: + ifLuminanceAlpha, tfRGBA4, ifR5G6B5, tfRGB5A1: begin Info.biBitCount := 16; Info.biCompression := BMP_COMP_BITFIELDS; end; - ifBGR8, ifRGB8: + ifBGR8, tfRGB8: Info.biBitCount := 24; - ifBGRA8, ifRGBA8, ifRGB10A2: + ifBGRA8, tfRGBA8, tfRGB10A2: begin Info.biBitCount := 32; Info.biCompression := BMP_COMP_BITFIELDS; end; else - raise EglBitmapUnsupportedInternalFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); end; Info.biXPelsPerMeter := 2835; Info.biYPelsPerMeter := 2835; @@ -5495,7 +5320,7 @@ begin // prepare row buffer. But only for RGB because RGBA supports color masks // so it's possible to change color within the image. - if InternalFormat = ifRGB8 then + if InternalFormat = tfRGB8 then GetMem(pTemp, fRowSize) else pTemp := nil; @@ -5504,7 +5329,7 @@ begin // write image data for LineIdx := 0 to Height - 1 do begin // preparing row - if InternalFormat = ifRGB8 then begin + if InternalFormat = tfRGB8 then begin Move(pData^, pTemp^, fRowSize); SwapRGB(pTemp, Width, False); end else @@ -5519,7 +5344,7 @@ begin end; finally // destroy row buffer - if InternalFormat = ifRGB8 then + if InternalFormat = tfRGB8 then FreeMem(pTemp); end; end; @@ -5560,238 +5385,8 @@ begin end; -procedure TglBitmap.CreateID; -begin - // Generate Texture - if ID <> 0 then - glDeleteTextures(1, @ID); - - glGenTextures(1, @ID); - - Bind(False); -end; - - -procedure TglBitmap.SetupParameters(var BuildWithGlu: Boolean); -begin - // Set up parameters - SetWrap(fWrapS, fWrapT, fWrapR); - SetFilter(fFilterMin, fFilterMag); - SetAnisotropic(fAnisotropic); - SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]); - - // Mip Maps generation Mode - BuildWithGlu := False; - - if (MipMap = mmMipmap) then begin - if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then - glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE) - else - BuildWithGlu := True; - end else - if (MipMap = mmMipmapGlu) then - BuildWithGlu := True; -end; - - -procedure TglBitmap.SelectFormat(DataFormat: TglBitmapInternalFormat; var glFormat, glInternalFormat, glType: Cardinal; CanConvertImage: Boolean = True); - - procedure Check12; - begin - if not GL_VERSION_1_2 then - raise EglBitmapUnsupportedInternalFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.'); - end; - -begin - glType := GL_UNSIGNED_BYTE; - // selecting Format - case DataFormat of - ifAlpha: - glFormat := GL_ALPHA; - ifLuminance: - glFormat := GL_LUMINANCE; - ifDepth8: - glFormat := GL_DEPTH_COMPONENT; - ifLuminanceAlpha: - glFormat := GL_LUMINANCE_ALPHA; - ifBGR8: - begin - if (GL_VERSION_1_2 or GL_EXT_bgra) then begin - glFormat := GL_BGR; - end else begin - if CanConvertImage then - ConvertTo(ifRGB8); - glFormat := GL_RGB; - end; - end; - ifBGRA8: - begin - if (GL_VERSION_1_2 or GL_EXT_bgra) then begin - glFormat := GL_BGRA; - end else begin - if CanConvertImage then - ConvertTo(ifRGBA8); - glFormat := GL_RGBA; - end; - end; - ifRGB8: - glFormat := GL_RGB; - ifRGBA8: - glFormat := GL_RGBA; - ifRGBA4: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_SHORT_4_4_4_4_REV; - end; - ifRGB5A1: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_SHORT_1_5_5_5_REV; - end; - ifRGB10A2: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_INT_2_10_10_10_REV; - end; - ifR5G6B5: - begin - Check12; - glFormat := GL_RGB; - glType := GL_UNSIGNED_SHORT_5_6_5; - end; - else - glFormat := 0; - end; - // Selecting InternalFormat - case DataFormat of - ifDXT1, ifDXT3, ifDXT5: - begin - if GL_EXT_texture_compression_s3tc then begin - case DataFormat of - ifDXT1: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - ifDXT3: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - ifDXT5: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - end; - end else begin - // Compression isn't supported so convert to RGBA - if CanConvertImage then - ConvertTo(ifRGBA8); - glFormat := GL_RGBA; - glInternalFormat := GL_RGBA8; - end; - end; - ifAlpha: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_ALPHA4; - tf8BitsPerChanel: - glInternalFormat := GL_ALPHA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_ALPHA - else - glInternalFormat := GL_ALPHA; - end; - else - glInternalFormat := GL_ALPHA; - end; - end; - ifLuminance: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_LUMINANCE4; - tf8BitsPerChanel: - glInternalFormat := GL_LUMINANCE8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_LUMINANCE - else - glInternalFormat := GL_LUMINANCE; - end; - else - glInternalFormat := GL_LUMINANCE; - end; - end; - ifDepth8: - begin - glInternalFormat := GL_DEPTH_COMPONENT; - end; - ifLuminanceAlpha: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_LUMINANCE4_ALPHA4; - tf8BitsPerChanel: - glInternalFormat := GL_LUMINANCE8_ALPHA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA - else - glInternalFormat := GL_LUMINANCE_ALPHA; - end; - else - glInternalFormat := GL_LUMINANCE_ALPHA; - end; - end; - ifBGR8, ifRGB8: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_RGB4; - tf8BitsPerChanel: - glInternalFormat := GL_RGB8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin - glInternalFormat := GL_COMPRESSED_RGB - end else begin - if (GL_EXT_texture_compression_s3tc) then - glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT - else - glInternalFormat := GL_RGB; - end; - end; - else - glInternalFormat := GL_RGB; - end; - end; - ifBGRA8, ifRGBA8, ifRGBA4, ifRGB5A1, ifRGB10A2, ifR5G6B5: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_RGBA4; - tf8BitsPerChanel: - glInternalFormat := GL_RGBA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin - glInternalFormat := GL_COMPRESSED_RGBA - end else begin - if (GL_EXT_texture_compression_s3tc) then - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - else - glInternalFormat := GL_RGBA; - end; - end; - else - glInternalFormat := GL_RGBA; - end; - end; - end; -end; function TglBitmap.FlipHorz: Boolean; @@ -5861,36 +5456,12 @@ begin end; -procedure TglBitmap.SetAnisotropic(const aValue: Integer); -var - MaxAniso: Integer; -begin - fAnisotropic := Value; - - if (ID > 0) then begin - if GL_EXT_texture_filter_anisotropic then begin - if fAnisotropic > 0 then begin - Bind(False); - - glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAniso); - - if Value > MaxAniso then - fAnisotropic := MaxAniso; - - glTexParameteri(Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, fAnisotropic); - end; - end else begin - fAnisotropic := 0; - end; - end; -end; - -procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapInternalFormat); +procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapFormat); begin if InternalFormat <> Value then begin if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT); // Update whatever SetDataPointer(Data, Value); @@ -5906,7 +5477,7 @@ end; function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction; - CreateTemp: Boolean; Format: TglBitmapInternalFormat; CustomData: Pointer): boolean; + CreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer): boolean; var pDest, NewImage, pSource: pByte; TempHeight, TempWidth: Integer; @@ -6062,7 +5633,7 @@ begin end; -function TglBitmap.ConvertTo(NewFormat: TglBitmapInternalFormat): boolean; +function TglBitmap.ConvertTo(NewFormat: TglBitmapFormat): boolean; var Source, Dest: TglBitmapPixelData; PixelDesc: TglBitmapPixelDesc; @@ -6123,7 +5694,7 @@ begin if (Assigned(Data)) then begin if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT); Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat)); end; @@ -6133,30 +5704,12 @@ end; function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean; begin if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData); end; -function TglBitmap.GetHeight: Integer; -begin - if ffY in fDimension.Fields then - Result := fDimension.Y - else - Result := -1; -end; - - -function TglBitmap.GetWidth: Integer; -begin - if ffX in fDimension.Fields then - Result := fDimension.X - else - Result := -1; -end; - - function TglBitmap.GetFileHeight: Integer; begin Result := Max(1, Height); @@ -6263,7 +5816,7 @@ end; { TglBitmap2D } -procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer); +procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width, Height: Integer); var Idx, LineWidth: Integer; begin @@ -6734,7 +6287,7 @@ var begin if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT); if Scale > 100 then Rec.Scale := 100 @@ -6855,14 +6408,14 @@ begin end; -procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapInternalFormat); +procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapFormat); var Temp: pByte; Size: Integer; glFormat, glInternalFormat, glType: Cardinal; begin if not FormatIsUncompressed(Format) then - raise EglBitmapUnsupportedInternalFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT); // Only to select Formats SelectFormat(Format, glFormat, glInternalFormat, glType, False); @@ -6890,7 +6443,7 @@ var Temp: pByte; TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer; TempType, TempIntFormat: Cardinal; - IntFormat: TglBitmapInternalFormat; + IntFormat: TglBitmapFormat; begin Bind; @@ -6921,20 +6474,20 @@ begin TempType := GL_UNSIGNED_SHORT_5_6_5; end; GL_RGB, GL_RGB8: - IntFormat := ifRGB8; + IntFormat := tfRGB8; GL_RGBA, GL_RGBA4, GL_RGBA8: begin if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin - IntFormat := ifRGBA4; + IntFormat := tfRGBA4; TempIntFormat := GL_BGRA; TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV; end else if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin - IntFormat := ifRGB5A1; + IntFormat := tfRGB5A1; TempIntFormat := GL_BGRA; TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV; end else begin - IntFormat := ifRGBA8; + IntFormat := tfRGBA8; end; end; GL_BGR: @@ -7333,15 +6886,14 @@ begin GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize); end; - - initialization - glBitmapSetDefaultFormat(tfDefault); + glBitmapSetDefaultFormat(tfEmpty); + glBitmapSetDefaultMipmap(mmMipmap); glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); - glBitmapSetDefaultWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); - glBitmapSetDefaultFreeDataAfterGenTexture(True); - glBitmapSetDefaultDeleteTextureOnFree(True); + glBitmapSetDefaultFreeDataAfterGenTexture(true); + glBitmapSetDefaultDeleteTextureOnFree (true); finalization From 2fabea9741641e2b321e923d5d4724f8aa4b97ee Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Mon, 28 Oct 2013 19:37:43 +0100 Subject: [PATCH 05/38] * refactoring nearly completed; now testing --- glBitmap.pas | 6207 ++++++++++++++++++++++++-------------------------- 1 file changed, 3032 insertions(+), 3175 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 04f4a9f..12e84af 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -168,9 +168,9 @@ History - function MoveMemory replaced with function Move (little speed change) - several calculations stored in variables (little speed change) 29-09-2003 -- property BuildMipsMaps added (default = True) +- property BuildMipsMaps added (default = true) if BuildMipMaps isn't set GenTextures uses glTexImage[12]D else it use gluBuild[12]dMipmaps -- property FreeDataAfterGenTexture added (default = True) +- property FreeDataAfterGenTexture added (default = true) if FreeDataAfterGenTexture is set the texturedata were deleted after the texture was generated. - parameter DisableOtherTextureUnits of Bind removed - parameter FreeDataAfterGeneration of GenTextures removed @@ -600,6 +600,7 @@ type AlphaRange: Cardinal; AlphaShift: Shortint; end; + PglBitmapPixelDesc = ^TglBitmapPixelDesc; //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapPixelData = packed record @@ -628,12 +629,12 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class; TglBitmapFunctionRec = record - Sender : TglBitmap; - Size: TglBitmapPixelPosition; + Sender: TglBitmap; + Size: TglBitmapPixelPosition; Position: TglBitmapPixelPosition; - Source: TglBitmapPixelData; - Dest: TglBitmapPixelData; - CustomData: Pointer; + Source: TglBitmapPixelData; + Dest: TglBitmapPixelData; + Args: PtrInt; end; TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); @@ -659,51 +660,63 @@ type TglBitmapFormat = ( tfEmpty = 0, - { TODO - tfAlpha4, - tfAlpha8, - tfAlpha12, - tfAlpha16, + //TODO + //tfAlpha4, + //tfAlpha8, + //tfAlpha12, + //tfAlpha16, - tfLuminance4, } + //tfLuminance4, tfLuminance8, -{ tfLuminance12, - tfLuminance16, - - tfuminance4Alpha4, - tfLuminance6Alpha2,} + //tfLuminance12, + //tfLuminance16, + // + //tfuminance4Alpha4, + //tfLuminance6Alpha2, tfLuminance8Alpha8, -{ tfLuminance12Alpha4, - tfLuminance12Alpha12, - tfLuminance16Alpha16, + //tfLuminance12Alpha4, + //tfLuminance12Alpha12, + //tfLuminance16Alpha16, - tfR3G3B2, - tfRGB4, - tfRGB5, } + //tfR3G3B2, + //tfRGB4, + tfRGB5, tfRGB8, -{ tfRGB10, - tfRGB12, - tfRGB16, + //tfRGB10, + //tfRGB12, + //tfRGB16, - tfRGBA2, - tfRGBA4, - tfRGB5A1, } + //tfRGBA2, + //tfRGBA4, + tfRGB5A1, tfRGBA8, -{ tfRGB10A2, - tfRGBA12, - tfRGBA16, - } + //tfRGB10A2, + //tfRGBA12, + //tfRGBA16, + + //tfBGR4, + //tfBGR5, tfBGR8, - tfBGRA8, - { - tfDepth16, - tfDepth24, - tfDepth32 } + //tfBGR10, + //tfBGR12, + //tfBGR16, + + //tfBGRA2, + //tfBGRA4, + //tfBGR5A1, + tfBGRA8 + //tfBGR10A2, + //tfBGRA12, + //tfBGRA16, + + //tfDepth16, + //tfDepth24, + //tfDepth32 ); //////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapGetPixel = procedure(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData) of object; - TglBitmapSetPixel = procedure(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData) of object; + TglBitmapGetPixel = procedure(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData) of object; + TglBitmapSetPixel = procedure(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData) of object; TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); @@ -716,13 +729,17 @@ type class function GetPixelDesc: TglBitmapPixelDesc; virtual; abstract; class function GetFormatDesc: TglBitmapFormatDesc; virtual; abstract; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); virtual; abstract; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); virtual; abstract; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); virtual; abstract; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); virtual; abstract; //virtual class function WithoutAlpha: TglBitmapFormat; virtual; class function WithAlpha: TglBitmapFormat; virtual; + class function GetSize: Single; virtual; overload; + class function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload; + class function GetColorCompCount: Integer; virtual; + class function IsEmpty: Boolean; virtual; class function HasAlpha: Boolean; virtual; class function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; @@ -739,11 +756,11 @@ type end; TglBitmapFormatDescClass = class of TglBitmapFormatDescriptor; - // Base Class +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class protected - fID: Cardinal; - fTarget: Cardinal; + fID: GLuint; + fTarget: GLuint; fAnisotropic: Integer; fDeleteTextureOnFree: Boolean; fFreeDataAfterGenTexture: Boolean; @@ -758,8 +775,8 @@ type // Mapping fPixelSize: Integer; fRowSize: Integer; - fUnmapFunc: TglBitmapUnMapFunc; - fMapFunc: TglBitmapMapFunc; + //TODO delete? fUnmapFunc: TglBitmapUnMapFunc; + //TODO delete? fMapFunc: TglBitmapMapFunc; // Filtering fFilterMin: Cardinal; @@ -770,8 +787,8 @@ type fWrapT: Cardinal; fWrapR: Cardinal; - fGetPixelFunc: TglBitmapGetPixel; - fSetPixelFunc: TglBitmapSetPixel; + //TODO delete? fGetPixelFunc: TglBitmapGetPixel; + //TODO delete? fSetPixelFunc: TglBitmapSetPixel; // CustomData fFilename: String; @@ -780,8 +797,11 @@ type fCustomData: Pointer; //Getter - function GetHeight: Integer; virtual; function GetWidth: Integer; virtual; + function GetHeight: Integer; virtual; + + function GetFileWidth: Integer; virtual; + function GetFileHeight: Integer; virtual; //Setter procedure SetCustomData(const aValue: Pointer); @@ -795,41 +815,22 @@ type procedure SetTarget(const aValue: Cardinal); procedure SetAnisotropic(const aValue: Integer); - //Load - {$IFDEF GLB_SUPPORT_PNG_READ} - function LoadPNG(Stream: TStream): Boolean; virtual; - {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_READ} - function LoadJPEG(Stream: TStream): Boolean; virtual; - {$ENDIF} - function LoadDDS(Stream: TStream): Boolean; virtual; - function LoadTGA(Stream: TStream): Boolean; virtual; - function LoadBMP(Stream: TStream): Boolean; virtual; - - //Save - {$IFDEF GLB_SUPPORT_PNG_WRITE} - procedure SavePNG(Stream: TStream); virtual; - {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_WRITE} - procedure SaveJPEG(Stream: TStream); virtual; - {$ENDIF} - procedure SaveDDS(Stream: TStream); virtual; - procedure SaveTGA(Stream: TStream); virtual; - procedure SaveBMP(Stream: TStream); virtual; - procedure CreateID; procedure SetupParameters(var aBuildWithGlu: Boolean); - procedure SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal); - - procedure SetDataPointer(NewData: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); virtual; - procedure GenTexture(TestTextureSize: Boolean = True); virtual; abstract; + procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; + procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract; function FlipHorz: Boolean; virtual; function FlipVert: Boolean; virtual; property Width: Integer read GetWidth; property Height: Integer read GetHeight; + + property FileWidth: Integer read GetFileWidth; + property FileHeight: Integer read GetFileHeight; public + //Properties property ID: Cardinal read fID write SetID; property Target: Cardinal read fTarget write SetTarget; property Format: TglBitmapFormat read fFormat write SetFormat; @@ -844,29 +845,33 @@ type property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree; property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture; - property Dimension: TglBitmapPixelPosition read fDimension; - property Data: PByte read fData; - property IsResident: Boolean read fIsResident; + property Dimension: TglBitmapPixelPosition read fDimension; + property Data: PByte read fData; + property IsResident: Boolean read fIsResident; procedure AfterConstruction; override; procedure BeforeDestruction; override; - //Loading - procedure LoadFromFile(const aFileName: String); + //Load + procedure LoadFromFile(const aFilename: String); procedure LoadFromStream(const aStream: TStream); virtual; procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0); {$IFDEF GLB_DELPHI} - procedure LoadFromResource(const aInstance: Cardinal; aResource: String; const aResType: PChar = nil); - procedure LoadFromResourceID(const sInstance: Cardinal; aResourceID: Integer; const aResType: PChar); + procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); + procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); {$ENDIF} + //Save procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual; - //function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer = nil): boolean; overload; - //function AddFunc(const aFunc: TglBitmapFunction; CreateTemp: Boolean; CustomData: Pointer = nil): boolean; overload; -(* TODO + //Convert + function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload; + function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean; + const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload; + public + //Alpha & Co {$IFDEF GLB_SDL} function AssignToSurface(out aSurface: PSDL_Surface): Boolean; function AssignFromSurface(const aSurface: PSDL_Surface): Boolean; @@ -881,19 +886,17 @@ type function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean; function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - {$ENDIF} - - function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual; - function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - {$IFDEF GLB_DELPHI} function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; {$ENDIF} + function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual; + function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean; function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean; function AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single = 0): Boolean; @@ -903,71 +906,96 @@ type function AddAlphaFromValueFloat(const aAlpha: Single): Boolean; function RemoveAlpha: Boolean; virtual; + public + //Common function Clone: TglBitmap; - function ConvertTo(const aFormat: TglBitmapFormat; const aInternalFormat: TglBitmapFormat): Boolean; virtual; - procedure SetBorderColor(Red, Green, Blue, Alpha: Single); - procedure Invert(const aUseRGB: Boolean = true; aUseAlpha: Boolean = false); + function ConvertTo(const aFormat: TglBitmapFormat): Boolean; virtual; + procedure Invert(const aUseRGB: Boolean = true; const aUseAlpha: Boolean = false); + procedure SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single); procedure FreeData; - procedure FillWithColor(const aRed, aGreen, aBlue: aByte; Alpha: Byte = 255); + //ColorFill + procedure FillWithColor(const aRed, aGreen, aBlue: Byte; const aAlpha: Byte = 255); procedure FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal = $FFFFFFFF); procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1); -*) + + //TexParameters procedure SetFilter(const aMin, aMag: Cardinal); procedure SetWrap( const S: Cardinal = GL_CLAMP_TO_EDGE; const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE); - procedure GetPixel(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); virtual; - procedure SetPixel(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); virtual; + procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); virtual; + procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual; - procedure Unbind(DisableTextureUnit: Boolean = True); virtual; - procedure Bind(EnableTextureUnit: Boolean = True); virtual; + procedure Bind(const aEnableTextureUnit: Boolean = true); virtual; + procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual; + //Constructors constructor Create; overload; - constructor Create(FileName: String); overload; - constructor Create(Stream: TStream); overload; + constructor Create(const aFileName: String); overload; + constructor Create(const aStream: TStream); overload; + constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload; + constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload; {$IFDEF GLB_DELPHI} - constructor CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar = nil); - constructor Create(Instance: Cardinal; Resource: String; ResType: PChar = nil); overload; - constructor Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); overload; + constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload; + constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload; {$ENDIF} - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat); overload; - constructor Create(Size: TglBitmapPixelPosition; Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer = nil); overload; - end; + private + {$IFDEF GLB_SUPPORT_PNG_READ} + function LoadPNG(const aStream: TStream): Boolean; virtual; + procedure SavePNG(const aStream: TStream); virtual; + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_READ} + function LoadJPEG(const aStream: TStream): Boolean; virtual; + procedure SaveJPEG(const aStream: TStream); virtual; + {$ENDIF} + function LoadBMP(const aStream: TStream): Boolean; virtual; + procedure SaveBMP(const aStream: TStream); virtual; + function LoadTGA(const aStream: TStream): Boolean; virtual; + procedure SaveTGA(const aStream: TStream); virtual; + function LoadDDS(const aStream: TStream): Boolean; virtual; + procedure SaveDDS(const aStream: TStream); virtual; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap2D = class(TglBitmap) protected // Bildeinstellungen fLines: array of PByte; + (* TODO procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData); procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - function GetScanline(Index: Integer): Pointer; - procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); + *) - procedure SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width: Integer = -1; Height: Integer = -1); override; - procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); + function GetScanline(const aIndex: Integer): Pointer; + procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer = - 1; const aHeight: Integer = - 1); override; + procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean); public property Width; property Height; - property Scanline[Index: Integer]: Pointer read GetScanline; + property Scanline[const aIndex: Integer]: Pointer read GetScanline; procedure AfterConstruction; override; procedure GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat); procedure GetDataFromTexture; - procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; const aScale: Single = 2; const aUseAlpha: Boolean = False); - procedure GenTexture(TestTextureSize: Boolean = True); override; + procedure GenTexture(const aTestTextureSize: Boolean = true); override; function FlipHorz: Boolean; override; function FlipVert: Boolean; override; + + procedure ToNormalMap(const aFunc: TglBitmapNormalMapFunc = nm3x3; + const aScale: Single = 2; const aUseAlpha: Boolean = false); end; (* TODO @@ -976,14 +1004,14 @@ type fGenMode: Integer; // Hide GenTexture - procedure GenTexture(TestTextureSize: Boolean = True); reintroduce; + procedure GenTexture(TestTextureSize: Boolean = true); reintroduce; public procedure AfterConstruction; override; procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true); - procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = True); reintroduce; virtual; - procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = True); reintroduce; virtual; + procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual; + procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual; end; @@ -1011,7 +1039,7 @@ type function FlipHorz: Boolean; override; // Generation - procedure GenTexture(TestTextureSize: Boolean = True); override; + procedure GenTexture(TestTextureSize: Boolean = true); override; end; *) @@ -1037,9 +1065,6 @@ procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; -// Formatfunctions -function FormatGetSize(const aFormat: TglBitmapFormat): Single; - var glBitmapDefaultDeleteTextureOnFree: Boolean; glBitmapDefaultFreeDataAfterGenTextures: Boolean; @@ -1061,6 +1086,61 @@ uses Math; type +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TBitfieldFormat = class(TObject) + private + fRedShift: ShortInt; + fGreenShift: ShortInt; + fBlueShift: ShortInt; + fAlphaShift: ShortInt; + + fRedRange: Cardinal; + fGreenRange: Cardinal; + fBlueRange: Cardinal; + fAlphaRange: Cardinal; + + fRedMask: UInt64; + fGreenMask: UInt64; + fBlueMask: UInt64; + fAlphaMask: UInt64; + function GetSize: Integer; + procedure SetAlphaMask(aValue: UInt64); + procedure SetAlphaRange(aValue: Cardinal); + procedure SetAlphaShift(aValue: ShortInt); + procedure SetBlueMask(aValue: UInt64); + procedure SetBlueRange(aValue: Cardinal); + procedure SetBlueShift(aValue: ShortInt); + procedure SetGreenMask(aValue: UInt64); + procedure SetGreenRange(aValue: Cardinal); + procedure SetGreenShift(aValue: ShortInt); + procedure SetRedMask(aValue: UInt64); + procedure SetRedRange(aValue: Cardinal); + procedure SetRedShift(aValue: ShortInt); + + procedure CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal; out aShift: ShortInt); + public + property RedShift: ShortInt read fRedShift write SetRedShift; + property GreenShift: ShortInt read fGreenShift write SetGreenShift; + property BlueShift: ShortInt read fBlueShift write SetBlueShift; + property AlphaShift: ShortInt read fAlphaShift write SetAlphaShift; + + property RedRange: Cardinal read fRedRange write SetRedRange; + property GreenRange: Cardinal read fGreenRange write SetGreenRange; + property BlueRange: Cardinal read fBlueRange write SetBlueRange; + property AlphaRange: Cardinal read fAlphaRange write SetAlphaRange; + + property RedMask: UInt64 read fRedMask write SetRedMask; + property GreenMask: UInt64 read fGreenMask write SetGreenMask; + property BlueMask: UInt64 read fBlueMask write SetBlueMask; + property AlphaMask: UInt64 read fAlphaMask write SetAlphaMask; + + property Size: Integer read GetSize; + + procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); + procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); overload; + procedure Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData); overload; + end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TfdEmpty = class(TglBitmapFormatDescriptor) public @@ -1068,8 +1148,8 @@ type class function GetPixelDesc: TglBitmapPixelDesc; override; class function GetFormatDesc: TglBitmapFormatDesc; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1080,8 +1160,8 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1092,10 +1172,22 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithoutAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdRGB5 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TfdRGB8 = class(TglBitmapFormatDescriptor) public @@ -1104,8 +1196,20 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdRGB5A1 = class(TglBitmapFormatDescriptor) + public + class function GetFormat: TglBitmapFormat; override; + class function GetPixelDesc: TglBitmapPixelDesc; override; + class function GetFormatDesc: TglBitmapFormatDesc; override; + class function WithoutAlpha: TglBitmapFormat; override; + + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1116,8 +1220,8 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithoutAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1128,8 +1232,8 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1140,46 +1244,59 @@ type class function GetFormatDesc: TglBitmapFormatDesc; override; class function WithoutAlpha: TglBitmapFormat; override; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); override; - class procedure Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); override; + class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; + class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; end; const LUMINANCE_WEIGHT_R = 0.30; LUMINANCE_WEIGHT_G = 0.59; LUMINANCE_WEIGHT_B = 0.11; - UNSUPPORTED_INTERNAL_FORMAT = 'the given format isn''t supported by this function.'; + + ALPHA_WEIGHT_R = 0.30; + ALPHA_WEIGHT_G = 0.59; + ALPHA_WEIGHT_B = 0.11; + + UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.'; + + FORMAT_DESCRIPTORS: array[TglBitmapFormat] of TglBitmapFormatDescClass = ( + TfdEmpty, + + TfdLuminance8, + TfdLuminance8Alpha8, + + TfdRGB5, + TfdRGB8, + + TfdRGB5A1, + TfdRGBA8, + + TfdBGR8, + TfdBGRA8 + ); + {$REGION Private Helper} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; begin - Result.Fields := []; + result.Fields := []; if X >= 0 then - Result.Fields := Result.Fields + [ffX]; + result.Fields := result.Fields + [ffX]; if Y >= 0 then - Result.Fields := Result.Fields + [ffY]; + result.Fields := result.Fields + [ffY]; - Result.X := Max(0, X); - Result.Y := Max(0, Y); -end; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function FormatGetImageSize(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat): Integer; -begin - if (aSize.X = 0) and (aSize.Y = 0) then - Result := 0 - else - Result := Ceil(Max(aSize.Y, 1) * Max(aSize.X, 1) * FormatGetSize(aFormat)); + result.X := Max(0, X); + result.Y := Max(0, Y); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin - //TODO check Formats! - result := []; - + //TODO Supported File Formats! + result := [ftDDS, ftTGA, ftBMP]; + (* {$IFDEF GLB_SUPPORT_PNG_WRITE} if aFormat in [ tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, @@ -1211,6 +1328,7 @@ begin tfDepth16, tfDepth24, tfDepth32] then result := result + [ftDDS, ftTGA, ftBMP]; + *) end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1222,7 +1340,17 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function GetBitSize(aBitSet: Cardinal): Integer; +function GetTopMostBit(aBitSet: UInt64): Integer; +begin + result := 0; + while aBitSet > 0 do begin + inc(result); + aBitSet := aBitSet shr 1; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function CountSetBits(aBitSet: UInt64): Integer; begin result := 0; while aBitSet > 0 do begin @@ -1233,6 +1361,8 @@ begin end; {$ENDREGION} +//TODO check _ARB functions and constants + (* GLB_NO_NATIVE_GL {$IFNDEF GLB_NO_NATIVE_GL} procedure ReadOpenGLExtensions; @@ -1281,19 +1411,19 @@ var ExtPos: Integer; begin ExtPos := Pos(Extension, Buffer); - Result := ExtPos > 0; + result := ExtPos > 0; - if Result then - Result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']); + if result then + result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']); end; function glLoad (aFunc: pAnsiChar): pointer; begin {$IFDEF LINUX} - Result := glXGetProcAddress(aFunc); + result := glXGetProcAddress(aFunc); {$else} - Result := wglGetProcAddress(aFunc); + result := wglGetProcAddress(aFunc); {$ENDIF} end; @@ -1310,29 +1440,29 @@ begin Buffer := glGetString(GL_VERSION); TrimVersionString(Buffer, MajorVersion, MinorVersion); - GL_VERSION_1_2 := False; - GL_VERSION_1_3 := False; - GL_VERSION_1_4 := False; - GL_VERSION_2_0 := False; + GL_VERSION_1_2 := false; + GL_VERSION_1_3 := false; + GL_VERSION_1_4 := false; + GL_VERSION_2_0 := false; if MajorVersion = 1 then begin if MinorVersion >= 1 then begin if MinorVersion >= 2 then - GL_VERSION_1_2 := True; + GL_VERSION_1_2 := true; if MinorVersion >= 3 then - GL_VERSION_1_3 := True; + GL_VERSION_1_3 := true; if MinorVersion >= 4 then - GL_VERSION_1_4 := True; + GL_VERSION_1_4 := true; end; end; if MajorVersion >= 2 then begin - GL_VERSION_1_2 := True; - GL_VERSION_1_3 := True; - GL_VERSION_1_4 := True; - GL_VERSION_2_0 := True; + GL_VERSION_1_2 := true; + GL_VERSION_1_3 := true; + GL_VERSION_1_4 := true; + GL_VERSION_2_0 := true; end; // Extensions @@ -1403,7 +1533,7 @@ begin {$R+} {$ENDIF} - Result := CreatePalette(Pal^); + result := CreatePalette(Pal^); FreeMem(Pal); end; @@ -1414,36 +1544,36 @@ end; {$IFDEF GLB_SDL_IMAGE} function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; begin - Result := TStream(context^.unknown.data1).Seek(offset, whence); + result := TStream(context^.unknown.data1).Seek(offset, whence); end; function glBitmapRWread(context: PSDL_RWops; Ptr: Pointer; size: Integer; maxnum : Integer): Integer; cdecl; begin - Result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum); + result := TStream(context^.unknown.data1).Read(Ptr^, size * maxnum); end; function glBitmapRWwrite(context: PSDL_RWops; Ptr: Pointer; size: Integer; num: Integer): Integer; cdecl; begin - Result := TStream(context^.unknown.data1).Write(Ptr^, size * num); + result := TStream(context^.unknown.data1).Write(Ptr^, size * num); end; function glBitmapRWclose(context: PSDL_RWops): Integer; cdecl; begin - Result := 0; + result := 0; end; function glBitmapCreateRWops(Stream: TStream): PSDL_RWops; begin - Result := SDL_AllocRW; + result := SDL_AllocRW; - if Result = nil then + if result = nil then raise EglBitmapException.Create('glBitmapCreateRWops - SDL_AllocRW failed.'); - Result^.seek := glBitmapRWseek; - Result^.read := glBitmapRWread; - Result^.write := glBitmapRWwrite; - Result^.close := glBitmapRWclose; - Result^.unknown.data1 := Stream; + result^.seek := glBitmapRWseek; + result^.read := glBitmapRWread; + result^.write := glBitmapRWwrite; + result^.close := glBitmapRWclose; + result^.unknown.data1 := Stream; end; {$ENDIF} *) @@ -1453,7 +1583,7 @@ function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; var glBitmap: TglBitmap2D; begin - Result := false; + result := false; Texture := 0; {$IFDEF GLB_DELPHI} @@ -1467,12 +1597,12 @@ begin glBitmap := TglBitmap2D.Create(FileName); try - glBitmap.DeleteTextureOnFree := False; - glBitmap.FreeDataAfterGenTexture := False; - glBitmap.GenTexture(True); + glBitmap.DeleteTextureOnFree := false; + glBitmap.FreeDataAfterGenTexture := false; + glBitmap.GenTexture(true); if (glBitmap.ID > 0) then begin Texture := glBitmap.ID; - Result := True; + result := true; end; finally glBitmap.Free; @@ -1492,7 +1622,7 @@ begin CM := TglBitmapCubeMap.Create; try - CM.DeleteTextureOnFree := False; + CM.DeleteTextureOnFree := false; // Maps {$IFDEF GLB_DELPHI} @@ -1544,7 +1674,7 @@ begin CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); Texture := CM.ID; - Result := True; + result := true; finally CM.Free; end; @@ -1558,11 +1688,11 @@ begin NM := TglBitmapNormalMap.Create; try - NM.DeleteTextureOnFree := False; + NM.DeleteTextureOnFree := false; NM.GenerateNormalMap(Size); Texture := NM.ID; - Result := True; + result := true; finally NM.Free; end; @@ -1649,6 +1779,188 @@ begin end; {$ENDREGION} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TCustomFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetAlphaMask(aValue: UInt64); +begin + if fAlphaMask = aValue then Exit; + fAlphaMask := aValue; + CalcShiftAndRange(fAlphaMask, fAlphaRange, fAlphaShift); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TBitfieldFormat.GetSize: Integer; +var + tmp: UInt64; +begin + tmp := + (fRedRange shl fRedShift) or + (fGreenRange shl fGreenShift) or + (fBlueRange shl fBlueShift) or + (fAlphaRange shl fAlphaShift); + result := Trunc(GetTopMostBit(tmp) / 8); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetAlphaRange(aValue: Cardinal); +begin + if fAlphaRange = aValue then Exit; + fAlphaRange := aValue; + fAlphaMask := fAlphaRange shl fAlphaShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetAlphaShift(aValue: ShortInt); +begin + if fAlphaShift = aValue then Exit; + fAlphaShift := aValue; + fAlphaMask := fAlphaRange shl fAlphaShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetBlueMask(aValue: UInt64); +begin + if fBlueMask = aValue then Exit; + fBlueMask := aValue; + CalcShiftAndRange(fBlueMask, fBlueRange, fBlueShift); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetBlueRange(aValue: Cardinal); +begin + if fBlueRange = aValue then Exit; + fBlueRange := aValue; + fBlueMask := fBlueRange shl fBlueShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetBlueShift(aValue: ShortInt); +begin + if fBlueShift = aValue then Exit; + fBlueShift := aValue; + fBlueMask := fBlueRange shl fBlueShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetGreenMask(aValue: UInt64); +begin + if fGreenMask = aValue then Exit; + fGreenMask := aValue; + CalcShiftAndRange(fGreenMask, fGreenRange, fGreenShift); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetGreenRange(aValue: Cardinal); +begin + if fGreenRange = aValue then Exit; + fGreenRange := aValue; + fGreenMask := fGreenRange shl fGreenShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetGreenShift(aValue: ShortInt); +begin + if fGreenShift = aValue then Exit; + fGreenShift := aValue; + fGreenMask := fGreenRange shl fGreenShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetRedMask(aValue: UInt64); +begin + if fRedMask = aValue then Exit; + fRedMask := aValue; + CalcShiftAndRange(fRedMask, fRedRange, fRedShift); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetRedRange(aValue: Cardinal); +begin + if fRedRange = aValue then Exit; + fRedRange := aValue; + fRedMask := fRedRange shl fRedShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetRedShift(aValue: ShortInt); +begin + if fRedShift = aValue then Exit; + fRedShift := aValue; + fRedMask := fRedRange shl fRedShift; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal; + out aShift: ShortInt); +begin + aShift := 0; + aRange := 0; + if (aMask = 0) then + exit; + while (aMask > 0) and ((aMask and 1) = 0) do begin + inc(aShift); + aMask := aMask shr 1; + end; + aRange := 1; + while (aMask > 0) do begin + aRange := aRange shl 1; + aMask := aMask shr 1; + end; + dec(aRange); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +var + data: UInt64; + s: Integer; +type + PUInt64 = ^UInt64; +begin + data := + ((aPixel.Red and fRedRange) shl fRedShift) or + ((aPixel.Green and fGreenRange) shl fGreenShift) or + ((aPixel.Blue and fBlueRange) shl fBlueShift) or + ((aPixel.Alpha and fAlphaRange) shl fAlphaShift); + s := Size; + case s of + 1: aData^ := data; + 2: PWord(aData)^ := data; + 4: PCardinal(aData)^ := data; + 8: PUInt64(aData)^ := data; + end; + inc(aData, s); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +var + data: UInt64; + s: Integer; +type + PUInt64 = ^UInt64; +begin + s := Size; + case s of + 1: data := aData^; + 2: data := PWord(aData)^; + 4: data := PCardinal(aData)^; + 8: data := PUInt64(aData)^; + end; + Unmap(data, aPixel); + inc(aData, s); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData); +begin + aPixel.Red := (aData shr fRedShift) and fRedRange; + aPixel.Green := (aData shr fGreenShift) and fGreenRange; + aPixel.Blue := (aData shr fBlueShift) and fBlueRange; + aPixel.Alpha := (aData shr fAlphaShift) and fAlphaRange; +end; + {$REGION TglBitmapFormatDescriptor} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1670,6 +1982,50 @@ begin result := tfEmpty; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.GetSize: Single; +var + tmp: UInt64; +begin + with GetPixelDesc do begin + tmp := + (RedRange shl RedShift) or + (GreenRange shl GreenShift) or + (BlueRange shl BlueShift) or + (AlphaRange shl AlphaShift); + end; + result := Trunc(GetTopMostBit(tmp) / 4) / 2; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer; +var + w, h: Integer; +begin + if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin + w := Max(1, aSize.X); + h := Max(1, aSize.Y); + result := Ceil(w * h * GetSize); + end else + result := 0; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.GetColorCompCount: Integer; +begin + result := 0; + with GetPixelDesc do begin + if (RedRange > 0) then + inc(result); + if (GreenRange > 0) then + inc(result); + if (BlueRange > 0) then + inc(result); + if (AlphaRange > 0) then + inc(result); + end; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class function TglBitmapFormatDescriptor.IsEmpty: Boolean; begin @@ -1687,7 +2043,7 @@ class function TglBitmapFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, a var PixelDesc: TglBitmapPixelDesc; begin - result := False; + result := false; if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); @@ -1703,14 +2059,15 @@ begin if (aAlphaMask <> 0) and (aAlphaMask <> (AlphaRange shl AlphaShift)) then exit; end; - result := True; + result := true; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class procedure TglBitmapFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData); begin FillChar(aPixel, SizeOf(aPixel), 0); - with GetPixelDesc do begin + aPixel.PixelDesc := GetPixelDesc; + with aPixel.PixelDesc do begin aPixel.Red := RedRange; aPixel.Green := GreenRange; aPixel.Blue := BlueRange; @@ -1747,12 +2104,12 @@ begin end; end; -class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte ); begin raise EglBitmapException.Create('format does not support mapping'); end; -class procedure TfdEmpty.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdEmpty.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin raise EglBitmapException.Create('format does not support unmapping'); end; @@ -1791,7 +2148,7 @@ begin result := tfLuminance8Alpha8; end; -class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin aData^ := Trunc( aPixel.Red * LUMINANCE_WEIGHT_R + @@ -1800,7 +2157,7 @@ begin inc(aData); end; -class procedure TfdLuminance8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Red := aData^; aPixel.Green := aData^; @@ -1843,7 +2200,7 @@ begin result := tfLuminance8; end; -class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin aData^ := Trunc( aPixel.Red * LUMINANCE_WEIGHT_R + @@ -1855,7 +2212,7 @@ begin inc(aData); end; -class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Red := aData^; aPixel.Green := aData^; @@ -1867,6 +2224,56 @@ begin end; {$ENDREGION} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGB5///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdRGB5.GetFormat: TglBitmapFormat; +begin + result := tfRGB5; +end; + +class function TfdRGB5.GetPixelDesc: TglBitmapPixelDesc; +begin + with result do begin + RedRange := $0000001F; RedShift := 0; + GreenRange := $0000001F; GreenShift := 5; + BlueRange := $0000001F; BlueShift := 10; + AlphaRange := $00000000; AlphaShift := 0; + end; +end; + +class function TfdRGB5.GetFormatDesc: TglBitmapFormatDesc; +begin + with result do begin + Format := GL_RGB; + InternalFormat := GL_RGB5; + DataType := GL_UNSIGNED_SHORT_5_5_5_1; + end; +end; + +class function TfdRGB5.WithAlpha: TglBitmapFormat; +begin + result := tfRGB5A1; +end; + +class procedure TfdRGB5.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +begin + PWord(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); + inc(aData, 2); +end; + +class procedure TfdRGB5.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +begin + aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange; + aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange; + aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange; + aPixel.Alpha := 0; + inc(aData, 2); +end; + {$REGION TfdRGB8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TfdRGB8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1900,7 +2307,7 @@ begin result := tfRGBA8; end; -class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin aData^ := aPixel.Red; inc(aData); @@ -1910,7 +2317,7 @@ begin inc(aData); end; -class procedure TfdRGB8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Red := aData^; inc(aData); @@ -1922,52 +2329,103 @@ begin end; {$ENDREGION} -{$REGION TfdRGBA8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdRGBA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGB5A1/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdRGBA8.GetFormat: TglBitmapFormat; +class function TfdRGB5A1.GetFormat: TglBitmapFormat; begin - result := tfRGBA8; + result := tfRGB5A1; end; -class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc; +class function TfdRGB5A1.GetPixelDesc: TglBitmapPixelDesc; begin with result do begin - RedRange := $000000FF; RedShift := 0; - GreenRange := $000000FF; GreenShift := 8; - BlueRange := $000000FF; BlueShift := 16; - AlphaRange := $000000FF; AlphaShift := 24; + RedRange := $0000001F; RedShift := 0; + GreenRange := $0000001F; GreenShift := 5; + BlueRange := $0000001F; BlueShift := 10; + AlphaRange := $00000001; AlphaShift := 15; end; end; -class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc; +class function TfdRGB5A1.GetFormatDesc: TglBitmapFormatDesc; begin with result do begin - Format := GL_RGB; - InternalFormat := GL_RGB8; - DataType := GL_UNSIGNED_BYTE; + Format := GL_RGBA; + InternalFormat := GL_RGB5_A1; + DataType := GL_UNSIGNED_SHORT_5_5_5_1; end; end; -class function TfdRGBA8.WithoutAlpha: TglBitmapFormat; +class function TfdRGB5A1.WithoutAlpha: TglBitmapFormat; begin - result := tfRGB8; + //TODO result := tfRGB5; end; -class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdRGB5A1.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin - aData^ := aPixel.Red; - inc(aData); - aData^ := aPixel.Green; - inc(aData); - aData^ := aPixel.Blue; + PWord(aData)^ := + ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or + ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or + ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or + ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inc(aData, 2); +end; + +class procedure TfdRGB5A1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +begin + aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange; + aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange; + aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange; + aPixel.Alpha := (PWord(aData)^ shr aPixel.PixelDesc.AlphaShift) and aPixel.PixelDesc.AlphaRange; + inc(aData, 2); +end; + +{$REGION TfdRGBA8} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGBA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TfdRGBA8.GetFormat: TglBitmapFormat; +begin + result := tfRGBA8; +end; + +class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc; +begin + with result do begin + RedRange := $000000FF; RedShift := 0; + GreenRange := $000000FF; GreenShift := 8; + BlueRange := $000000FF; BlueShift := 16; + AlphaRange := $000000FF; AlphaShift := 24; + end; +end; + +class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc; +begin + with result do begin + Format := GL_RGB; + InternalFormat := GL_RGB8; + DataType := GL_UNSIGNED_BYTE; + end; +end; + +class function TfdRGBA8.WithoutAlpha: TglBitmapFormat; +begin + result := tfRGB8; +end; + +class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +begin + aData^ := aPixel.Red; + inc(aData); + aData^ := aPixel.Green; + inc(aData); + aData^ := aPixel.Blue; inc(aData); aData^ := aPixel.Alpha; inc(aData); end; -class procedure TfdRGBA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Red := aData^; inc(aData); @@ -2013,7 +2471,7 @@ begin result := tfBGRA8; end; -class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin aData^ := aPixel.Blue; inc(aData); @@ -2023,7 +2481,7 @@ begin inc(aData); end; -class procedure TfdBGR8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Blue := aData^; inc(aData); @@ -2067,7 +2525,7 @@ begin result := tfBGR8; end; -class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); +class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); begin aData^ := aPixel.Blue; inc(aData); @@ -2079,7 +2537,7 @@ begin inc(aData); end; -class procedure TfdBGRA8.Unmap(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); +class procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); begin aPixel.Blue := aData^; inc(aData); @@ -2092,19 +2550,163 @@ begin end; {$ENDREGION} -{$REGION TglBitmap } +{$REGION TglBitmap} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TglBitmap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap - Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.GetHeight: Integer; +procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec); begin - if (ffY in fDimension.Fields) then - result := fDimension.Y - else - result := -1; + with aFuncRec do begin + if (Source.PixelDesc.RedRange > 0) then + Dest.Red := Source.Red; + if (Source.PixelDesc.GreenRange > 0) then + Dest.Green := Source.Green; + if (Source.PixelDesc.BlueRange > 0) then + Dest.Blue := Source.Blue; + if (Source.PixelDesc.AlphaRange > 0) then + Dest.Alpha := Source.Alpha; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec); +begin + with aFuncRec do begin + if (Source.PixelDesc.RedRange > 0) then + Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange); + if (Source.PixelDesc.GreenRange > 0) then + Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange); + if (Source.PixelDesc.BlueRange > 0) then + Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange); + if (Source.PixelDesc.AlphaRange > 0) then + Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange); + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec); +begin + with aFuncRec do + with PglBitmapPixelDesc(Args)^ do begin + if (Source.PixelDesc.RedRange > 0) then + Dest.Red := Source.Red shr RedShift; + if (Source.PixelDesc.GreenRange > 0) then + Dest.Green := Source.Green shr GreenShift; + if (Source.PixelDesc.BlueRange > 0) then + Dest.Blue := Source.Blue shr BlueShift; + if (Source.PixelDesc.AlphaRange > 0) then + Dest.Alpha := Source.Alpha shr AlphaShift; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec); +begin + with aFuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + Dest.Alpha := Source.Alpha; + if (Args and $1 > 0) then begin + Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange; + Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange; + Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange; + end; + if (Args and $2 > 0) then begin + Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange; + end; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec); +type + PglBitmapPixelData = ^TglBitmapPixelData; +begin + with aFuncRec do begin + Dest.Red := PglBitmapPixelData(Args)^.Red; + Dest.Green := PglBitmapPixelData(Args)^.Green; + Dest.Blue := PglBitmapPixelData(Args)^.Blue; + Dest.Alpha := PglBitmapPixelData(Args)^.Alpha; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec); +var + Temp: Single; +begin + with FuncRec do begin + if (FuncRec.Args = 0) then begin //source has no alpha + Temp := + Source.Red / Source.PixelDesc.RedRange * ALPHA_WEIGHT_R + + Source.Green / Source.PixelDesc.GreenRange * ALPHA_WEIGHT_G + + Source.Blue / Source.PixelDesc.BlueRange * ALPHA_WEIGHT_B; + Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Temp); + end else + Dest.Alpha := Round(Source.Alpha / Source.PixelDesc.AlphaRange * Dest.PixelDesc.AlphaRange); + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec); +type + PglBitmapPixelData = ^TglBitmapPixelData; +begin + with FuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + + with PglBitmapPixelData(Args)^ do + if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and + (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and + (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then + Dest.Alpha := 0 + else + Dest.Alpha := Dest.PixelDesc.AlphaRange; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec); +type + PglBitmapPixelData = ^TglBitmapPixelData; +begin + with FuncRec do begin + Dest.Red := Source.Red; + Dest.Green := Source.Green; + Dest.Blue := Source.Blue; + with PglBitmapPixelData(Args)^ do + Dest.Alpha := Alpha; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure SwapRGB(aData: PByte; aWidth: Integer; const aHasAlpha: Boolean); +type + PRGBPix = ^TRGBPix; + TRGBPix = array [0..2] of byte; +var + Temp: Byte; +begin + while aWidth > 0 do begin + Temp := PRGBPix(aData)^[0]; + PRGBPix(aData)^[0] := PRGBPix(aData)^[2]; + PRGBPix(aData)^[2] := Temp; + + if aHasAlpha then + Inc(aData, 4) + else + Inc(aData, 3); + dec(aWidth); + end; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap - PROTECTED/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{$REGION Getter} function TglBitmap.GetWidth: Integer; begin if (ffX in fDimension.Fields) then @@ -2113,6 +2715,28 @@ begin result := -1; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetHeight: Integer; +begin + if (ffY in fDimension.Fields) then + result := fDimension.Y + else + result := -1; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetFileWidth: Integer; +begin + result := Max(1, Width); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetFileHeight: Integer; +begin + result := Max(1, Height); +end; +{$ENDREGION} + {$REGION Setter} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SetCustomData(const aValue: Pointer); @@ -2151,7 +2775,9 @@ procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat); begin if fFormat = aValue then exit; - fFormat := aValue; + if (FORMAT_DESCRIPTORS[Format].GetSize <> FORMAT_DESCRIPTORS[aValue].GetSize) then + raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT); + SetDataPointer(Data, aValue, Width, Height); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2191,11 +2817,11 @@ procedure TglBitmap.SetAnisotropic(const aValue: Integer); var MaxAnisotropic: Integer; begin - fAnisotropic := Value; + fAnisotropic := aValue; if (ID > 0) then begin if GL_EXT_texture_filter_anisotropic then begin if fAnisotropic > 0 then begin - Bind(False); + Bind(false); glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @MaxAnisotropic); if aValue > MaxAnisotropic then fAnisotropic := MaxAnisotropic; @@ -2208,38 +2834,12 @@ begin end; {$ENDREGION} -procedure TglBitmap.AfterConstruction; -begin - inherited AfterConstruction; - - fID := 0; - fTarget := 0; - fIsResident := False; - - fFormat := glBitmapGetDefaultFormat; - fMipMap := glBitmapDefaultMipmap; - fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; - fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; - - glBitmapGetDefaultFilter (fFilterMin, fFilterMag); - glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); -end; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.BeforeDestruction; -begin - SetDataPointer(nil, ifEmpty); - if (ID > 0) and fDeleteTextureOnFree then - glDeleteTextures(1, @ID); - inherited BeforeDestruction; -end; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.CreateID; begin - if ID <> 0 then - glDeleteTextures(1, @ID); - glGenTextures(1, @ID); + if (ID <> 0) then + glDeleteTextures(1, @fID); + glGenTextures(1, @fID); Bind(false); end; @@ -2253,657 +2853,406 @@ begin SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]); // Mip Maps Generation Mode - aBuildWithGlu := False; + aBuildWithGlu := false; if (MipMap = mmMipmap) then begin if (GL_VERSION_1_4 or GL_SGIS_generate_mipmap) then glTexParameteri(Target, GL_GENERATE_MIPMAP, GL_TRUE) else - BuildWithGlu := True; + aBuildWithGlu := true; end else if (MipMap = mmMipmapGlu) then - BuildWithGlu := True; + aBuildWithGlu := true; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SelectFormat(const aFormat: TglBitmapFormat; var glFormat, glInternalFormat, glType: Cardinal); +procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer; const aHeight: Integer); +var + s: Single; +begin + if (Data <> aData) then begin + if (Assigned(Data)) then + FreeMem(Data); + fData := aData; + end; - procedure Check12; - begin - if not GL_VERSION_1_2 then - raise EglBitmapUnsupportedFormatFormat.Create('SelectFormat - You need at least OpenGL 1.2 to support these format.'); + FillChar(fDimension, SizeOf(fDimension), 0); + if not Assigned(fData) then begin + fFormat := tfEmpty; + fPixelSize := 0; + fRowSize := 0; + end else begin + if aWidth <> -1 then begin + fDimension.Fields := fDimension.Fields + [ffX]; + fDimension.X := aWidth; + end; + + if aHeight <> -1 then begin + fDimension.Fields := fDimension.Fields + [ffY]; + fDimension.Y := aHeight; + end; + + s := FORMAT_DESCRIPTORS[aFormat].GetSize; + fFormat := aFormat; + fPixelSize := Ceil(s); + fRowSize := Ceil(s * aWidth); end; +end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.FlipHorz: Boolean; begin - PIXEL_DESC_ALPHA12; - glType := GL_UNSIGNED_BYTE; - glInternalFormat := Cardinal(aFormat); + result := false; +end; - case aFormat of - tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16: - glFormat := GL_ALPHA; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.FlipVert: Boolean; +begin + result := false; +end; - tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16: - glFormat := GL_LUMINANCE; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap - PUBLIC////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.AfterConstruction; +begin + inherited AfterConstruction; - tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, - tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16: - glFormat := GL_LUMINANCE_ALPHA; + fID := 0; + fTarget := 0; + fIsResident := false; - tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16: - glFormat := GL_RGB; + fFormat := glBitmapGetDefaultFormat; + fMipMap := glBitmapDefaultMipmap; + fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; + fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; - tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16: - glFormat := GL_RGBA; + glBitmapGetDefaultFilter (fFilterMin, fFilterMag); + glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); +end; - tfDepth16, tfDepth24, tfDepth32: - glFormat := GL_DEPTH_COMPONENT; - else - glFormat := 0; - end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.BeforeDestruction; +begin + SetDataPointer(nil, tfEmpty); + if (fID > 0) and fDeleteTextureOnFree then + glDeleteTextures(1, @fID); + inherited BeforeDestruction; +end; - case aFormat of - tfRGBA4: - glType := GL_UNSIGNED_SHORT_4_4_4_4; - tfRGB5A1: - glType := GL_UNSIGNED_SHORT_5_5_5_1; - tfRG +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.LoadFromFile(const aFilename: String); +var + fs: TFileStream; +begin + fFilename := aFilename; + fs := TFileStream.Create(fFilename, fmOpenRead); + try + fs.Position := 0; + LoadFromStream(fs); + finally + fs.Free; end; +end; - - // selecting Format - case DataFormat of - ifAlpha: - glFormat := GL_ALPHA; - ifLuminance: - glFormat := GL_LUMINANCE; - ifDepth8: - glFormat := GL_DEPTH_COMPONENT; - ifLuminanceAlpha: - glFormat := GL_LUMINANCE_ALPHA; - ifBGR8: - begin - if (GL_VERSION_1_2 or GL_EXT_bgra) then begin - glFormat := GL_BGR; - end else begin - if CanConvertImage then - ConvertTo(tfRGB8); - glFormat := GL_RGB; - end; - end; - ifBGRA8: - begin - if (GL_VERSION_1_2 or GL_EXT_bgra) then begin - glFormat := GL_BGRA; - end else begin - if CanConvertImage then - ConvertTo(tfRGBA8); - glFormat := GL_RGBA; - end; - end; - tfRGB8: - glFormat := GL_RGB; - tfRGBA8: - glFormat := GL_RGBA; - tfRGBA4: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_SHORT_4_4_4_4_REV; - end; - tfRGB5A1: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_SHORT_1_5_5_5_REV; - end; - tfRGB10A2: - begin - Check12; - glFormat := GL_BGRA; - glType := GL_UNSIGNED_INT_2_10_10_10_REV; - end; - ifR5G6B5: - begin - Check12; - glFormat := GL_RGB; - glType := GL_UNSIGNED_SHORT_5_6_5; - end; - else - glFormat := 0; - end; - - // Selecting InternalFormat - case DataFormat of - ifDXT1, ifDXT3, ifDXT5: - begin - if GL_EXT_texture_compression_s3tc then begin - case DataFormat of - ifDXT1: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - ifDXT3: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - ifDXT5: - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - end; - end else begin - // Compression isn't supported so convert to RGBA - if CanConvertImage then - ConvertTo(tfRGBA8); - glFormat := GL_RGBA; - glInternalFormat := GL_RGBA8; - end; - end; - ifAlpha: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_ALPHA4; - tf8BitsPerChanel: - glInternalFormat := GL_ALPHA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_ALPHA - else - glInternalFormat := GL_ALPHA; - end; - else - glInternalFormat := GL_ALPHA; - end; - end; - ifLuminance: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_LUMINANCE4; - tf8BitsPerChanel: - glInternalFormat := GL_LUMINANCE8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_LUMINANCE - else - glInternalFormat := GL_LUMINANCE; - end; - else - glInternalFormat := GL_LUMINANCE; - end; - end; - ifDepth8: - begin - glInternalFormat := GL_DEPTH_COMPONENT; - end; - ifLuminanceAlpha: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_LUMINANCE4_ALPHA4; - tf8BitsPerChanel: - glInternalFormat := GL_LUMINANCE8_ALPHA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then - glInternalFormat := GL_COMPRESSED_LUMINANCE_ALPHA - else - glInternalFormat := GL_LUMINANCE_ALPHA; - end; - else - glInternalFormat := GL_LUMINANCE_ALPHA; - end; - end; - ifBGR8, tfRGB8: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_RGB4; - tf8BitsPerChanel: - glInternalFormat := GL_RGB8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin - glInternalFormat := GL_COMPRESSED_RGB - end else begin - if (GL_EXT_texture_compression_s3tc) then - glInternalFormat := GL_COMPRESSED_RGB_S3TC_DXT1_EXT - else - glInternalFormat := GL_RGB; - end; - end; - else - glInternalFormat := GL_RGB; - end; - end; - ifBGRA8, tfRGBA8, tfRGBA4, tfRGB5A1, tfRGB10A2, ifR5G6B5: - begin - case Format of - tf4BitsPerChanel: - glInternalFormat := GL_RGBA4; - tf8BitsPerChanel: - glInternalFormat := GL_RGBA8; - tfCompressed: - begin - if (GL_ARB_texture_compression or GL_VERSION_1_3) then begin - glInternalFormat := GL_COMPRESSED_RGBA - end else begin - if (GL_EXT_texture_compression_s3tc) then - glInternalFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT - else - glInternalFormat := GL_RGBA; - end; - end; - else - glInternalFormat := GL_RGBA; - end; - end; - end; -end; - - - - - - - - - - - - - - - - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.LoadFromStream(const aStream: TStream); +begin + {$IFDEF GLB_SUPPORT_PNG_READ} + if not LoadPNG(aStream) then + {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_READ} + if not LoadJPEG(aStream) then + {$ENDIF} + if not LoadDDS(aStream) then + if not LoadTGA(aStream) then + if not LoadBMP(aStream) then + raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.'); +end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TglBitmap.Create; -begin - {$IFNDEF GLB_NO_NATIVE_GL} - ReadOpenGLExtensions; - {$ENDIF} - - if (ClassType = TglBitmap) then - raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); - - inherited Create; -end; - - -constructor TglBitmap.Create(FileName: String); -begin - Create; - LoadFromFile(FileName); -end; - - -constructor TglBitmap.Create(Stream: TStream); -begin - Create; - LoadFromStream(Stream); -end; - - -{$IFDEF GLB_DELPHI} -constructor TglBitmap.CreateFromResourceName(Instance: Cardinal; Resource: String; ResType: PChar); -begin - Create; - LoadFromResource(Instance, Resource, ResType); -end; - - -constructor TglBitmap.Create(Instance: Cardinal; Resource: String; ResType: PChar); -begin - Create; - LoadFromResource(Instance, Resource, ResType); -end; - - - -constructor TglBitmap.Create(Instance: Cardinal; ResourceID: Integer; ResType: PChar); -begin - Create; - LoadFromResourceID(Instance, ResourceID, ResType); -end; -{$ENDIF} - - -constructor TglBitmap.Create(Size: TglBitmapPixelPosition; - Format: TglBitmapFormat); -var - Image: pByte; - ImageSize: Integer; -begin - Create; - - ImageSize := FormatGetImageSize(Size, Format); - GetMem(Image, ImageSize); - try - FillChar(Image^, ImageSize, #$FF); - - SetDataPointer(Image, Format, Size.X, Size.Y); - except - FreeMem(Image); - raise; - end; -end; - - -constructor TglBitmap.Create(Size: TglBitmapPixelPosition; - Format: TglBitmapFormat; Func: TglBitmapFunction; CustomData: Pointer); -begin - Create; - LoadFromFunc(Size, Func, Format, CustomData); -end; - - -function TglBitmap.Clone: TglBitmap; +procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; + const aFormat: TglBitmapFormat; const aArgs: PtrInt); var - Temp: TglBitmap; - TempPtr: pByte; - Size: Integer; + tmpData: PByte; + size: Integer; begin - Temp := ClassType.Create as TglBitmap; + size := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize); + GetMem(tmpData, size); try - // copy texture data if assigned - if Assigned(Data) then begin - Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat); - - GetMem(TempPtr, Size); - try - Move(Data^, TempPtr^, Size); - Temp.SetDataPointer(TempPtr, InternalFormat, Width, Height); - except - FreeMem(TempPtr); - raise; - end; - end else - Temp.SetDataPointer(nil, InternalFormat, Width, Height); - - // copy properties - Temp.fID := ID; - Temp.fTarget := Target; - Temp.fFormat := Format; - Temp.fMipMap := MipMap; - Temp.fAnisotropic := Anisotropic; - Temp.fBorderColor := fBorderColor; - Temp.fDeleteTextureOnFree := DeleteTextureOnFree; - Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture; - Temp.fFilterMin := fFilterMin; - Temp.fFilterMag := fFilterMag; - Temp.fWrapS := fWrapS; - Temp.fWrapT := fWrapT; - Temp.fWrapR := fWrapR; - Temp.fFilename := fFilename; - Temp.fCustomName := fCustomName; - Temp.fCustomNameW := fCustomNameW; - Temp.fCustomDataPointer := fCustomDataPointer; - - Result := Temp; + FillChar(tmpData^, size, #$FF); + SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); except - FreeAndNil(Temp); + FreeMem(tmpData); raise; end; + AddFunc(Self, aFunc, false, Format, aArgs); end; - -procedure TglBitmap.LoadFromFile(const aFileName: String); -var - FS: TFileStream; -begin - fFilename := FileName; - - FS := TFileStream.Create(FileName, fmOpenRead); - try - FS.Position := 0; - - LoadFromStream(FS); - finally - FS.Free; - end; -end; - - -procedure TglBitmap.LoadFromStream(const aStream: TStream); -begin - {$IFDEF GLB_SUPPORT_PNG_READ} - if not LoadPNG(Stream) then - {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_READ} - if not LoadJPEG(Stream) then - {$ENDIF} - if not LoadDDS(Stream) then - if not LoadTGA(Stream) then - if not LoadBMP(Stream) then - raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.'); -end; - - {$IFDEF GLB_DELPHI} -procedure TglBitmap.LoadFromResource(Instance: Cardinal; Resource: String; ResType: PChar); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); var - RS: TResourceStream; + rs: TResourceStream; TempPos: Integer; ResTypeStr: String; TempResType: PChar; begin - if Assigned(ResType) then + if not Assigned(ResType) then begin + TempPos := Pos('.', Resource); + ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); + Resource := UpperCase(Copy(Resource, 0, TempPos -1)); + TempResType := PChar(ResTypeStr); + end else TempResType := ResType - else - begin - TempPos := Pos('.', Resource); - ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); - Resource := UpperCase(Copy(Resource, 0, TempPos -1)); - TempResType := PChar(ResTypeStr); - end; - RS := TResourceStream.Create(Instance, Resource, TempResType); + rs := TResourceStream.Create(Instance, Resource, TempResType); try - LoadFromStream(RS); + LoadFromStream(rs); finally - RS.Free; + rs.Free; end; end; - -procedure TglBitmap.LoadFromResourceID(Instance: Cardinal; ResourceID: Integer; ResType: PChar); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); var - RS: TResourceStream; + rs: TResourceStream; begin - RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType); + rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType); try - LoadFromStream(RS); + LoadFromStream(rs); finally - RS.Free; + rs.Free; end; end; {$ENDIF} - - -procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; - const aFunc: TglBitmapFunction; const aFormat: TglBitmapFormat; - const aArgs: PtrInt); -var - Image: pByte; - ImageSize: Integer; -begin - ImageSize := FormatGetImageSize(Size, Format); - GetMem(Image, ImageSize); - try - FillChar(Image^, ImageSize, #$FF); - - SetDataPointer(Image, Format, Size.X, Size.Y); - except - FreeMem(Image); - raise; - end; - - AddFunc(Self, Func, False, Format, CustomData) -end; - - -procedure TglBitmap.SaveToFile(const aFileName: String; - const aFileType: TglBitmapFileType); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); var - FS: TFileStream; + fs: TFileStream; begin - FS := TFileStream.Create(FileName, fmCreate); + fs := TFileStream.Create(aFileName, fmCreate); try - FS.Position := 0; - SaveToStream(FS, FileType); + fs.Position := 0; + SaveToStream(fs, aFileType); finally - FS.Free; + fs.Free; end; end; - -procedure TglBitmap.SaveToStream(const aStream: TStream; - const aFileType: TglBitmapFileType); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); begin - case FileType of + case aFileType of {$IFDEF GLB_SUPPORT_PNG_WRITE} - ftPNG: SavePng(Stream); + ftPNG: SavePng(aStream); {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} - ftJPEG: SaveJPEG(Stream); + ftJPEG: SaveJPEG(aStream); {$ENDIF} - ftDDS: SaveDDS(Stream); - ftTGA: SaveTGA(Stream); - ftBMP: SaveBMP(Stream); + ftDDS: SaveDDS(aStream); + ftTGA: SaveTGA(aStream); + ftBMP: SaveBMP(aStream); end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean; +begin + result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs); +end; -{$IFDEF GLB_SDL} -function TglBitmap.AssignToSurface(out Surface: PSDL_Surface): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean; + const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean; var - Row, RowSize: Integer; - pSource, pData: PByte; - TempDepth: Integer; - Pix: TglBitmapPixelData; - - function GetRowPointer(Row: Integer): pByte; - begin - Result := Surface.pixels; - Inc(Result, Row * RowSize); - end; + DestData, TmpData, SourceData: pByte; + TempHeight, TempWidth: Integer; + SourceFD, DestFD: TglBitmapFormatDescClass; + FuncRec: TglBitmapFunctionRec; begin - Result := False; - - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); - - if Assigned(Data) then begin - case Trunc(FormatGetSize(InternalFormat)) of - 1: TempDepth := 8; - 2: TempDepth := 16; - 3: TempDepth := 24; - 4: TempDepth := 32; - else - raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; - - FormatPreparePixel(Pix, InternalFormat); + Assert(Assigned(Data)); + Assert(Assigned(aSource)); + Assert(Assigned(aSource.Data)); - with Pix.PixelDesc do - Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift); + result := false; + if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin + SourceFD := FORMAT_DESCRIPTORS[aSource.Format]; + DestFD := FORMAT_DESCRIPTORS[aFormat]; - pSource := Data; - RowSize := Trunc(FileWidth * FormatGetSize(InternalFormat)); + // inkompatible Formats so CreateTemp + if (SourceFD.GetSize <> DestFD.GetSize) then + aCreateTemp := true; - for Row := 0 to FileHeight -1 do begin - pData := GetRowPointer(Row); + // Values + TempHeight := Max(1, aSource.Height); + TempWidth := Max(1, aSource.Width); - if Assigned(pData) then begin - Move(pSource^, pData^, RowSize); - Inc(pSource, RowSize); - end; - end; + FuncRec.Sender := Self; + FuncRec.Args := aArgs; - Result := True; - end; -end; + TmpData := nil; + if aCreateTemp then begin + GetMem(TmpData, Ceil(FORMAT_DESCRIPTORS[aFormat].GetSize * TempHeight * TempWidth)); + DestData := TmpData; + end else + DestData := Data; + try + SourceFD.PreparePixel(FuncRec.Source); + DestFD.PreparePixel (FuncRec.Dest); -function TglBitmap.AssignFromSurface(const Surface: PSDL_Surface): boolean; -var - pSource, pData, pTempData: PByte; - Row, RowSize, TempWidth, TempHeight: Integer; - IntFormat: TglBitmapInternalFormat; + FuncRec.Size := aSource.Dimension; + FuncRec.Position.Fields := FuncRec.Size.Fields; - function GetRowPointer(Row: Integer): pByte; - begin - Result := Surface^.pixels; - Inc(Result, Row * RowSize); - end; + if {FormatIsUncompressed(Source.InternalFormat)} true then begin + SourceData := aSource.Data; + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + SourceFD.Unmap(SourceData, FuncRec.Source); + aFunc(FuncRec); + DestFD.Map(FuncRec.Dest, DestData); + inc(FuncRec.Position.X); + end; + inc(FuncRec.Position.Y); + end; + end else begin + (* TODO + // Compressed Images + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + // Get Data + fGetPixelFunc(FuncRec.Position, FuncRec.Source); + // Func + Func(FuncRec); + // Set Data + MapFunc(FuncRec.Dest, dest); + Inc(FuncRec.Position.X); + end; + Inc(FuncRec.Position.Y); + end; + *) + end; -begin - Result := False; + // Updating Image or InternalFormat + if aCreateTemp then + SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) + else if (aFormat <> fFormat) then + Format := aFormat; - if (Assigned(Surface)) then begin - with Surface^.format^ do begin - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminance) then - IntFormat := ifLuminance - else + result := true; + except + if aCreateTemp then + FreeMem(TmpData); + raise; + end; + end; +end; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifLuminanceAlpha) then - IntFormat := ifLuminanceAlpha - else +{$IFDEF GLB_SDL} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignToSurface(out aSurface: PSDL_Surface): Boolean; +var + Row, RowSize: Integer; + SourceData, TmpData: PByte; + TempDepth: Integer; + Pix: TglBitmapPixelData; + FormatDesc: TglBitmapFormatDescriptor; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA4) then - IntFormat := ifRGBA4 - else + function GetRowPointer(Row: Integer): pByte; + begin + result := Surface.pixels; + Inc(result, Row * RowSize); + end; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifR5G6B5) then - IntFormat := ifR5G6B5 - else +begin + result := false; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB5A1) then - IntFormat := ifRGB5A1 - else + (* TODO + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); + *) - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGR8) then - IntFormat := ifBGR8 - else + FormatDesc := FORMAT_DESCRIPTORS[Format]; + if Assigned(Data) then begin + case Trunc(FormatDesc.GetSize) of + 1: TempDepth := 8; + 2: TempDepth := 16; + 3: TempDepth := 24; + 4: TempDepth := 32; + else + raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + FormatDesc.PreparePixel(Pix); + with Pix.PixelDesc do + Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, + RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift); - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB8) then - IntFormat := ifRGB8 - else + SourceData := Data; + RowSize := Ceil(FileWidth * FormatDesc.GetSize); - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifBGRA8) then - IntFormat := ifBGRA8 - else + for Row := 0 to FileHeight -1 do begin + TmpData := GetRowPointer(Row); + if Assigned(TmpData) then begin + Move(SourceData^, TmpData^, RowSize); + inc(SourceData, RowSize); + end; + end; + result := true; + end; +end; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGBA8) then - IntFormat := ifRGBA8 - else +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean; +var + pSource, pData, pTempData: PByte; + Row, RowSize, TempWidth, TempHeight: Integer; + IntFormat, f: TglBitmapInternalFormat; + FormatDesc: TglBitmapFormatDescriptor; - if FormatCheckFormat(RMask, GMask, BMask, AMask, ifRGB10A2) then - IntFormat := ifRGB10A2 - else + function GetRowPointer(Row: Integer): pByte; + begin + result := Surface^.pixels; + Inc(result, Row * RowSize); + end; + +begin + result := false; + if (Assigned(Surface)) then begin + with Surface^.format^ do begin + IntFormat := tfEmpty; + for f := Low(f) to High(f) do begin + if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin + IntFormat := f; + break; + end; + end; + if (IntFormat = tfEmpty) then raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.'); end; - TempWidth := Surface^.w; + FormatDesc := FORMAT_DESCRIPTORS[IntFormat]; + TempWidth := Surface^.w; TempHeight := Surface^.h; - - RowSize := Trunc(TempWidth * FormatGetSize(IntFormat)); - + RowSize := Trunc(TempWidth * FormatDesc.GetSize); GetMem(pData, TempHeight * RowSize); try pTempData := pData; - for Row := 0 to TempHeight -1 do begin pSource := GetRowPointer(Row); - if (Assigned(pSource)) then begin Move(pSource^, pTempData^, RowSize); Inc(pTempData, RowSize); end; end; - SetDataPointer(pData, IntFormat, TempWidth, TempHeight); - - Result := True; + result := true; except FreeMem(pData); raise; @@ -2911,40 +3260,35 @@ begin end; end; - -function TglBitmap.AssignAlphaToSurface(out Surface: PSDL_Surface): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean; var Row, Col, AlphaInterleave: Integer; pSource, pDest: PByte; function GetRowPointer(Row: Integer): pByte; begin - Result := Surface.pixels; - Inc(Result, Row * Width); + result := aSurface.pixels; + Inc(result, Row * Width); end; begin - Result := False; - + result := false; if Assigned(Data) then begin - if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifBGRA8, ifRGBA8] then begin - Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0); + if Format in [tfAlpha8, tfLuminance8Alpha8, tfBGRA8, tfRGBA8] then begin + aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, 8, $FF, $FF, $FF, 0); - case InternalFormat of - ifLuminanceAlpha: + AlphaInterleave := 0; + case Format of + ifLuminance8Alpha8: AlphaInterleave := 1; ifBGRA8, ifRGBA8: AlphaInterleave := 3; - else - AlphaInterleave := 0; end; - // Copy Data pSource := Data; - for Row := 0 to Height -1 do begin pDest := GetRowPointer(Row); - if Assigned(pDest) then begin for Col := 0 to Width -1 do begin Inc(pSource, AlphaInterleave); @@ -2954,37 +3298,83 @@ begin end; end; end; - - Result := True; + result := true; end; end; end; - -function TglBitmap.AddAlphaFromSurface(Surface: PSDL_Surface; Func: TglBitmapFunction; CustomData: Pointer): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; var - glBitmap: TglBitmap2D; + bmp: TglBitmap2D; begin - glBitmap := TglBitmap2D.Create; + bmp := TglBitmap2D.Create; try - glBitmap.AssignFromSurface(Surface); - - Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); + bmp.AssignFromSurface(Surface); + result := AddAlphaFromGlBitmap(bmp, Func, CustomData); finally - glBitmap.Free; + bmp.Free; end; end; {$ENDIF} - {$IFDEF GLB_DELPHI} -function TglBitmap.AssignFromBitmap(const Bitmap: TBitmap): boolean; +//TODO rework & test +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean; +var + Row: Integer; + pSource, pData: PByte; +begin + result := false; + if Assigned(Data) then begin + if Assigned(aBitmap) then begin + aBitmap.Width := Width; + aBitmap.Height := Height; + + case Format of + tfAlpha8, ifLuminance, ifDepth8: + begin + Bitmap.PixelFormat := pf8bit; + Bitmap.Palette := CreateGrayPalette; + end; + ifRGB5A1: + Bitmap.PixelFormat := pf15bit; + ifR5G6B5: + Bitmap.PixelFormat := pf16bit; + ifRGB8, ifBGR8: + Bitmap.PixelFormat := pf24bit; + ifRGBA8, ifBGRA8: + Bitmap.PixelFormat := pf32bit; + else + raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); + end; + + pSource := Data; + for Row := 0 to FileHeight -1 do begin + pData := Bitmap.Scanline[Row]; + + Move(pSource^, pData^, fRowSize); + Inc(pSource, fRowSize); + + // swap RGB(A) to BGR(A) + if InternalFormat in [ifRGB8, ifRGBA8] then + SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8); + end; + + result := true; + end; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean; var pSource, pData, pTempData: PByte; Row, RowSize, TempWidth, TempHeight: Integer; IntFormat: TglBitmapInternalFormat; begin - Result := False; + result := false; if (Assigned(Bitmap)) then begin case Bitmap.PixelFormat of @@ -3022,7 +3412,7 @@ begin SetDataPointer(pData, IntFormat, TempWidth, TempHeight); - Result := True; + result := true; except FreeMem(pData); raise; @@ -3030,61 +3420,13 @@ begin end; end; - -function TglBitmap.AssignToBitmap(const Bitmap: TBitmap): boolean; -var - Row: Integer; - pSource, pData: PByte; -begin - Result := False; - - if Assigned(Data) then begin - if Assigned(Bitmap) then begin - Bitmap.Width := Width; - Bitmap.Height := Height; - - case InternalFormat of - ifAlpha, ifLuminance, ifDepth8: - begin - Bitmap.PixelFormat := pf8bit; - Bitmap.Palette := CreateGrayPalette; - end; - ifRGB5A1: - Bitmap.PixelFormat := pf15bit; - ifR5G6B5: - Bitmap.PixelFormat := pf16bit; - ifRGB8, ifBGR8: - Bitmap.PixelFormat := pf24bit; - ifRGBA8, ifBGRA8: - Bitmap.PixelFormat := pf32bit; - else - raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); - end; - - pSource := Data; - for Row := 0 to FileHeight -1 do begin - pData := Bitmap.Scanline[Row]; - - Move(pSource^, pData^, fRowSize); - Inc(pSource, fRowSize); - - // swap RGB(A) to BGR(A) - if InternalFormat in [ifRGB8, ifRGBA8] then - SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8); - end; - - Result := True; - end; - end; -end; - - -function TglBitmap.AssignAlphaToBitmap(const Bitmap: TBitmap): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean; var Row, Col, AlphaInterleave: Integer; pSource, pDest: PByte; begin - Result := False; + result := false; if Assigned(Data) then begin if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin @@ -3119,58 +3461,29 @@ begin end; end; - Result := True; + result := true; end; end; end; end; - -function TglBitmap.AddAlphaFromBitmap(Bitmap: TBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean; -var - glBitmap: TglBitmap2D; -begin - glBitmap := TglBitmap2D.Create; - try - glBitmap.AssignFromBitmap(Bitmap); - - Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); - finally - glBitmap.Free; - end; -end; -{$ENDIF} - - -function TglBitmap.AddAlphaFromFile(FileName: String; Func: TglBitmapFunction; CustomData: Pointer): boolean; -var - FS: TFileStream; -begin - FS := TFileStream.Create(FileName, fmOpenRead); - try - Result := AddAlphaFromStream(FS, Func, CustomData); - finally - FS.Free; - end; -end; - - -function TglBitmap.AddAlphaFromStream(Stream: TStream; Func: TglBitmapFunction; CustomData: Pointer): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; var - glBitmap: TglBitmap2D; + tex: TglBitmap2D; begin - glBitmap := TglBitmap2D.Create(Stream); + tex := TglBitmap2D.Create; try - Result := AddAlphaFromglBitmap(glBitmap, Func, CustomData); + tex.AssignFromBitmap(Bitmap); + result := AddAlphaFromglBitmap(tex, Func, CustomData); finally - glBitmap.Free; + tex.Free; end; end; - -{$IFDEF GLB_DELPHI} -function TglBitmap.AddAlphaFromResource(Instance: Cardinal; Resource: String; - ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar; + const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; var RS: TResourceStream; TempPos: Integer; @@ -3189,167 +3502,373 @@ begin RS := TResourceStream.Create(Instance, Resource, TempResType); try - Result := AddAlphaFromStream(RS, Func, CustomData); + result := AddAlphaFromStream(RS, Func, CustomData); finally RS.Free; end; end; - -function TglBitmap.AddAlphaFromResourceID(Instance: Cardinal; ResourceID: Integer; - ResType: PChar; Func: TglBitmapFunction; CustomData: Pointer): boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; + const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; var RS: TResourceStream; begin RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType); try - Result := AddAlphaFromStream(RS, Func, CustomData); + result := AddAlphaFromStream(RS, Func, CustomData); finally RS.Free; end; end; {$ENDIF} - -procedure glBitmapColorKeyAlphaFunc(var FuncRec: TglBitmapFunctionRec); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; begin - with FuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; + (* TODO + if not FormatIsUncompressed(InternalFormat) then + raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT); + *) + result := AddFunc(Self, aFunc, false, FORMAT_DESCRIPTORS[Format].WithAlpha, aArgs); +end; - with TglBitmapPixelData(CustomData^) do - if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and - (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and - (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then - Dest.Alpha := 0 - else - Dest.Alpha := Dest.PixelDesc.AlphaRange; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +var + FS: TFileStream; +begin + FS := TFileStream.Create(FileName, fmOpenRead); + try + result := AddAlphaFromStream(FS, aFunc, aArgs); + finally + FS.Free; end; end; - -function TglBitmap.AddAlphaFromColorKey(Red, Green, Blue: Byte; Deviation: Byte - ): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +var + tex: TglBitmap2D; begin - Result := AddAlphaFromColorKeyFloat(Red / $FF, Green / $FF, Blue / $FF, Deviation / $FF); + tex := TglBitmap2D.Create(aStream); + try + result := AddAlphaFromglBitmap(tex, aFunc, aArgs); + finally + tex.Free; + end; end; - -function TglBitmap.AddAlphaFromColorKeyRange(Red, Green, Blue: Cardinal; Deviation: Cardinal = 0): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; var - PixelData: TglBitmapPixelData; + DestData, DestData2, SourceData: pByte; + TempHeight, TempWidth: Integer; + SourceFD, DestFD: TglBitmapFormatDescClass; + + FuncRec: TglBitmapFunctionRec; begin - FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + result := false; - Result := AddAlphaFromColorKeyFloat( - Red / PixelData.PixelDesc.RedRange, - Green / PixelData.PixelDesc.GreenRange, - Blue / PixelData.PixelDesc.BlueRange, - Deviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange))); -end; + Assert(Assigned(Data)); + Assert(Assigned(aBitmap)); + Assert(Assigned(aBitmap.Data)); + if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin + result := ConvertTo(FORMAT_DESCRIPTORS[Format].WithAlpha); + if not Assigned(aFunc) then + aFunc := glBitmapAlphaFunc; -function TglBitmap.AddAlphaFromColorKeyFloat(Red, Green, Blue: Single; Deviation: Single = 0): Boolean; -var - TempR, TempG, TempB: Cardinal; - PixelData: TglBitmapPixelData; -begin - FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + SourceFD := FORMAT_DESCRIPTORS[aBitmap.Format]; + DestFD := FORMAT_DESCRIPTORS[Format]; - // Calculate Colorrange - with PixelData.PixelDesc do begin - TempR := Trunc(RedRange * Deviation); - TempG := Trunc(GreenRange * Deviation); - TempB := Trunc(BlueRange * Deviation); - - PixelData.Red := Min(RedRange, Trunc(RedRange * Red) + TempR); - RedRange := Max(0, Trunc(RedRange * Red) - TempR); - PixelData.Green := Min(GreenRange, Trunc(GreenRange * Green) + TempG); - GreenRange := Max(0, Trunc(GreenRange * Green) - TempG); - PixelData.Blue := Min(BlueRange, Trunc(BlueRange * Blue) + TempB); - BlueRange := Max(0, Trunc(BlueRange * Blue) - TempB); - PixelData.Alpha := 0; - AlphaRange := 0; - end; + // Values + TempHeight := aBitmap.FileHeight; + TempWidth := aBitmap.FileWidth; - Result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData); -end; + FuncRec.Sender := Self; + FuncRec.Args := aArgs; + FuncRec.Size := Dimension; + FuncRec.Position.Fields := FuncRec.Size.Fields; + FuncRec.Args := PtrInt(SourceFD.HasAlpha) and 1; + DestData := Data; + DestData2 := Data; + SourceData := aBitmap.Data; -procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec); -begin - with FuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; + // Mapping + SourceFD.PreparePixel(FuncRec.Source); + DestFD.PreparePixel (FuncRec.Dest); - with TglBitmapPixelData(CustomData^) do - Dest.Alpha := Alpha; + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + SourceFD.Unmap(SourceData, FuncRec.Source); + DestFD.Unmap (DestData, FuncRec.Dest); + aFunc(FuncRec); + DestFD.Map(FuncRec.Dest, DestData2); + inc(FuncRec.Position.X); + end; + inc(FuncRec.Position.Y); + end; end; end; -function TglBitmap.AddAlphaFromValue(Alpha: Byte): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean; begin - Result := AddAlphaFromValueFloat(Alpha / $FF); + result := AddAlphaFromColorKeyFloat(aRed / $FF, aGreen / $FF, aBlue / $FF, aDeviation / $FF); end; - -function TglBitmap.AddAlphaFromValueFloat(Alpha: Single): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal): Boolean; var PixelData: TglBitmapPixelData; begin - FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); - - with PixelData.PixelDesc do - PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * Alpha))); + FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + result := AddAlphaFromColorKeyFloat( + aRed / PixelData.PixelDesc.RedRange, + aGreen / PixelData.PixelDesc.GreenRange, + aBlue / PixelData.PixelDesc.BlueRange, + aDeviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange))); +end; - Result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean; +var + TempR, TempG, TempB: Cardinal; + PixelData: TglBitmapPixelData; +begin + FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + with PixelData.PixelDesc do begin + TempR := Trunc(RedRange * aDeviation); + TempG := Trunc(GreenRange * aDeviation); + TempB := Trunc(BlueRange * aDeviation); + + PixelData.Red := Min(RedRange, Trunc(RedRange * aRed) + TempR); + RedRange := Max(0, Trunc(RedRange * aRed) - TempR); + PixelData.Green := Min(GreenRange, Trunc(GreenRange * aGreen) + TempG); + GreenRange := Max(0, Trunc(GreenRange * aGreen) - TempG); + PixelData.Blue := Min(BlueRange, Trunc(BlueRange * aBlue) + TempB); + BlueRange := Max(0, Trunc(BlueRange * aBlue) - TempB); + PixelData.Alpha := 0; + AlphaRange := 0; + end; + result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData)); end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromValue(const aAlpha: Byte): Boolean; +begin + result := AddAlphaFromValueFloat(aAlpha / $FF); +end; -function TglBitmap.AddAlphaFromValueRange(Alpha: Cardinal): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean; var PixelData: TglBitmapPixelData; begin - FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); + FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + result := AddAlphaFromValueFloat(aAlpha / PixelData.PixelDesc.AlphaRange); +end; - Result := AddAlphaFromValueFloat(Alpha / PixelData.PixelDesc.AlphaRange); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean; +var + PixelData: TglBitmapPixelData; +begin + FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + with PixelData.PixelDesc do + PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * aAlpha))); + result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData)); end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.RemoveAlpha: Boolean; +var + FormatDesc: TglBitmapFormatDescClass; +begin + result := false; + FormatDesc := FORMAT_DESCRIPTORS[Format]; + if Assigned(Data) then begin + if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then + raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT); + result := ConvertTo(FormatDesc.WithoutAlpha); + end; +end; -procedure glBitmapInvertFunc(var FuncRec: TglBitmapFunctionRec); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.Clone: TglBitmap; +var + Temp: TglBitmap; + TempPtr: PByte; + Size: Integer; begin - with FuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; - Dest.Alpha := Source.Alpha; + result := nil; + Temp := (ClassType.Create as TglBitmap); + try + // copy texture data if assigned + if Assigned(Data) then begin + Size := FORMAT_DESCRIPTORS[Format].GetSize(fDimension); + GetMem(TempPtr, Size); + try + Move(Data^, TempPtr^, Size); + Temp.SetDataPointer(TempPtr, Format, Width, Height); + except + FreeMem(TempPtr); + raise; + end; + end else + Temp.SetDataPointer(nil, Format, Width, Height); - if (Integer(CustomData) and $1 > 0) then begin - Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange; - Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange; - Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange; - end; + // copy properties + Temp.fID := ID; + Temp.fTarget := Target; + Temp.fFormat := Format; + Temp.fMipMap := MipMap; + Temp.fAnisotropic := Anisotropic; + Temp.fBorderColor := fBorderColor; + Temp.fDeleteTextureOnFree := DeleteTextureOnFree; + Temp.fFreeDataAfterGenTexture := FreeDataAfterGenTexture; + Temp.fFilterMin := fFilterMin; + Temp.fFilterMag := fFilterMag; + Temp.fWrapS := fWrapS; + Temp.fWrapT := fWrapT; + Temp.fWrapR := fWrapR; + Temp.fFilename := fFilename; + Temp.fCustomName := fCustomName; + Temp.fCustomNameW := fCustomNameW; + Temp.fCustomData := fCustomData; + + result := Temp; + except + FreeAndNil(Temp); + raise; + end; +end; - if (Integer(CustomData) and $2 > 0) then begin - Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean; +var + SourceFD, DestFD: TglBitmapFormatDescClass; + SourcePD, DestPD: TglBitmapPixelData; + PixelDesc: TglBitmapPixelDesc; + + function CanCopyDirect: Boolean; + begin + result := + ((SourcePD.PixelDesc.RedRange = DestPD.PixelDesc.RedRange) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and + ((SourcePD.PixelDesc.GreenRange = DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and + ((SourcePD.PixelDesc.BlueRange = DestPD.PixelDesc.BlueRange) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and + ((SourcePD.PixelDesc.AlphaRange = DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0)); + end; + + function CanShift: Boolean; + begin + result := + ((SourcePD.PixelDesc.RedRange >= DestPD.PixelDesc.RedRange ) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and + ((SourcePD.PixelDesc.GreenRange >= DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and + ((SourcePD.PixelDesc.BlueRange >= DestPD.PixelDesc.BlueRange ) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and + ((SourcePD.PixelDesc.AlphaRange >= DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0)); + end; + + function GetShift(aSource, aDest: Cardinal) : ShortInt; + begin + result := 0; + while (aSource > aDest) and (aSource > 0) do begin + inc(result); + aSource := aSource shr 1; end; end; + +begin + if aFormat <> fFormat then begin + SourceFD := FORMAT_DESCRIPTORS[Format]; + DestFD := FORMAT_DESCRIPTORS[aFormat]; + + SourceFD.PreparePixel(SourcePD); + DestFD.PreparePixel (DestPD); + + if CanCopyDirect then + result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat) + else if CanShift then begin + PixelDesc.RedShift := GetShift(SourcePD.PixelDesc.RedRange, DestPD.PixelDesc.RedRange); + PixelDesc.GreenShift := GetShift(SourcePD.PixelDesc.GreenRange, DestPD.PixelDesc.GreenRange); + PixelDesc.BlueShift := GetShift(SourcePD.PixelDesc.BlueRange, DestPD.PixelDesc.BlueRange); + PixelDesc.AlphaShift := GetShift(SourcePD.PixelDesc.AlphaRange, DestPD.PixelDesc.AlphaRange); + result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@PixelDesc)); + end else + result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat); + end else + result := true; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean); +begin + if aUseRGB or aUseAlpha then + AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1)); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetBorderColor(const aRed, aGreen, aBlue, aAlpha: Single); +begin + fBorderColor[0] := aRed; + fBorderColor[1] := aGreen; + fBorderColor[2] := aBlue; + fBorderColor[3] := aAlpha; + if (ID > 0) then begin + Bind(false); + glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]); + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.FreeData; +begin + SetDataPointer(nil, tfEmpty); end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.FillWithColor(const aRed, aGreen, aBlue: Byte; + const aAlpha: Byte); +begin + FillWithColorFloat(aRed/$FF, aGreen/$FF, aBlue/$FF, aAlpha/$FF); +end; -procedure TglBitmap.Invert(UseRGB: Boolean; UseAlpha: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; const aAlpha: Cardinal); +var + PixelData: TglBitmapPixelData; begin - if ((UseRGB) or (UseAlpha)) then - AddFunc(glBitmapInvertFunc, False, Pointer(Integer(UseAlpha) shl 1 or Integer(UseRGB))); + FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + FillWithColorFloat( + aRed / PixelData.PixelDesc.RedRange, + aGreen / PixelData.PixelDesc.GreenRange, + aBlue / PixelData.PixelDesc.BlueRange, + aAlpha / PixelData.PixelDesc.AlphaRange); end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha: Single); +var + PixelData: TglBitmapPixelData; +begin + FORMAT_DESCRIPTORS[Format].PreparePixel(PixelData); + PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * aRed))); + PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * aGreen))); + PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * aBlue))); + PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * aAlpha))); + AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData)); +end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal); begin - case Min of + //check MIN filter + case aMin of GL_NEAREST: fFilterMin := GL_NEAREST; GL_LINEAR: @@ -3363,25 +3882,25 @@ begin GL_LINEAR_MIPMAP_LINEAR: fFilterMin := GL_LINEAR_MIPMAP_LINEAR; else - raise EglBitmapException.Create('SetFilter - Unknow Minfilter.'); + raise EglBitmapException.Create('SetFilter - Unknow MIN filter.'); end; - case Mag of + //check MAG filter + case aMag of GL_NEAREST: fFilterMag := GL_NEAREST; GL_LINEAR: fFilterMag := GL_LINEAR; else - raise EglBitmapException.Create('SetFilter - Unknow Magfilter.'); + raise EglBitmapException.Create('SetFilter - Unknow MAG filter.'); end; - // If texture is created then assign filter - if ID > 0 then begin - Bind(False); - + //apply filter + if (ID > 0) then begin + Bind(false); glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, fFilterMag); - if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE_ARB) then begin + if (MipMap = mmNone) or (Target = GL_TEXTURE_RECTANGLE) then begin case fFilterMin of GL_NEAREST, GL_LINEAR: glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, fFilterMin); @@ -3395,180 +3914,199 @@ begin end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal); -procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; - const R: Cardinal); -begin - case S of - GL_CLAMP: - fWrapS := GL_CLAMP; - GL_REPEAT: - fWrapS := GL_REPEAT; - GL_CLAMP_TO_EDGE: - begin + procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal); + begin + case aValue of + GL_CLAMP: + aTarget := GL_CLAMP; + + GL_REPEAT: + aTarget := GL_REPEAT; + + GL_CLAMP_TO_EDGE: begin if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then - fWrapS := GL_CLAMP_TO_EDGE + aTarget := GL_CLAMP_TO_EDGE else - fWrapS := GL_CLAMP; + aTarget := GL_CLAMP; end; - GL_CLAMP_TO_BORDER: - begin + + GL_CLAMP_TO_BORDER: begin if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then - fWrapS := GL_CLAMP_TO_BORDER + aTarget := GL_CLAMP_TO_BORDER else - fWrapS := GL_CLAMP; + aTarget := GL_CLAMP; end; - GL_MIRRORED_REPEAT: - begin + + GL_MIRRORED_REPEAT: begin if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then - fWrapS := GL_MIRRORED_REPEAT + aTarget := GL_MIRRORED_REPEAT else raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).'); end; else raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).'); + end; end; - case T of - GL_CLAMP: - fWrapT := GL_CLAMP; - GL_REPEAT: - fWrapT := GL_REPEAT; - GL_CLAMP_TO_EDGE: - begin - if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then - fWrapT := GL_CLAMP_TO_EDGE - else - fWrapT := GL_CLAMP; - end; - GL_CLAMP_TO_BORDER: - begin - if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then - fWrapT := GL_CLAMP_TO_BORDER - else - fWrapT := GL_CLAMP; - end; - GL_MIRRORED_REPEAT: - begin - if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then - fWrapT := GL_MIRRORED_REPEAT - else - raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (T).'); - end; - else - raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (T).'); - end; - - case R of - GL_CLAMP: - fWrapR := GL_CLAMP; - GL_REPEAT: - fWrapR := GL_REPEAT; - GL_CLAMP_TO_EDGE: - begin - if GL_VERSION_1_2 or GL_EXT_texture_edge_clamp then - fWrapR := GL_CLAMP_TO_EDGE - else - fWrapR := GL_CLAMP; - end; - GL_CLAMP_TO_BORDER: - begin - if GL_VERSION_1_3 or GL_ARB_texture_border_clamp then - fWrapR := GL_CLAMP_TO_BORDER - else - fWrapR := GL_CLAMP; - end; - GL_MIRRORED_REPEAT: - begin - if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then - fWrapR := GL_MIRRORED_REPEAT - else - raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (R).'); - end; - else - raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (R).'); - end; +begin + CheckAndSetWrap(S, fWrapS); + CheckAndSetWrap(T, fWrapT); + CheckAndSetWrap(R, fWrapR); - if ID > 0 then begin - Bind (False); + if (ID > 0) then begin + Bind(false); glTexParameteri(Target, GL_TEXTURE_WRAP_S, fWrapS); glTexParameteri(Target, GL_TEXTURE_WRAP_T, fWrapT); glTexParameteri(Target, GL_TEXTURE_WRAP_R, fWrapR); end; end; - -procedure TglBitmap.SetDataPointer(NewData: pByte; - Format: TglBitmapFormat; Width: Integer; Height: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); begin - // Data - if Data <> NewData then begin - if (Assigned(Data)) - then FreeMem(Data); + { TODO delete? + if Assigned (fGetPixelFunc) then + fGetPixelFunc(aPos, aPixel); + } +end; - fData := NewData; - end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); +begin + {TODO delete? + if Assigned (fSetPixelFunc) then + fSetPixelFuc(aPos, aPixel); + } +end; - if Data = nil then begin - fInternalFormat := ifEmpty; - fPixelSize := 0; - fRowSize := 0; - end else begin - if Width <> -1 then begin - fDimension.Fields := fDimension.Fields + [ffX]; - fDimension.X := Width; - end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean); +begin + if aEnableTextureUnit then + glEnable(Target); + if (ID > 0) then + glBindTexture(Target, ID); +end; - if Height <> -1 then begin - fDimension.Fields := fDimension.Fields + [ffY]; - fDimension.Y := Height; - end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.Unbind(const aDisableTextureUnit: Boolean); +begin + if aDisableTextureUnit then + glDisable(Target); + glBindTexture(Target, 0); +end; - fInternalFormat := Format; - fPixelSize := Trunc(FormatGetSize(InternalFormat)); - fRowSize := Trunc(FormatGetSize(InternalFormat) * Self.Width); - end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create; +begin +{$IFNDEF GLB_NO_NATIVE_GL} + ReadOpenGLExtensions; +{$ENDIF} + if (ClassType = TglBitmap) then + raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); + inherited Create; end; -{$IFDEF GLB_SUPPORT_PNG_READ} -{$IFDEF GLB_LIB_PNG} -procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aFileName: String); begin - TStream(png_get_io_ptr(png)).Read(buffer^, size); + Create; + LoadFromFile(FileName); end; -{$ENDIF} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aStream: TStream); +begin + Create; + LoadFromStream(aStream); +end; -function TglBitmap.LoadPNG(Stream: TStream): Boolean; -{$IFDEF GLB_SDL_IMAGE} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); var - Surface: PSDL_Surface; - RWops: PSDL_RWops; + Image: PByte; + ImageSize: Integer; begin - Result := False; - - RWops := glBitmapCreateRWops(Stream); + Create; + ImageSize := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize); + GetMem(Image, ImageSize); try - if IMG_isPNG(RWops) > 0 then begin - Surface := IMG_LoadPNG_RW(RWops); - try - AssignFromSurface(Surface); - Result := True; - finally - SDL_FreeSurface(Surface); - end; - end; - finally - SDL_FreeRW(RWops); + FillChar(Image^, ImageSize, #$FF); + SetDataPointer(Image, aFormat, aSize.X, aSize.Y); + except + FreeMem(Image); + raise; end; end; -{$ENDIF} -{$IFDEF GLB_LIB_PNG} -var - StreamPos: Int64; - signature: array [0..7] of byte; - png: png_structp; - png_info: png_infop; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; + const aFunc: TglBitmapFunction; const aArgs: PtrInt); +begin + Create; + LoadFromFunc(aSize, aFunc, aFormat, aArgs); +end; + +{$IFDEF GLB_DELPHI} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar); +begin + Create; + LoadFromResource(aInstance, aResource, aResType); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TglBitmap.Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); +begin + Create; + LoadFromResourceID(aInstance, aResourceID, aResType); +end; +{$ENDIF} + +{$IFDEF GLB_SUPPORT_PNG_READ} +{$IF DEFINED(GLB_SDL_IMAGE)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//PNG///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadPNG(const aStream: TStream): Boolean; +var + Surface: PSDL_Surface; + RWops: PSDL_RWops; +begin + result := false; + RWops := glBitmapCreateRWops(aStream); + try + if IMG_isPNG(RWops) > 0 then begin + Surface := IMG_LoadPNG_RW(RWops); + try + AssignFromSurface(Surface); + Rresult := true; + finally + SDL_FreeSurface(Surface); + end; + end; + finally + SDL_FreeRW(RWops); + end; +end; + +{$ELSEIF DEFINED(GLB_LIB_PNG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmap_libPNG_read_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; +begin + TStream(png_get_io_ptr(png)).Read(buffer^, size); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadPNG(const aStream: TStream): Boolean; +var + StreamPos: Int64; + signature: array [0..7] of byte; + png: png_structp; + png_info: png_infop; TempHeight, TempWidth: Integer; Format: TglBitmapInternalFormat; @@ -3577,7 +4115,7 @@ var png_rows: array of pByte; Row, LineSize: Integer; begin - Result := False; + result := false; if not init_libPNG then raise Exception.Create('LoadPNG - unable to initialize libPNG.'); @@ -3614,13 +4152,13 @@ begin // format case png_get_color_type(png, png_info) of PNG_COLOR_TYPE_GRAY: - Format := ifLuminance; + Format := tfLuminance8; PNG_COLOR_TYPE_GRAY_ALPHA: - Format := ifLuminanceAlpha; + Format := tfLuminance8Alpha8; PNG_COLOR_TYPE_RGB: - Format := ifRGB8; + Format := tfRGB8; PNG_COLOR_TYPE_RGB_ALPHA: - Format := ifRGBA8; + Format := tfRGBA8; else raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); end; @@ -3657,7 +4195,7 @@ begin // set new data SetDataPointer(png_data, Format, TempWidth, TempHeight); - Result := True; + result := true; except FreeMem(png_data); raise; @@ -3667,8 +4205,10 @@ begin quit_libPNG; end; end; -{$ENDIF} -{$IFDEF GLB_PNGIMAGE} + +{$ELSEIF DEFINED(GLB_PNGIMAGE)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadPNG(const aStream: TStream): Boolean; var StreamPos: Int64; Png: TPNGObject; @@ -3681,7 +4221,7 @@ const PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10); begin - Result := False; + result := false; StreamPos := Stream.Position; Stream.Read(Header[0], SizeOf(Header)); @@ -3746,7 +4286,7 @@ begin SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height); - Result := True; + result := true; except FreeMem(NewImage); raise; @@ -3756,10 +4296,175 @@ begin end; end; end; +{$IFEND} {$ENDIF} + +{$IFDEF GLB_SUPPORT_PNG_WRITE} +{$IFDEF GLB_LIB_PNG} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; +begin + TStream(png_get_io_ptr(png)).Write(buffer^, size); +end; {$ENDIF} +{$IF DEFINED(GLB_LIB_PNG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SavePNG(const aStream: TStream); +var + png: png_structp; + png_info: png_infop; + png_rows: array of pByte; + LineSize: Integer; + ColorType: Integer; + Row: Integer; +begin + if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if not init_libPNG then + raise Exception.Create('SavePNG - unable to initialize libPNG.'); + + try + case FInternalFormat of + ifAlpha, ifLuminance, ifDepth8: + ColorType := PNG_COLOR_TYPE_GRAY; + ifLuminanceAlpha: + ColorType := PNG_COLOR_TYPE_GRAY_ALPHA; + ifBGR8, ifRGB8: + ColorType := PNG_COLOR_TYPE_RGB; + ifBGRA8, ifRGBA8: + ColorType := PNG_COLOR_TYPE_RGBA; + else + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + LineSize := Trunc(FormatGetSize(FInternalFormat) * Width); + + // creating array for scanline + SetLength(png_rows, Height); + try + for Row := 0 to Height - 1 do begin + png_rows[Row] := Data; + Inc(png_rows[Row], Row * LineSize) + end; + + // write struct + png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil); + if png = nil then + raise EglBitmapException.Create('SavePng - couldn''t create write struct.'); + + // create png info + png_info := png_create_info_struct(png); + if png_info = nil then begin + png_destroy_write_struct(@png, nil); + raise EglBitmapException.Create('SavePng - couldn''t create info struct.'); + end; + + // set read callback + png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil); + + // set compression + png_set_compression_level(png, 6); + + if InternalFormat in [ifBGR8, ifBGRA8] then + png_set_bgr(png); + + png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, png_info); + png_write_image(png, @png_rows[0]); + png_write_end(png, png_info); + png_destroy_write_struct(@png, @png_info); + finally + SetLength(png_rows, 0); + end; + finally + quit_libPNG; + end; +end; + +{$ELSEIF DEFINED(GLB_PNGIMAGE)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SavePNG(const aStream: TStream); +var + Png: TPNGObject; + + pSource, pDest: pByte; + X, Y, PixSize: Integer; + ColorType: Cardinal; + Alpha: Boolean; + + pTemp: pByte; + Temp: Byte; +begin + if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + + case FInternalFormat of + ifAlpha, ifLuminance, ifDepth8: begin + ColorType := COLOR_GRAYSCALE; + PixSize := 1; + Alpha := false; + end; + ifLuminanceAlpha: begin + ColorType := COLOR_GRAYSCALEALPHA; + PixSize := 1; + Alpha := true; + end; + ifBGR8, ifRGB8: begin + ColorType := COLOR_RGB; + PixSize := 3; + Alpha := false; + end; + ifBGRA8, ifRGBA8: begin + ColorType := COLOR_RGBALPHA; + PixSize := 3; + Alpha := true + end; + else + raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + end; + + Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height); + try + // Copy ImageData + pSource := Data; + for Y := 0 to Height -1 do begin + pDest := png.ScanLine[Y]; + for X := 0 to Width -1 do begin + Move(pSource^, pDest^, PixSize); + Inc(pDest, PixSize); + Inc(pSource, PixSize); + if Alpha then begin + png.AlphaScanline[Y]^[X] := pSource^; + Inc(pSource); + end; + end; + + // convert RGB line to BGR + if InternalFormat in [ifRGB8, ifRGBA8] then begin + pTemp := png.ScanLine[Y]; + for X := 0 to Width -1 do begin + Temp := pByteArray(pTemp)^[0]; + pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2]; + pByteArray(pTemp)^[2] := Temp; + Inc(pTemp, 3); + end; + end; + end; + + // Save to Stream + Png.CompressionLevel := 6; + Png.SaveToStream(Stream); + finally + FreeAndNil(Png); + end; +end; +{$IFEND} +{$ENDIF} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//JPEG//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// {$IFDEF GLB_LIB_JPEG} type glBitmap_libJPEG_source_mgr_ptr = ^glBitmap_libJPEG_source_mgr; @@ -3770,7 +4475,6 @@ type SrcBuffer: array [1..4096] of byte; end; - glBitmap_libJPEG_dest_mgr_ptr = ^glBitmap_libJPEG_dest_mgr; glBitmap_libJPEG_dest_mgr = record pub: jpeg_destination_mgr; @@ -3779,41 +4483,41 @@ type DestBuffer: array [1..4096] of byte; end; - - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{ procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl; -//var -// Msg: String; +var + Msg: String; begin -// SetLength(Msg, 256); -// cinfo^.err^.format_message(cinfo, pChar(Msg)); - -// Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); - -// cinfo^.global_state := 0; - -// jpeg_abort(cinfo); + SetLength(Msg, 256); + cinfo^.err^.format_message(cinfo, pChar(Msg)); + Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); + cinfo^.global_state := 0; + jpeg_abort(cinfo); end; +} - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{ procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl; -//var -// Msg: String; +var + Msg: String; begin -// SetLength(Msg, 256); -// cinfo^.err^.format_message(cinfo, pChar(Msg)); - -// Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); - -// cinfo^.global_state := 0; + SetLength(Msg, 256); + cinfo^.err^.format_message(cinfo, pChar(Msg)); + Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); + cinfo^.global_state := 0; end; +} - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{ procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl; begin end; +} - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl; var src: glBitmap_libJPEG_source_mgr_ptr; @@ -3834,7 +4538,7 @@ begin result := true; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmap_libJPEG_skip_input_data(cinfo: j_decompress_ptr; num_bytes: Longint); cdecl; var src: glBitmap_libJPEG_source_mgr_ptr; @@ -3854,17 +4558,21 @@ begin end; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{ procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl; begin end; +} - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +{ procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl; begin end; +} - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl; var dest: glBitmap_libJPEG_dest_mgr_ptr; @@ -3880,10 +4588,10 @@ begin dest^.pub.free_in_buffer := Length(dest^.DestBuffer); end; - Result := True; + result := true; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmap_libJPEG_term_destination(cinfo: j_compress_ptr); cdecl; var Idx: Integer; @@ -3898,22 +4606,22 @@ begin dest^.DestStream.Write(dest^.DestBuffer[Idx], 2); // leave - Break; + break; end else dest^.DestStream.Write(dest^.DestBuffer[Idx], 1); end; end; {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_READ} -function TglBitmap.LoadJPEG(Stream: TStream): Boolean; -{$IFDEF GLB_SDL_IMAGE} +{$IF DEFINED(GLB_SDL_IMAGE)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; var Surface: PSDL_Surface; RWops: PSDL_RWops; begin - Result := False; + result := false; RWops := glBitmapCreateRWops(Stream); try @@ -3921,7 +4629,7 @@ begin Surface := IMG_LoadJPG_RW(RWops); try AssignFromSurface(Surface); - Result := True; + result := true; finally SDL_FreeSurface(Surface); end; @@ -3930,8 +4638,10 @@ begin SDL_FreeRW(RWops); end; end; -{$ENDIF} -{$IFDEF GLB_LIB_JPEG} + +{$ELSEIF DEFINED(GLB_LIB_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; var StreamPos: Int64; Temp: array[0..1]of Byte; @@ -3946,7 +4656,7 @@ var pTemp: pByte; Row: Integer; begin - Result := False; + result := false; if not init_libJPEG then raise Exception.Create('LoadJPG - unable to initialize libJPEG.'); @@ -3991,7 +4701,7 @@ begin jpeg.global_state := DSTATE_START; // read header of jpeg - jpeg_read_header(@jpeg, False); + jpeg_read_header(@jpeg, false); // setting output parameter case jpeg.jpeg_color_space of @@ -4029,7 +4739,7 @@ begin SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); - Result := True; + result := true; except FreeMem(pImage); raise; @@ -4039,15 +4749,17 @@ begin quit_libJPEG; end; end; -{$ENDIF} -{$IFDEF GLB_DELPHI_JPEG} + +{$ELSEIF DEFINED(GLB_DELPHI_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; var bmp: TBitmap; jpg: TJPEGImage; StreamPos: Int64; Temp: array[0..1]of Byte; begin - Result := False; + result := false; // reading first two bytes to test file and set cursor back to begin StreamPos := Stream.Position; @@ -4062,7 +4774,7 @@ begin try jpg.LoadFromStream(Stream); bmp.Assign(jpg); - Result := AssignFromBitmap(bmp); + result := AssignFromBitmap(bmp); finally jpg.Free; end; @@ -4071,20 +4783,159 @@ begin end; end; end; +{$IFEND} {$ENDIF} -{$ENDIF} - - -const - BMP_MAGIC = $4D42; - BMP_COMP_RGB = 0; - BMP_COMP_RLE8 = 1; - BMP_COMP_RLE4 = 2; - BMP_COMP_BITFIELDS = 3; +{$IFDEF GLB_SUPPORT_JPEG_WRITE} +{$IF DEFEFINED(GLB_LIB_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveJPEG(Stream: TStream); +var + jpeg: jpeg_compress_struct; + jpeg_err: jpeg_error_mgr; + Row: Integer; + pTemp, pTemp2: pByte; -type - TBMPHeader = packed record + procedure CopyRow(pDest, pSource: pByte); + var + X: Integer; + begin + for X := 0 to Width - 1 do begin + pByteArray(pDest)^[0] := pByteArray(pSource)^[2]; + pByteArray(pDest)^[1] := pByteArray(pSource)^[1]; + pByteArray(pDest)^[2] := pByteArray(pSource)^[0]; + Inc(pDest, 3); + Inc(pSource, 3); + end; + end; + +begin + if not (ftJPEG in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + + if not init_libJPEG then + raise Exception.Create('SaveJPG - unable to initialize libJPEG.'); + + try + FillChar(jpeg, SizeOf(jpeg_compress_struct), $00); + FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); + + // error managment + jpeg.err := jpeg_std_error(@jpeg_err); + jpeg_err.error_exit := glBitmap_libJPEG_error_exit; + jpeg_err.output_message := glBitmap_libJPEG_output_message; + + // compression struct + jpeg_create_compress(@jpeg); + + // allocation space for streaming methods + jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr)); + + // seeting up custom functions + with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin + pub.init_destination := glBitmap_libJPEG_init_destination; + pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer; + pub.term_destination := glBitmap_libJPEG_term_destination; + + pub.next_output_byte := @DestBuffer[1]; + pub.free_in_buffer := Length(DestBuffer); + + DestStream := Stream; + end; + + // very important state + jpeg.global_state := CSTATE_START; + jpeg.image_width := Width; + jpeg.image_height := Height; + case InternalFormat of + ifAlpha, ifLuminance, ifDepth8: begin + jpeg.input_components := 1; + jpeg.in_color_space := JCS_GRAYSCALE; + end; + ifRGB8, ifBGR8: begin + jpeg.input_components := 3; + jpeg.in_color_space := JCS_RGB; + end; + end; + + jpeg_set_defaults(@jpeg); + jpeg_set_quality(@jpeg, 95, true); + jpeg_start_compress(@jpeg, true); + pTemp := Data; + + if InternalFormat = ifBGR8 then + GetMem(pTemp2, fRowSize) + else + pTemp2 := pTemp; + + try + for Row := 0 to jpeg.image_height -1 do begin + // prepare row + if InternalFormat = ifBGR8 then + CopyRow(pTemp2, pTemp) + else + pTemp2 := pTemp; + + // write row + jpeg_write_scanlines(@jpeg, @pTemp2, 1); + inc(pTemp, fRowSize); + end; + finally + // free memory + if InternalFormat = ifBGR8 then + FreeMem(pTemp2); + end; + jpeg_finish_compress(@jpeg); + jpeg_destroy_compress(@jpeg); + finally + quit_libJPEG; + end; +end; + +{$ELSEIF DEFINED(GLB_DELPHI_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveJPEG(Stream: TStream); +var + Bmp: TBitmap; + Jpg: TJPEGImage; +begin + if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then + raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + + Bmp := TBitmap.Create; + try + Jpg := TJPEGImage.Create; + try + AssignToBitmap(Bmp); + if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin + Jpg.Grayscale := true; + Jpg.PixelFormat := jf8Bit; + end; + Jpg.Assign(Bmp); + Jpg.SaveToStream(Stream); + finally + FreeAndNil(Jpg); + end; + finally + FreeAndNil(Bmp); + end; +end; +{$ENDIF} +{$ENDIF} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//BMP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const + BMP_MAGIC = $4D42; + + BMP_COMP_RGB = 0; + BMP_COMP_RLE8 = 1; + BMP_COMP_RLE4 = 2; + BMP_COMP_BITFIELDS = 3; + +type + TBMPHeader = packed record bfType: Word; bfSize: Cardinal; bfReserved1: Word; @@ -4116,357 +4967,356 @@ type // TBMPPalette = record // case Boolean of -// True : (Colors: array[Byte] of TRGBQUAD); -// False: (redMask, greenMask, blueMask: Cardinal); +// true : (Colors: array[Byte] of TRGBQUAD); +// false: (redMask, greenMask, blueMask: Cardinal); // end; -function TglBitmap.LoadBMP(Stream: TStream): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadBMP(const aStream: TStream): Boolean; +type + TMaskValues = packed record + Red: Cardinal; + Green: Cardinal; + Blue: Cardinal; + Alpha: Cardinal; + end; + var - StreamPos: Int64; - Header: TBMPHeader; - Info: TBMPInfo; - NewImage, pData: pByte; + StartPos: Int64; - Format: TglBitmapFormat; - LineSize, Padding, LineIdx: Integer; - RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; + ////////////////////////////////////////////////////////////////////////////////////////////////// + function ReadInfo(var aInfo: TBMPInfo; var aMask: TMaskValues): TglBitmapFormat; + begin + result := tfEmpty; + aStream.Read(aInfo, SizeOf(aInfo)); + FillChar(aMask, SizeOf(aMask), 0); - PaddingBuff: Cardinal; + //Read Compression + if aInfo.biCompression <> BMP_COMP_RGB then begin + if aInfo.biCompression = BMP_COMP_BITFIELDS then begin + // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!) + if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin + aStream.Read(aMask.Red, SizeOf(Cardinal)); + aStream.Read(aMask.Green, SizeOf(Cardinal)); + aStream.Read(aMask.Blue, SizeOf(Cardinal)); + aStream.Read(aMask.Alpha, SizeOf(Cardinal)); + end else + raise EglBitmapException.Create('Bitmask is not supported for 24bit formats'); + end else begin + aStream.Position := StartPos; + raise EglBitmapException.Create('RLE compression is not supported'); + end; + end; + //get suitable format + case aInfo.biBitCount of + 8: result := tfLuminance8; + 16: result := tfRGB5A1; + 24: result := tfBGR8; + 32: result := tfBGRA8; + end; + end; - function GetLineWidth : Integer; + ////////////////////////////////////////////////////////////////////////////////////////////////// + function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TMaskValues): TBitfieldFormat; + var + TmpFormat: TglBitmapFormat; + FormatDesc: TglBitmapFormatDescClass; begin - Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3; - end; + result := nil; + if (aMask.Red <> 0) or (aMask.Green <> 0) or (aMask.Blue <> 0) or (aMask.Alpha <> 0) then begin + for TmpFormat := High(FORMAT_DESCRIPTORS) downto Low(FORMAT_DESCRIPTORS) do begin + FormatDesc := FORMAT_DESCRIPTORS[TmpFormat]; + if FormatDesc.MaskMatch(aMask.Red, aMask.Green, aMask.Blue, aMask.Alpha) then begin + aFormat := FormatDesc.GetFormat; + exit; + end; + end; - -begin - Result := False; + if (aMask.Alpha = 0) then + aFormat := FORMAT_DESCRIPTORS[aFormat].WithoutAlpha; - RedMask := 0; - GreenMask := 0; - BlueMask := 0; - Format := ifEmpty; + result := TBitfieldFormat.Create; + result.RedMask := aMask.Red; + result.GreenMask := aMask.Green; + result.BlueMask := aMask.Blue; + result.AlphaMask := aMask.Alpha; + end; + end; - // Header - StreamPos := Stream.Position; - Stream.Read(Header, SizeOf(Header)); +var + //simple types + ImageSize, rbLineSize, wbLineSize, Padding, i: Integer; + PaddingBuff: Cardinal; + LineBuf, ImageData, TmpData: PByte; + BmpFormat: TglBitmapFormat; - if Header.bfType = BMP_MAGIC then begin - Stream.Read(Info, SizeOf(Info)); + //records + Mask: TMaskValues; + Header: TBMPHeader; + Info: TBMPInfo; - // Check for Compression - if Info.biCompression <> BMP_COMP_RGB then begin - if Info.biCompression = BMP_COMP_BITFIELDS then begin - // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!) - if (Info.biBitCount = 16) or (Info.biBitCount = 32) then begin - Stream.Read(RedMask, SizeOf(Cardinal)); - Stream.Read(GreenMask, SizeOf(Cardinal)); - Stream.Read(BlueMask, SizeOf(Cardinal)); - Stream.Read(AlphaMask, SizeOf(Cardinal)); - end; - end else begin - // RLE compression is unsupported - Stream.Position := StreamPos; + //classes + BitfieldFormat: TBitfieldFormat; + FormatDesc: TglBitmapFormatDescClass; - Exit; - end; - end; - // Skip palette - if Info.biBitCount < 16 then - Stream.Position := Stream.Position + Info.biClrUsed * 4; + Tick: QWord; +{ - // Jump to the data - Stream.Position := StreamPos + Header.bfOffBits; - // Select Format - case Info.biBitCount of - 8 : Format := ifLuminance; - 16: - begin - if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin - Format := tfRGB5A1; - end else begin - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifLuminanceAlpha) then - Format := ifLuminanceAlpha; + ImageData, pData, pTmp, LineBuf, TmpData: PByte; + BitOffset: Byte; + BmpFormat: TglBitmapFormat; + LineSize, Padding, LineIdx, PixelIdx: Integer; + RedMask, GreenMask, BlueMask, AlphaMask, FormatSize: Cardinal; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA4) then - Format := tfRGBA4; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, tfRGB5A1) then - Format := tfRGB5A1; + Pixel: TglBitmapPixelData; + PaddingBuff: Cardinal; - if FormatCheckFormat(RedMask, GreenMask, BlueMask, 0, ifR5G6B5) then - Format := ifR5G6B5; - end; - end; - 24: Format := ifBGR8; - 32: - begin - if (RedMask = 0) and (GreenMask = 0) and (BlueMask = 0) then begin - Format := ifBGRA8; - end else begin - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGBA8) then - Format := tfRGBA8; - - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, ifBGRA8) then - Format := ifBGRA8; - - if FormatCheckFormat(RedMask, GreenMask, BlueMask, AlphaMask, tfRGB10A2) then - Format := tfRGB10A2; - end; - end; - end; - if Format <> ifEmpty then begin - LineSize := Trunc(Info.biWidth * FormatGetSize(Format)); - Padding := GetLineWidth - LineSize; - // copying data - GetMem(NewImage, Info.biHeight * LineSize); - try - FillChar(NewImage^, Info.biHeight * LineSize, $FF); + } - // Set pData to last Line - pData := NewImage; - Inc(pData, LineSize * (Info.biHeight -1)); + ////////////////////////////////////////////////////////////////////////////////////////////////// + procedure ReadBitfieldLine(aData: PByte; aLineBuf: PByte); + var + i: Integer; + Pixel: TglBitmapPixelData; - // Copy Image Data - for LineIdx := 0 to Info.biHeight - 1 do begin - Stream.Read(pData^, LineSize); - Dec(pData, LineSize); + //////////////////////////////////////////////////////////////////////////////////////////////// + procedure ChangeRange(var aValue: Cardinal; const aOldRange, aNewRange: Cardinal); + begin + if (aOldRange = aNewRange) then + exit; + if (aOldRange > 0) then + aValue := Round(aValue / aOldRange * aNewRange) + else + aValue := 0; + end; - Stream.Read(PaddingBuff, Padding); - end; + begin + aStream.Read(aLineBuf^, rbLineSize); + for i := 0 to Info.biWidth-1 do begin + BitfieldFormat.Unmap(PCardinal(aLineBuf)^, Pixel); //if is 16bit Bitfield only 2 last significant Bytes are taken from Cardinal + inc(aLineBuf, Info.biBitCount shr 3); + with FormatDesc.GetPixelDesc do begin + ChangeRange(Pixel.Red, BitfieldFormat.RedRange, RedRange); + ChangeRange(Pixel.Green, BitfieldFormat.GreenRange, GreenRange); + ChangeRange(Pixel.Blue, BitfieldFormat.BlueRange, BlueRange); + ChangeRange(Pixel.Alpha, BitfieldFormat.AlphaRange, AlphaRange); + end; + FormatDesc.Map(Pixel, aData); + end; + end; - // Set new Image - SetDataPointer(NewImage, Format, Info.biWidth, Info.biHeight); +begin + result := false; + BmpFormat := tfEmpty; + BitfieldFormat := nil; + LineBuf := nil; - Result := True; - except - FreeMem(NewImage); - raise; - end; + // Header + StartPos := aStream.Position; + aStream.Read(Header, SizeOf(Header)); + + if Header.bfType = BMP_MAGIC then begin + BmpFormat := ReadInfo(Info, Mask); + BitfieldFormat := CheckBitfields(BmpFormat, Mask); + try + if (Info.biBitCount < 16) then + aStream.Position := aStream.Position + Info.biClrUsed * 4; + aStream.Position := StartPos + Header.bfOffBits; + + if (BmpFormat <> tfEmpty) then begin + FormatDesc := FORMAT_DESCRIPTORS[BmpFormat]; + rbLineSize := Info.biWidth * (Info.biBitCount shr 3); //ReadBuffer LineSize + wbLineSize := Trunc(Info.biWidth * FormatDesc.GetSize); + Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize; + + //get Memory + ImageSize := FormatDesc.GetSize(glBitmapPosition(Info.biWidth, Info.biHeight)); + GetMem(ImageData, ImageSize); + if Assigned(BitfieldFormat) then + GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields + + //read Data + try try + FillChar(ImageData^, ImageSize, $FF); + TmpData := ImageData; + Inc(TmpData, wbLineSize * (Info.biHeight -1)); + for i := 0 to Info.biHeight-1 do begin + if Assigned(BitfieldFormat) then + ReadBitfieldLine(TmpData, LineBuf) //if is bitfield format read and convert data + else + aStream.Read(TmpData^, wbLineSize); //else only read data + Dec(TmpData, wbLineSize); + aStream.Read(PaddingBuff, Padding); + end; + SetDataPointer(ImageData, BmpFormat, Info.biWidth, Info.biHeight); + result := true; + finally + if Assigned(LineBuf) then + FreeMem(LineBuf); + end; + except + FreeMem(ImageData); + raise; + end; + end else + raise EglBitmapException.Create('LoadBMP - No suitable format found'); + finally + FreeAndNil(BitfieldFormat); end; end - else Stream.Position := StreamPos; + else aStream.Position := StartPos; end; -{$ENDREGION} -const - DDS_MAGIC = $20534444; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveBMP(const aStream: TStream); +var + Header: TBMPHeader; + Info: TBMPInfo; + pData, pTemp: pByte; - // DDS_header.dwFlags - DDSD_CAPS = $00000001; - DDSD_HEIGHT = $00000002; - DDSD_WIDTH = $00000004; - DDSD_PITCH = $00000008; - DDSD_PIXELFORMAT = $00001000; - DDSD_MIPMAPCOUNT = $00020000; - DDSD_LINEARSIZE = $00080000; - DDSD_DEPTH = $00800000; + PixelFormat: TglBitmapPixelData; + ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer; + Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; - // DDS_header.sPixelFormat.dwFlags - DDPF_ALPHAPIXELS = $00000001; - DDPF_FOURCC = $00000004; - DDPF_INDEXED = $00000020; - DDPF_RGB = $00000040; + PaddingBuff: Cardinal; - // DDS_header.sCaps.dwCaps1 - DDSCAPS_COMPLEX = $00000008; - DDSCAPS_TEXTURE = $00001000; - DDSCAPS_MIPMAP = $00400000; + function GetLineWidth : Integer; + begin + result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3; + end; - // DDS_header.sCaps.dwCaps2 - DDSCAPS2_CUBEMAP = $00000200; - DDSCAPS2_CUBEMAP_POSITIVEX = $00000400; - DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800; - DDSCAPS2_CUBEMAP_POSITIVEY = $00001000; - DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000; - DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000; - DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000; - DDSCAPS2_VOLUME = $00200000; +begin + if not (ftBMP in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); - D3DFMT_DXT1 = $31545844; - D3DFMT_DXT3 = $33545844; - D3DFMT_DXT5 = $35545844; + ImageSize := FORMAT_DESCRIPTORS[Format].GetSize(Dimension); -type - TDDSPixelFormat = packed record - dwSize: Cardinal; - dwFlags: Cardinal; - dwFourCC: Cardinal; - dwRGBBitCount: Cardinal; - dwRBitMask: Cardinal; - dwGBitMask: Cardinal; - dwBBitMask: Cardinal; - dwAlphaBitMask: Cardinal; - end; - - TDDSCaps = packed record - dwCaps1: Cardinal; - dwCaps2: Cardinal; - dwDDSX: Cardinal; - dwReserved: Cardinal; - end; - - TDDSHeader = packed record - dwMagic: Cardinal; - dwSize: Cardinal; - dwFlags: Cardinal; - dwHeight: Cardinal; - dwWidth: Cardinal; - dwPitchOrLinearSize: Cardinal; - dwDepth: Cardinal; - dwMipMapCount: Cardinal; - dwReserved: array[0..10] of Cardinal; - PixelFormat: TDDSPixelFormat; - Caps: TDDSCaps; - dwReserved2: Cardinal; - end; - - - -function TglBitmap.LoadDDS(Stream: TStream): Boolean; -var - Header: TDDSHeader; - StreamPos: Int64; - Y, LineSize: Cardinal; + Header.bfType := BMP_MAGIC; + Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; + Header.bfReserved1 := 0; + Header.bfReserved2 := 0; + Header.bfOffBits := SizeOf(Header) + SizeOf(Info); -// MipMapCount, X, Y, XSize, YSize: Cardinal; - RowSize: Cardinal; - NewImage, pData: pByte; - Format: TglBitmapFormat; + FillChar(Info, SizeOf(Info), 0); + Info.biSize := SizeOf(Info); + Info.biWidth := Width; + Info.biHeight := Height; + Info.biPlanes := 1; + Info.biCompression := BMP_COMP_RGB; + Info.biSizeImage := ImageSize; + case Format of + //TODO tfAlpha8, ifLuminance8, ifDepth8: + tfLuminance8: + begin + Info.biBitCount := 8; + Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); - function RaiseEx : Exception; - begin - Result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + Info.biClrUsed := 256; + Info.biClrImportant := 256; + end; + //TODO ifLuminance8Alpha8, tfRGBA4, ifR5G6B5, tfRGB5A1: + tfLuminance8Alpha8, tfRGB5A1: + begin + Info.biBitCount := 16; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + tfBGR8, tfRGB8: + Info.biBitCount := 24; + //TODO tfBGRA8, tfRGBA8, tfRGB10A2: + tfBGRA8, tfRGBA8: + begin + Info.biBitCount := 32; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + else + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); end; + Info.biXPelsPerMeter := 2835; + Info.biYPelsPerMeter := 2835; - - function GetInternalFormat: TglBitmapFormat; - begin - with Header.PixelFormat do begin - // Compresses - 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; - end; - end else - - // RGB - if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin - case dwRGBBitCount of - 8: - begin - if dwFlags and DDPF_ALPHAPIXELS > 0 then - Result := ifAlpha - else - Result := ifLuminance; - end; - 16: - begin - if dwFlags and DDPF_ALPHAPIXELS > 0 then begin - // Alpha - case GetBitSize(dwRBitMask) of - 5: Result := tfRGB5A1; - 4: Result := tfRGBA4; - else - Result := ifLuminanceAlpha; - end; - end else begin - // no Alpha - Result := ifR5G6B5; - end; - end; - 24: - begin - if dwRBitMask > dwBBitMask then - Result := ifBGR8 - else - Result := tfRGB8; - end; - 32: - begin - if GetBitSize(dwRBitMask) = 10 then - Result := tfRGB10A2 - else + // prepare bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + Info.biSize := Info.biSize + 4 * SizeOf(Cardinal); + Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); - if dwRBitMask > dwBBitMask then - Result := ifBGRA8 - else - Result := tfRGBA8; - end; - else - raise RaiseEx; - end; - end else - raise RaiseEx; + FORMAT_DESCRIPTORS[Format].PreparePixel(PixelFormat); + with PixelFormat.PixelDesc do begin + RedMask := RedRange shl RedShift; + GreenMask := GreenRange shl GreenShift; + BlueMask := BlueRange shl BlueShift; + AlphaMask := AlphaRange shl AlphaShift; end; end; -begin - Result := False; - - // Header - StreamPos := Stream.Position; - Stream.Read(Header, sizeof(Header)); + // headers + aStream.Write(Header, SizeOf(Header)); + aStream.Write(Info, SizeOf(Info)); - 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 - Stream.Position := StreamPos; - Exit; + // colortable + if Info.biBitCount = 8 then begin + Temp := 0; + for ColorIdx := Low(Byte) to High(Byte) do begin + aStream.Write(Temp, 4); + Temp := Temp + $00010101; + end; end; - // Pixelformat -// if Header.dwFlags and DDSD_MIPMAPCOUNT <> 0 -// then MipMapCount := Header.dwMipMapCount -// else MipMapCount := 1; - - Format := GetInternalFormat; - LineSize := Trunc(Header.dwWidth * FormatGetSize(Format)); - - GetMem(NewImage, Header.dwHeight * LineSize); - try - pData := NewImage; - - // Compressed - 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 - Stream.Read(pData^, RowSize); - Inc(pData, LineSize); - end; - end else + // bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + aStream.Write(RedMask, SizeOf(Cardinal)); + aStream.Write(GreenMask, SizeOf(Cardinal)); + aStream.Write(BlueMask, SizeOf(Cardinal)); + aStream.Write(AlphaMask, SizeOf(Cardinal)); + end; - // RGB(A) - if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin - RowSize := Header.dwPitchOrLinearSize; + // image data + LineSize := Trunc(Width * FORMAT_DESCRIPTORS[Format].GetSize); + Padding := GetLineWidth - LineSize; + PaddingBuff := 0; - for Y := 0 to Header.dwHeight -1 do begin - Stream.Read(pData^, RowSize); - Inc(pData, LineSize); - end; - end - else raise RaiseEx; + pData := Data; + Inc(pData, (Height -1) * LineSize); - SetDataPointer(NewImage, Format, Header.dwWidth, Header.dwHeight); + // prepare row buffer. But only for RGB because RGBA supports color masks + // so it's possible to change color within the image. + if (Format = tfRGB8) then + GetMem(pTemp, fRowSize) + else + pTemp := nil; - Result := True; - except - FreeMem(NewImage); - raise; + try + // write image data + for LineIdx := 0 to Height - 1 do begin + // preparing row + if Format = tfRGB8 then begin + Move(pData^, pTemp^, fRowSize); + SwapRGB(pTemp, Width, false); + end else + pTemp := pData; + aStream.Write(pTemp^, LineSize); + Dec(pData, LineSize); + if Padding > 0 then + aStream.Write(PaddingBuff, Padding); + end; + finally + // destroy row buffer + if Format = tfRGB8 then + FreeMem(pTemp); end; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TGA///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type TTGAHeader = packed record ImageID: Byte; @@ -4487,9 +5337,8 @@ const TGA_COMPRESSED_RGB = 10; TGA_COMPRESSED_GRAY = 11; - - -function TglBitmap.LoadTGA(Stream: TStream): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadTGA(const aStream: TStream): Boolean; var Header: TTGAHeader; NewImage, pData: PByte; @@ -4500,23 +5349,22 @@ var const CACHE_SIZE = $4000; + //////////////////////////////////////////////////////////////////////////////////////// procedure ReadUncompressed; var RowSize: Integer; begin RowSize := Header.Width * PixelSize; - // copy line by line while YStart <> YEnd + YInc do begin pData := NewImage; Inc(pData, YStart * LineSize); - - Stream.Read(pData^, RowSize); + aStream.Read(pData^, RowSize); Inc(YStart, YInc); end; end; - + //////////////////////////////////////////////////////////////////////////////////////// procedure ReadCompressed; var HeaderWidth, HeaderHeight: Integer; @@ -4531,7 +5379,7 @@ const PixelRepeat: Boolean; PixelToRead, TempPixels: Integer; - + ///////////////////////////////////////////////////////////////// procedure CheckLine; begin if LinePixelsRead >= HeaderWidth then begin @@ -4542,8 +5390,8 @@ const end; end; - - procedure CachedRead(var Buffer; Count: Integer); + ///////////////////////////////////////////////////////////////// + procedure CachedRead(out Buffer; Count: Integer); var BytesRead: Integer; begin @@ -4553,14 +5401,13 @@ const // Read Data if CacheSize - CachePos > 0 then begin BytesRead := CacheSize - CachePos; - Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead); Inc(CachePos, BytesRead); end; // Reload Data - CacheSize := Min(CACHE_SIZE, Stream.Size - Stream.Position); - Stream.Read(Cache^, CacheSize); + CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position); + aStream.Read(Cache^, CacheSize); CachePos := 0; // Read else @@ -4574,7 +5421,6 @@ const end; end; - begin CacheSize := 0; CachePos := 0; @@ -4596,7 +5442,7 @@ const CachedRead(Temp, 1); PixelRepeat := Temp and $80 > 0; - PixelToRead := (Temp and $7F) + 1; + PixelToRead := (Temp and $7F) + 1; Inc(ImgPixelsRead, PixelToRead); @@ -4611,36 +5457,31 @@ const TempPixels := HeaderWidth - LinePixelsRead; if PixelToRead < TempPixels then TempPixels := PixelToRead; - + Inc(LinePixelsRead, TempPixels); Dec(PixelToRead, TempPixels); while TempPixels > 0 do begin case PixelSize of - 1: - begin - pData^ := TempBuf[0]; - Inc(pData); - end; - 2: - begin - pWord(pData)^ := pWord(@TempBuf[0])^; - Inc(pData, 2); - end; - 3: - begin - pWord(pData)^ := pWord(@TempBuf[0])^; - Inc(pData, 2); - pData^ := TempBuf[2]; - Inc(pData); - end; - 4: - begin - pDWord(pData)^ := pDWord(@TempBuf[0])^; - Inc(pData, 4); - end; + 1: begin + pData^ := TempBuf[0]; + Inc(pData); + end; + 2: begin + pWord(pData)^ := pWord(@TempBuf[0])^; + Inc(pData, 2); + end; + 3: begin + pWord(pData)^ := pWord(@TempBuf[0])^; + Inc(pData, 2); + pData^ := TempBuf[2]; + Inc(pData); + end; + 4: begin + pDWord(pData)^ := pDWord(@TempBuf[0])^; + Inc(pData, 4); + end; end; - Dec(TempPixels); end; end; @@ -4648,16 +5489,12 @@ const // copy x pixels while PixelToRead > 0 do begin CheckLine; - TempPixels := HeaderWidth - LinePixelsRead; if PixelToRead < TempPixels then TempPixels := PixelToRead; - CachedRead(pData^, PixelSize * TempPixels); Inc(pData, PixelSize * TempPixels); - Inc(LinePixelsRead, TempPixels); - Dec(PixelToRead, TempPixels); end; end; @@ -4668,30 +5505,30 @@ const end; begin - Result := False; + result := false; // reading header to test file and set cursor back to begin - StreamPos := Stream.Position; - Stream.Read(Header, SizeOf(Header)); + StreamPos := aStream.Position; + aStream.Read(Header, SizeOf(Header)); // no colormapped files if (Header.ColorMapType = 0) then begin if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin case Header.Bpp of - 8: Format := ifAlpha; - 16: Format := ifLuminanceAlpha; - 24: Format := ifBGR8; - 32: Format := ifBGRA8; - else - raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.'); + //TODO 8: Format := tfAlpha8; + 16: Format := tfLuminance8Alpha8; + 24: Format := tfBGR8; + 32: Format := tfBGRA8; + else + raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.'); end; // skip image ID if Header.ImageID <> 0 then - Stream.Position := Stream.Position + Header.ImageID; + aStream.Position := aStream.Position + Header.ImageID; - PixelSize := Trunc(FormatGetSize(Format)); - LineSize := Trunc(Header.Width * PixelSize); + PixelSize := Trunc(FORMAT_DESCRIPTORS[Format].GetSize); + LineSize := Trunc(Header.Width * PixelSize); GetMem(NewImage, LineSize * Header.Height); try @@ -4715,216 +5552,320 @@ begin end; SetDataPointer(NewImage, Format, Header.Width, Header.Height); - - Result := True; + result := true; except FreeMem(NewImage); raise; end; end - else Stream.Position := StreamPos; + else aStream.Position := StreamPos; end - else Stream.Position := StreamPos; + else aStream.Position := StreamPos; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveTGA(const aStream: TStream); +var + Header: TTGAHeader; + Size: Integer; + pTemp: pByte; + FormatDesc: TglBitmapFormatDescClass; -{$IFDEF GLB_SUPPORT_PNG_WRITE} -{$IFDEF GLB_LIB_PNG} -procedure glBitmap_libPNG_write_func(png: png_structp; buffer: png_bytep; size: cardinal); cdecl; -begin - TStream(png_get_io_ptr(png)).Write(buffer^, size); -end; -{$ENDIF} + procedure ConvertData(pTemp: pByte); + var + Idx, PixelSize: Integer; + Temp: byte; + begin + PixelSize := fPixelSize; + for Idx := 1 to Height * Width do begin + Temp := pByteArray(pTemp)^[2]; + pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0]; + pByteArray(pTemp)^[0] := Temp; + Inc(pTemp, PixelSize); + end; + end; -procedure TglBitmap.SavePNG(Stream: TStream); -{$IFDEF GLB_LIB_PNG} -var - png: png_structp; - png_info: png_infop; - png_rows: array of pByte; - LineSize: Integer; - ColorType: Integer; - Row: Integer; begin - if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); - - if not init_libPNG then - raise Exception.Create('SavePNG - unable to initialize libPNG.'); + if not (ftTGA in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); - try - case FInternalFormat of - ifAlpha, ifLuminance, ifDepth8: - ColorType := PNG_COLOR_TYPE_GRAY; - ifLuminanceAlpha: - ColorType := PNG_COLOR_TYPE_GRAY_ALPHA; - ifBGR8, ifRGB8: - ColorType := PNG_COLOR_TYPE_RGB; - ifBGRA8, ifRGBA8: - ColorType := PNG_COLOR_TYPE_RGBA; - else - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + FillChar(Header, SizeOf(Header), 0); + case Format of + //TODO ifAlpha8, ifLuminance8, ifDepth8: begin + tfLuminance8: begin + Header.ImageType := TGA_UNCOMPRESSED_GRAY; + Header.Bpp := 8; + end; + tfLuminance8Alpha8: begin + Header.ImageType := TGA_UNCOMPRESSED_GRAY; + Header.Bpp := 16; end; + tfRGB8, tfBGR8: begin + Header.ImageType := TGA_UNCOMPRESSED_RGB; + Header.Bpp := 24; + end; + tfRGBA8, tfBGRA8: begin + Header.ImageType := TGA_UNCOMPRESSED_RGB; + Header.Bpp := 32; + end; + else + raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); + end; - LineSize := Trunc(FormatGetSize(FInternalFormat) * Width); + Header.Width := Width; + Header.Height := Height; + Header.ImageDes := $20; + FormatDesc := FORMAT_DESCRIPTORS[Format]; - // creating array for scanline - SetLength(png_rows, Height); - try - for Row := 0 to Height - 1 do begin - png_rows[Row] := Data; - Inc(png_rows[Row], Row * LineSize) - end; + if FormatDesc.HasAlpha then + Header.ImageDes := Header.ImageDes or $08; + aStream.Write(Header, SizeOf(Header)); - // write struct - png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil); - if png = nil then - raise EglBitmapException.Create('SavePng - couldn''t create write struct.'); + // convert RGB(A) to BGR(A) + Size := FormatDesc.GetSize(Dimension); + if Format in [tfRGB8, tfRGBA8] then begin + GetMem(pTemp, Size); + end else + pTemp := Data; - // create png info - png_info := png_create_info_struct(png); - if png_info = nil then begin - png_destroy_write_struct(@png, nil); - raise EglBitmapException.Create('SavePng - couldn''t create info struct.'); - end; + try + // convert data + if Format in [tfRGB8, tfRGBA8] then begin + Move(Data^, pTemp^, Size); + ConvertData(pTemp); + end; - // set read callback - png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil); + // write data + aStream.Write(pTemp^, Size); + finally + // free tempdata + if Format in [tfRGB8, tfRGBA8] then + FreeMem(pTemp); + end; +end; - // set compression - png_set_compression_level(png, 6); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//DDS///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const + DDS_MAGIC = $20534444; - if InternalFormat in [ifBGR8, ifBGRA8] then - png_set_bgr(png); + // DDS_header.dwFlags + DDSD_CAPS = $00000001; + DDSD_HEIGHT = $00000002; + DDSD_WIDTH = $00000004; + DDSD_PITCH = $00000008; + DDSD_PIXELFORMAT = $00001000; + DDSD_MIPMAPCOUNT = $00020000; + DDSD_LINEARSIZE = $00080000; + DDSD_DEPTH = $00800000; - // setup header - png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + // DDS_header.sPixelFormat.dwFlags + DDPF_ALPHAPIXELS = $00000001; + DDPF_FOURCC = $00000004; + DDPF_INDEXED = $00000020; + DDPF_RGB = $00000040; - // write info - png_write_info(png, png_info); + // DDS_header.sCaps.dwCaps1 + DDSCAPS_COMPLEX = $00000008; + DDSCAPS_TEXTURE = $00001000; + DDSCAPS_MIPMAP = $00400000; - // write image data - png_write_image(png, @png_rows[0]); + // DDS_header.sCaps.dwCaps2 + DDSCAPS2_CUBEMAP = $00000200; + DDSCAPS2_CUBEMAP_POSITIVEX = $00000400; + DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800; + DDSCAPS2_CUBEMAP_POSITIVEY = $00001000; + DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000; + DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000; + DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000; + DDSCAPS2_VOLUME = $00200000; - // write end - png_write_end(png, png_info); + D3DFMT_DXT1 = $31545844; + D3DFMT_DXT3 = $33545844; + D3DFMT_DXT5 = $35545844; - // destroy write struct - png_destroy_write_struct(@png, @png_info); - finally - SetLength(png_rows, 0); - end; - finally - quit_libPNG; +type + TDDSPixelFormat = packed record + dwSize: Cardinal; + dwFlags: Cardinal; + dwFourCC: Cardinal; + dwRGBBitCount: Cardinal; + dwRBitMask: Cardinal; + dwGBitMask: Cardinal; + dwBBitMask: Cardinal; + dwAlphaBitMask: Cardinal; end; -end; -{$ENDIF} -{$IFDEF GLB_PNGIMAGE} + + TDDSCaps = packed record + dwCaps1: Cardinal; + dwCaps2: Cardinal; + dwDDSX: Cardinal; + dwReserved: Cardinal; + end; + + TDDSHeader = packed record + dwMagic: Cardinal; + dwSize: Cardinal; + dwFlags: Cardinal; + dwHeight: Cardinal; + dwWidth: Cardinal; + dwPitchOrLinearSize: Cardinal; + dwDepth: Cardinal; + dwMipMapCount: Cardinal; + dwReserved: array[0..10] of Cardinal; + PixelFormat: TDDSPixelFormat; + Caps: TDDSCaps; + dwReserved2: Cardinal; + end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadDDS(const aStream: TStream): Boolean; var - Png: TPNGObject; + Header: TDDSHeader; + StreamPos: Int64; + Y, LineSize: Cardinal; + RowSize: Cardinal; + NewImage, pData: pByte; + ddsFormat: TglBitmapFormat; - pSource, pDest: pByte; - X, Y, PixSize: Integer; - ColorType: Cardinal; - Alpha: Boolean; + function RaiseEx : Exception; + begin + result := EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + end; - pTemp: pByte; - Temp: Byte; -begin - if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + function GetDDSFormat: TglBitmapFormat; + begin + with Header.PixelFormat do begin + // Compresses + if (dwFlags and DDPF_FOURCC) > 0 then begin + (* TODO + case Header.PixelFormat.dwFourCC of + D3DFMT_DXT1: result := ifDXT1; + D3DFMT_DXT3: result := ifDXT3; + D3DFMT_DXT5: result := ifDXT5; + else + raise RaiseEx; + end; + *) + raise RaiseEx; + end else - case FInternalFormat of - ifAlpha, ifLuminance, ifDepth8: - begin - ColorType := COLOR_GRAYSCALE; - PixSize := 1; - Alpha := False; - end; - ifLuminanceAlpha: - begin - ColorType := COLOR_GRAYSCALEALPHA; - PixSize := 1; - Alpha := True; - end; - ifBGR8, ifRGB8: - begin - ColorType := COLOR_RGB; - PixSize := 3; - Alpha := False; - end; - ifBGRA8, ifRGBA8: - begin - ColorType := COLOR_RGBALPHA; - PixSize := 3; - Alpha := True - end; - else - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + // RGB + if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin + case dwRGBBitCount of + 8: begin + (* TODO if dwFlags and DDPF_ALPHAPIXELS > 0 then + result := tfAlpha + else + *) + result := tfLuminance8; + end; + 16: begin + if dwFlags and DDPF_ALPHAPIXELS > 0 then begin + // Alpha + case CountSetBits(dwRBitMask) of + 5: result := tfRGB5A1; + //TODO 4: result := tfRGBA4; + else + result := tfLuminance8Alpha8; + end; + end else begin + // no Alpha + //TODO result := ifR5G6B5; + raise RaiseEx; + end; + end; + 24: begin + if dwRBitMask > dwBBitMask then + result := tfBGR8 + else + result := tfRGB8; + end; + 32: begin + if CountSetBits(dwRBitMask) = 10 then + //TODO result := tfRGB10A2 + raise RaiseEx + else + + if dwRBitMask > dwBBitMask then + result := tfBGRA8 + else + result := tfRGBA8; + end; + else + raise RaiseEx; + end; + end else + raise RaiseEx; + end; end; - Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height); - try - // Copy ImageData - pSource := Data; - for Y := 0 to Height -1 do begin - pDest := png.ScanLine[Y]; +begin + result := false; - for X := 0 to Width -1 do begin - Move(pSource^, pDest^, PixSize); + // Header + StreamPos := aStream.Position; + aStream.Read(Header, sizeof(Header)); - Inc(pDest, PixSize); - Inc(pSource, PixSize); + 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 + aStream.Position := StreamPos; + exit; + end; - if Alpha then begin - png.AlphaScanline[Y]^[X] := pSource^; - Inc(pSource); - end; - end; + ddsFormat := GetDDSFormat; + LineSize := Trunc(Header.dwWidth * FORMAT_DESCRIPTORS[ddsFormat].GetSize); + GetMem(NewImage, Header.dwHeight * LineSize); + try + pData := NewImage; - // convert RGB line to BGR - if InternalFormat in [ifRGB8, ifRGBA8] then begin - pTemp := png.ScanLine[Y]; + // Compressed + 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); + end; + end else - for X := 0 to Width -1 do begin - Temp := pByteArray(pTemp)^[0]; - pByteArray(pTemp)^[0] := pByteArray(pTemp)^[2]; - pByteArray(pTemp)^[2] := Temp; + // RGB(A) + if (Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS)) > 0 then begin + RowSize := Header.dwPitchOrLinearSize; - Inc(pTemp, 3); - end; + for Y := 0 to Header.dwHeight -1 do begin + aStream.Read(pData^, RowSize); + Inc(pData, LineSize); end; - end; + end else + raise RaiseEx; - // Save to Stream - Png.CompressionLevel := 6; - Png.SaveToStream(Stream); - finally - FreeAndNil(Png); + SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); + result := true; + except + FreeMem(NewImage); + raise; end; end; -{$ENDIF} -{$ENDIF} - -procedure TglBitmap.SaveDDS(Stream: TStream); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveDDS(const aStream: TStream); var Header: TDDSHeader; Pix: TglBitmapPixelData; begin - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_INTERNAL_FORMAT); + //if not FormatIsUncompressed(InternalFormat) then + // raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT); - if InternalFormat = ifAlpha then - FormatPreparePixel(Pix, ifLuminance) - else - FormatPreparePixel(Pix, InternalFormat); + (* TODO if Format = tfAlpha8 then + FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix); + else *) + FORMAT_DESCRIPTORS[Format].PreparePixel(Pix); // Generell FillChar(Header, SizeOf(Header), 0); - Header.dwMagic := DDS_MAGIC; - Header.dwSize := 124; + Header.dwSize := 124; Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT; if Width > 0 then begin @@ -4937,1255 +5878,289 @@ begin Header.dwFlags := Header.dwFlags or DDSD_HEIGHT; end; - Header.dwPitchOrLinearSize := fRowSize; - Header.dwMipMapCount := 1; - - // Caps - Header.Caps.dwCaps1 := DDSCAPS_TEXTURE; - - // Pixelformat - Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat); - Header.PixelFormat.dwFlags := DDPF_RGB; - - if FormatHasAlpha(InternalFormat) and (InternalFormat <> ifAlpha) - then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS; - - Header.PixelFormat.dwRGBBitCount := Trunc(FormatGetSize(InternalFormat) * 8); - Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift; - Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift; - Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift; - Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift; - - // Write - Stream.Write(Header, SizeOf(Header)); - - Stream.Write(Data^, FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat)); -end; - - -procedure TglBitmap.SaveTGA(Stream: TStream); -var - Header: TTGAHeader; - Size: Integer; - pTemp: pByte; - - - procedure ConvertData(pTemp: pByte); - var - Idx, PixelSize: Integer; - Temp: byte; - begin - PixelSize := fPixelSize; - - for Idx := 1 to Height * Width do begin - Temp := pByteArray(pTemp)^[2]; - pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0]; - pByteArray(pTemp)^[0] := Temp; - - Inc(pTemp, PixelSize); - end; - end; - - -begin - if not (ftTGA in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); - - FillChar(Header, SizeOf(Header), 0); - - case InternalFormat of - ifAlpha, ifLuminance, ifDepth8: - begin - Header.ImageType := TGA_UNCOMPRESSED_GRAY; - Header.Bpp := 8; - end; - ifLuminanceAlpha: - begin - Header.ImageType := TGA_UNCOMPRESSED_GRAY; - Header.Bpp := 16; - end; - tfRGB8, ifBGR8: - begin - Header.ImageType := TGA_UNCOMPRESSED_RGB; - Header.Bpp := 24; - end; - tfRGBA8, ifBGRA8: - begin - Header.ImageType := TGA_UNCOMPRESSED_RGB; - Header.Bpp := 32; - end; - else - raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; - - Header.Width := Width; - Header.Height := Height; - Header.ImageDes := $20; - - if FormatHasAlpha(InternalFormat) then - Header.ImageDes := Header.ImageDes or $08; - - Stream.Write(Header, SizeOf(Header)); - - // convert RGB(A) to BGR(A) - Size := FormatGetImageSize(glBitmapPosition(Width, Height), InternalFormat); - if InternalFormat in [tfRGB8, tfRGBA8] then begin - GetMem(pTemp, Size); - end else - pTemp := Data; - - try - // convert data - if InternalFormat in [tfRGB8, tfRGBA8] then begin - Move(Data^, pTemp^, Size); - ConvertData(pTemp); - end; - - // write data - Stream.Write(pTemp^, Size); - finally - // free tempdata - if InternalFormat in [tfRGB8, tfRGBA8] then - FreeMem(pTemp); - end; -end; - - -{$IFDEF GLB_SUPPORT_JPEG_WRITE} -procedure TglBitmap.SaveJPEG(Stream: TStream); -{$IFDEF GLB_LIB_JPEG} -var - jpeg: jpeg_compress_struct; - jpeg_err: jpeg_error_mgr; - Row: Integer; - pTemp, pTemp2: pByte; - - - procedure CopyRow(pDest, pSource: pByte); - var - X: Integer; - begin - for X := 0 to Width - 1 do begin - pByteArray(pDest)^[0] := pByteArray(pSource)^[2]; - pByteArray(pDest)^[1] := pByteArray(pSource)^[1]; - pByteArray(pDest)^[2] := pByteArray(pSource)^[0]; - - Inc(pDest, 3); - Inc(pSource, 3); - end; - end; - -begin - if not (ftJPEG in FormatGetSupportedFiles(InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); - - if not init_libJPEG then - raise Exception.Create('SaveJPG - unable to initialize libJPEG.'); - - try - FillChar(jpeg, SizeOf(jpeg_compress_struct), $00); - FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); - - // error managment - jpeg.err := jpeg_std_error(@jpeg_err); - jpeg_err.error_exit := glBitmap_libJPEG_error_exit; - jpeg_err.output_message := glBitmap_libJPEG_output_message; - - // compression struct - jpeg_create_compress(@jpeg); - - // allocation space for streaming methods - jpeg.dest := jpeg.mem^.alloc_small(@jpeg, JPOOL_PERMANENT, SizeOf(glBitmap_libJPEG_dest_mgr)); - - // seeting up custom functions - with glBitmap_libJPEG_dest_mgr_ptr(jpeg.dest)^ do begin - pub.init_destination := glBitmap_libJPEG_init_destination; - pub.empty_output_buffer := glBitmap_libJPEG_empty_output_buffer; - pub.term_destination := glBitmap_libJPEG_term_destination; - - pub.next_output_byte := @DestBuffer[1]; - pub.free_in_buffer := Length(DestBuffer); - - DestStream := Stream; - end; - - // very important state - jpeg.global_state := CSTATE_START; - - jpeg.image_width := Width; - jpeg.image_height := Height; - case InternalFormat of - ifAlpha, ifLuminance, ifDepth8: - begin - jpeg.input_components := 1; - jpeg.in_color_space := JCS_GRAYSCALE; - end; - ifRGB8, ifBGR8: - begin - jpeg.input_components := 3; - jpeg.in_color_space := JCS_RGB; - end; - end; - - // setting defaults - jpeg_set_defaults(@jpeg); - - // compression quality - jpeg_set_quality(@jpeg, 95, True); - - // start compression - jpeg_start_compress(@jpeg, true); - - // write rows - pTemp := Data; - - // initialing row - if InternalFormat = ifBGR8 then - GetMem(pTemp2, fRowSize) - else - pTemp2 := pTemp; - - try - for Row := 0 to jpeg.image_height -1 do begin - // prepare row - if InternalFormat = ifBGR8 then - CopyRow(pTemp2, pTemp) - else - pTemp2 := pTemp; - - // write row - jpeg_write_scanlines(@jpeg, @pTemp2, 1); - inc(pTemp, fRowSize); - end; - finally - // free memory - if InternalFormat = ifBGR8 then - FreeMem(pTemp2); - end; - - // finish compression - jpeg_finish_compress(@jpeg); - - // destroy compression - jpeg_destroy_compress(@jpeg); - finally - quit_libJPEG; - end; -end; -{$ENDIF} -{$IFDEF GLB_DELPHI_JPEG} -var - Bmp: TBitmap; - Jpg: TJPEGImage; -begin - if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); - - Bmp := TBitmap.Create; - try - Jpg := TJPEGImage.Create; - try - AssignToBitmap(Bmp); - - if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin - Jpg.Grayscale := True; - Jpg.PixelFormat := jf8Bit; - end; - - Jpg.Assign(Bmp); - - Jpg.SaveToStream(Stream); - finally - FreeAndNil(Jpg); - end; - finally - FreeAndNil(Bmp); - end; -end; -{$ENDIF} -{$ENDIF} - - -procedure TglBitmap.SaveBMP(Stream: TStream); -var - Header: TBMPHeader; - Info: TBMPInfo; - pData, pTemp: pByte; - - PixelFormat: TglBitmapPixelData; - ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer; - Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; - - PaddingBuff: Cardinal; - - - function GetLineWidth : Integer; - begin - Result := ((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3; - end; - - -begin - if not (ftBMP in FormatGetSupportedFiles(InternalFormat)) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); - - ImageSize := Trunc(Width * Height * FormatGetSize(InternalFormat)); - - Header.bfType := BMP_MAGIC; - Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; - Header.bfReserved1 := 0; - Header.bfReserved2 := 0; - Header.bfOffBits := SizeOf(Header) + SizeOf(Info); - - FillChar(Info, SizeOf(Info), 0); - Info.biSize := SizeOf(Info); - Info.biWidth := Width; - Info.biHeight := Height; - Info.biPlanes := 1; - Info.biCompression := BMP_COMP_RGB; - Info.biSizeImage := ImageSize; - case InternalFormat of - ifAlpha, ifLuminance, ifDepth8: - begin - Info.biBitCount := 8; - - Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); - Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); - - Info.biClrUsed := 256; - Info.biClrImportant := 256; - end; - ifLuminanceAlpha, tfRGBA4, ifR5G6B5, tfRGB5A1: - begin - Info.biBitCount := 16; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - ifBGR8, tfRGB8: - Info.biBitCount := 24; - ifBGRA8, tfRGBA8, tfRGB10A2: - begin - Info.biBitCount := 32; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - else - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_INTERNAL_FORMAT); - end; - Info.biXPelsPerMeter := 2835; - Info.biYPelsPerMeter := 2835; - - // prepare bitmasks - if Info.biCompression = BMP_COMP_BITFIELDS then begin - Info.biSize := Info.biSize + 4 * SizeOf(Cardinal); - Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); - Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); - - FormatPreparePixel(PixelFormat, InternalFormat); - - with PixelFormat.PixelDesc do begin - RedMask := RedRange shl RedShift; - GreenMask := GreenRange shl GreenShift; - BlueMask := BlueRange shl BlueShift; - AlphaMask := AlphaRange shl AlphaShift; - end; - end; - - // headers - Stream.Write(Header, SizeOf(Header)); - Stream.Write(Info, SizeOf(Info)); - - // colortable - if Info.biBitCount = 8 then begin - Temp := 0; - for ColorIdx := Low(Byte) to High(Byte) do begin - Stream.Write(Temp, 4); - Temp := Temp + $00010101; - end; - end; - - // bitmasks - if Info.biCompression = BMP_COMP_BITFIELDS then begin - Stream.Write(RedMask, SizeOf(Cardinal)); - Stream.Write(GreenMask, SizeOf(Cardinal)); - Stream.Write(BlueMask, SizeOf(Cardinal)); - Stream.Write(AlphaMask, SizeOf(Cardinal)); - end; - - // image data - LineSize := Trunc(Width * FormatGetSize(InternalFormat)); - Padding := GetLineWidth - LineSize; - PaddingBuff := 0; - - pData := Data; - Inc(pData, (Height -1) * LineSize); - - // prepare row buffer. But only for RGB because RGBA supports color masks - // so it's possible to change color within the image. - if InternalFormat = tfRGB8 then - GetMem(pTemp, fRowSize) - else - pTemp := nil; - - try - // write image data - for LineIdx := 0 to Height - 1 do begin - // preparing row - if InternalFormat = tfRGB8 then begin - Move(pData^, pTemp^, fRowSize); - SwapRGB(pTemp, Width, False); - end else - pTemp := pData; - - Stream.Write(pTemp^, LineSize); - - Dec(pData, LineSize); - - if Padding > 0 then - Stream.Write(PaddingBuff, Padding); - end; - finally - // destroy row buffer - if InternalFormat = tfRGB8 then - FreeMem(pTemp); - end; -end; - - -procedure TglBitmap.Bind(EnableTextureUnit: Boolean); -begin - if EnableTextureUnit then - glEnable(Target); - - if ID > 0 then - glBindTexture(Target, ID); -end; - - -procedure TglBitmap.Unbind(DisableTextureUnit: Boolean); -begin - if DisableTextureUnit then - glDisable(Target); - - glBindTexture(Target, 0); -end; - - -procedure TglBitmap.GetPixel(const Pos: TglBitmapPixelPosition; - var Pixel: TglBitmapPixelData); -begin - if Assigned (fGetPixelFunc) then - fGetPixelFunc(Pos, Pixel); -end; - - -procedure TglBitmap.SetPixel (const Pos: TglBitmapPixelPosition; - const Pixel: TglBitmapPixelData); -begin - if Assigned (fSetPixelFunc) then - fSetPixelFunc(Pos, Pixel); -end; - - - - - - -function TglBitmap.FlipHorz: Boolean; -begin - Result := False; -end; - - -function TglBitmap.FlipVert: Boolean; -begin - Result := False; -end; - - -procedure TglBitmap.FreeData; -begin - SetDataPointer(nil, ifEmpty); -end; - - -procedure glBitmapFillWithColorFunc(var FuncRec: TglBitmapFunctionRec); -type - PglBitmapPixelData = ^TglBitmapPixelData; -begin - with FuncRec do begin - Dest.Red := PglBitmapPixelData(CustomData)^.Red; - Dest.Green := PglBitmapPixelData(CustomData)^.Green; - Dest.Blue := PglBitmapPixelData(CustomData)^.Blue; - Dest.Alpha := PglBitmapPixelData(CustomData)^.Alpha; - end; -end; - - -procedure TglBitmap.FillWithColor(Red, Green, Blue: Byte; Alpha: Byte); -begin - FillWithColorFloat(Red / $FF, Green / $FF, Blue / $FF, Alpha / $FF); -end; - - -procedure TglBitmap.FillWithColorFloat(Red, Green, Blue: Single; Alpha: Single); -var - PixelData: TglBitmapPixelData; -begin - FormatPreparePixel(PixelData, InternalFormat); - - PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * Red))); - PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * Green))); - PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * Blue))); - PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * Alpha))); - - AddFunc(glBitmapFillWithColorFunc, False, @PixelData); -end; - - -procedure TglBitmap.FillWithColorRange(Red, Green, Blue: Cardinal; - Alpha: Cardinal); -var - PixelData: TglBitmapPixelData; -begin - FormatPreparePixel(PixelData, FormatGetWithAlpha(InternalFormat)); - - FillWithColorFloat( - Red / PixelData.PixelDesc.RedRange, - Green / PixelData.PixelDesc.GreenRange, - Blue / PixelData.PixelDesc.BlueRange, - Alpha / PixelData.PixelDesc.AlphaRange); -end; - - - -procedure TglBitmap.SetInternalFormat(const aValue: TglBitmapFormat); -begin - if InternalFormat <> Value then begin - if FormatGetSize(Value) <> FormatGetSize(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_INTERNAL_FORMAT); - - // Update whatever - SetDataPointer(Data, Value); - end; -end; - - -function TglBitmap.AddFunc(Func: TglBitmapFunction; CreateTemp: Boolean; - CustomData: Pointer): boolean; -begin - Result := AddFunc(Self, Func, CreateTemp, InternalFormat, CustomData); -end; - - -function TglBitmap.AddFunc(Source: TglBitmap; Func: TglBitmapFunction; - CreateTemp: Boolean; Format: TglBitmapFormat; CustomData: Pointer): boolean; -var - pDest, NewImage, pSource: pByte; - TempHeight, TempWidth: Integer; - MapFunc: TglBitmapMapFunc; - UnMapFunc: TglBitmapUnMapFunc; - - FuncRec: TglBitmapFunctionRec; -begin - Assert(Assigned(Data)); - Assert(Assigned(Source)); - Assert(Assigned(Source.Data)); - - Result := False; - - if Assigned (Source.Data) and FormatIsUncompressed(Format) and - ((Source.Height > 0) or (Source.Width > 0)) then begin - - // inkompatible Formats so CreateTemp - if FormatGetSize(Format) <> FormatGetSize(InternalFormat) then - CreateTemp := True; - - // Values - TempHeight := Max(1, Source.Height); - TempWidth := Max(1, Source.Width); - - FuncRec.Sender := Self; - FuncRec.CustomData := CustomData; - - NewImage := nil; - - if CreateTemp then begin - GetMem(NewImage, Trunc(FormatGetSize(Format) * TempHeight * TempWidth)); - pDest := NewImage; - end - else pDest := Data; - - try - // Mapping - MapFunc := FormatGetMapFunc(Format); - FormatPreparePixel(FuncRec.Dest, Format); - FormatPreparePixel(FuncRec.Source, Source.InternalFormat); - - FuncRec.Size := Source.Dimension; - FuncRec.Position.Fields := FuncRec.Size.Fields; - - if FormatIsUncompressed(Source.InternalFormat) then begin - // Uncompressed Images - pSource := Source.Data; - UnMapFunc := FormatGetUnMapFunc(Source.InternalFormat); - - FuncRec.Position.Y := 0; - while FuncRec.Position.Y < TempHeight do begin - FuncRec.Position.X := 0; - while FuncRec.Position.X < TempWidth do begin - // Get Data - UnMapFunc(pSource, FuncRec.Source); - // Func - Func(FuncRec); - // Set Data - MapFunc(FuncRec.Dest, pDest); - Inc(FuncRec.Position.X); - end; - Inc(FuncRec.Position.Y); - end; - end else begin - // Compressed Images - FuncRec.Position.Y := 0; - while FuncRec.Position.Y < TempHeight do begin - FuncRec.Position.X := 0; - while FuncRec.Position.X < TempWidth do begin - // Get Data - fGetPixelFunc(FuncRec.Position, FuncRec.Source); - // Func - Func(FuncRec); - // Set Data - MapFunc(FuncRec.Dest, pDest); - Inc(FuncRec.Position.X); - end; - Inc(FuncRec.Position.Y); - end; - end; - - // Updating Image or InternalFormat - if CreateTemp then - SetDataPointer(NewImage, Format) - else - - if Format <> InternalFormat then - SetInternalFormat(Format); - - Result := True; - except - if CreateTemp - then FreeMem(NewImage); - raise; - end; - end; -end; - - -procedure glBitmapConvertCopyFunc(var FuncRec: TglBitmapFunctionRec); -begin - with FuncRec do begin - if Source.PixelDesc.RedRange > 0 then - Dest.Red := Source.Red; - - if Source.PixelDesc.GreenRange > 0 then - Dest.Green := Source.Green; - - if Source.PixelDesc.BlueRange > 0 then - Dest.Blue := Source.Blue; - - if Source.PixelDesc.AlphaRange > 0 then - Dest.Alpha := Source.Alpha; - end; -end; - - -procedure glBitmapConvertCalculateRGBAFunc(var FuncRec: TglBitmapFunctionRec); -begin - with FuncRec do begin - if Source.PixelDesc.RedRange > 0 then - Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange); - - if Source.PixelDesc.GreenRange > 0 then - Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange); - - if Source.PixelDesc.BlueRange > 0 then - Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange); - - if Source.PixelDesc.AlphaRange > 0 then - Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange); - end; -end; - - -procedure glBitmapConvertShiftRGBAFunc(var FuncRec: TglBitmapFunctionRec); -begin - with FuncRec do - with TglBitmapPixelDesc(CustomData^) do begin - if Source.PixelDesc.RedRange > 0 then - Dest.Red := Source.Red shr RedShift; - - if Source.PixelDesc.GreenRange > 0 then - Dest.Green := Source.Green shr GreenShift; - - if Source.PixelDesc.BlueRange > 0 then - Dest.Blue := Source.Blue shr BlueShift; - - if Source.PixelDesc.AlphaRange > 0 then - Dest.Alpha := Source.Alpha shr AlphaShift; - end; -end; - - -function TglBitmap.ConvertTo(NewFormat: TglBitmapFormat): boolean; -var - Source, Dest: TglBitmapPixelData; - PixelDesc: TglBitmapPixelDesc; - - function CopyDirect: Boolean; - begin - Result := - ((Source.PixelDesc.RedRange = Dest.PixelDesc.RedRange) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and - ((Source.PixelDesc.GreenRange = Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and - ((Source.PixelDesc.BlueRange = Dest.PixelDesc.BlueRange) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and - ((Source.PixelDesc.AlphaRange = Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0)); - end; - - function CanShift: Boolean; - begin - Result := - ((Source.PixelDesc.RedRange >= Dest.PixelDesc.RedRange ) or (Source.PixelDesc.RedRange = 0) or (Dest.PixelDesc.RedRange = 0)) and - ((Source.PixelDesc.GreenRange >= Dest.PixelDesc.GreenRange) or (Source.PixelDesc.GreenRange = 0) or (Dest.PixelDesc.GreenRange = 0)) and - ((Source.PixelDesc.BlueRange >= Dest.PixelDesc.BlueRange ) or (Source.PixelDesc.BlueRange = 0) or (Dest.PixelDesc.BlueRange = 0)) and - ((Source.PixelDesc.AlphaRange >= Dest.PixelDesc.AlphaRange) or (Source.PixelDesc.AlphaRange = 0) or (Dest.PixelDesc.AlphaRange = 0)); - end; - - function GetShift(Source, Dest: Cardinal) : ShortInt; - begin - Result := 0; - - while (Source > Dest) and (Source > 0) do begin - Inc(Result); - Source := Source shr 1; - end; - end; - -begin - if NewFormat <> InternalFormat then begin - FormatPreparePixel(Source, InternalFormat); - FormatPreparePixel(Dest, NewFormat); - - if CopyDirect then - Result := AddFunc(Self, glBitmapConvertCopyFunc, False, NewFormat) - else - if CanShift then begin - PixelDesc.RedShift := GetShift(Source.PixelDesc.RedRange, Dest.PixelDesc.RedRange); - PixelDesc.GreenShift := GetShift(Source.PixelDesc.GreenRange, Dest.PixelDesc.GreenRange); - PixelDesc.BlueShift := GetShift(Source.PixelDesc.BlueRange, Dest.PixelDesc.BlueRange); - PixelDesc.AlphaShift := GetShift(Source.PixelDesc.AlphaRange, Dest.PixelDesc.AlphaRange); - - Result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, False, NewFormat, @PixelDesc); - end - else Result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, False, NewFormat); - end - else Result := True; -end; - - -function TglBitmap.RemoveAlpha: Boolean; -begin - Result := False; - - if (Assigned(Data)) then begin - if not (FormatIsUncompressed(InternalFormat) or FormatHasAlpha(InternalFormat)) then - raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_INTERNAL_FORMAT); - - Result := ConvertTo(FormatGetWithoutAlpha(InternalFormat)); - end; -end; - - -function TglBitmap.AddAlphaFromFunc(Func: TglBitmapFunction; CustomData: Pointer): boolean; -begin - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_INTERNAL_FORMAT); - - Result := AddFunc(Self, Func, False, FormatGetWithAlpha(InternalFormat), CustomData); -end; - - -function TglBitmap.GetFileHeight: Integer; -begin - Result := Max(1, Height); -end; - - -function TglBitmap.GetFileWidth: Integer; -begin - Result := Max(1, Width); -end; - - -procedure glBitmapAlphaFunc(var FuncRec: TglBitmapFunctionRec); -var - Temp: Single; -begin - with FuncRec do begin - Temp := - Source.Red / Source.PixelDesc.RedRange * 0.3 + - Source.Green / Source.PixelDesc.GreenRange * 0.59 + - Source.Blue / Source.PixelDesc.BlueRange * 0.11; - - Dest.Alpha := Round (Dest.PixelDesc.AlphaRange * Temp); - end; -end; - - -function TglBitmap.AddAlphaFromglBitmap(glBitmap: TglBitmap; Func: TglBitmapFunction; CustomData: Pointer): boolean; -var - pDest, pDest2, pSource: pByte; - TempHeight, TempWidth: Integer; - MapFunc: TglBitmapMapFunc; - DestUnMapFunc, UnMapFunc: TglBitmapUnMapFunc; - - FuncRec: TglBitmapFunctionRec; -begin - Result := False; - - assert(Assigned(Data)); - assert(Assigned(glBitmap)); - assert(Assigned(glBitmap.Data)); - - if ((glBitmap.Width = Width) and (glBitmap.Height = Height)) then begin - // Convert to Data with Alpha - Result := ConvertTo(FormatGetWithAlpha(FormatGetUncompressed(InternalFormat))); - - if not Assigned(Func) then - Func := glBitmapAlphaFunc; - - // Values - TempHeight := glBitmap.FileHeight; - TempWidth := glBitmap.FileWidth; - - FuncRec.Sender := Self; - FuncRec.CustomData := CustomData; - - pDest := Data; - pDest2 := Data; - pSource := glBitmap.Data; - - // Mapping - FormatPreparePixel(FuncRec.Dest, InternalFormat); - FormatPreparePixel(FuncRec.Source, glBitmap.InternalFormat); - MapFunc := FormatGetMapFunc(InternalFormat); - DestUnMapFunc := FormatGetUnMapFunc(InternalFormat); - UnMapFunc := FormatGetUnMapFunc(glBitmap.InternalFormat); - - FuncRec.Size := Dimension; - FuncRec.Position.Fields := FuncRec.Size.Fields; - - FuncRec.Position.Y := 0; - while FuncRec.Position.Y < TempHeight do begin - FuncRec.Position.X := 0; - while FuncRec.Position.X < TempWidth do begin - // Get Data - UnMapFunc(pSource, FuncRec.Source); - DestUnMapFunc(pDest2, FuncRec.Dest); - // Func - Func(FuncRec); - // Set Data - MapFunc(FuncRec.Dest, pDest); - Inc(FuncRec.Position.X); - end; - Inc(FuncRec.Position.Y); - end; - end; -end; - - -procedure TglBitmap.SetBorderColor(Red, Green, Blue, Alpha: Single); -begin - fBorderColor[0] := Red; - fBorderColor[1] := Green; - fBorderColor[2] := Blue; - fBorderColor[3] := Alpha; - - if ID > 0 then begin - Bind (False); - - glTexParameterfv(Target, GL_TEXTURE_BORDER_COLOR, @fBorderColor[0]); - end; -end; - - -{ TglBitmap2D } - -procedure TglBitmap2D.SetDataPointer(Data: pByte; Format: TglBitmapFormat; Width, Height: Integer); -var - Idx, LineWidth: Integer; -begin - inherited; - - // Format - if FormatIsUncompressed(Format) then begin - fUnmapFunc := FormatGetUnMapFunc(Format); - fGetPixelFunc := GetPixel2DUnmap; - - fMapFunc := FormatGetMapFunc(Format); - fSetPixelFunc := SetPixel2DUnmap; - - // Assigning Data - if Assigned(Data) then begin - SetLength(fLines, GetHeight); - - LineWidth := Trunc(GetWidth * FormatGetSize(InternalFormat)); - - for Idx := 0 to GetHeight -1 do begin - fLines[Idx] := Data; - Inc(fLines[Idx], Idx * LineWidth); - end; - end - else SetLength(fLines, 0); - end else begin - SetLength(fLines, 0); - - fSetPixelFunc := nil; - - case Format of - ifDXT1: - fGetPixelFunc := GetPixel2DDXT1; - ifDXT3: - fGetPixelFunc := GetPixel2DDXT3; - ifDXT5: - fGetPixelFunc := GetPixel2DDXT5; - else - fGetPixelFunc := nil; - end; - end; -end; - - -procedure TglBitmap2D.GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData); -type - PDXT1Chunk = ^TDXT1Chunk; - TDXT1Chunk = packed record - Color1: WORD; - Color2: WORD; - Pixels: array [0..3] of byte; - end; - -var - BasePtr: pDXT1Chunk; - PixPos: Integer; - Colors: array [0..3] of TRGBQuad; -begin - BasePtr := pDXT1Chunk(pData); - - PixPos := BasePtr^.Pixels[relY] shr (relX * 2) and $3; - - if PixPos in [0, 2, 3] then begin - Colors[0].rgbRed := BasePtr^.Color1 and $F800 shr 8; - Colors[0].rgbGreen := BasePtr^.Color1 and $07E0 shr 3; - Colors[0].rgbBlue := BasePtr^.Color1 and $001F shl 3; - Colors[0].rgbReserved := 255; - end; - - if PixPos in [1, 2, 3] then begin - Colors[1].rgbRed := BasePtr^.Color2 and $F800 shr 8; - Colors[1].rgbGreen := BasePtr^.Color2 and $07E0 shr 3; - Colors[1].rgbBlue := BasePtr^.Color2 and $001F shl 3; - Colors[1].rgbReserved := 255; - end; - - if PixPos = 2 then begin - Colors[2].rgbRed := (Colors[0].rgbRed * 67 + Colors[1].rgbRed * 33) div 100; - Colors[2].rgbGreen := (Colors[0].rgbGreen * 67 + Colors[1].rgbGreen * 33) div 100; - Colors[2].rgbBlue := (Colors[0].rgbBlue * 67 + Colors[1].rgbBlue * 33) div 100; - Colors[2].rgbReserved := 255; - end; - - if PixPos = 3 then begin - Colors[3].rgbRed := (Colors[0].rgbRed * 33 + Colors[1].rgbRed * 67) div 100; - Colors[3].rgbGreen := (Colors[0].rgbGreen * 33 + Colors[1].rgbGreen * 67) div 100; - Colors[3].rgbBlue := (Colors[0].rgbBlue * 33 + Colors[1].rgbBlue * 67) div 100; - if BasePtr^.Color1 > BasePtr^.Color2 then - Colors[3].rgbReserved := 255 - else - Colors[3].rgbReserved := 0; - end; - - Pixel.Red := Colors[PixPos].rgbRed; - Pixel.Green := Colors[PixPos].rgbGreen; - Pixel.Blue := Colors[PixPos].rgbBlue; - Pixel.Alpha := Colors[PixPos].rgbReserved; -end; - - -procedure TglBitmap2D.GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); -var - BasePtr: pByte; - PosX, PosY: Integer; -begin - inherited; - - if (Pos.Y <= Height) and (Pos.X <= Width) then begin - PosX := Pos.X div 4; - PosY := Pos.Y div 4; - - BasePtr := Data; - Inc(BasePtr, (PosY * Width div 4 + PosX) * 8); - - GetDXTColorBlock(BasePtr, Pos.X - PosX * 4, Pos.Y - PosY * 4, Pixel); - end; -end; - - -procedure TglBitmap2D.GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); -type - PDXT3AlphaChunk = ^TDXT3AlphaChunk; - TDXT3AlphaChunk = array [0..3] of WORD; - -var - ColorPtr: pByte; - AlphaPtr: PDXT3AlphaChunk; - PosX, PosY, relX, relY: Integer; -begin - inherited; - - if (Pos.Y <= Height) and (Pos.X <= Width) then begin - PosX := Pos.X div 4; - PosY := Pos.Y div 4; - relX := Pos.X - PosX * 4; - relY := Pos.Y - PosY * 4; - - // get color value - AlphaPtr := PDXT3AlphaChunk(Data); - Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2); - - ColorPtr := pByte(AlphaPtr); - Inc(ColorPtr, 8); - - GetDXTColorBlock(ColorPtr, relX, relY, Pixel); - - // extracting alpha - Pixel.Alpha := AlphaPtr^[relY] shr (4 * relX) and $0F shl 4; - end; -end; - - -procedure TglBitmap2D.GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); -var - ColorPtr: pByte; - AlphaPtr: PInt64; - PixPos, PosX, PosY, relX, relY: Integer; - Alpha0, Alpha1: Byte; -begin - inherited; - - if (Pos.Y <= Height) and (Pos.X <= Width) then begin - PosX := Pos.X div 4; - PosY := Pos.Y div 4; - relX := Pos.X - PosX * 4; - relY := Pos.Y - PosY * 4; - - // get color value - AlphaPtr := PInt64(Data); - Inc(AlphaPtr, (PosY * Width div 4 + PosX) * 2); - - ColorPtr := pByte(AlphaPtr); - Inc(ColorPtr, 8); - - GetDXTColorBlock(ColorPtr, relX, relY, Pixel); - - // extracting alpha - Alpha0 := AlphaPtr^ and $FF; - Alpha1 := AlphaPtr^ shr 8 and $FF; - - PixPos := AlphaPtr^ shr (16 + (relY * 4 + relX) * 3) and $07; - - // use alpha 0 - if PixPos = 0 then begin - Pixel.Alpha := Alpha0; - end else - - // use alpha 1 - if PixPos = 1 then begin - Pixel.Alpha := Alpha1; - end else - - // alpha interpolate 7 Steps - if Alpha0 > Alpha1 then begin - Pixel.Alpha := ((8 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 7; - end else - - // alpha is 100% transparent or not transparent - if PixPos >= 6 then begin - if PixPos = 6 then - Pixel.Alpha := 0 - else - Pixel.Alpha := 255; - end else - - // alpha interpolate 5 Steps - begin - Pixel.Alpha := ((6 - PixPos) * Alpha0 + (PixPos - 1) * Alpha1) div 5; - end; - end; -end; - - -procedure TglBitmap2D.GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); -var - pTemp: pByte; -begin - pTemp := fLines[Pos.Y]; - Inc(pTemp, Pos.X * fPixelSize); - - fUnmapFunc(pTemp, Pixel); -end; - - -procedure TglBitmap2D.SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); -var - pTemp: pByte; -begin - pTemp := fLines[Pos.Y]; - Inc(pTemp, Pos.X * fPixelSize); - - fMapFunc(Pixel, pTemp); -end; - - -function TglBitmap2D.FlipHorz: Boolean; -var - Col, Row: Integer; - pTempDest, pDest, pSource: pByte; - ImgSize: Integer; -begin - Result := Inherited FlipHorz; - - if Assigned(Data) then begin - pSource := Data; - ImgSize := Height * fRowSize; + Header.dwPitchOrLinearSize := fRowSize; + Header.dwMipMapCount := 1; - GetMem(pDest, ImgSize); - try - pTempDest := pDest; + // Caps + Header.Caps.dwCaps1 := DDSCAPS_TEXTURE; - Dec(pTempDest, fRowSize + fPixelSize); - for Row := 0 to Height -1 do begin - Inc(pTempDest, fRowSize * 2); - for Col := 0 to Width -1 do begin - Move(pSource^, pTempDest^, fPixelSize); + // Pixelformat + Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat); + Header.PixelFormat.dwFlags := DDPF_RGB; - Inc(pSource, fPixelSize); - Dec(pTempDest, fPixelSize); - end; - end; + (* TODO tfAlpha8 + if FORMAT_DESCRIPTORS[Format].HasAlpha and (Format <> tfAlpha8) then + Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS; + *) - SetDataPointer(pDest, InternalFormat); + Header.PixelFormat.dwRGBBitCount := Trunc(FORMAT_DESCRIPTORS[Format].GetSize * 8); + Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift; + Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift; + Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift; + Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift; - Result := True; - except - FreeMem(pDest); - raise; - end; - end; + aStream.Write(Header, SizeOf(Header)); + aStream.Write(Data^, FORMAT_DESCRIPTORS[Format].GetSize(Dimension)); end; +{$ENDREGION} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap2D///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap2D.GetScanline(const aIndex: Integer): Pointer; +begin + if (aIndex >= Low(fLines)) and (aIndex <= High(fLines)) then + result := fLines[aIndex] + else + result := nil; +end; -function TglBitmap2D.FlipVert: Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer; const aHeight: Integer); var - Row: Integer; - pTempDest, pDest, pSource: pByte; + Idx, LineWidth: Integer; begin - Result := Inherited FlipVert; - - if Assigned(Data) then begin - pSource := Data; - GetMem(pDest, Height * fRowSize); - try - pTempDest := pDest; - - Inc(pTempDest, Width * (Height -1) * fPixelSize); + inherited SetDataPointer(aData, aFormat, aWidth, aHeight); - for Row := 0 to Height -1 do begin - Move(pSource^, pTempDest^, fRowSize); + //TODO compression + if {FormatIsUncompressed(Format)} true then begin + (* TODO PixelFuncs + fGetPixelFunc := GetPixel2DUnmap; + fSetPixelFunc := SetPixel2DUnmap; + *) + // Assigning Data + if Assigned(Data) then begin + SetLength(fLines, GetHeight); + LineWidth := Trunc(GetWidth * FORMAT_DESCRIPTORS[Format].GetSize); - Dec(pTempDest, fRowSize); - Inc(pSource, fRowSize); + for Idx := 0 to GetHeight -1 do begin + fLines[Idx] := Data; + Inc(fLines[Idx], Idx * LineWidth); end; + end + else SetLength(fLines, 0); + end else begin + (* + SetLength(fLines, 0); - SetDataPointer(pDest, InternalFormat); + fSetPixelFunc := nil; - Result := True; - except - FreeMem(pDest); - raise; + case Format of + ifDXT1: + fGetPixelFunc := GetPixel2DDXT1; + ifDXT3: + fGetPixelFunc := GetPixel2DDXT3; + ifDXT5: + fGetPixelFunc := GetPixel2DDXT5; + else + fGetPixelFunc := nil; end; + *) end; end; - -procedure TglBitmap2D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean); +var + FormatDescriptor: TglBitmapFormatDescClass; + FormatDesc: TglBitmapFormatDesc; begin glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Upload data + (* 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 + *) - if BuildWithGlu then - gluBuild2DMipmaps(Target, InternalFormat, Width, Height, Format, Typ, Data) + FormatDescriptor := FORMAT_DESCRIPTORS[Format]; + FormatDesc := FormatDescriptor.GetFormatDesc; + if aBuildWithGlu then + gluBuild2DMipmaps(aTarget, FormatDescriptor.GetColorCompCount, Width, Height, + FormatDesc.Format, FormatDesc.DataType, Data) else - glTexImage2D(Target, 0, InternalFormat, Width, Height, 0, Format, Typ, Data); + glTexImage2D(aTarget, 0, FormatDesc.InternalFormat, Width, Height, 0, + FormatDesc.Format, FormatDesc.DataType, Data); // Freigeben if (FreeDataAfterGenTexture) then FreeData; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.AfterConstruction; +begin + inherited; + Target := GL_TEXTURE_2D; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; const aFormat: TglBitmapFormat); +var + Temp: pByte; + Size, w, h: Integer; + FormatDesc: TglBitmapFormatDescClass; + glFormatDesc: TglBitmapFormatDesc; +begin + (* TODO compression + if not FormatIsUncompressed(Format) then + raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT); + *) + + w := aRight - aLeft; + h := aBottom - aTop; + FormatDesc := FORMAT_DESCRIPTORS[Format]; + glFormatDesc := FormatDesc.GetFormatDesc; + Size := FormatDesc.GetSize(glBitmapPosition(w, h)); + GetMem(Temp, Size); + try + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(aLeft, aTop, w, h, glFormatDesc.Format, glFormatDesc.DataType, Temp); + SetDataPointer(Temp, Format, w, h); + FlipVert; + except + FreeMem(Temp); + raise; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.GetDataFromTexture; +var + Temp: PByte; + TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer; + TempType, TempIntFormat: Cardinal; + IntFormat: TglBitmapFormat; + FormatDesc: TglBitmapFormatDescClass; +begin + Bind; + + // Request Data + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); + + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize); + + IntFormat := tfEmpty; + for FormatDesc in FORMAT_DESCRIPTORS do + if (FormatDesc.GetFormatDesc.InternalFormat = TempIntFormat) then begin + IntFormat := FormatDesc.GetFormat; + break; + end; + + // Getting data from OpenGL + GetMem(Temp, FormatDesc.GetSize(glBitmapPosition(TempWidth, TempHeight))); + try + (* TODO Compression + if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then + glGetCompressedTexImage(Target, 0, Temp) + else + *) + with FormatDesc.GetFormatDesc do + glGetTexImage(Target, 0, InternalFormat, DataType, Temp); + SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); + except + FreeMem(Temp); + raise; + end; +end; -procedure TglBitmap2D.GenTexture(TestTextureSize: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.GenTexture(const aTestTextureSize: Boolean); var BuildWithGlu, PotTex, TexRec: Boolean; - glFormat, glInternalFormat, glType: Cardinal; TexSize: Integer; begin if Assigned(Data) then begin // Check Texture Size - if (TestTextureSize) then begin + if (aTestTextureSize) then begin glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); if ((Height > TexSize) or (Width > TexSize)) then raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); - PotTex := IsPowerOfTwo (Height) and IsPowerOfTwo (Width); - TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and - (Target = GL_TEXTURE_RECTANGLE_ARB); + PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width); + TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB); if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); end; CreateId; - SetupParameters(BuildWithGlu); - SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); - - UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu); - - // Infos sammeln - glAreTexturesResident(1, @ID, @fIsResident); + UploadData(Target, BuildWithGlu); + glAreTexturesResident(1, @fID, @fIsResident); end; end; - -procedure TglBitmap2D.AfterConstruction; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap2D.FlipHorz: Boolean; +var + Col, Row: Integer; + TempDestData, DestData, SourceData: PByte; + ImgSize: Integer; begin - inherited; - - Target := GL_TEXTURE_2D; + result := inherited FlipHorz; + if Assigned(Data) then begin + SourceData := Data; + ImgSize := Height * fRowSize; + GetMem(DestData, ImgSize); + try + TempDestData := DestData; + Dec(TempDestData, fRowSize + fPixelSize); + for Row := 0 to Height -1 do begin + Inc(TempDestData, fRowSize * 2); + for Col := 0 to Width -1 do begin + Move(SourceData^, TempDestData^, fPixelSize); + Inc(SourceData, fPixelSize); + Dec(TempDestData, fPixelSize); + end; + end; + SetDataPointer(DestData, Format); + result := true; + except + FreeMem(DestData); + raise; + end; + end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap2D.FlipVert: Boolean; +var + Row: Integer; + TempDestData, DestData, SourceData: PByte; +begin + result := inherited FlipVert; + if Assigned(Data) then begin + SourceData := Data; + GetMem(DestData, Height * fRowSize); + try + TempDestData := DestData; + Inc(TempDestData, Width * (Height -1) * fPixelSize); + for Row := 0 to Height -1 do begin + Move(SourceData^, TempDestData^, fRowSize); + Dec(TempDestData, fRowSize); + Inc(SourceData, fRowSize); + end; + SetDataPointer(DestData, Format); + result := true; + except + FreeMem(DestData); + raise; + end; + end; +end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap2D - ToNormalMap/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type TMatrixItem = record X, Y: Integer; @@ -6203,24 +6178,25 @@ type const oneover255 = 1 / 255; -procedure glBitmapToNormalMapPrepareFunc (var FuncRec: TglBitmapFunctionRec); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec); var Val: Single; begin with FuncRec do begin Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11; - PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255; + PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255; end; end; - -procedure glBitmapToNormalMapPrepareAlphaFunc (var FuncRec: TglBitmapFunctionRec); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec); begin with FuncRec do - PglBitmapToNormalMapRec (CustomData)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255; + PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapToNormalMapFunc (var FuncRec: TglBitmapFunctionRec); type TVec = Array[0..2] of Single; @@ -6235,14 +6211,13 @@ var with FuncRec do begin X := Max(0, Min(Size.X -1, X)); Y := Max(0, Min(Size.Y -1, Y)); - - Result := PglBitmapToNormalMapRec (CustomData)^.Heights[Y * Size.X + X]; + result := PglBitmapToNormalMapRec(Args)^.Heights[Y * Size.X + X]; end; end; begin with FuncRec do begin - with PglBitmapToNormalMapRec (CustomData)^ do begin + with PglBitmapToNormalMapRec(Args)^ do begin du := 0; for Idx := Low(MatrixU) to High(MatrixU) do du := du + GetHeight(Position.X + MatrixU[Idx].X, Position.Y + MatrixU[Idx].Y) * MatrixU[Idx].W; @@ -6271,8 +6246,8 @@ begin end; end; - -procedure TglBitmap2D.ToNormalMap(Func: TglBitmapNormalMapFunc; Scale: Single; UseAlpha: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap2D.ToNormalMap(const aFunc: TglBitmapNormalMapFunc; const aScale: Single; const aUseAlpha: Boolean); var Rec: TglBitmapToNormalMapRec; @@ -6286,253 +6261,134 @@ var end; begin + (* TODO Compression if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT); + *) - if Scale > 100 then + if aScale > 100 then Rec.Scale := 100 - else - if Scale < -100 then + else if aScale < -100 then Rec.Scale := -100 else - Rec.Scale := Scale; + Rec.Scale := aScale; SetLength(Rec.Heights, Width * Height); try - case Func of - nm4Samples: - begin - SetLength(Rec.MatrixU, 2); - SetEntry(Rec.MatrixU, 0, -1, 0, -0.5); - SetEntry(Rec.MatrixU, 1, 1, 0, 0.5); - - SetLength(Rec.MatrixV, 2); - SetEntry(Rec.MatrixV, 0, 0, 1, 0.5); - SetEntry(Rec.MatrixV, 1, 0, -1, -0.5); - end; - nmSobel: - begin - SetLength(Rec.MatrixU, 6); - SetEntry(Rec.MatrixU, 0, -1, 1, -1.0); - SetEntry(Rec.MatrixU, 1, -1, 0, -2.0); - SetEntry(Rec.MatrixU, 2, -1, -1, -1.0); - SetEntry(Rec.MatrixU, 3, 1, 1, 1.0); - SetEntry(Rec.MatrixU, 4, 1, 0, 2.0); - SetEntry(Rec.MatrixU, 5, 1, -1, 1.0); - - SetLength(Rec.MatrixV, 6); - SetEntry(Rec.MatrixV, 0, -1, 1, 1.0); - SetEntry(Rec.MatrixV, 1, 0, 1, 2.0); - SetEntry(Rec.MatrixV, 2, 1, 1, 1.0); - SetEntry(Rec.MatrixV, 3, -1, -1, -1.0); - SetEntry(Rec.MatrixV, 4, 0, -1, -2.0); - SetEntry(Rec.MatrixV, 5, 1, -1, -1.0); - end; - nm3x3: - begin - SetLength(Rec.MatrixU, 6); - SetEntry(Rec.MatrixU, 0, -1, 1, -1/6); - SetEntry(Rec.MatrixU, 1, -1, 0, -1/6); - SetEntry(Rec.MatrixU, 2, -1, -1, -1/6); - SetEntry(Rec.MatrixU, 3, 1, 1, 1/6); - SetEntry(Rec.MatrixU, 4, 1, 0, 1/6); - SetEntry(Rec.MatrixU, 5, 1, -1, 1/6); - - SetLength(Rec.MatrixV, 6); - SetEntry(Rec.MatrixV, 0, -1, 1, 1/6); - SetEntry(Rec.MatrixV, 1, 0, 1, 1/6); - SetEntry(Rec.MatrixV, 2, 1, 1, 1/6); - SetEntry(Rec.MatrixV, 3, -1, -1, -1/6); - SetEntry(Rec.MatrixV, 4, 0, -1, -1/6); - SetEntry(Rec.MatrixV, 5, 1, -1, -1/6); - end; - nm5x5: - begin - SetLength(Rec.MatrixU, 20); - SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16); - SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10); - SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10); - SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16); - SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10); - SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8); - SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8); - SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10); - SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8); - SetEntry(Rec.MatrixU, 9, -1, 0, -0.5); - SetEntry(Rec.MatrixU, 10, 1, 0, 0.5); - SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8); - SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10); - SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8); - SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8); - SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10); - SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16); - SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10); - SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10); - SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16); - - SetLength(Rec.MatrixV, 20); - SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16); - SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10); - SetEntry(Rec.MatrixV, 2, 0, 2, 0.25); - SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10); - SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16); - SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10); - SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8); - SetEntry(Rec.MatrixV, 7, 0, 1, 0.5); - SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8); - SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16); - SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16); - SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8); - SetEntry(Rec.MatrixV, 12, 0, -1, -0.5); - SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8); - SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10); - SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16); - SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10); - SetEntry(Rec.MatrixV, 17, 0, -2, -0.25); - SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10); - SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16); - end; + case aFunc of + nm4Samples: begin + SetLength(Rec.MatrixU, 2); + SetEntry(Rec.MatrixU, 0, -1, 0, -0.5); + SetEntry(Rec.MatrixU, 1, 1, 0, 0.5); + + SetLength(Rec.MatrixV, 2); + SetEntry(Rec.MatrixV, 0, 0, 1, 0.5); + SetEntry(Rec.MatrixV, 1, 0, -1, -0.5); + end; + + nmSobel: begin + SetLength(Rec.MatrixU, 6); + SetEntry(Rec.MatrixU, 0, -1, 1, -1.0); + SetEntry(Rec.MatrixU, 1, -1, 0, -2.0); + SetEntry(Rec.MatrixU, 2, -1, -1, -1.0); + SetEntry(Rec.MatrixU, 3, 1, 1, 1.0); + SetEntry(Rec.MatrixU, 4, 1, 0, 2.0); + SetEntry(Rec.MatrixU, 5, 1, -1, 1.0); + + SetLength(Rec.MatrixV, 6); + SetEntry(Rec.MatrixV, 0, -1, 1, 1.0); + SetEntry(Rec.MatrixV, 1, 0, 1, 2.0); + SetEntry(Rec.MatrixV, 2, 1, 1, 1.0); + SetEntry(Rec.MatrixV, 3, -1, -1, -1.0); + SetEntry(Rec.MatrixV, 4, 0, -1, -2.0); + SetEntry(Rec.MatrixV, 5, 1, -1, -1.0); + end; + + nm3x3: begin + SetLength(Rec.MatrixU, 6); + SetEntry(Rec.MatrixU, 0, -1, 1, -1/6); + SetEntry(Rec.MatrixU, 1, -1, 0, -1/6); + SetEntry(Rec.MatrixU, 2, -1, -1, -1/6); + SetEntry(Rec.MatrixU, 3, 1, 1, 1/6); + SetEntry(Rec.MatrixU, 4, 1, 0, 1/6); + SetEntry(Rec.MatrixU, 5, 1, -1, 1/6); + + SetLength(Rec.MatrixV, 6); + SetEntry(Rec.MatrixV, 0, -1, 1, 1/6); + SetEntry(Rec.MatrixV, 1, 0, 1, 1/6); + SetEntry(Rec.MatrixV, 2, 1, 1, 1/6); + SetEntry(Rec.MatrixV, 3, -1, -1, -1/6); + SetEntry(Rec.MatrixV, 4, 0, -1, -1/6); + SetEntry(Rec.MatrixV, 5, 1, -1, -1/6); + end; + + nm5x5: begin + SetLength(Rec.MatrixU, 20); + SetEntry(Rec.MatrixU, 0, -2, 2, -1 / 16); + SetEntry(Rec.MatrixU, 1, -1, 2, -1 / 10); + SetEntry(Rec.MatrixU, 2, 1, 2, 1 / 10); + SetEntry(Rec.MatrixU, 3, 2, 2, 1 / 16); + SetEntry(Rec.MatrixU, 4, -2, 1, -1 / 10); + SetEntry(Rec.MatrixU, 5, -1, 1, -1 / 8); + SetEntry(Rec.MatrixU, 6, 1, 1, 1 / 8); + SetEntry(Rec.MatrixU, 7, 2, 1, 1 / 10); + SetEntry(Rec.MatrixU, 8, -2, 0, -1 / 2.8); + SetEntry(Rec.MatrixU, 9, -1, 0, -0.5); + SetEntry(Rec.MatrixU, 10, 1, 0, 0.5); + SetEntry(Rec.MatrixU, 11, 2, 0, 1 / 2.8); + SetEntry(Rec.MatrixU, 12, -2, -1, -1 / 10); + SetEntry(Rec.MatrixU, 13, -1, -1, -1 / 8); + SetEntry(Rec.MatrixU, 14, 1, -1, 1 / 8); + SetEntry(Rec.MatrixU, 15, 2, -1, 1 / 10); + SetEntry(Rec.MatrixU, 16, -2, -2, -1 / 16); + SetEntry(Rec.MatrixU, 17, -1, -2, -1 / 10); + SetEntry(Rec.MatrixU, 18, 1, -2, 1 / 10); + SetEntry(Rec.MatrixU, 19, 2, -2, 1 / 16); + + SetLength(Rec.MatrixV, 20); + SetEntry(Rec.MatrixV, 0, -2, 2, 1 / 16); + SetEntry(Rec.MatrixV, 1, -1, 2, 1 / 10); + SetEntry(Rec.MatrixV, 2, 0, 2, 0.25); + SetEntry(Rec.MatrixV, 3, 1, 2, 1 / 10); + SetEntry(Rec.MatrixV, 4, 2, 2, 1 / 16); + SetEntry(Rec.MatrixV, 5, -2, 1, 1 / 10); + SetEntry(Rec.MatrixV, 6, -1, 1, 1 / 8); + SetEntry(Rec.MatrixV, 7, 0, 1, 0.5); + SetEntry(Rec.MatrixV, 8, 1, 1, 1 / 8); + SetEntry(Rec.MatrixV, 9, 2, 1, 1 / 16); + SetEntry(Rec.MatrixV, 10, -2, -1, -1 / 16); + SetEntry(Rec.MatrixV, 11, -1, -1, -1 / 8); + SetEntry(Rec.MatrixV, 12, 0, -1, -0.5); + SetEntry(Rec.MatrixV, 13, 1, -1, -1 / 8); + SetEntry(Rec.MatrixV, 14, 2, -1, -1 / 10); + SetEntry(Rec.MatrixV, 15, -2, -2, -1 / 16); + SetEntry(Rec.MatrixV, 16, -1, -2, -1 / 10); + SetEntry(Rec.MatrixV, 17, 0, -2, -0.25); + SetEntry(Rec.MatrixV, 18, 1, -2, -1 / 10); + SetEntry(Rec.MatrixV, 19, 2, -2, -1 / 16); + end; end; // Daten Sammeln - if UseAlpha and FormatHasAlpha(InternalFormat) then - AddFunc(glBitmapToNormalMapPrepareAlphaFunc, False, @Rec) + if aUseAlpha and FORMAT_DESCRIPTORS[Format].HasAlpha then + AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec)) else - AddFunc(glBitmapToNormalMapPrepareFunc, False, @Rec); - - // Neues Bild berechnen - AddFunc(glBitmapToNormalMapFunc, False, @Rec); + AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec)); + AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec)); finally SetLength(Rec.Heights, 0); end; end; -procedure TglBitmap2D.GrabScreen(Top, Left, Right, Bottom: Integer; Format: TglBitmapFormat); -var - Temp: pByte; - Size: Integer; - glFormat, glInternalFormat, glType: Cardinal; -begin - if not FormatIsUncompressed(Format) then - raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_INTERNAL_FORMAT); - - // Only to select Formats - SelectFormat(Format, glFormat, glInternalFormat, glType, False); - - Size := FormatGetImageSize(glBitmapPosition(Right - Left, Bottom - Top), Format); - GetMem(Temp, Size); - try - glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(Left, Top, Right - Left, Bottom - Top, glFormat, glType, Temp); - - // Set Data - SetDataPointer(Temp, Format, Right - Left, Bottom - Top); - - // Flip - FlipVert; - except - FreeMem(Temp); - raise; - end; -end; - - -procedure TglBitmap2D.GetDataFromTexture; -var - Temp: pByte; - TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer; - TempType, TempIntFormat: Cardinal; - IntFormat: TglBitmapFormat; -begin - Bind; - - // Request Data - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); - - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize); - - // Get glBitmapInternalFormat from TempIntFormat - TempType := GL_UNSIGNED_BYTE; - case TempIntFormat of - GL_ALPHA: - IntFormat := ifAlpha; - GL_LUMINANCE: - IntFormat := ifLuminance; - GL_LUMINANCE_ALPHA: - IntFormat := ifLuminanceAlpha; - GL_RGB4: - begin - IntFormat := ifR5G6B5; - TempIntFormat := GL_RGB; - TempType := GL_UNSIGNED_SHORT_5_6_5; - end; - GL_RGB, GL_RGB8: - IntFormat := tfRGB8; - GL_RGBA, GL_RGBA4, GL_RGBA8: - begin - if (RedSize = 4) and (BlueSize = 4) and (GreenSize = 4) and (AlphaSize = 4) then begin - IntFormat := tfRGBA4; - TempIntFormat := GL_BGRA; - TempType := GL_UNSIGNED_SHORT_4_4_4_4_REV; - end else - if (RedSize = 5) and (BlueSize = 5) and (GreenSize = 5) and (AlphaSize = 1) then begin - IntFormat := tfRGB5A1; - TempIntFormat := GL_BGRA; - TempType := GL_UNSIGNED_SHORT_1_5_5_5_REV; - end else begin - IntFormat := tfRGBA8; - end; - end; - GL_BGR: - IntFormat := ifBGR8; - GL_BGRA: - IntFormat := ifBGRA8; - GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - IntFormat := ifDXT1; - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - IntFormat := ifDXT1; - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - IntFormat := ifDXT3; - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - IntFormat := ifDXT5; - else - IntFormat := ifEmpty; - end; - // Getting data from OpenGL - GetMem(Temp, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat)); - try - if FormatIsCompressed(IntFormat) and (GL_VERSION_1_3 or GL_ARB_texture_compression) then - glGetCompressedTexImage(Target, 0, Temp) - else - glGetTexImage(Target, 0, TempIntFormat, TempType, Temp); - SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); - except - FreeMem(Temp); - raise; - end; -end; -function TglBitmap2D.GetScanline(Index: Integer): Pointer; -begin - if (Index >= Low(fLines)) and (Index <= High(fLines)) then - Result := fLines[Index] - else - Result := nil; -end; -{ TglBitmap1D } +(* procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer); var pTemp: pByte; @@ -6575,7 +6431,7 @@ var Col: Integer; pTempDest, pDest, pSource: pByte; begin - Result := Inherited FlipHorz; + result := inherited FlipHorz; if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin pSource := Data; @@ -6594,7 +6450,7 @@ begin SetDataPointer(pDest, InternalFormat); - Result := True; + result := true; finally FreeMem(pDest); end; @@ -6650,7 +6506,7 @@ begin UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu); // Infos sammeln - glAreTexturesResident(1, @ID, @fIsResident); + glAreTexturesResident(1, @fID, @fIsResident); end; end; @@ -6724,7 +6580,7 @@ end; procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean); begin - Assert(False, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.'); + Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.'); end; @@ -6849,7 +6705,7 @@ var begin Rec.HalfSize := Size div 2; - FreeDataAfterGenTexture := False; + FreeDataAfterGenTexture := false; SizeRec.Fields := [ffX, ffY]; SizeRec.X := Size; @@ -6885,6 +6741,7 @@ begin LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize); end; +*) initialization glBitmapSetDefaultFormat(tfEmpty); From 79fb46a12b3999eb46576392ed3cf922ab5ee348 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 2 Nov 2013 14:50:56 +0100 Subject: [PATCH 06/38] * refactored FormatDescriptor * reimplemented LoadBMP (everything except RLE compression is supported) --- glBitmap.pas | 2897 +++++++++++++++++++++++++++++++------------------- 1 file changed, 1800 insertions(+), 1097 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 12e84af..b2a1476 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -590,171 +590,115 @@ type EglBitmapUnsupportedFormatFormat = class(EglBitmapException); //////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapPixelDesc = packed record - RedRange: Cardinal; - RedShift: Shortint; - GreenRange: Cardinal; - GreenShift: Shortint; - BlueRange: Cardinal; - BlueShift: Shortint; - AlphaRange: Cardinal; - AlphaShift: Shortint; - end; - PglBitmapPixelDesc = ^TglBitmapPixelDesc; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapPixelData = packed record - Red: Cardinal; - Green: Cardinal; - Blue: Cardinal; - Alpha: Cardinal; - PixelDesc: TglBitmapPixelDesc; - end; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapFormatDesc = packed record - Format: Cardinal; - InternalFormat: Cardinal; - DataType: Cardinal; - end; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapPixelPositionFields = set of (ffX, ffY); - TglBitmapPixelPosition = record - Fields : TglBitmapPixelPositionFields; - X : Word; - Y : Word; - end; - -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmap = class; - TglBitmapFunctionRec = record - Sender: TglBitmap; - Size: TglBitmapPixelPosition; - Position: TglBitmapPixelPosition; - Source: TglBitmapPixelData; - Dest: TglBitmapPixelData; - Args: PtrInt; - end; - TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); - -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapFileType = ( - {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} - ftDDS, - ftTGA, - ftBMP); - TglBitmapFileTypes = set of TglBitmapFileType; - - TglBitmapMipMap = ( - mmNone, - mmMipmap, - mmMipmapGlu); - - TglBitmapNormalMapFunc = ( - nm4Samples, - nmSobel, - nm3x3, - nm5x5); - TglBitmapFormat = ( tfEmpty = 0, - //TODO + //tfAlpha4, - //tfAlpha8, + tfAlpha8, //tfAlpha12, - //tfAlpha16, + tfAlpha16, //tfLuminance4, tfLuminance8, //tfLuminance12, - //tfLuminance16, - // - //tfuminance4Alpha4, - //tfLuminance6Alpha2, + tfLuminance16, + + tfLuminance4Alpha4, + tfLuminance6Alpha2, tfLuminance8Alpha8, - //tfLuminance12Alpha4, + tfLuminance12Alpha4, //tfLuminance12Alpha12, - //tfLuminance16Alpha16, + tfLuminance16Alpha16, - //tfR3G3B2, - //tfRGB4, + tfR3G3B2, + tfRGB4, + tfR5G6B5, tfRGB5, tfRGB8, - //tfRGB10, + tfRGB10, //tfRGB12, - //tfRGB16, + tfRGB16, - //tfRGBA2, - //tfRGBA4, + tfRGBA2, + tfRGBA4, tfRGB5A1, tfRGBA8, - //tfRGB10A2, + tfRGB10A2, //tfRGBA12, - //tfRGBA16, + tfRGBA16, - //tfBGR4, - //tfBGR5, + tfBGR4, + tfB5G6R5, + tfBGR5, tfBGR8, - //tfBGR10, + tfBGR10, //tfBGR12, - //tfBGR16, + tfBGR16, - //tfBGRA2, - //tfBGRA4, - //tfBGR5A1, - tfBGRA8 - //tfBGR10A2, + tfBGRA2, + tfBGRA4, + tfBGR5A1, + tfBGRA8, + tfBGR10A2, //tfBGRA12, - //tfBGRA16, + tfBGRA16 //tfDepth16, //tfDepth24, //tfDepth32 ); -//////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapGetPixel = procedure(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData) of object; - TglBitmapSetPixel = procedure(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData) of object; - - TglBitmapMapFunc = procedure(const aPixel: TglBitmapPixelData; var aData: PByte; var aBitOffset: Byte); - TglBitmapUnMapFunc = procedure(var aData: PByte; var aBitOffset: Byte; var aPixel: TglBitmapPixelData); + TglBitmapFileType = ( + {$IFDEF GLB_SUPPORT_PNG_WRITE} ftPNG, {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_WRITE}ftJPEG, {$ENDIF} + ftDDS, + ftTGA, + ftBMP); + TglBitmapFileTypes = set of TglBitmapFileType; + + TglBitmapMipMap = ( + mmNone, + mmMipmap, + mmMipmapGlu); + + TglBitmapNormalMapFunc = ( + nm4Samples, + nmSobel, + nm3x3, + nm5x5); //////////////////////////////////////////////////////////////////////////////////////////////////// - TglBitmapFormatDescriptor = class(TObject) - public - //virtual abstract - class function GetFormat: TglBitmapFormat; virtual; abstract; - class function GetPixelDesc: TglBitmapPixelDesc; virtual; abstract; - class function GetFormatDesc: TglBitmapFormatDesc; virtual; abstract; - - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); virtual; abstract; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); virtual; abstract; - - //virtual - class function WithoutAlpha: TglBitmapFormat; virtual; - class function WithAlpha: TglBitmapFormat; virtual; - - class function GetSize: Single; virtual; overload; - class function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload; - class function GetColorCompCount: Integer; virtual; + TglBitmapColorRec = packed record + case Integer of + 0: (r, g, b, a: Cardinal); + 1: (arr: array[0..3] of Cardinal); + end; - class function IsEmpty: Boolean; virtual; - class function HasAlpha: Boolean; virtual; - class function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; + TglBitmapPixelData = packed record + Data, Range: TglBitmapColorRec; + Format: TglBitmapFormat; + end; + PglBitmapPixelData = ^TglBitmapPixelData; - class procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual; +//////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmapPixelPositionFields = set of (ffX, ffY); + TglBitmapPixelPosition = record + Fields : TglBitmapPixelPositionFields; + X : Word; + Y : Word; + end; - (* TODO - function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; - function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; - function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; - function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; - function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; - *) +//////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmap = class; + TglBitmapFunctionRec = record + Sender: TglBitmap; + Size: TglBitmapPixelPosition; + Position: TglBitmapPixelPosition; + Source: TglBitmapPixelData; + Dest: TglBitmapPixelData; + Args: PtrInt; end; - TglBitmapFormatDescClass = class of TglBitmapFormatDescriptor; + TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class @@ -775,8 +719,6 @@ type // Mapping fPixelSize: Integer; fRowSize: Integer; - //TODO delete? fUnmapFunc: TglBitmapUnMapFunc; - //TODO delete? fMapFunc: TglBitmapMapFunc; // Filtering fFilterMin: Cardinal; @@ -787,9 +729,6 @@ type fWrapT: Cardinal; fWrapR: Cardinal; - //TODO delete? fGetPixelFunc: TglBitmapGetPixel; - //TODO delete? fSetPixelFunc: TglBitmapSetPixel; - // CustomData fFilename: String; fCustomName: String; @@ -1064,6 +1003,7 @@ procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal); procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; +function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec; var glBitmapDefaultDeleteTextureOnFree: Boolean; @@ -1082,170 +1022,301 @@ function CreateGrayPalette: HPALETTE; implementation + + (* TODO + function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; + function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; + function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; + function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; + function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; + *) + uses - Math; + Math, syncobjs; type -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TBitfieldFormat = class(TObject) +//////////////////////////////////////////////////////////////////////////////////////////////////// + TShiftRec = packed record + case Integer of + 0: (r, g, b, a: Byte); + 1: (arr: array[0..3] of Byte); + end; + + TFormatDescriptor = class(TObject) private - fRedShift: ShortInt; - fGreenShift: ShortInt; - fBlueShift: ShortInt; - fAlphaShift: ShortInt; - - fRedRange: Cardinal; - fGreenRange: Cardinal; - fBlueRange: Cardinal; - fAlphaRange: Cardinal; - - fRedMask: UInt64; - fGreenMask: UInt64; - fBlueMask: UInt64; - fAlphaMask: UInt64; - function GetSize: Integer; - procedure SetAlphaMask(aValue: UInt64); - procedure SetAlphaRange(aValue: Cardinal); - procedure SetAlphaShift(aValue: ShortInt); - procedure SetBlueMask(aValue: UInt64); - procedure SetBlueRange(aValue: Cardinal); - procedure SetBlueShift(aValue: ShortInt); - procedure SetGreenMask(aValue: UInt64); - procedure SetGreenRange(aValue: Cardinal); - procedure SetGreenShift(aValue: ShortInt); - procedure SetRedMask(aValue: UInt64); - procedure SetRedRange(aValue: Cardinal); - procedure SetRedShift(aValue: ShortInt); - - procedure CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal; out aShift: ShortInt); + function GetRedMask: UInt64; + function GetGreenMask: UInt64; + function GetBlueMask: UInt64; + function GetAlphaMask: UInt64; + protected + fFormat: TglBitmapFormat; + fWithAlpha: TglBitmapFormat; + fWithoutAlpha: TglBitmapFormat; + fPixelSize: Single; + + fRange: TglBitmapColorRec; + fShift: TShiftRec; + + fglFormat: Cardinal; + fglInternalFormat: Cardinal; + fglDataFormat: Cardinal; + + function GetComponents: Integer; virtual; public - property RedShift: ShortInt read fRedShift write SetRedShift; - property GreenShift: ShortInt read fGreenShift write SetGreenShift; - property BlueShift: ShortInt read fBlueShift write SetBlueShift; - property AlphaShift: ShortInt read fAlphaShift write SetAlphaShift; + property Format: TglBitmapFormat read fFormat; + property WithAlpha: TglBitmapFormat read fWithAlpha; + property WithoutAlpha: TglBitmapFormat read fWithoutAlpha; + property Components: Integer read GetComponents; + property PixelSize: Single read fPixelSize; - property RedRange: Cardinal read fRedRange write SetRedRange; - property GreenRange: Cardinal read fGreenRange write SetGreenRange; - property BlueRange: Cardinal read fBlueRange write SetBlueRange; - property AlphaRange: Cardinal read fAlphaRange write SetAlphaRange; + property glFormat: Cardinal read fglFormat; + property glInternalFormat: Cardinal read fglInternalFormat; + property glDataFormat: Cardinal read fglDataFormat; - property RedMask: UInt64 read fRedMask write SetRedMask; - property GreenMask: UInt64 read fGreenMask write SetGreenMask; - property BlueMask: UInt64 read fBlueMask write SetBlueMask; - property AlphaMask: UInt64 read fAlphaMask write SetAlphaMask; + property Range: TglBitmapColorRec read fRange; + property Shift: TShiftRec read fShift; - property Size: Integer read GetSize; + property RedMask: UInt64 read GetRedMask; + property GreenMask: UInt64 read GetGreenMask; + property BlueMask: UInt64 read GetBlueMask; + property AlphaMask: UInt64 read GetAlphaMask; - procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); overload; - procedure Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData); overload; - end; + procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract; + procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdEmpty = class(TglBitmapFormatDescriptor) + function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload; + function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload; + + function CreateMappingData: Pointer; virtual; + procedure FreeMappingData(var aMappingData: Pointer); virtual; + + function IsEmpty: Boolean; virtual; + function HasAlpha: Boolean; virtual; + function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; + + procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual; + + constructor Create; virtual; public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; + class procedure Init; + class function Get(const aFormat: TglBitmapFormat): TFormatDescriptor; + class function GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor; + class procedure Clear; + class procedure Finalize; + end; + TFormatDescriptorClass = class of TFormatDescriptor; + + TfdEmpty = class(TFormatDescriptor); - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdAlpha8 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdLuminance8 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithAlpha: TglBitmapFormat; override; + TfdAlpha16 = 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; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdLuminance8 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdLuminance8Alpha8 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithoutAlpha: TglBitmapFormat; override; + TfdLuminance16 = 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; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; - end; + TfdLuminance4Alpha4 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdRGB5 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithAlpha: TglBitmapFormat; override; + TfdLuminance6Alpha2 = class(TfdLuminance4Alpha4) + constructor Create; override; + end; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdLuminance8Alpha8 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdRGB8 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithAlpha: TglBitmapFormat; override; + TfdLuminance12Alpha4 = class(TfdLuminance8Alpha8) + constructor Create; override; + end; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdLuminance16Alpha16 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdRGB5A1 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithoutAlpha: TglBitmapFormat; override; + TfdR3G3B2 = 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; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdRGB4 = 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; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdRGBA8 = class(TglBitmapFormatDescriptor) - public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithoutAlpha: TglBitmapFormat; override; + TfdR5G6B5 = class(TfdRGB4) + constructor Create; override; + end; + + TfdRGB5 = class(TfdRGB4) + constructor Create; override; + end; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + TfdRGB8 = 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; + + TfdRGB10 = 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; + + TfdRGB16 = 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; + + TfdRGBA2 = class(TfdR3G3B2) + constructor Create; override; + end; + + TfdRGBA4 = class(TfdRGB4) + constructor Create; override; + end; + + TfdRGB5A1 = class(TfdRGB5) + constructor Create; override; + end; + + TfdRGBA8 = class(TfdRGB8) + 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; + + TfdRGB10A2 = class(TfdRGB10) + constructor Create; override; + end; + + TfdRGBA16 = class(TfdRGB16) + 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; + + TfdBGR4 = class(TfdRGB4) + constructor Create; override; + end; + + TfdB5G6R5 = class(TfdRGB4) + constructor Create; override; + end; + + TfdBGR5 = class(TfdRGB5) + constructor Create; override; + end; + + TfdBGR8 = 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; + + TfdBGR10 = class(TfdRGB10) + constructor Create; override; + end; + + TfdBGR16 = 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; + + TfdBGRA2 = class(TfdRGBA2) + constructor Create; override; + end; + + TfdBGRA4 = class(TfdRGBA4) + constructor Create; override; + end; + + TfdBGR5A1 = class(TfdRGB5A1) + constructor Create; override; + end; + + TfdBGRA8 = class(TfdBGR8) + 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; + + TfdBGR10A2 = class(TfdRGB10A2) + constructor Create; override; + end; + + TfdBGRA16 = class(TfdBGR16) + 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; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdBGR8 = class(TglBitmapFormatDescriptor) + TBitfieldFormat = class(TFormatDescriptor) + private + procedure SetRedMask (const aValue: UInt64); + procedure SetGreenMask(const aValue: UInt64); + procedure SetBlueMask (const aValue: UInt64); + procedure SetAlphaMask(const aValue: UInt64); + + procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte); public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithAlpha: TglBitmapFormat; override; + property RedMask: UInt64 read GetRedMask write SetRedMask; + property GreenMask: UInt64 read GetGreenMask write SetGreenMask; + property BlueMask: UInt64 read GetBlueMask write SetBlueMask; + property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask; + + property PixelSize: Single read fPixelSize write fPixelSize; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TfdBGRA8 = class(TglBitmapFormatDescriptor) + TColorTableEnty = packed record + b, g, r, a: Byte; + end; + TColorTable = array of TColorTableEnty; + TColorTableFormat = class(TFormatDescriptor) + private + fColorTable: TColorTable; public - class function GetFormat: TglBitmapFormat; override; - class function GetPixelDesc: TglBitmapPixelDesc; override; - class function GetFormatDesc: TglBitmapFormatDesc; override; - class function WithoutAlpha: TglBitmapFormat; override; + property PixelSize: Single read fPixelSize write fPixelSize; + property ColorTable: TColorTable read fColorTable write fColorTable; + property Range: TglBitmapColorRec read fRange write fRange; - class procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte); override; - class procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); override; + procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + destructor Destroy; override; end; const @@ -1259,24 +1330,68 @@ const UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.'; - FORMAT_DESCRIPTORS: array[TglBitmapFormat] of TglBitmapFormatDescClass = ( + FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = ( TfdEmpty, + //TfdAlpha4, + TfdAlpha8, + //TfdAlpha12, + TfdAlpha16, + + //TfdLuminance4, TfdLuminance8, + //TfdLuminance12, + TfdLuminance16, + + TfdLuminance4Alpha4, + TfdLuminance6Alpha2, TfdLuminance8Alpha8, + TfdLuminance12Alpha4, + //TfdLuminance12Alpha12, + TfdLuminance16Alpha16, + TfdR3G3B2, + TfdRGB4, + TfdR5G6B5, TfdRGB5, TfdRGB8, + TfdRGB10, + //TfdRGB12, + TfdRGB16, + TfdRGBA2, + TfdRGBA4, TfdRGB5A1, TfdRGBA8, + TfdRGB10A2, + //TfdRGBA12, + TfdRGBA16, + TfdBGR4, + TfdB5G6R5, + TfdBGR5, TfdBGR8, - TfdBGRA8 + TfdBGR10, + //TfdBGR12, + TfdBGR16, + + TfdBGRA2, + TfdBGRA4, + TfdBGR5A1, + TfdBGRA8, + TfdBGR10A2, + //TfdBGRA12, + TfdBGRA16 + + //TfdDepth16, + //TfdDepth24, + //TfdDepth32 ); +var + FormatDescriptorCS: TCriticalSection; + FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor; -{$REGION Private Helper} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; begin @@ -1291,6 +1406,15 @@ begin result.Y := Max(0, Y); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec; +begin + result.r := r; + result.g := g; + result.b := b; + result.a := a; +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin @@ -1359,7 +1483,15 @@ begin aBitSet := aBitSet shr 1; end; end; -{$ENDREGION} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function LuminanceWeight(const aPixel: TglBitmapPixelData): Cardinal; +begin + result := Trunc( + LUMINANCE_WEIGHT_R * aPixel.Data.r + + LUMINANCE_WEIGHT_G * aPixel.Data.g + + LUMINANCE_WEIGHT_B * aPixel.Data.b); +end; //TODO check _ARB functions and constants @@ -1699,7 +1831,6 @@ begin end; *) -{$REGION default Setter and Gettter} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean); begin @@ -1777,857 +1908,1430 @@ begin T := glBitmapDefaultWrapT; R := glBitmapDefaultWrapR; end; -{$ENDREGION} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TCustomFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetAlphaMask(aValue: UInt64); +function TFormatDescriptor.GetRedMask: UInt64; begin - if fAlphaMask = aValue then Exit; - fAlphaMask := aValue; - CalcShiftAndRange(fAlphaMask, fAlphaRange, fAlphaShift); + result := fRange.r shl fShift.r; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TBitfieldFormat.GetSize: Integer; -var - tmp: UInt64; +function TFormatDescriptor.GetGreenMask: UInt64; begin - tmp := - (fRedRange shl fRedShift) or - (fGreenRange shl fGreenShift) or - (fBlueRange shl fBlueShift) or - (fAlphaRange shl fAlphaShift); - result := Trunc(GetTopMostBit(tmp) / 8); + result := fRange.g shl fShift.g; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetAlphaRange(aValue: Cardinal); +function TFormatDescriptor.GetBlueMask: UInt64; begin - if fAlphaRange = aValue then Exit; - fAlphaRange := aValue; - fAlphaMask := fAlphaRange shl fAlphaShift; + result := fRange.b shl fShift.b; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetAlphaShift(aValue: ShortInt); +function TFormatDescriptor.GetAlphaMask: UInt64; begin - if fAlphaShift = aValue then Exit; - fAlphaShift := aValue; - fAlphaMask := fAlphaRange shl fAlphaShift; + result := fRange.a shl fShift.a; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetBlueMask(aValue: UInt64); +function TFormatDescriptor.GetComponents: Integer; +var + i: Integer; begin - if fBlueMask = aValue then Exit; - fBlueMask := aValue; - CalcShiftAndRange(fBlueMask, fBlueRange, fBlueShift); + result := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + inc(result); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetBlueRange(aValue: Cardinal); +function TFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer; +var + w, h: Integer; begin - if fBlueRange = aValue then Exit; - fBlueRange := aValue; - fBlueMask := fBlueRange shl fBlueShift; + if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin + w := Max(1, aSize.X); + h := Max(1, aSize.Y); + result := GetSize(w, h); + end else + result := 0; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetBlueShift(aValue: ShortInt); +function TFormatDescriptor.GetSize(const aWidth, aHeight: Integer): Integer; begin - if fBlueShift = aValue then Exit; - fBlueShift := aValue; - fBlueMask := fBlueRange shl fBlueShift; + result := 0; + if (aWidth <= 0) or (aHeight <= 0) then + exit; + result := Ceil(aWidth * aHeight * fPixelSize); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetGreenMask(aValue: UInt64); +function TFormatDescriptor.CreateMappingData: Pointer; begin - if fGreenMask = aValue then Exit; - fGreenMask := aValue; - CalcShiftAndRange(fGreenMask, fGreenRange, fGreenShift); + result := nil; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetGreenRange(aValue: Cardinal); +procedure TFormatDescriptor.FreeMappingData(var aMappingData: Pointer); begin - if fGreenRange = aValue then Exit; - fGreenRange := aValue; - fGreenMask := fGreenRange shl fGreenShift; + //DUMMY end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetGreenShift(aValue: ShortInt); +function TFormatDescriptor.IsEmpty: Boolean; begin - if fGreenShift = aValue then Exit; - fGreenShift := aValue; - fGreenMask := fGreenRange shl fGreenShift; + result := (fFormat = tfEmpty); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetRedMask(aValue: UInt64); +function TFormatDescriptor.HasAlpha: Boolean; begin - if fRedMask = aValue then Exit; - fRedMask := aValue; - CalcShiftAndRange(fRedMask, fRedRange, fRedShift); + result := (fRange.a > 0); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetRedRange(aValue: Cardinal); +function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; begin - if fRedRange = aValue then Exit; - fRedRange := aValue; - fRedMask := fRedRange shl fRedShift; + result := false; + + if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then + raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); + + if (aRedMask <> RedMask) then + exit; + if (aGreenMask <> GreenMask) then + exit; + if (aBlueMask <> BlueMask) then + exit; + if (aAlphaMask <> AlphaMask) then + exit; + result := true; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetRedShift(aValue: ShortInt); +procedure TFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData); begin - if fRedShift = aValue then Exit; - fRedShift := aValue; - fRedMask := fRedRange shl fRedShift; + FillChar(aPixel, SizeOf(aPixel), 0); + aPixel.Data := fRange; + aPixel.Range := fRange; + aPixel.Format := fFormat; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.CalcShiftAndRange(aMask: UInt64; out aRange: Cardinal; - out aShift: ShortInt); +constructor TFormatDescriptor.Create; begin - aShift := 0; - aRange := 0; - if (aMask = 0) then - exit; - while (aMask > 0) and ((aMask and 1) = 0) do begin - inc(aShift); - aMask := aMask shr 1; - end; - aRange := 1; - while (aMask > 0) do begin - aRange := aRange shl 1; - aMask := aMask shr 1; - end; - dec(aRange); + inherited Create; + + fFormat := tfEmpty; + fWithAlpha := tfEmpty; + fWithoutAlpha := tfEmpty; + fPixelSize := 0.0; + + fglFormat := 0; + fglInternalFormat := 0; + fglDataFormat := 0; + + FillChar(fRange, 0, SizeOf(fRange)); + FillChar(fShift, 0, SizeOf(fShift)); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte); -var - data: UInt64; - s: Integer; -type - PUInt64 = ^UInt64; +//TfdAlpha8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdAlpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - data := - ((aPixel.Red and fRedRange) shl fRedShift) or - ((aPixel.Green and fGreenRange) shl fGreenShift) or - ((aPixel.Blue and fBlueRange) shl fBlueShift) or - ((aPixel.Alpha and fAlphaRange) shl fAlphaShift); - s := Size; - case s of - 1: aData^ := data; - 2: PWord(aData)^ := data; - 4: PCardinal(aData)^ := data; - 8: PUInt64(aData)^ := data; - end; - inc(aData, s); + aData^ := aPixel.Data.a; + inc(aData); end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); -var - data: UInt64; - s: Integer; -type - PUInt64 = ^UInt64; +procedure TfdAlpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - s := Size; - case s of - 1: data := aData^; - 2: data := PWord(aData)^; - 4: data := PCardinal(aData)^; - 8: data := PUInt64(aData)^; - end; - Unmap(data, aPixel); - inc(aData, s); + aPixel.Data.r := 0; + aPixel.Data.g := 0; + aPixel.Data.b := 0; + aPixel.Data.a := aData^; + inc(aData^); end; +constructor TfdAlpha8.Create; +begin + inherited Create; + fPixelSize := 1.0; + fFormat := tfAlpha8; + fRange.a := $FF; + fglFormat := GL_ALPHA; + fglInternalFormat := GL_ALPHA8; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdAlpha16////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Unmap(const aData: UInt64; var aPixel: TglBitmapPixelData); +procedure TfdAlpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); +end; + +procedure TfdAlpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := 0; + aPixel.Data.g := 0; + aPixel.Data.b := 0; + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdAlpha16.Create; begin - aPixel.Red := (aData shr fRedShift) and fRedRange; - aPixel.Green := (aData shr fGreenShift) and fGreenRange; - aPixel.Blue := (aData shr fBlueShift) and fBlueRange; - aPixel.Alpha := (aData shr fAlphaShift) and fAlphaRange; + inherited Create; + fPixelSize := 2.0; + fFormat := tfAlpha16; + fRange.a := $FFFF; + fglFormat := GL_ALPHA; + fglInternalFormat := GL_ALPHA16; + fglDataFormat := GL_UNSIGNED_SHORT; end; -{$REGION TglBitmapFormatDescriptor} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.WithoutAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - if not HasAlpha then - result := GetFormat - else - result := tfEmpty; + aData^ := LuminanceWeight(aPixel); + inc(aData); +end; + +procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := aData^; + aPixel.Data.g := aData^; + aPixel.Data.b := aData^; + aPixel.Data.a := 0; + inc(aData); end; +constructor TfdLuminance8.Create; +begin + inherited Create; + fPixelSize := 1.0; + fFormat := tfLuminance8; + fWithAlpha := tfLuminance8Alpha8; + fWithoutAlpha := tfLuminance8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE8; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.WithAlpha: TglBitmapFormat; +procedure TfdLuminance16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - if HasAlpha then - result := GetFormat - else - result := tfEmpty; + PWord(aData)^ := LuminanceWeight(aPixel); + inc(aData, 2); end; +procedure TfdLuminance16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := PWord(aData)^; + aPixel.Data.g := PWord(aData)^; + aPixel.Data.b := PWord(aData)^; + aPixel.Data.a := 0; + inc(aData, 2); +end; + +constructor TfdLuminance16.Create; +begin + inherited Create; + fPixelSize := 2.0; + fFormat := tfLuminance16; + fWithAlpha := tfLuminance16Alpha16; + fWithoutAlpha := tfLuminance16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE16; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.GetSize: Single; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminance4Alpha4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + aData^ := + ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or + ((aPixel.Data.a and fRange.a) shl fShift.a); + inc(aData); +end; + +procedure TfdLuminance4Alpha4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); var - tmp: UInt64; + i: Integer; begin - with GetPixelDesc do begin - tmp := - (RedRange shl RedShift) or - (GreenRange shl GreenShift) or - (BlueRange shl BlueShift) or - (AlphaRange shl AlphaShift); - end; - result := Trunc(GetTopMostBit(tmp) / 4) / 2; + for i := 0 to 3 do + aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData); +end; + +constructor TfdLuminance4Alpha4.Create; +begin + inherited Create; + fPixelSize := 1.0; + fFormat := tfLuminance4Alpha4; + fWithAlpha := tfLuminance4Alpha4; + fWithoutAlpha := tfLuminance8; + fRange.r := $F; + fRange.g := $F; + fRange.b := $F; + fRange.a := $F; + fShift.a := 4; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE4_ALPHA4; + fglDataFormat := GL_UNSIGNED_BYTE; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.GetSize(const aSize: TglBitmapPixelPosition): Integer; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdLuminance6Alpha2.Create; +begin + inherited Create; + fFormat := tfLuminance6Alpha2; + fWithAlpha := tfLuminance6Alpha2; + fWithoutAlpha := tfLuminance8; + fRange.r := $3F; + fRange.g := $3F; + fRange.b := $3F; + fRange.a := $03; + fShift.a := 6; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE6_ALPHA2; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := + ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or + ((aPixel.Data.a and fRange.a) shl fShift.a); + inc(aData, 2); +end; + +procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); var - w, h: Integer; + i: Integer; begin - if (ffX in aSize.Fields) or (ffY in aSize.Fields) then begin - w := Max(1, aSize.X); - h := Max(1, aSize.Y); - result := Ceil(w * h * GetSize); - end else - result := 0; + for i := 0 to 3 do + aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 2); +end; + +constructor TfdLuminance8Alpha8.Create; +begin + inherited Create; + fPixelSize := 2.0; + fFormat := tfLuminance8Alpha8; + fWithAlpha := tfLuminance8Alpha8; + fWithoutAlpha := tfLuminance8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fRange.a := $FF; + fShift.a := 8; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE8_ALPHA8; + fglDataFormat := GL_UNSIGNED_SHORT; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.GetColorCompCount: Integer; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdLuminance12Alpha4.Create; begin - result := 0; - with GetPixelDesc do begin - if (RedRange > 0) then - inc(result); - if (GreenRange > 0) then - inc(result); - if (BlueRange > 0) then - inc(result); - if (AlphaRange > 0) then - inc(result); - end; + inherited Create; + fFormat := tfLuminance12Alpha4; + fWithAlpha := tfLuminance12Alpha4; + fWithoutAlpha := tfLuminance16; + fRange.r := $FFF; + fRange.g := $FFF; + fRange.b := $FFF; + fRange.a := $00F; + fShift.a := 12; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE12_ALPHA4; + fglDataFormat := GL_UNSIGNED_SHORT; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.IsEmpty: Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminance16Alpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - result := (GetFormat = tfEmpty); + PCardinal(aData)^ := + ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or + ((aPixel.Data.a and fRange.a) shl fShift.a); + inc(aData, 4); end; +procedure TfdLuminance16Alpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; +begin + for i := 0 to 3 do + aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 4); +end; + +constructor TfdLuminance16Alpha16.Create; +begin + inherited Create; + fFormat := tfLuminance16Alpha16; + fWithAlpha := tfLuminance16Alpha16; + fWithoutAlpha := tfLuminance16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fRange.a := $FFFF; + fShift.a := 16; + fglFormat := GL_LUMINANCE; + fglInternalFormat := GL_LUMINANCE16_ALPHA16; + fglDataFormat := GL_UNSIGNED_INT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.HasAlpha: Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdR3G3B2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + i: Integer; +begin + aData^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); + inc(aData); +end; + +procedure TfdR3G3B2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; begin - result := (GetPixelDesc.AlphaRange > 0); + for i := 0 to 3 do + aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData); +end; + +constructor TfdR3G3B2.Create; +begin + inherited Create; + fPixelSize := 1.0; + fFormat := tfR3G3B2; + fWithAlpha := tfRGBA2; + fWithoutAlpha := tfR3G3B2; + fRange.r := $7; + fRange.g := $7; + fRange.b := $3; + fShift.r := 0; + fShift.g := 3; + fShift.b := 5; + fglFormat := GL_RGB; + fglInternalFormat := GL_R3_G3_B2; + fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TglBitmapFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); var - PixelDesc: TglBitmapPixelDesc; + i: Integer; begin - result := false; + PWord(aData)^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); + inc(aData, 2); +end; - if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then - raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); +procedure TfdRGB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; +begin + for i := 0 to 3 do + aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 2); +end; - PixelDesc := GetPixelDesc; - with PixelDesc do begin - if (aRedMask <> 0) and (aRedMask <> (RedRange shl RedShift)) then - exit; - if (aGreenMask <> 0) and (aGreenMask <> (GreenRange shl GreenShift)) then - exit; - if (aBlueMask <> 0) and (aBlueMask <> (BlueRange shl BlueShift)) then - exit; - if (aAlphaMask <> 0) and (aAlphaMask <> (AlphaRange shl AlphaShift)) then - exit; - end; - result := true; +constructor TfdRGB4.Create; +begin + inherited Create; + fPixelSize := 2.0; + fFormat := tfRGB4; + fWithAlpha := tfRGBA4; + fWithoutAlpha := tfRGB4; + fRange.r := $F; + fRange.g := $F; + fRange.b := $F; + fShift.r := 0; + fShift.g := 4; + fShift.b := 8; + fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA + fglInternalFormat := GL_RGB4; + fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class procedure TglBitmapFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdR5G6B5.Create; begin - FillChar(aPixel, SizeOf(aPixel), 0); - aPixel.PixelDesc := GetPixelDesc; - with aPixel.PixelDesc do begin - aPixel.Red := RedRange; - aPixel.Green := GreenRange; - aPixel.Blue := BlueRange; - aPixel.Alpha := AlphaRange; - end; + inherited Create; + fPixelSize := 2.0; + fFormat := tfR5G6B5; + fWithAlpha := tfRGBA4; + fWithoutAlpha := tfR5G6B5; + fRange.r := $1F; + fRange.g := $3F; + fRange.b := $1F; + fShift.r := 0; + fShift.g := 5; + fShift.b := 11; + fglFormat := GL_RGB; + fglInternalFormat := GL_RGB8; + fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV; end; -{$ENDREGION} -{$REGION TfdEmpty} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdEmpty//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdEmpty.GetFormat: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdRGB5.Create; begin - result := tfEmpty; + inherited Create; + fPixelSize := 2.0; + fFormat := tfRGB5; + fWithAlpha := tfRGB5A1; + fWithoutAlpha := tfRGB5; + fRange.r := $1F; + fRange.g := $1F; + fRange.b := $1F; + fShift.r := 0; + fShift.g := 5; + fShift.b := 10; + fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA + fglInternalFormat := GL_RGB5; + fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -class function TfdEmpty.GetPixelDesc: TglBitmapPixelDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - with result do begin - RedRange := $00000000; RedShift := 0; - GreenRange := $00000000; GreenShift := 0; - BlueRange := $00000000; BlueShift := 0; - AlphaRange := $00000000; AlphaShift := 0; - end; + aData^ := aPixel.Data.r; + inc(aData); + aData^ := aPixel.Data.g; + inc(aData); + aData^ := aPixel.Data.b; + inc(aData); end; -class function TfdEmpty.GetFormatDesc: TglBitmapFormatDesc; +procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - with result do begin - Format := 0; - InternalFormat := 0; - DataType := 0; - end; + aPixel.Data.r := aData^; + inc(aData); + aPixel.Data.g := aData^; + inc(aData); + aPixel.Data.b := aData^; + inc(aData); + aPixel.Data.a := 0; end; -class procedure TfdEmpty.Map(const aPixel: TglBitmapPixelData; var aData: PByte ); +constructor TfdRGB8.Create; begin - raise EglBitmapException.Create('format does not support mapping'); + inherited Create; + fPixelSize := 3.0; + fFormat := tfRGB8; + fWithAlpha := tfRGBA8; + fWithoutAlpha := tfRGB8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fShift.r := 0; + fShift.g := 8; + fShift.b := 16; + fglFormat := GL_RGB; + fglInternalFormat := GL_RGB8; + fglDataFormat := GL_UNSIGNED_BYTE; end; -class procedure TfdEmpty.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGB10.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + i: Integer; +begin + PCardinal(aData)^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); + inc(aData, 4); +end; + +procedure TfdRGB10.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; begin - raise EglBitmapException.Create('format does not support unmapping'); + for i := 0 to 3 do + aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 4); +end; + +constructor TfdRGB10.Create; +begin + inherited Create; + fPixelSize := 4.0; + fFormat := tfRGB10; + fWithAlpha := tfRGB10A2; + fWithoutAlpha := tfRGB10; + fRange.r := $3FF; + fRange.g := $3FF; + fRange.b := $3FF; + fShift.r := 0; + fShift.g := 10; + fShift.b := 20; + fglFormat := GL_RGB; + fglInternalFormat := GL_RGB10; + fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -{$ENDREGION} -{$REGION TfdLuminance8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdLuminance8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdLuminance8.GetFormat: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGB16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := aPixel.Data.r; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.g; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.b; + inc(aData, 2); +end; + +procedure TfdRGB16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - result := tfEmpty; + aPixel.Data.r := PWord(aData)^; + inc(aData, 2); + aPixel.Data.g := PWord(aData)^; + inc(aData, 2); + aPixel.Data.b := PWord(aData)^; + inc(aData, 2); + aPixel.Data.a := 0; end; -class function TfdLuminance8.GetPixelDesc: TglBitmapPixelDesc; +constructor TfdRGB16.Create; begin - with result do begin - RedRange := $000000FF; RedShift := 0; - GreenRange := $000000FF; GreenShift := 0; - BlueRange := $000000FF; BlueShift := 0; - AlphaRange := $00000000; AlphaShift := 0; - end; + inherited Create; + fPixelSize := 6.0; + fFormat := tfRGB16; + fWithAlpha := tfRGBA16; + fWithoutAlpha := tfRGB16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fShift.r := 0; + fShift.g := 16; + fShift.b := 32; + fglFormat := GL_RGB; + fglInternalFormat := GL_RGB16; + fglDataFormat := GL_UNSIGNED_SHORT; end; -class function TfdLuminance8.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdRGBA2.Create; begin - with result do begin - Format := GL_LUMINANCE; - InternalFormat := GL_LUMINANCE8; - DataType := GL_UNSIGNED_BYTE; - end; + inherited Create; + fFormat := tfRGBA2; + fWithAlpha := tfRGBA2; + fWithoutAlpha := tfR3G3B2; + fRange.r := $3; + fRange.g := $3; + fRange.b := $3; + fRange.a := $3; + fShift.r := 0; + fShift.g := 2; + fShift.b := 4; + fShift.a := 6; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGBA2; + fglDataFormat := GL_UNSIGNED_BYTE; end; -class function TfdLuminance8.WithAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdRGBA4.Create; +begin + inherited Create; + fFormat := tfRGBA4; + fWithAlpha := tfRGBA4; + fWithoutAlpha := tfRGB4; + fRange.r := $F; + fRange.g := $F; + fRange.b := $F; + fRange.a := $F; + fShift.r := 0; + fShift.g := 4; + fShift.b := 8; + fShift.a := 12; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGBA4; + fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdRGB5A1.Create; begin - result := tfLuminance8Alpha8; + inherited Create; + fFormat := tfRGB5A1; + fWithAlpha := tfRGB5A1; + fWithoutAlpha := tfRGB5; + fRange.r := $1F; + fRange.g := $1F; + fRange.b := $1F; + fRange.a := $01; + fShift.r := 0; + fShift.g := 5; + fShift.b := 10; + fShift.a := 15; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGB5_A1; + fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -class procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - aData^ := Trunc( - aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B); + inherited Map(aPixel, aData, aMapData); + aData^ := aPixel.Data.a; inc(aData); end; -class procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - aPixel.Red := aData^; - aPixel.Green := aData^; - aPixel.Blue := aData^; - aPixel.Alpha := 0; + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := aData^; inc(aData); end; -{$ENDREGION} -{$REGION TfdLuminance8Alpha8} +constructor TfdRGBA8.Create; +begin + inherited Create; + fPixelSize := 4.0; + fFormat := tfRGBA8; + fWithAlpha := tfRGBA8; + fWithoutAlpha := tfRGB8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fRange.a := $FF; + fShift.r := 0; + fShift.g := 8; + fShift.b := 16; + fShift.a := 24; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGBA8; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdLuminance8Alpha8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdLuminance8Alpha8.GetFormat: TglBitmapFormat; +constructor TfdRGB10A2.Create; begin - result := tfLuminance8Alpha8; + inherited Create; + fFormat := tfRGB10A2; + fWithAlpha := tfRGB10A2; + fWithoutAlpha := tfRGB10; + fRange.r := $3FF; + fRange.g := $3FF; + fRange.b := $3FF; + fRange.a := $003; + fShift.r := 0; + fShift.g := 10; + fShift.b := 20; + fShift.a := 30; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGB10_A2; + fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -class function TfdLuminance8Alpha8.GetPixelDesc: TglBitmapPixelDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGBA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - with result do begin - RedRange := $000000FF; RedShift := 0; - GreenRange := $000000FF; GreenShift := 0; - BlueRange := $000000FF; BlueShift := 0; - AlphaRange := $000000FF; AlphaShift := 8; - end; + inherited Map(aPixel, aData, aMapData); + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); end; -class function TfdLuminance8Alpha8.GetFormatDesc: TglBitmapFormatDesc; +procedure TfdRGBA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - with result do begin - Format := GL_LUMINANCE_ALPHA; - InternalFormat := GL_LUMINANCE8_ALPHA8; - DataType := GL_UNSIGNED_BYTE; - end; + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdRGBA16.Create; +begin + inherited Create; + fPixelSize := 8.0; + fFormat := tfRGBA16; + fWithAlpha := tfRGBA16; + fWithoutAlpha := tfRGB16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fRange.a := $FFFF; + fShift.r := 0; + fShift.g := 16; + fShift.b := 32; + fShift.a := 48; + fglFormat := GL_RGBA; + fglInternalFormat := GL_RGBA16; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGR4.Create; +begin + inherited Create; + fPixelSize := 2.0; + fFormat := tfBGR4; + fWithAlpha := tfBGRA4; + fWithoutAlpha := tfBGR4; + fRange.r := $F; + fRange.g := $F; + fRange.b := $F; + fRange.a := $0; + fShift.r := 8; + fShift.g := 4; + fShift.b := 0; + fShift.a := 0; + fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA + fglInternalFormat := GL_RGB4; + fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdB5G6R5.Create; +begin + inherited Create; + fPixelSize := 2.0; + fFormat := tfB5G6R5; + fWithAlpha := tfBGRA4; + fWithoutAlpha := tfB5G6R5; + fRange.r := $1F; + fRange.g := $3F; + fRange.b := $1F; + fShift.r := 11; + fShift.g := 5; + fShift.b := 0; + fglFormat := GL_RGB; + fglInternalFormat := GL_RGB8; + fglDataFormat := GL_UNSIGNED_SHORT_5_6_5; end; -class function TfdLuminance8Alpha8.WithoutAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGR5.Create; begin - result := tfLuminance8; + inherited Create; + fPixelSize := 2.0; + fFormat := tfBGR5; + fWithAlpha := tfBGR5A1; + fWithoutAlpha := tfBGR5; + fRange.r := $1F; + fRange.g := $1F; + fRange.b := $1F; + fRange.a := $00; + fShift.r := 10; + fShift.g := 5; + fShift.b := 0; + fShift.a := 0; + fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA + fglInternalFormat := GL_RGB5; + fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -class procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - aData^ := Trunc( - aPixel.Red * LUMINANCE_WEIGHT_R + - aPixel.Green * LUMINANCE_WEIGHT_G + - aPixel.Blue * LUMINANCE_WEIGHT_B); + aData^ := aPixel.Data.b; inc(aData); - - aData^ := aPixel.Alpha; + aData^ := aPixel.Data.g; + inc(aData); + aData^ := aPixel.Data.r; inc(aData); end; -class procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - aPixel.Red := aData^; - aPixel.Green := aData^; - aPixel.Blue := aData^; + aPixel.Data.b := aData^; inc(aData); - - aPixel.Alpha := aData^; + aPixel.Data.g := aData^; inc(aData); -end; -{$ENDREGION} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdRGB5///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdRGB5.GetFormat: TglBitmapFormat; -begin - result := tfRGB5; + aPixel.Data.r := aData^; + inc(aData); + aPixel.Data.a := 0; end; -class function TfdRGB5.GetPixelDesc: TglBitmapPixelDesc; +constructor TfdBGR8.Create; begin - with result do begin - RedRange := $0000001F; RedShift := 0; - GreenRange := $0000001F; GreenShift := 5; - BlueRange := $0000001F; BlueShift := 10; - AlphaRange := $00000000; AlphaShift := 0; - end; + inherited Create; + fPixelSize := 3.0; + fFormat := tfBGR8; + fWithAlpha := tfBGRA8; + fWithoutAlpha := tfBGR8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fRange.a := $00; + fShift.r := 16; + fShift.g := 8; + fShift.b := 0; + fShift.a := 0; + fglFormat := GL_BGR; + fglInternalFormat := GL_RGB8; + fglDataFormat := GL_UNSIGNED_BYTE; end; -class function TfdRGB5.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGR10.Create; begin - with result do begin - Format := GL_RGB; - InternalFormat := GL_RGB5; - DataType := GL_UNSIGNED_SHORT_5_5_5_1; - end; + inherited Create; + fFormat := tfBGR10; + fWithAlpha := tfBGR10A2; + fWithoutAlpha := tfBGR10; + fRange.r := $3FF; + fRange.g := $3FF; + fRange.b := $3FF; + fRange.a := $000; + fShift.r := 20; + fShift.g := 10; + fShift.b := 0; + fShift.a := 0; + fglFormat := GL_BGR; + fglInternalFormat := GL_RGB10; + fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -class function TfdRGB5.WithAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGR16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - result := tfRGB5A1; + PWord(aData)^ := aPixel.Data.b; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.g; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.r; + inc(aData, 2); end; -class procedure TfdRGB5.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +procedure TfdBGR16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - PWord(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift); + aPixel.Data.b := PWord(aData)^; + inc(aData, 2); + aPixel.Data.g := PWord(aData)^; inc(aData, 2); + aPixel.Data.r := PWord(aData)^; + inc(aData, 2); + aPixel.Data.a := 0; end; -class procedure TfdRGB5.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +constructor TfdBGR16.Create; begin - aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange; - aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange; - aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange; - aPixel.Alpha := 0; - inc(aData, 2); + inherited Create; + fPixelSize := 6.0; + fFormat := tfBGR16; + fWithAlpha := tfBGRA16; + fWithoutAlpha := tfBGR16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fRange.a := $0000; + fShift.r := 32; + fShift.g := 16; + fShift.b := 0; + fShift.a := 0; + fglFormat := GL_BGR; + fglInternalFormat := GL_RGB16; + fglDataFormat := GL_UNSIGNED_SHORT; end; -{$REGION TfdRGB8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdRGB8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdRGB8.GetFormat: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGRA2.Create; begin - result := tfRGB8; + inherited Create; + fFormat := tfBGRA2; + fWithAlpha := tfBGRA4; + fWithoutAlpha := tfBGR4; + fRange.r := $3; + fRange.g := $3; + fRange.b := $3; + fRange.a := $3; + fShift.r := 4; + fShift.g := 2; + fShift.b := 0; + fShift.a := 6; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGBA2; + fglDataFormat := GL_UNSIGNED_BYTE; end; -class function TfdRGB8.GetPixelDesc: TglBitmapPixelDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGRA4.Create; begin - with result do begin - RedRange := $000000FF; RedShift := 0; - GreenRange := $000000FF; GreenShift := 8; - BlueRange := $000000FF; BlueShift := 16; - AlphaRange := $00000000; AlphaShift := 0; - end; + inherited Create; + fFormat := tfBGRA4; + fWithAlpha := tfBGRA4; + fWithoutAlpha := tfBGR4; + fRange.r := $F; + fRange.g := $F; + fRange.b := $F; + fRange.a := $F; + fShift.r := 8; + fShift.g := 4; + fShift.b := 0; + fShift.a := 12; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGBA4; + fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; end; -class function TfdRGB8.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGR5A1.Create; begin - with result do begin - Format := GL_LUMINANCE; - InternalFormat := GL_LUMINANCE8; - DataType := GL_UNSIGNED_BYTE; - end; + inherited Create; + fFormat := tfBGR5A1; + fWithAlpha := tfBGR5A1; + fWithoutAlpha := tfBGR5; + fRange.r := $1F; + fRange.g := $1F; + fRange.b := $1F; + fRange.a := $01; + fShift.r := 10; + fShift.g := 5; + fShift.b := 0; + fShift.a := 15; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGB5_A1; + fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -class function TfdRGB8.WithAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////s +procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - result := tfRGBA8; + inherited Map(aPixel, aData, aMapData); + aData^ := aPixel.Data.a; + inc(aData); end; -class procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - aData^ := aPixel.Red; - inc(aData); - aData^ := aPixel.Green; - inc(aData); - aData^ := aPixel.Blue; + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := aData^; inc(aData); end; -class procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +constructor TfdBGRA8.Create; begin - aPixel.Red := aData^; - inc(aData); - aPixel.Green := aData^; - inc(aData); - aPixel.Blue := aData^; - inc(aData); - aPixel.Alpha := 0; + inherited Create; + fPixelSize := 4.0; + fFormat := tfBGRA8; + fWithAlpha := tfBGRA8; + fWithoutAlpha := tfBGR8; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fRange.a := $FF; + fShift.r := 16; + fShift.g := 8; + fShift.b := 0; + fShift.a := 24; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGBA8; + fglDataFormat := GL_UNSIGNED_BYTE; end; -{$ENDREGION} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdRGB5A1/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdRGB5A1.GetFormat: TglBitmapFormat; -begin - result := tfRGB5A1; -end; - -class function TfdRGB5A1.GetPixelDesc: TglBitmapPixelDesc; -begin - with result do begin - RedRange := $0000001F; RedShift := 0; - GreenRange := $0000001F; GreenShift := 5; - BlueRange := $0000001F; BlueShift := 10; - AlphaRange := $00000001; AlphaShift := 15; - end; -end; - -class function TfdRGB5A1.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TfdBGR10A2.Create; begin - with result do begin - Format := GL_RGBA; - InternalFormat := GL_RGB5_A1; - DataType := GL_UNSIGNED_SHORT_5_5_5_1; - end; + inherited Create; + fFormat := tfBGR10A2; + fWithAlpha := tfBGR10A2; + fWithoutAlpha := tfBGR10; + fRange.r := $3FF; + fRange.g := $3FF; + fRange.b := $3FF; + fRange.a := $003; + fShift.r := 20; + fShift.g := 10; + fShift.b := 0; + fShift.a := 30; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGB10_A2; + fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -class function TfdRGB5A1.WithoutAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGRA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - //TODO result := tfRGB5; + inherited Map(aPixel, aData, aMapData); + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); end; -class procedure TfdRGB5A1.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +procedure TfdBGRA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - PWord(aData)^ := - ((aPixel.Red and aPixel.PixelDesc.RedRange) shl aPixel.PixelDesc.RedShift) or - ((aPixel.Green and aPixel.PixelDesc.GreenRange) shl aPixel.PixelDesc.GreenShift) or - ((aPixel.Blue and aPixel.PixelDesc.BlueRange) shl aPixel.PixelDesc.BlueShift) or - ((aPixel.Alpha and aPixel.PixelDesc.AlphaRange) shl aPixel.PixelDesc.AlphaShift); + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := PWord(aData)^; inc(aData, 2); end; -class procedure TfdRGB5A1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +constructor TfdBGRA16.Create; begin - aPixel.Red := (PWord(aData)^ shr aPixel.PixelDesc.RedShift) and aPixel.PixelDesc.RedRange; - aPixel.Green := (PWord(aData)^ shr aPixel.PixelDesc.GreenShift) and aPixel.PixelDesc.GreenRange; - aPixel.Blue := (PWord(aData)^ shr aPixel.PixelDesc.BlueShift) and aPixel.PixelDesc.BlueRange; - aPixel.Alpha := (PWord(aData)^ shr aPixel.PixelDesc.AlphaShift) and aPixel.PixelDesc.AlphaRange; - inc(aData, 2); + inherited Create; + fPixelSize := 8.0; + fFormat := tfBGRA16; + fWithAlpha := tfBGRA16; + fWithoutAlpha := tfBGR16; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fRange.a := $FFFF; + fShift.r := 32; + fShift.g := 16; + fShift.b := 0; + fShift.a := 48; + fglFormat := GL_BGRA; + fglInternalFormat := GL_RGBA16; + fglDataFormat := GL_UNSIGNED_SHORT; end; -{$REGION TfdRGBA8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdRGBA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdRGBA8.GetFormat: TglBitmapFormat; -begin - result := tfRGBA8; -end; - -class function TfdRGBA8.GetPixelDesc: TglBitmapPixelDesc; +class procedure TFormatDescriptor.Init; begin - with result do begin - RedRange := $000000FF; RedShift := 0; - GreenRange := $000000FF; GreenShift := 8; - BlueRange := $000000FF; BlueShift := 16; - AlphaRange := $000000FF; AlphaShift := 24; - end; + if not Assigned(FormatDescriptorCS) then + FormatDescriptorCS := TCriticalSection.Create; end; -class function TfdRGBA8.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TFormatDescriptor.Get(const aFormat: TglBitmapFormat): TFormatDescriptor; begin - with result do begin - Format := GL_RGB; - InternalFormat := GL_RGB8; - DataType := GL_UNSIGNED_BYTE; + FormatDescriptorCS.Enter; + try + result := FormatDescriptors[aFormat]; + if not Assigned(result) then begin + result := FORMAT_DESCRIPTOR_CLASSES[aFormat].Create; + FormatDescriptors[aFormat] := result; + end; + finally + FormatDescriptorCS.Leave; end; end; -class function TfdRGBA8.WithoutAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TFormatDescriptor.GetWithAlpha(const aFormat: TglBitmapFormat): TFormatDescriptor; begin - result := tfRGB8; + result := Get(Get(aFormat).WithAlpha); end; -class procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class procedure TFormatDescriptor.Clear; +var + f: TglBitmapFormat; begin - aData^ := aPixel.Red; - inc(aData); - aData^ := aPixel.Green; - inc(aData); - aData^ := aPixel.Blue; - inc(aData); - aData^ := aPixel.Alpha; - inc(aData); + FormatDescriptorCS.Enter; + try + for f := low(FormatDescriptors) to high(FormatDescriptors) do + FreeAndNil(FormatDescriptors[f]); + finally + FormatDescriptorCS.Leave; + end; end; -class procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class procedure TFormatDescriptor.Finalize; begin - aPixel.Red := aData^; - inc(aData); - aPixel.Green := aData^; - inc(aData); - aPixel.Blue := aData^; - inc(aData); - aPixel.Alpha := aData^; - inc(aData); + Clear; + FreeAndNil(FormatDescriptorCS); end; -{$ENDREGION} -{$REGION TfdBGR8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdBGR8///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TBitfieldFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdBGR8.GetFormat: TglBitmapFormat; +procedure TBitfieldFormat.SetRedMask(const aValue: UInt64); begin - result := tfBGR8; + Update(aValue, fRange.r, fShift.r); end; -class function TfdBGR8.GetPixelDesc: TglBitmapPixelDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetGreenMask(const aValue: UInt64); begin - with result do begin - RedRange := $000000FF; RedShift := 16; - GreenRange := $000000FF; GreenShift := 8; - BlueRange := $000000FF; BlueShift := 0; - AlphaRange := $00000000; AlphaShift := 0; - end; + Update(aValue, fRange.g, fShift.g); end; -class function TfdBGR8.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetBlueMask(const aValue: UInt64); begin - with result do begin - Format := GL_BGR; - InternalFormat := GL_RGB8; - DataType := GL_UNSIGNED_BYTE; - end; + Update(aValue, fRange.b, fShift.b); end; -class function TfdBGR8.WithAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.SetAlphaMask(const aValue: UInt64); begin - result := tfBGRA8; + Update(aValue, fRange.a, fShift.a); end; -class procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out + aShift: Byte); begin - aData^ := aPixel.Blue; - inc(aData); - aData^ := aPixel.Green; - inc(aData); - aData^ := aPixel.Red; - inc(aData); -end; + aShift := 0; + aRange := 0; + if (aMask = 0) then + exit; + while (aMask > 0) and ((aMask and 1) = 0) do begin + inc(aShift); + aMask := aMask shr 1; + end; + aRange := 1; + while (aMask > 0) do begin + aRange := aRange shl 1; + aMask := aMask shr 1; + end; + dec(aRange); -class procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); -begin - aPixel.Blue := aData^; - inc(aData); - aPixel.Green := aData^; - inc(aData); - aPixel.Red := aData^; - inc(aData); + fPixelSize := Round(GetTopMostBit(RedMask or GreenMask or BlueMask or AlphaMask) / 8); end; -{$ENDREGION} -{$REGION TfdBGRA8} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdBGRA8//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -class function TfdBGRA8.GetFormat: TglBitmapFormat; -begin - result := tfBGRA8; -end; - -class function TfdBGRA8.GetPixelDesc: TglBitmapPixelDesc; +procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + data: UInt64; + s: Integer; +type + PUInt64 = ^UInt64; begin - with result do begin - RedRange := $000000FF; RedShift := 16; - GreenRange := $000000FF; GreenShift := 8; - BlueRange := $000000FF; BlueShift := 0; - AlphaRange := $000000FF; AlphaShift := 24; + data := + ((aPixel.Data.r and fRange.r) shl fShift.r) or + ((aPixel.Data.g and fRange.g) shl fShift.g) or + ((aPixel.Data.b and fRange.b) shl fShift.b) or + ((aPixel.Data.a and fRange.a) shl fShift.a); + s := Round(fPixelSize); + case s of + 1: aData^ := data; + 2: PWord(aData)^ := data; + 4: PCardinal(aData)^ := data; + 8: PUInt64(aData)^ := data; + else + raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; + inc(aData, s); end; -class function TfdBGRA8.GetFormatDesc: TglBitmapFormatDesc; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + data: UInt64; + s, i: Integer; +type + PUInt64 = ^UInt64; begin - with result do begin - Format := GL_BGRA; - InternalFormat := GL_RGBA8; - DataType := GL_UNSIGNED_BYTE; + s := Round(fPixelSize); + case s of + 1: data := aData^; + 2: data := PWord(aData)^; + 4: data := PCardinal(aData)^; + 8: data := PUInt64(aData)^; + else + raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; + for i := 0 to 3 do + aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, s); end; -class function TfdBGRA8.WithoutAlpha: TglBitmapFormat; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TColorTableFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - result := tfBGR8; + raise EglBitmapException.Create('mapping of color table formats is not supported'); end; -class procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte); +procedure TColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +type + PUInt64 = ^UInt64; +var + idx: UInt64; + s: Integer; + bits: Byte; + f: Single; begin - aData^ := aPixel.Blue; - inc(aData); - aData^ := aPixel.Green; - inc(aData); - aData^ := aPixel.Red; - inc(aData); - aData^ := aPixel.Alpha; - inc(aData); + s := Trunc(fPixelSize); + f := fPixelSize - s; + bits := Round(8 * f); + case s of + 0: idx := (aData^ shr (8 - bits - PtrInt(aMapData))) and ((1 shl bits) - 1); + 1: idx := aData^; + 2: idx := PWord(aData)^; + 4: idx := PCardinal(aData)^; + 8: idx := PUInt64(aData)^; + else + raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]); + end; + if (idx >= Length(fColorTable)) then + raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]); + with fColorTable[idx] do begin + aPixel.Data.r := r; + aPixel.Data.g := g; + aPixel.Data.b := b; + aPixel.Data.a := a; + end; + inc(aMapData, bits); + if (PtrInt(aMapData) >= 8) then begin + inc(aData, 1); + dec(aMapData, 8); + end; + inc(aData, s); end; -class procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData); +destructor TColorTableFormat.Destroy; begin - aPixel.Blue := aData^; - inc(aData); - aPixel.Green := aData^; - inc(aData); - aPixel.Red := aData^; - inc(aData); - aPixel.Alpha := aData^; - inc(aData); + SetLength(fColorTable, 0); + inherited Destroy; end; -{$ENDREGION} -{$REGION TglBitmap} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap - Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec); begin with aFuncRec do begin - if (Source.PixelDesc.RedRange > 0) then - Dest.Red := Source.Red; - if (Source.PixelDesc.GreenRange > 0) then - Dest.Green := Source.Green; - if (Source.PixelDesc.BlueRange > 0) then - Dest.Blue := Source.Blue; - if (Source.PixelDesc.AlphaRange > 0) then - Dest.Alpha := Source.Alpha; + if (Source.Range.r > 0) then + Dest.Data.r := Source.Data.r; + if (Source.Range.g > 0) then + Dest.Data.g := Source.Data.g; + if (Source.Range.b > 0) then + Dest.Data.b := Source.Data.b; + if (Source.Range.a > 0) then + Dest.Data.a := Source.Data.a; end; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapConvertCalculateRGBAFunc(var aFuncRec: TglBitmapFunctionRec); +var + i: Integer; begin with aFuncRec do begin - if (Source.PixelDesc.RedRange > 0) then - Dest.Red := Round(Dest.PixelDesc.RedRange * Source.Red / Source.PixelDesc.RedRange); - if (Source.PixelDesc.GreenRange > 0) then - Dest.Green := Round(Dest.PixelDesc.GreenRange * Source.Green / Source.PixelDesc.GreenRange); - if (Source.PixelDesc.BlueRange > 0) then - Dest.Blue := Round(Dest.PixelDesc.BlueRange * Source.Blue / Source.PixelDesc.BlueRange); - if (Source.PixelDesc.AlphaRange > 0) then - Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Source.Alpha / Source.PixelDesc.AlphaRange); + for i := 0 to 3 do + if (Source.Range.arr[i] > 0) then + Dest.Data.arr[i] := Round(Dest.Range.arr[i] * Source.Data.arr[i] / Source.Range.arr[i]); end; end; +type + TShiftData = packed record + case Integer of + 0: (r, g, b, a: SmallInt); + 1: (arr: array[0..3] of SmallInt); + end; + PShiftData = ^TShiftData; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapConvertShiftRGBAFunc(var aFuncRec: TglBitmapFunctionRec); +var + i: Integer; begin with aFuncRec do - with PglBitmapPixelDesc(Args)^ do begin - if (Source.PixelDesc.RedRange > 0) then - Dest.Red := Source.Red shr RedShift; - if (Source.PixelDesc.GreenRange > 0) then - Dest.Green := Source.Green shr GreenShift; - if (Source.PixelDesc.BlueRange > 0) then - Dest.Blue := Source.Blue shr BlueShift; - if (Source.PixelDesc.AlphaRange > 0) then - Dest.Alpha := Source.Alpha shr AlphaShift; - end; + for i := 0 to 3 do + if (Source.Range.arr[i] > 0) then + Dest.Data.arr[i] := Source.Data.arr[i] shr PShiftData(Args)^.arr[i]; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec); begin with aFuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; - Dest.Alpha := Source.Alpha; + Dest.Data.r := Source.Data.r; + Dest.Data.g := Source.Data.g; + Dest.Data.b := Source.Data.b; + Dest.Data.a := Source.Data.a; if (Args and $1 > 0) then begin - Dest.Red := Dest.Red xor Dest.PixelDesc.RedRange; - Dest.Green := Dest.Green xor Dest.PixelDesc.GreenRange; - Dest.Blue := Dest.Blue xor Dest.PixelDesc.BlueRange; + Dest.Data.r := Dest.Data.r xor Dest.Range.r; + Dest.Data.g := Dest.Data.g xor Dest.Range.g; + Dest.Data.b := Dest.Data.b xor Dest.Range.b; end; if (Args and $2 > 0) then begin - Dest.Alpha := Dest.Alpha xor Dest.PixelDesc.AlphaRange; + Dest.Data.a := Dest.Data.a xor Dest.Range.a; end; end; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapFillWithColorFunc(var aFuncRec: TglBitmapFunctionRec); -type - PglBitmapPixelData = ^TglBitmapPixelData; +var + i: Integer; begin with aFuncRec do begin - Dest.Red := PglBitmapPixelData(Args)^.Red; - Dest.Green := PglBitmapPixelData(Args)^.Green; - Dest.Blue := PglBitmapPixelData(Args)^.Blue; - Dest.Alpha := PglBitmapPixelData(Args)^.Alpha; + for i := 0 to 3 do + Dest.Data.arr[i] := PglBitmapPixelData(Args)^.Data.arr[i]; end; end; @@ -2639,12 +3343,12 @@ begin with FuncRec do begin if (FuncRec.Args = 0) then begin //source has no alpha Temp := - Source.Red / Source.PixelDesc.RedRange * ALPHA_WEIGHT_R + - Source.Green / Source.PixelDesc.GreenRange * ALPHA_WEIGHT_G + - Source.Blue / Source.PixelDesc.BlueRange * ALPHA_WEIGHT_B; - Dest.Alpha := Round(Dest.PixelDesc.AlphaRange * Temp); + Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R + + Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G + + Source.Data.b / Source.Range.b * ALPHA_WEIGHT_B; + Dest.Data.a := Round(Dest.Range.a * Temp); end else - Dest.Alpha := Round(Source.Alpha / Source.PixelDesc.AlphaRange * Dest.PixelDesc.AlphaRange); + Dest.Data.a := Round(Source.Data.a / Source.Range.a * Dest.Range.a); end; end; @@ -2654,17 +3358,17 @@ type PglBitmapPixelData = ^TglBitmapPixelData; begin with FuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; + Dest.Data.r := Source.Data.r; + Dest.Data.g := Source.Data.g; + Dest.Data.b := Source.Data.b; with PglBitmapPixelData(Args)^ do - if ((Dest.Red <= Red ) and (Dest.Red >= PixelDesc.RedRange ) and - (Dest.Green <= Green) and (Dest.Green >= PixelDesc.GreenRange) and - (Dest.Blue <= Blue ) and (Dest.Blue >= PixelDesc.BlueRange )) then - Dest.Alpha := 0 + if ((Dest.Data.r <= Data.r) and (Dest.Data.r >= Range.r) and + (Dest.Data.g <= Data.g) and (Dest.Data.g >= Range.g) and + (Dest.Data.b <= Data.b) and (Dest.Data.b >= Range.b)) then + Dest.Data.a := 0 else - Dest.Alpha := Dest.PixelDesc.AlphaRange; + Dest.Data.a := Dest.Range.a; end; end; @@ -2674,11 +3378,10 @@ type PglBitmapPixelData = ^TglBitmapPixelData; begin with FuncRec do begin - Dest.Red := Source.Red; - Dest.Green := Source.Green; - Dest.Blue := Source.Blue; - with PglBitmapPixelData(Args)^ do - Dest.Alpha := Alpha; + Dest.Data.r := Source.Data.r; + Dest.Data.g := Source.Data.g; + Dest.Data.b := Source.Data.b; + Dest.Data.a := PCardinal(Args)^; end; end; @@ -2706,7 +3409,6 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap - PROTECTED/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{$REGION Getter} function TglBitmap.GetWidth: Integer; begin if (ffX in fDimension.Fields) then @@ -2735,9 +3437,7 @@ function TglBitmap.GetFileHeight: Integer; begin result := Max(1, Height); end; -{$ENDREGION} -{$REGION Setter} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SetCustomData(const aValue: Pointer); begin @@ -2775,7 +3475,7 @@ procedure TglBitmap.SetFormat(const aValue: TglBitmapFormat); begin if fFormat = aValue then exit; - if (FORMAT_DESCRIPTORS[Format].GetSize <> FORMAT_DESCRIPTORS[aValue].GetSize) then + if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT); SetDataPointer(Data, aValue, Width, Height); end; @@ -2832,7 +3532,6 @@ begin end; end; end; -{$ENDREGION} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.CreateID; @@ -2891,7 +3590,7 @@ begin fDimension.Y := aHeight; end; - s := FORMAT_DESCRIPTORS[aFormat].GetSize; + s := TFormatDescriptor.Get(aFormat).PixelSize; fFormat := aFormat; fPixelSize := Ceil(s); fRowSize := Ceil(s * aWidth); @@ -2976,7 +3675,7 @@ var tmpData: PByte; size: Integer; begin - size := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize); + size := TFormatDescriptor.Get(aFormat).GetSize(aSize); GetMem(tmpData, size); try FillChar(tmpData^, size, #$FF); @@ -3069,7 +3768,8 @@ function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunct var DestData, TmpData, SourceData: pByte; TempHeight, TempWidth: Integer; - SourceFD, DestFD: TglBitmapFormatDescClass; + SourceFD, DestFD: TFormatDescriptor; + SourceMD, DestMD: Pointer; FuncRec: TglBitmapFunctionRec; begin @@ -3079,11 +3779,11 @@ begin result := false; if Assigned(aSource.Data) and ((aSource.Height > 0) or (aSource.Width > 0)) then begin - SourceFD := FORMAT_DESCRIPTORS[aSource.Format]; - DestFD := FORMAT_DESCRIPTORS[aFormat]; + SourceFD := TFormatDescriptor.Get(aSource.Format); + DestFD := TFormatDescriptor.Get(aFormat); // inkompatible Formats so CreateTemp - if (SourceFD.GetSize <> DestFD.GetSize) then + if (SourceFD.PixelSize <> DestFD.PixelSize) then aCreateTemp := true; // Values @@ -3095,7 +3795,7 @@ begin TmpData := nil; if aCreateTemp then begin - GetMem(TmpData, Ceil(FORMAT_DESCRIPTORS[aFormat].GetSize * TempHeight * TempWidth)); + GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight)); DestData := TmpData; end else DestData := Data; @@ -3104,49 +3804,37 @@ begin SourceFD.PreparePixel(FuncRec.Source); DestFD.PreparePixel (FuncRec.Dest); + SourceMD := SourceFD.CreateMappingData; + DestMD := DestFD.CreateMappingData; + FuncRec.Size := aSource.Dimension; FuncRec.Position.Fields := FuncRec.Size.Fields; - if {FormatIsUncompressed(Source.InternalFormat)} true then begin + try SourceData := aSource.Data; FuncRec.Position.Y := 0; while FuncRec.Position.Y < TempHeight do begin FuncRec.Position.X := 0; while FuncRec.Position.X < TempWidth do begin - SourceFD.Unmap(SourceData, FuncRec.Source); + SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD); aFunc(FuncRec); - DestFD.Map(FuncRec.Dest, DestData); + DestFD.Map(FuncRec.Dest, DestData, DestMD); inc(FuncRec.Position.X); end; inc(FuncRec.Position.Y); end; - end else begin - (* TODO - // Compressed Images - FuncRec.Position.Y := 0; - while FuncRec.Position.Y < TempHeight do begin - FuncRec.Position.X := 0; - while FuncRec.Position.X < TempWidth do begin - // Get Data - fGetPixelFunc(FuncRec.Position, FuncRec.Source); - // Func - Func(FuncRec); - // Set Data - MapFunc(FuncRec.Dest, dest); - Inc(FuncRec.Position.X); - end; - Inc(FuncRec.Position.Y); - end; - *) - end; - // Updating Image or InternalFormat - if aCreateTemp then - SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) - else if (aFormat <> fFormat) then - Format := aFormat; + // Updating Image or InternalFormat + if aCreateTemp then + SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) + else if (aFormat <> fFormat) then + Format := aFormat; - result := true; + result := true; + finally + SourceFD.FreeMappingData(SourceMD); + DestFD.FreeMappingData(DestMD); + end; except if aCreateTemp then FreeMem(TmpData); @@ -3530,7 +4218,7 @@ begin if not FormatIsUncompressed(InternalFormat) then raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT); *) - result := AddFunc(Self, aFunc, false, FORMAT_DESCRIPTORS[Format].WithAlpha, aArgs); + result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3564,7 +4252,8 @@ function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitm var DestData, DestData2, SourceData: pByte; TempHeight, TempWidth: Integer; - SourceFD, DestFD: TglBitmapFormatDescClass; + SourceFD, DestFD: TFormatDescriptor; + SourceMD, DestMD, DestMD2: Pointer; FuncRec: TglBitmapFunctionRec; begin @@ -3575,12 +4264,12 @@ begin Assert(Assigned(aBitmap.Data)); if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin - result := ConvertTo(FORMAT_DESCRIPTORS[Format].WithAlpha); + result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha); if not Assigned(aFunc) then aFunc := glBitmapAlphaFunc; - SourceFD := FORMAT_DESCRIPTORS[aBitmap.Format]; - DestFD := FORMAT_DESCRIPTORS[Format]; + SourceFD := TFormatDescriptor.Get(aBitmap.Format); + DestFD := TFormatDescriptor.Get(Format); // Values TempHeight := aBitmap.FileHeight; @@ -3600,22 +4289,30 @@ begin SourceFD.PreparePixel(FuncRec.Source); DestFD.PreparePixel (FuncRec.Dest); - FuncRec.Position.Y := 0; - while FuncRec.Position.Y < TempHeight do begin - FuncRec.Position.X := 0; - while FuncRec.Position.X < TempWidth do begin - SourceFD.Unmap(SourceData, FuncRec.Source); - DestFD.Unmap (DestData, FuncRec.Dest); - aFunc(FuncRec); - DestFD.Map(FuncRec.Dest, DestData2); - inc(FuncRec.Position.X); + SourceMD := SourceFD.CreateMappingData; + DestMD := DestFD.CreateMappingData; + DestMD2 := DestFD.CreateMappingData; + try + FuncRec.Position.Y := 0; + while FuncRec.Position.Y < TempHeight do begin + FuncRec.Position.X := 0; + while FuncRec.Position.X < TempWidth do begin + SourceFD.Unmap(SourceData, FuncRec.Source, SourceMD); + DestFD.Unmap (DestData, FuncRec.Dest, DestMD); + aFunc(FuncRec); + DestFD.Map(FuncRec.Dest, DestData2, DestMD2); + inc(FuncRec.Position.X); + end; + inc(FuncRec.Position.Y); end; - inc(FuncRec.Position.Y); + finally + SourceFD.FreeMappingData(SourceMD); + DestFD.FreeMappingData(DestMD); + DestFD.FreeMappingData(DestMD2); end; end; end; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte): Boolean; begin @@ -3627,34 +4324,35 @@ function TglBitmap.AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal var PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); result := AddAlphaFromColorKeyFloat( - aRed / PixelData.PixelDesc.RedRange, - aGreen / PixelData.PixelDesc.GreenRange, - aBlue / PixelData.PixelDesc.BlueRange, - aDeviation / Max(PixelData.PixelDesc.RedRange, Max(PixelData.PixelDesc.GreenRange, PixelData.PixelDesc.BlueRange))); + aRed / PixelData.Range.r, + aGreen / PixelData.Range.g, + aBlue / PixelData.Range.b, + aDeviation / Max(PixelData.Range.r, Max(PixelData.Range.g, PixelData.Range.b))); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AddAlphaFromColorKeyFloat(const aRed, aGreen, aBlue: Single; const aDeviation: Single): Boolean; var - TempR, TempG, TempB: Cardinal; + values: array[0..2] of Single; + tmp: Cardinal; + i: Integer; PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); - with PixelData.PixelDesc do begin - TempR := Trunc(RedRange * aDeviation); - TempG := Trunc(GreenRange * aDeviation); - TempB := Trunc(BlueRange * aDeviation); - - PixelData.Red := Min(RedRange, Trunc(RedRange * aRed) + TempR); - RedRange := Max(0, Trunc(RedRange * aRed) - TempR); - PixelData.Green := Min(GreenRange, Trunc(GreenRange * aGreen) + TempG); - GreenRange := Max(0, Trunc(GreenRange * aGreen) - TempG); - PixelData.Blue := Min(BlueRange, Trunc(BlueRange * aBlue) + TempB); - BlueRange := Max(0, Trunc(BlueRange * aBlue) - TempB); - PixelData.Alpha := 0; - AlphaRange := 0; + TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); + with PixelData do begin + values[0] := aRed; + values[1] := aGreen; + values[2] := aBlue; + + for i := 0 to 2 do begin + tmp := Trunc(Range.arr[i] * aDeviation); + Data.arr[i] := Min(Range.arr[i], Trunc(Range.arr[i] * values[i] + tmp)); + Range.arr[i] := Max(0, Trunc(Range.arr[i] * values[i] - tmp)); + end; + Data.a := 0; + Range.a := 0; end; result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData)); end; @@ -3670,8 +4368,8 @@ function TglBitmap.AddAlphaFromValueRange(const aAlpha: Cardinal): Boolean; var PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); - result := AddAlphaFromValueFloat(aAlpha / PixelData.PixelDesc.AlphaRange); + TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); + result := AddAlphaFromValueFloat(aAlpha / PixelData.Range.a); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3679,19 +4377,19 @@ function TglBitmap.AddAlphaFromValueFloat(const aAlpha: Single): Boolean; var PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); - with PixelData.PixelDesc do - PixelData.Alpha := Min(AlphaRange, Max(0, Round(AlphaRange * aAlpha))); - result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData)); + TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); + with PixelData do + Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha))); + result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData.Data.a)); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.RemoveAlpha: Boolean; var - FormatDesc: TglBitmapFormatDescClass; + FormatDesc: TFormatDescriptor; begin result := false; - FormatDesc := FORMAT_DESCRIPTORS[Format]; + FormatDesc := TFormatDescriptor.Get(Format); if Assigned(Data) then begin if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT); @@ -3711,7 +4409,7 @@ begin try // copy texture data if assigned if Assigned(Data) then begin - Size := FORMAT_DESCRIPTORS[Format].GetSize(fDimension); + Size := TFormatDescriptor.Get(Format).GetSize(fDimension); GetMem(TempPtr, Size); try Move(Data^, TempPtr^, Size); @@ -3752,26 +4450,26 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.ConvertTo(const aFormat: TglBitmapFormat): Boolean; var - SourceFD, DestFD: TglBitmapFormatDescClass; + SourceFD, DestFD: TFormatDescriptor; SourcePD, DestPD: TglBitmapPixelData; - PixelDesc: TglBitmapPixelDesc; + ShiftData: TShiftData; function CanCopyDirect: Boolean; begin result := - ((SourcePD.PixelDesc.RedRange = DestPD.PixelDesc.RedRange) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and - ((SourcePD.PixelDesc.GreenRange = DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and - ((SourcePD.PixelDesc.BlueRange = DestPD.PixelDesc.BlueRange) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and - ((SourcePD.PixelDesc.AlphaRange = DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0)); + ((SourcePD.Range.r = DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and + ((SourcePD.Range.g = DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and + ((SourcePD.Range.b = DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and + ((SourcePD.Range.a = DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0)); end; function CanShift: Boolean; begin result := - ((SourcePD.PixelDesc.RedRange >= DestPD.PixelDesc.RedRange ) or (SourcePD.PixelDesc.RedRange = 0) or (DestPD.PixelDesc.RedRange = 0)) and - ((SourcePD.PixelDesc.GreenRange >= DestPD.PixelDesc.GreenRange) or (SourcePD.PixelDesc.GreenRange = 0) or (DestPD.PixelDesc.GreenRange = 0)) and - ((SourcePD.PixelDesc.BlueRange >= DestPD.PixelDesc.BlueRange ) or (SourcePD.PixelDesc.BlueRange = 0) or (DestPD.PixelDesc.BlueRange = 0)) and - ((SourcePD.PixelDesc.AlphaRange >= DestPD.PixelDesc.AlphaRange) or (SourcePD.PixelDesc.AlphaRange = 0) or (DestPD.PixelDesc.AlphaRange = 0)); + ((SourcePD.Range.r >= DestPD.Range.r) or (SourcePD.Range.r = 0) or (DestPD.Range.r = 0)) and + ((SourcePD.Range.g >= DestPD.Range.g) or (SourcePD.Range.g = 0) or (DestPD.Range.g = 0)) and + ((SourcePD.Range.b >= DestPD.Range.b) or (SourcePD.Range.b = 0) or (DestPD.Range.b = 0)) and + ((SourcePD.Range.a >= DestPD.Range.a) or (SourcePD.Range.a = 0) or (DestPD.Range.a = 0)); end; function GetShift(aSource, aDest: Cardinal) : ShortInt; @@ -3785,8 +4483,8 @@ var begin if aFormat <> fFormat then begin - SourceFD := FORMAT_DESCRIPTORS[Format]; - DestFD := FORMAT_DESCRIPTORS[aFormat]; + SourceFD := TFormatDescriptor.Get(Format); + DestFD := TFormatDescriptor.Get(aFormat); SourceFD.PreparePixel(SourcePD); DestFD.PreparePixel (DestPD); @@ -3794,11 +4492,11 @@ begin if CanCopyDirect then result := AddFunc(Self, glBitmapConvertCopyFunc, false, aFormat) else if CanShift then begin - PixelDesc.RedShift := GetShift(SourcePD.PixelDesc.RedRange, DestPD.PixelDesc.RedRange); - PixelDesc.GreenShift := GetShift(SourcePD.PixelDesc.GreenRange, DestPD.PixelDesc.GreenRange); - PixelDesc.BlueShift := GetShift(SourcePD.PixelDesc.BlueRange, DestPD.PixelDesc.BlueRange); - PixelDesc.AlphaShift := GetShift(SourcePD.PixelDesc.AlphaRange, DestPD.PixelDesc.AlphaRange); - result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@PixelDesc)); + ShiftData.r := GetShift(SourcePD.Range.r, DestPD.Range.r); + ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g); + ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b); + ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a); + result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@ShiftData)); end else result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat); end else @@ -3843,12 +4541,12 @@ procedure TglBitmap.FillWithColorRange(const aRed, aGreen, aBlue: Cardinal; cons var PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[FORMAT_DESCRIPTORS[Format].WithAlpha].PreparePixel(PixelData); + TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); FillWithColorFloat( - aRed / PixelData.PixelDesc.RedRange, - aGreen / PixelData.PixelDesc.GreenRange, - aBlue / PixelData.PixelDesc.BlueRange, - aAlpha / PixelData.PixelDesc.AlphaRange); + aRed / PixelData.Range.r, + aGreen / PixelData.Range.g, + aBlue / PixelData.Range.b, + aAlpha / PixelData.Range.a); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3856,11 +4554,13 @@ procedure TglBitmap.FillWithColorFloat(const aRed, aGreen, aBlue: Single; const var PixelData: TglBitmapPixelData; begin - FORMAT_DESCRIPTORS[Format].PreparePixel(PixelData); - PixelData.Red := Max(0, Min(PixelData.PixelDesc.RedRange, Trunc(PixelData.PixelDesc.RedRange * aRed))); - PixelData.Green := Max(0, Min(PixelData.PixelDesc.GreenRange, Trunc(PixelData.PixelDesc.GreenRange * aGreen))); - PixelData.Blue := Max(0, Min(PixelData.PixelDesc.BlueRange, Trunc(PixelData.PixelDesc.BlueRange * aBlue))); - PixelData.Alpha := Max(0, Min(PixelData.PixelDesc.AlphaRange, Trunc(PixelData.PixelDesc.AlphaRange * aAlpha))); + TFormatDescriptor.Get(Format).PreparePixel(PixelData); + with PixelData do begin + Data.r := Max(0, Min(Range.r, Trunc(Range.r * aRed))); + Data.g := Max(0, Min(Range.g, Trunc(Range.g * aGreen))); + Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue))); + Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha))); + end; AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData)); end; @@ -4031,7 +4731,7 @@ var ImageSize: Integer; begin Create; - ImageSize := FORMAT_DESCRIPTORS[aFormat].GetSize(aSize); + TFormatDescriptor.Get(aFormat).GetSize(aSize); GetMem(Image, ImageSize); try FillChar(Image^, ImageSize, #$FF); @@ -4957,6 +5657,7 @@ type biClrImportant: Cardinal; end; + (* TODO: delete? TBMPInfoOS = packed record biSize: Cardinal; biWidth: Longint; @@ -4964,201 +5665,203 @@ type biPlanes: Word; biBitCount: Word; end; - -// TBMPPalette = record -// case Boolean of -// true : (Colors: array[Byte] of TRGBQUAD); -// false: (redMask, greenMask, blueMask: Cardinal); -// end; + *) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadBMP(const aStream: TStream): Boolean; -type - TMaskValues = packed record - Red: Cardinal; - Green: Cardinal; - Blue: Cardinal; - Alpha: Cardinal; - end; - -var - StartPos: Int64; ////////////////////////////////////////////////////////////////////////////////////////////////// - function ReadInfo(var aInfo: TBMPInfo; var aMask: TMaskValues): TglBitmapFormat; + function ReadInfo(var aInfo: TBMPInfo; var aMask: TglBitmapColorRec): TglBitmapFormat; begin result := tfEmpty; aStream.Read(aInfo, SizeOf(aInfo)); FillChar(aMask, SizeOf(aMask), 0); //Read Compression - if aInfo.biCompression <> BMP_COMP_RGB then begin - if aInfo.biCompression = BMP_COMP_BITFIELDS then begin - // Read Bitmasks for 16 or 32 Bit (24 Bit dosn't support Bitmasks!) + case aInfo.biCompression of + BMP_COMP_RLE4, + BMP_COMP_RLE8: begin + raise EglBitmapException.Create('RLE compression is not supported'); + end; + BMP_COMP_BITFIELDS: begin if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin - aStream.Read(aMask.Red, SizeOf(Cardinal)); - aStream.Read(aMask.Green, SizeOf(Cardinal)); - aStream.Read(aMask.Blue, SizeOf(Cardinal)); - aStream.Read(aMask.Alpha, SizeOf(Cardinal)); + aStream.Read(aMask.r, SizeOf(aMask.r)); + aStream.Read(aMask.g, SizeOf(aMask.g)); + aStream.Read(aMask.b, SizeOf(aMask.b)); + aStream.Read(aMask.a, SizeOf(aMask.a)); end else - raise EglBitmapException.Create('Bitmask is not supported for 24bit formats'); - end else begin - aStream.Position := StartPos; - raise EglBitmapException.Create('RLE compression is not supported'); + raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats'); end; end; //get suitable format case aInfo.biBitCount of 8: result := tfLuminance8; - 16: result := tfRGB5A1; + 16: result := tfBGR5; 24: result := tfBGR8; 32: result := tfBGRA8; end; end; + function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TColorTableFormat; + var + i, c: Integer; + ColorTable: TColorTable; + begin + result := nil; + if (aInfo.biBitCount >= 16) then + exit; + aFormat := tfLuminance8; + c := aInfo.biClrUsed; + if (c = 0) then + c := 1 shl aInfo.biBitCount; + SetLength(ColorTable, c); + for i := 0 to c-1 do begin + aStream.Read(ColorTable[i], SizeOf(TColorTableEnty)); + if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then + aFormat := tfRGB8; + end; + + result := TColorTableFormat.Create; + result.PixelSize := aInfo.biBitCount / 8; + result.ColorTable := ColorTable; + result.Range := glBitmapColorRec($FF, $FF, $FF, $00); + end; + ////////////////////////////////////////////////////////////////////////////////////////////////// - function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TMaskValues): TBitfieldFormat; + function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec; + const aInfo: TBMPInfo): TBitfieldFormat; var TmpFormat: TglBitmapFormat; - FormatDesc: TglBitmapFormatDescClass; + FormatDesc: TFormatDescriptor; begin result := nil; - if (aMask.Red <> 0) or (aMask.Green <> 0) or (aMask.Blue <> 0) or (aMask.Alpha <> 0) then begin - for TmpFormat := High(FORMAT_DESCRIPTORS) downto Low(FORMAT_DESCRIPTORS) do begin - FormatDesc := FORMAT_DESCRIPTORS[TmpFormat]; - if FormatDesc.MaskMatch(aMask.Red, aMask.Green, aMask.Blue, aMask.Alpha) then begin - aFormat := FormatDesc.GetFormat; + if (aMask.r <> 0) or (aMask.g <> 0) or (aMask.b <> 0) or (aMask.a <> 0) then begin + for TmpFormat := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin + FormatDesc := TFormatDescriptor.Get(TmpFormat); + if FormatDesc.MaskMatch(aMask.r, aMask.g, aMask.b, aMask.a) then begin + aFormat := FormatDesc.Format; exit; end; end; - if (aMask.Alpha = 0) then - aFormat := FORMAT_DESCRIPTORS[aFormat].WithoutAlpha; + if (aMask.a = 0) and TFormatDescriptor.Get(aFormat).HasAlpha then + aFormat := TFormatDescriptor.Get(aFormat).WithoutAlpha; + if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then + aFormat := TFormatDescriptor.Get(aFormat).WithAlpha; result := TBitfieldFormat.Create; - result.RedMask := aMask.Red; - result.GreenMask := aMask.Green; - result.BlueMask := aMask.Blue; - result.AlphaMask := aMask.Alpha; + result.PixelSize := aInfo.biBitCount / 8; + result.RedMask := aMask.r; + result.GreenMask := aMask.g; + result.BlueMask := aMask.b; + result.AlphaMask := aMask.a; end; end; var //simple types + StartPos: Int64; ImageSize, rbLineSize, wbLineSize, Padding, i: Integer; PaddingBuff: Cardinal; LineBuf, ImageData, TmpData: PByte; + SourceMD, DestMD: Pointer; BmpFormat: TglBitmapFormat; + ColorTable: TColorTable; //records - Mask: TMaskValues; + Mask: TglBitmapColorRec; Header: TBMPHeader; Info: TBMPInfo; //classes - BitfieldFormat: TBitfieldFormat; - FormatDesc: TglBitmapFormatDescClass; - - - Tick: QWord; -{ - - - ImageData, pData, pTmp, LineBuf, TmpData: PByte; - BitOffset: Byte; - BmpFormat: TglBitmapFormat; - LineSize, Padding, LineIdx, PixelIdx: Integer; - RedMask, GreenMask, BlueMask, AlphaMask, FormatSize: Cardinal; - - - Pixel: TglBitmapPixelData; - PaddingBuff: Cardinal; - - - - } + SpecialFormat: TFormatDescriptor; + FormatDesc: TFormatDescriptor; ////////////////////////////////////////////////////////////////////////////////////////////////// - procedure ReadBitfieldLine(aData: PByte; aLineBuf: PByte); + procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte); var - i: Integer; + i, j: Integer; Pixel: TglBitmapPixelData; - - //////////////////////////////////////////////////////////////////////////////////////////////// - procedure ChangeRange(var aValue: Cardinal; const aOldRange, aNewRange: Cardinal); - begin - if (aOldRange = aNewRange) then - exit; - if (aOldRange > 0) then - aValue := Round(aValue / aOldRange * aNewRange) - else - aValue := 0; - end; - begin aStream.Read(aLineBuf^, rbLineSize); + SpecialFormat.PreparePixel(Pixel); for i := 0 to Info.biWidth-1 do begin - BitfieldFormat.Unmap(PCardinal(aLineBuf)^, Pixel); //if is 16bit Bitfield only 2 last significant Bytes are taken from Cardinal - inc(aLineBuf, Info.biBitCount shr 3); - with FormatDesc.GetPixelDesc do begin - ChangeRange(Pixel.Red, BitfieldFormat.RedRange, RedRange); - ChangeRange(Pixel.Green, BitfieldFormat.GreenRange, GreenRange); - ChangeRange(Pixel.Blue, BitfieldFormat.BlueRange, BlueRange); - ChangeRange(Pixel.Alpha, BitfieldFormat.AlphaRange, AlphaRange); + SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD); + with FormatDesc do begin + //TODO: use convert function + for j := 0 to 3 do + if (SpecialFormat.Range.arr[j] <> Range.arr[j]) then begin + if (SpecialFormat.Range.arr[j] > 0) then + Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / SpecialFormat.Range.arr[j] * Range.arr[j]) + else + Pixel.Data.arr[j] := 0; + end; end; - FormatDesc.Map(Pixel, aData); + FormatDesc.Map(Pixel, aData, DestMD); end; end; begin - result := false; - BmpFormat := tfEmpty; - BitfieldFormat := nil; - LineBuf := nil; + result := false; + BmpFormat := tfEmpty; + SpecialFormat := nil; + LineBuf := nil; + SourceMD := nil; + DestMD := nil; // Header StartPos := aStream.Position; aStream.Read(Header, SizeOf(Header)); if Header.bfType = BMP_MAGIC then begin - BmpFormat := ReadInfo(Info, Mask); - BitfieldFormat := CheckBitfields(BmpFormat, Mask); - try - if (Info.biBitCount < 16) then - aStream.Position := aStream.Position + Info.biClrUsed * 4; + try try + BmpFormat := ReadInfo(Info, Mask); + SpecialFormat := ReadColorTable(BmpFormat, Info); + if not Assigned(SpecialFormat) then + SpecialFormat := CheckBitfields(BmpFormat, Mask, Info); aStream.Position := StartPos + Header.bfOffBits; if (BmpFormat <> tfEmpty) then begin - FormatDesc := FORMAT_DESCRIPTORS[BmpFormat]; - rbLineSize := Info.biWidth * (Info.biBitCount shr 3); //ReadBuffer LineSize - wbLineSize := Trunc(Info.biWidth * FormatDesc.GetSize); + FormatDesc := TFormatDescriptor.Get(BmpFormat); + rbLineSize := Round(Info.biWidth * Info.biBitCount / 8); //ReadBuffer LineSize + wbLineSize := Trunc(Info.biWidth * FormatDesc.PixelSize); Padding := (((Info.biWidth * Info.biBitCount + 31) and - 32) shr 3) - rbLineSize; //get Memory - ImageSize := FormatDesc.GetSize(glBitmapPosition(Info.biWidth, Info.biHeight)); + DestMD := FormatDesc.CreateMappingData; + ImageSize := FormatDesc.GetSize(Info.biWidth, abs(Info.biHeight)); GetMem(ImageData, ImageSize); - if Assigned(BitfieldFormat) then + if Assigned(SpecialFormat) then begin GetMem(LineBuf, rbLineSize); //tmp Memory for converting Bitfields + SourceMD := SpecialFormat.CreateMappingData; + end; //read Data try try FillChar(ImageData^, ImageSize, $FF); TmpData := ImageData; - Inc(TmpData, wbLineSize * (Info.biHeight -1)); - for i := 0 to Info.biHeight-1 do begin - if Assigned(BitfieldFormat) then - ReadBitfieldLine(TmpData, LineBuf) //if is bitfield format read and convert data + if (Info.biHeight > 0) then + Inc(TmpData, wbLineSize * (Info.biHeight-1)); + for i := 0 to Abs(Info.biHeight)-1 do begin + if Assigned(SpecialFormat) then + SpecialFormatReadLine(TmpData, LineBuf) //if is special format read and convert data else aStream.Read(TmpData^, wbLineSize); //else only read data - Dec(TmpData, wbLineSize); + if (Info.biHeight > 0) then + dec(TmpData, wbLineSize) + else + inc(TmpData, wbLineSize); aStream.Read(PaddingBuff, Padding); end; - SetDataPointer(ImageData, BmpFormat, Info.biWidth, Info.biHeight); + SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); result := true; finally if Assigned(LineBuf) then FreeMem(LineBuf); + if Assigned(SourceMD) then + SpecialFormat.FreeMappingData(SourceMD); + FormatDesc.FreeMappingData(DestMD); end; except FreeMem(ImageData); @@ -5166,8 +5869,12 @@ begin end; end else raise EglBitmapException.Create('LoadBMP - No suitable format found'); + except + aStream.Position := StartPos; + raise; + end; finally - FreeAndNil(BitfieldFormat); + FreeAndNil(SpecialFormat); end; end else aStream.Position := StartPos; @@ -5181,6 +5888,7 @@ var pData, pTemp: pByte; PixelFormat: TglBitmapPixelData; + FormatDesc: TFormatDescriptor; ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer; Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; @@ -5195,7 +5903,7 @@ begin if not (ftBMP in FormatGetSupportedFiles(Format)) then raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); - ImageSize := FORMAT_DESCRIPTORS[Format].GetSize(Dimension); + ImageSize := TFormatDescriptor.Get(Format).GetSize(Dimension); Header.bfType := BMP_MAGIC; Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; @@ -5248,13 +5956,11 @@ begin Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); - FORMAT_DESCRIPTORS[Format].PreparePixel(PixelFormat); - with PixelFormat.PixelDesc do begin - RedMask := RedRange shl RedShift; - GreenMask := GreenRange shl GreenShift; - BlueMask := BlueRange shl BlueShift; - AlphaMask := AlphaRange shl AlphaShift; - end; + FormatDesc := TFormatDescriptor.Get(Format); + RedMask := FormatDesc.RedMask; + GreenMask := FormatDesc.GreenMask; + BlueMask := FormatDesc.BlueMask; + AlphaMask := FormatDesc.AlphaMask; end; // headers @@ -5279,7 +5985,7 @@ begin end; // image data - LineSize := Trunc(Width * FORMAT_DESCRIPTORS[Format].GetSize); + LineSize := Trunc(Width * TFormatDescriptor.Get(Format).PixelSize); Padding := GetLineWidth - LineSize; PaddingBuff := 0; @@ -5527,7 +6233,7 @@ begin if Header.ImageID <> 0 then aStream.Position := aStream.Position + Header.ImageID; - PixelSize := Trunc(FORMAT_DESCRIPTORS[Format].GetSize); + PixelSize := TFormatDescriptor.Get(Format).GetSize(1, 1); LineSize := Trunc(Header.Width * PixelSize); GetMem(NewImage, LineSize * Header.Height); @@ -5569,7 +6275,7 @@ var Header: TTGAHeader; Size: Integer; pTemp: pByte; - FormatDesc: TglBitmapFormatDescClass; + FormatDesc: TFormatDescriptor; procedure ConvertData(pTemp: pByte); var @@ -5615,7 +6321,7 @@ begin Header.Width := Width; Header.Height := Height; Header.ImageDes := $20; - FormatDesc := FORMAT_DESCRIPTORS[Format]; + FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.HasAlpha then Header.ImageDes := Header.ImageDes or $08; @@ -5694,7 +6400,7 @@ type dwRBitMask: Cardinal; dwGBitMask: Cardinal; dwBBitMask: Cardinal; - dwAlphaBitMask: Cardinal; + dwABitMask: Cardinal; end; TDDSCaps = packed record @@ -5815,7 +6521,7 @@ begin end; ddsFormat := GetDDSFormat; - LineSize := Trunc(Header.dwWidth * FORMAT_DESCRIPTORS[ddsFormat].GetSize); + LineSize := Trunc(Header.dwWidth * TFormatDescriptor.Get(ddsFormat).PixelSize); GetMem(NewImage, Header.dwHeight * LineSize); try pData := NewImage; @@ -5853,6 +6559,7 @@ procedure TglBitmap.SaveDDS(const aStream: TStream); var Header: TDDSHeader; Pix: TglBitmapPixelData; + FormatDesc: TFormatDescriptor; begin //if not FormatIsUncompressed(InternalFormat) then // raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT); @@ -5860,7 +6567,7 @@ begin (* TODO if Format = tfAlpha8 then FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix); else *) - FORMAT_DESCRIPTORS[Format].PreparePixel(Pix); + TFormatDescriptor.Get(Format).PreparePixel(Pix); // Generell FillChar(Header, SizeOf(Header), 0); @@ -5893,16 +6600,16 @@ begin Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS; *) - Header.PixelFormat.dwRGBBitCount := Trunc(FORMAT_DESCRIPTORS[Format].GetSize * 8); - Header.PixelFormat.dwRBitMask := Pix.PixelDesc.RedRange shl Pix.PixelDesc.RedShift; - Header.PixelFormat.dwGBitMask := Pix.PixelDesc.GreenRange shl Pix.PixelDesc.GreenShift; - Header.PixelFormat.dwBBitMask := Pix.PixelDesc.BlueRange shl Pix.PixelDesc.BlueShift; - Header.PixelFormat.dwAlphaBitMask := Pix.PixelDesc.AlphaRange shl Pix.PixelDesc.AlphaShift; + FormatDesc := TFormatDescriptor.Get(Format); + Header.PixelFormat.dwRGBBitCount := Trunc(FormatDesc.PixelSize * 8); + Header.PixelFormat.dwRBitMask := FormatDesc.RedMask; + Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask; + Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask; + Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask; aStream.Write(Header, SizeOf(Header)); - aStream.Write(Data^, FORMAT_DESCRIPTORS[Format].GetSize(Dimension)); + aStream.Write(Data^, FormatDesc.GetSize(Dimension)); end; -{$ENDREGION} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap2D///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5932,7 +6639,7 @@ begin // Assigning Data if Assigned(Data) then begin SetLength(fLines, GetHeight); - LineWidth := Trunc(GetWidth * FORMAT_DESCRIPTORS[Format].GetSize); + LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize); for Idx := 0 to GetHeight -1 do begin fLines[Idx] := Data; @@ -5963,8 +6670,7 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean); var - FormatDescriptor: TglBitmapFormatDescClass; - FormatDesc: TglBitmapFormatDesc; + FormatDesc: TFormatDescriptor; begin glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -5974,14 +6680,13 @@ begin else *) - FormatDescriptor := FORMAT_DESCRIPTORS[Format]; - FormatDesc := FormatDescriptor.GetFormatDesc; + FormatDesc := TFormatDescriptor.Get(Format); if aBuildWithGlu then - gluBuild2DMipmaps(aTarget, FormatDescriptor.GetColorCompCount, Width, Height, - FormatDesc.Format, FormatDesc.DataType, Data) + gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height, + FormatDesc.glFormat, FormatDesc.glDataFormat, Data) else - glTexImage2D(aTarget, 0, FormatDesc.InternalFormat, Width, Height, 0, - FormatDesc.Format, FormatDesc.DataType, Data); + glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, + FormatDesc.glFormat, FormatDesc.glDataFormat, Data); // Freigeben if (FreeDataAfterGenTexture) then @@ -6000,8 +6705,7 @@ procedure TglBitmap2D.GrabScreen(const aTop, aLeft, aRight, aBottom: Integer; co var Temp: pByte; Size, w, h: Integer; - FormatDesc: TglBitmapFormatDescClass; - glFormatDesc: TglBitmapFormatDesc; + FormatDesc: TFormatDescriptor; begin (* TODO compression if not FormatIsUncompressed(Format) then @@ -6010,13 +6714,12 @@ begin w := aRight - aLeft; h := aBottom - aTop; - FormatDesc := FORMAT_DESCRIPTORS[Format]; - glFormatDesc := FormatDesc.GetFormatDesc; - Size := FormatDesc.GetSize(glBitmapPosition(w, h)); + FormatDesc := TFormatDescriptor.Get(Format); + Size := FormatDesc.GetSize(w, h); GetMem(Temp, Size); try glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(aLeft, aTop, w, h, glFormatDesc.Format, glFormatDesc.DataType, Temp); + glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp); SetDataPointer(Temp, Format, w, h); FlipVert; except @@ -6029,10 +6732,10 @@ end; procedure TglBitmap2D.GetDataFromTexture; var Temp: PByte; - TempWidth, TempHeight, RedSize, GreenSize, BlueSize, AlphaSize, LumSize: Integer; + TempWidth, TempHeight: Integer; TempType, TempIntFormat: Cardinal; - IntFormat: TglBitmapFormat; - FormatDesc: TglBitmapFormatDescClass; + IntFormat, f: TglBitmapFormat; + FormatDesc: TFormatDescriptor; begin Bind; @@ -6041,29 +6744,23 @@ begin glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_RED_SIZE, @RedSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_GREEN_SIZE, @GreenSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_BLUE_SIZE, @BlueSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_ALPHA_SIZE, @AlphaSize); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_LUMINANCE_SIZE, @LumSize); - IntFormat := tfEmpty; - for FormatDesc in FORMAT_DESCRIPTORS do - if (FormatDesc.GetFormatDesc.InternalFormat = TempIntFormat) then begin - IntFormat := FormatDesc.GetFormat; + for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do + if (TFormatDescriptor.Get(f).glInternalFormat = TempIntFormat) then begin + IntFormat := FormatDesc.Format; break; end; // Getting data from OpenGL - GetMem(Temp, FormatDesc.GetSize(glBitmapPosition(TempWidth, TempHeight))); + 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 glGetCompressedTexImage(Target, 0, Temp) else *) - with FormatDesc.GetFormatDesc do - glGetTexImage(Target, 0, InternalFormat, DataType, Temp); + glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp); SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); except FreeMem(Temp); @@ -6176,7 +6873,7 @@ type end; const - oneover255 = 1 / 255; + ONE_OVER_255 = 1 / 255; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapToNormalMapPrepareFunc(var FuncRec: TglBitmapFunctionRec); @@ -6184,8 +6881,11 @@ var Val: Single; begin with FuncRec do begin - Val := Source.Red * 0.3 + Source.Green * 0.59 + Source.Blue * 0.11; - PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * oneover255; + Val := + Source.Data.r * LUMINANCE_WEIGHT_R + + Source.Data.g * LUMINANCE_WEIGHT_G + + Source.Data.b * LUMINANCE_WEIGHT_B; + PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Val * ONE_OVER_255; end; end; @@ -6193,7 +6893,7 @@ end; procedure glBitmapToNormalMapPrepareAlphaFunc(var FuncRec: TglBitmapFunctionRec); begin with FuncRec do - PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Alpha * oneover255; + PglBitmapToNormalMapRec(Args)^.Heights[Position.Y * Size.X + Position.X] := Source.Data.a * ONE_OVER_255; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -6240,9 +6940,9 @@ begin end; // Farbe zuweisem - Dest.Red := Trunc((Vec[0] + 1) * 127.5); - Dest.Green := Trunc((Vec[1] + 1) * 127.5); - Dest.Blue := Trunc((Vec[2] + 1) * 127.5); + Dest.Data.r := Trunc((Vec[0] + 1) * 127.5); + Dest.Data.g := Trunc((Vec[1] + 1) * 127.5); + Dest.Data.b := Trunc((Vec[2] + 1) * 127.5); end; end; @@ -6370,7 +7070,7 @@ begin end; // Daten Sammeln - if aUseAlpha and FORMAT_DESCRIPTORS[Format].HasAlpha then + if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec)) else AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec)); @@ -6752,6 +7452,9 @@ initialization glBitmapSetDefaultFreeDataAfterGenTexture(true); glBitmapSetDefaultDeleteTextureOnFree (true); + TFormatDescriptor.Init; + finalization + TFormatDescriptor.Finalize; end. From 27f2bb249b3e0dd57b8af7a2c2018f0bc9603930 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 2 Nov 2013 19:03:49 +0100 Subject: [PATCH 07/38] * refactored FormatDescriptors (again) --- glBitmap.pas | 1474 +++++++++++++++++++++++++++++--------------------- 1 file changed, 859 insertions(+), 615 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index b2a1476..74b9233 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -593,21 +593,21 @@ type TglBitmapFormat = ( tfEmpty = 0, - //tfAlpha4, + tfAlpha4, tfAlpha8, - //tfAlpha12, + tfAlpha12, tfAlpha16, - //tfLuminance4, + tfLuminance4, tfLuminance8, - //tfLuminance12, + tfLuminance12, tfLuminance16, tfLuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, - //tfLuminance12Alpha12, + tfLuminance12Alpha12, tfLuminance16Alpha16, tfR3G3B2, @@ -616,7 +616,7 @@ type tfRGB5, tfRGB8, tfRGB10, - //tfRGB12, + tfRGB12, tfRGB16, tfRGBA2, @@ -624,7 +624,7 @@ type tfRGB5A1, tfRGBA8, tfRGB10A2, - //tfRGBA12, + tfRGBA12, tfRGBA16, tfBGR4, @@ -632,7 +632,7 @@ type tfBGR5, tfBGR8, tfBGR10, - //tfBGR12, + tfBGR12, tfBGR16, tfBGRA2, @@ -640,12 +640,12 @@ type tfBGR5A1, tfBGRA8, tfBGR10A2, - //tfBGRA12, - tfBGRA16 + tfBGRA12, + tfBGRA16, - //tfDepth16, - //tfDepth24, - //tfDepth32 + tfDepth16, + tfDepth24, + tfDepth32 ); TglBitmapFileType = ( @@ -1108,175 +1108,305 @@ type TfdEmpty = class(TFormatDescriptor); - TfdAlpha8 = class(TFormatDescriptor) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte 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; - TfdAlpha16 = class(TFormatDescriptor) + TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte 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; - TfdLuminance8 = class(TFormatDescriptor) + TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte 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; - TfdLuminance16 = class(TFormatDescriptor) + TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte 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; - TfdLuminance4Alpha4 = class(TFormatDescriptor) + TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte 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; - TfdLuminance6Alpha2 = class(TfdLuminance4Alpha4) + TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse) + 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; - TfdLuminance8Alpha8 = class(TFormatDescriptor) + TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte 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; - TfdLuminance12Alpha4 = class(TfdLuminance8Alpha8) + TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse) + 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; - TfdLuminance16Alpha16 = class(TFormatDescriptor) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short 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; - TfdR3G3B2 = class(TFormatDescriptor) + TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short 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; - TfdRGB4 = class(TFormatDescriptor) + TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short 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; - TfdR5G6B5 = class(TfdRGB4) + TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short + 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; - TfdRGB5 = class(TfdRGB4) + TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short + 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; - TfdRGB8 = class(TFormatDescriptor) + TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short 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; - TfdRGB10 = class(TFormatDescriptor) + TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse) 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; - TfdRGB16 = class(TFormatDescriptor) + TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short 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; - TfdRGBA2 = class(TfdR3G3B2) + TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse) + 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; - TfdRGBA4 = class(TfdRGB4) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int + 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; - TfdRGB5A1 = class(TfdRGB5) + TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int + 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; - TfdRGBA8 = class(TfdRGB8) - procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TfdAlpha4 = class(TfdAlpha_UB1) constructor Create; override; end; - TfdRGB10A2 = class(TfdRGB10) + TfdAlpha8 = class(TfdAlpha_UB1) constructor Create; override; end; - TfdRGBA16 = class(TfdRGB16) - procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + TfdAlpha12 = class(TfdAlpha_US1) constructor Create; override; end; - TfdBGR4 = class(TfdRGB4) + TfdAlpha16 = class(TfdAlpha_US1) constructor Create; override; end; - TfdB5G6R5 = class(TfdRGB4) + TfdLuminance4 = class(TfdLuminance_UB1) constructor Create; override; end; - TfdBGR5 = class(TfdRGB5) + TfdLuminance8 = class(TfdLuminance_UB1) constructor Create; override; end; - TfdBGR8 = 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; + TfdLuminance12 = class(TfdLuminance_US1) constructor Create; override; end; - TfdBGR10 = class(TfdRGB10) + TfdLuminance16 = class(TfdLuminance_US1) constructor Create; override; end; - TfdBGR16 = 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; + TfdLuminance4Alpha4 = class(TfdLuminanceAlpha_UB2) constructor Create; override; end; - TfdBGRA2 = class(TfdRGBA2) + TfdLuminance6Alpha2 = class(TfdLuminanceAlpha_UB2) constructor Create; override; end; - TfdBGRA4 = class(TfdRGBA4) + TfdLuminance8Alpha8 = class(TfdLuminanceAlpha_UB2) constructor Create; override; end; - TfdBGR5A1 = class(TfdRGB5A1) + TfdLuminance12Alpha4 = class(TfdLuminanceAlpha_US2) constructor Create; override; end; - TfdBGRA8 = class(TfdBGR8) - procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + TfdLuminance12Alpha12 = class(TfdLuminanceAlpha_US2) constructor Create; override; end; - TfdBGR10A2 = class(TfdRGB10A2) + TfdLuminance16Alpha16 = class(TfdLuminanceAlpha_US2) constructor Create; override; end; - TfdBGRA16 = class(TfdBGR16) - procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + TfdR3G3B2 = class(TfdUniversal_UB1) + constructor Create; override; + end; + + TfdRGB4 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdR5G6B5 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdRGB5 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdRGB8 = class(TfdRGB_UB3) + constructor Create; override; + end; + + TfdRGB10 = class(TfdUniversal_UI1) + constructor Create; override; + end; + + TfdRGB12 = class(TfdRGB_US3) + constructor Create; override; + end; + + TfdRGB16 = class(TfdRGB_US3) + constructor Create; override; + end; + + TfdRGBA2 = class(TfdRGBA_UB4) + constructor Create; override; + end; + + TfdRGBA4 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdRGB5A1 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdRGBA8 = class(TfdRGBA_UB4) + constructor Create; override; + end; + + TfdRGB10A2 = class(TfdUniversal_UI1) + constructor Create; override; + end; + + TfdRGBA12 = class(TfdRGBA_US4) + constructor Create; override; + end; + + TfdRGBA16 = class(TfdRGBA_US4) + constructor Create; override; + end; + + TfdBGR4 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdB5G6R5 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdBGR5 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdBGR8 = class(TfdBGR_UB3) + constructor Create; override; + end; + + TfdBGR10 = class(TfdUniversal_UI1) + constructor Create; override; + end; + + TfdBGR12 = class(TfdBGR_US3) + constructor Create; override; + end; + + TfdBGR16 = class(TfdBGR_US3) + constructor Create; override; + end; + + TfdBGRA2 = class(TfdBGRA_UB4) + constructor Create; override; + end; + + TfdBGRA4 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdBGR5A1 = class(TfdUniversal_US1) + constructor Create; override; + end; + + TfdBGRA8 = class(TfdBGRA_UB4) + constructor Create; override; + end; + + TfdBGR10A2 = class(TfdUniversal_UI1) + constructor Create; override; + end; + + TfdBGRA12 = class(TfdBGRA_US4) + constructor Create; override; + end; + + TfdBGRA16 = class(TfdBGRA_US4) + constructor Create; override; + end; + + TfdDepth16 = class(TfdDepth_US1) + constructor Create; override; + end; + + TfdDepth24 = class(TfdDepth_UI1) + constructor Create; override; + end; + + TfdDepth32 = class(TfdDepth_UI1) constructor Create; override; end; @@ -1328,26 +1458,30 @@ const ALPHA_WEIGHT_G = 0.59; ALPHA_WEIGHT_B = 0.11; + DEPTH_WEIGHT_R = 0.333333333; + DEPTH_WEIGHT_G = 0.333333333; + DEPTH_WEIGHT_B = 0.333333333; + UNSUPPORTED_FORMAT = 'the given format isn''t supported by this function.'; FORMAT_DESCRIPTOR_CLASSES: array[TglBitmapFormat] of TFormatDescriptorClass = ( TfdEmpty, - //TfdAlpha4, + TfdAlpha4, TfdAlpha8, - //TfdAlpha12, + TfdAlpha12, TfdAlpha16, - //TfdLuminance4, + TfdLuminance4, TfdLuminance8, - //TfdLuminance12, + TfdLuminance12, TfdLuminance16, TfdLuminance4Alpha4, TfdLuminance6Alpha2, TfdLuminance8Alpha8, TfdLuminance12Alpha4, - //TfdLuminance12Alpha12, + TfdLuminance12Alpha12, TfdLuminance16Alpha16, TfdR3G3B2, @@ -1356,7 +1490,7 @@ const TfdRGB5, TfdRGB8, TfdRGB10, - //TfdRGB12, + TfdRGB12, TfdRGB16, TfdRGBA2, @@ -1364,7 +1498,7 @@ const TfdRGB5A1, TfdRGBA8, TfdRGB10A2, - //TfdRGBA12, + TfdRGBA12, TfdRGBA16, TfdBGR4, @@ -1372,7 +1506,7 @@ const TfdBGR5, TfdBGR8, TfdBGR10, - //TfdBGR12, + TfdBGR12, TfdBGR16, TfdBGRA2, @@ -1380,12 +1514,12 @@ const TfdBGR5A1, TfdBGRA8, TfdBGR10A2, - //TfdBGRA12, - TfdBGRA16 + TfdBGRA12, + TfdBGRA16, - //TfdDepth16, - //TfdDepth24, - //TfdDepth32 + TfdDepth16, + TfdDepth24, + TfdDepth32 ); var @@ -1493,6 +1627,14 @@ begin LUMINANCE_WEIGHT_B * aPixel.Data.b); end; +function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal; +begin + result := Trunc( + DEPTH_WEIGHT_R * aPixel.Data.r + + DEPTH_WEIGHT_G * aPixel.Data.g + + DEPTH_WEIGHT_B * aPixel.Data.b); +end; + //TODO check _ARB functions and constants (* GLB_NO_NATIVE_GL @@ -2039,15 +2181,15 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdAlpha8/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdAlpha_UB1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdAlpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdAlpha_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin aData^ := aPixel.Data.a; inc(aData); end; -procedure TfdAlpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdAlpha_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := 0; aPixel.Data.g := 0; @@ -2056,56 +2198,25 @@ begin inc(aData^); end; -constructor TfdAlpha8.Create; +constructor TfdAlpha_UB1.Create; begin inherited Create; fPixelSize := 1.0; - fFormat := tfAlpha8; fRange.a := $FF; fglFormat := GL_ALPHA; - fglInternalFormat := GL_ALPHA8; fglDataFormat := GL_UNSIGNED_BYTE; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TfdAlpha16////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdAlpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - PWord(aData)^ := aPixel.Data.a; - inc(aData, 2); -end; - -procedure TfdAlpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -begin - aPixel.Data.r := 0; - aPixel.Data.g := 0; - aPixel.Data.b := 0; - aPixel.Data.a := PWord(aData)^; - inc(aData, 2); -end; - -constructor TfdAlpha16.Create; -begin - inherited Create; - fPixelSize := 2.0; - fFormat := tfAlpha16; - fRange.a := $FFFF; - fglFormat := GL_ALPHA; - fglInternalFormat := GL_ALPHA16; - fglDataFormat := GL_UNSIGNED_SHORT; -end; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminance_UB1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdLuminance8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdLuminance_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin aData^ := LuminanceWeight(aPixel); inc(aData); end; -procedure TfdLuminance8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdLuminance_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := aData^; aPixel.Data.g := aData^; @@ -2114,229 +2225,659 @@ begin inc(aData); end; -constructor TfdLuminance8.Create; +constructor TfdLuminance_UB1.Create; begin inherited Create; fPixelSize := 1.0; - fFormat := tfLuminance8; - fWithAlpha := tfLuminance8Alpha8; - fWithoutAlpha := tfLuminance8; fRange.r := $FF; fRange.g := $FF; fRange.b := $FF; fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE8; fglDataFormat := GL_UNSIGNED_BYTE; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdUniversal_UB1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdLuminance16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdUniversal_UB1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + i: Integer; begin - PWord(aData)^ := LuminanceWeight(aPixel); - inc(aData, 2); + aData^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); + inc(aData); end; -procedure TfdLuminance16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdUniversal_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; begin - aPixel.Data.r := PWord(aData)^; - aPixel.Data.g := PWord(aData)^; - aPixel.Data.b := PWord(aData)^; - aPixel.Data.a := 0; - inc(aData, 2); + for i := 0 to 3 do + aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData); end; -constructor TfdLuminance16.Create; +constructor TfdUniversal_UB1.Create; begin inherited Create; - fPixelSize := 2.0; - fFormat := tfLuminance16; - fWithAlpha := tfLuminance16Alpha16; - fWithoutAlpha := tfLuminance16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE16; - fglDataFormat := GL_UNSIGNED_SHORT; + fPixelSize := 1.0; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminanceAlpha_UB2/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdLuminance4Alpha4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdLuminanceAlpha_UB2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - aData^ := - ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or - ((aPixel.Data.a and fRange.a) shl fShift.a); + inherited Map(aPixel, aData, aMapData); + aData^ := aPixel.Data.a; inc(aData); end; -procedure TfdLuminance4Alpha4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -var - i: Integer; +procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - for i := 0 to 3 do - aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i]; + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := aData^; inc(aData); end; -constructor TfdLuminance4Alpha4.Create; -begin - inherited Create; - fPixelSize := 1.0; - fFormat := tfLuminance4Alpha4; - fWithAlpha := tfLuminance4Alpha4; - fWithoutAlpha := tfLuminance8; - fRange.r := $F; - fRange.g := $F; - fRange.b := $F; - fRange.a := $F; - fShift.a := 4; - fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE4_ALPHA4; - fglDataFormat := GL_UNSIGNED_BYTE; -end; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TfdLuminance6Alpha2.Create; +constructor TfdLuminanceAlpha_UB2.Create; begin inherited Create; - fFormat := tfLuminance6Alpha2; - fWithAlpha := tfLuminance6Alpha2; - fWithoutAlpha := tfLuminance8; - fRange.r := $3F; - fRange.g := $3F; - fRange.b := $3F; - fRange.a := $03; - fShift.a := 6; - fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE6_ALPHA2; + fPixelSize := 2.0; + fRange.a := $FF; + fShift.a := 8; + fglFormat := GL_LUMINANCE_ALPHA; fglDataFormat := GL_UNSIGNED_BYTE; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGB_UB3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdLuminance8Alpha8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdRGB_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - PWord(aData)^ := - ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or - ((aPixel.Data.a and fRange.a) shl fShift.a); - inc(aData, 2); + aData^ := aPixel.Data.r; + inc(aData); + aData^ := aPixel.Data.g; + inc(aData); + aData^ := aPixel.Data.b; + inc(aData); end; -procedure TfdLuminance8Alpha8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -var - i: Integer; +procedure TfdRGB_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - for i := 0 to 3 do - aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i]; - inc(aData, 2); + aPixel.Data.r := aData^; + inc(aData); + aPixel.Data.g := aData^; + inc(aData); + aPixel.Data.b := aData^; + inc(aData); + aPixel.Data.a := 0; end; -constructor TfdLuminance8Alpha8.Create; +constructor TfdRGB_UB3.Create; begin inherited Create; - fPixelSize := 2.0; - fFormat := tfLuminance8Alpha8; - fWithAlpha := tfLuminance8Alpha8; - fWithoutAlpha := tfLuminance8; + fPixelSize := 3.0; + fRange.r := $FF; + fRange.g := $FF; + fRange.b := $FF; + fShift.r := 0; + fShift.g := 8; + fShift.b := 16; + fglFormat := GL_RGB; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGR_UB3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGR_UB3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + aData^ := aPixel.Data.b; + inc(aData); + aData^ := aPixel.Data.g; + inc(aData); + aData^ := aPixel.Data.r; + inc(aData); +end; + +procedure TfdBGR_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.b := aData^; + inc(aData); + aPixel.Data.g := aData^; + inc(aData); + aPixel.Data.r := aData^; + inc(aData); + aPixel.Data.a := 0; +end; + +constructor TfdBGR_UB3.Create; +begin + fPixelSize := 3.0; fRange.r := $FF; fRange.g := $FF; fRange.b := $FF; + fShift.r := 16; + fShift.g := 8; + fShift.b := 0; + fglFormat := GL_BGR; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TdfRGBA_UB4///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGBA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + inherited Map(aPixel, aData, aMapData); + aData^ := aPixel.Data.a; + inc(aData); +end; + +procedure TfdRGBA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := aData^; + inc(aData); +end; + +constructor TfdRGBA_UB4.Create; +begin + inherited Create; + fPixelSize := 4.0; fRange.a := $FF; - fShift.a := 8; + fShift.a := 24; + fglFormat := GL_RGBA; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGRA_UB4///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGRA_UB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + inherited Map(aPixel, aData, aMapData); + aData^ := aPixel.Data.a; + inc(aData); +end; + +procedure TfdBGRA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := aData^; + inc(aData); +end; + +constructor TfdBGRA_UB4.Create; +begin + inherited Create; + fPixelSize := 4.0; + fRange.a := $FF; + fShift.a := 24; + fglFormat := GL_BGRA; + fglDataFormat := GL_UNSIGNED_BYTE; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdAlpha_US1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdAlpha_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); +end; + +procedure TfdAlpha_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := 0; + aPixel.Data.g := 0; + aPixel.Data.b := 0; + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdAlpha_US1.Create; +begin + inherited Create; + fPixelSize := 2.0; + fRange.a := $FFFF; + fglFormat := GL_ALPHA; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminance_US1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminance_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := LuminanceWeight(aPixel); + inc(aData, 2); +end; + +procedure TfdLuminance_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := PWord(aData)^; + aPixel.Data.g := PWord(aData)^; + aPixel.Data.b := PWord(aData)^; + aPixel.Data.a := 0; + inc(aData, 2); +end; + +constructor TfdLuminance_US1.Create; +begin + inherited Create; + fPixelSize := 2.0; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE8_ALPHA8; fglDataFormat := GL_UNSIGNED_SHORT; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdUniversal_US1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdUniversal_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + i: Integer; +begin + PWord(aData)^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); + inc(aData, 2); +end; + +procedure TfdUniversal_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +var + i: Integer; +begin + for i := 0 to 3 do + aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 2); +end; + +constructor TfdUniversal_US1.Create; +begin + inherited Create; + fPixelSize := 2.0; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdDepth_US1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdDepth_US1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := DepthWeight(aPixel); + inc(aData, 2); +end; + +procedure TfdDepth_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := PWord(aData)^; + aPixel.Data.g := PWord(aData)^; + aPixel.Data.b := PWord(aData)^; + aPixel.Data.a := 0; + inc(aData, 2); +end; + +constructor TfdDepth_US1.Create; +begin + inherited Create; + fPixelSize := 2.0; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fglFormat := GL_DEPTH_COMPONENT; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdLuminanceAlpha_US2/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdLuminanceAlpha_US2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + inherited Map(aPixel, aData, aMapData); + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); +end; + +procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdLuminanceAlpha_US2.Create; +begin + inherited Create; + fPixelSize := 4.0; + fRange.a := $FFFF; + fShift.a := 16; + fglFormat := GL_LUMINANCE_ALPHA; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGB_US3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGB_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := aPixel.Data.r; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.g; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.b; + inc(aData, 2); +end; + +procedure TfdRGB_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := PWord(aData)^; + inc(aData, 2); + aPixel.Data.g := PWord(aData)^; + inc(aData, 2); + aPixel.Data.b := PWord(aData)^; + inc(aData, 2); + aPixel.Data.a := 0; +end; + +constructor TfdRGB_US3.Create; +begin + inherited Create; + fPixelSize := 6.0; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fShift.r := 0; + fShift.g := 16; + fShift.b := 32; + fglFormat := GL_RGB; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGR_US3////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdBGR_US3.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PWord(aData)^ := aPixel.Data.b; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.g; + inc(aData, 2); + PWord(aData)^ := aPixel.Data.r; + inc(aData, 2); +end; + +procedure TfdBGR_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.b := PWord(aData)^; + inc(aData, 2); + aPixel.Data.g := PWord(aData)^; + inc(aData, 2); + aPixel.Data.r := PWord(aData)^; + inc(aData, 2); + aPixel.Data.a := 0; +end; + +constructor TfdBGR_US3.Create; +begin + inherited Create; + fPixelSize := 6.0; + fRange.r := $FFFF; + fRange.g := $FFFF; + fRange.b := $FFFF; + fShift.r := 32; + fShift.g := 16; + fShift.b := 0; + fglFormat := GL_BGR; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdRGBA_US4///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdRGBA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + inherited Map(aPixel, aData, aMapData); + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); +end; + +procedure TfdRGBA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdRGBA_US4.Create; +begin + inherited Create; + fPixelSize := 8.0; + fRange.a := $FFFF; + fShift.a := 48; + fglFormat := GL_RGBA; + fglDataFormat := GL_UNSIGNED_SHORT; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdBGRA_US4///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TfdLuminance12Alpha4.Create; +procedure TfdBGRA_US4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + inherited Map(aPixel, aData, aMapData); + PWord(aData)^ := aPixel.Data.a; + inc(aData, 2); +end; + +procedure TfdBGRA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + inherited Unmap(aData, aPixel, aMapData); + aPixel.Data.a := PWord(aData)^; + inc(aData, 2); +end; + +constructor TfdBGRA_US4.Create; begin inherited Create; - fFormat := tfLuminance12Alpha4; - fWithAlpha := tfLuminance12Alpha4; - fWithoutAlpha := tfLuminance16; - fRange.r := $FFF; - fRange.g := $FFF; - fRange.b := $FFF; - fRange.a := $00F; - fShift.a := 12; - fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE12_ALPHA4; + fPixelSize := 8.0; + fRange.a := $FFFF; + fShift.a := 48; + fglFormat := GL_BGRA; fglDataFormat := GL_UNSIGNED_SHORT; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdUniversal_UI1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdLuminance16Alpha16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TfdUniversal_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + i: Integer; begin - PCardinal(aData)^ := - ((LuminanceWeight(aPixel) and fRange.r) shl fShift.r) or - ((aPixel.Data.a and fRange.a) shl fShift.a); + PCardinal(aData)^ := 0; + for i := 0 to 3 do + if (fRange.arr[i] > 0) then + PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); inc(aData, 4); end; -procedure TfdLuminance16Alpha16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdUniversal_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); var i: Integer; begin for i := 0 to 3 do aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i]; + inc(aData, 2); +end; + +constructor TfdUniversal_UI1.Create; +begin + inherited Create; + fPixelSize := 4.0; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TfdDepth_UI1//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TfdDepth_UI1.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +begin + PCardinal(aData)^ := DepthWeight(aPixel); inc(aData, 4); end; -constructor TfdLuminance16Alpha16.Create; +procedure TfdDepth_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +begin + aPixel.Data.r := PCardinal(aData)^; + aPixel.Data.g := PCardinal(aData)^; + aPixel.Data.b := PCardinal(aData)^; + aPixel.Data.a := 0; + inc(aData, 4); +end; + +constructor TfdDepth_UI1.Create; begin inherited Create; - fFormat := tfLuminance16Alpha16; - fWithAlpha := tfLuminance16Alpha16; - fWithoutAlpha := tfLuminance16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fRange.a := $FFFF; - fShift.a := 16; - fglFormat := GL_LUMINANCE; - fglInternalFormat := GL_LUMINANCE16_ALPHA16; + fPixelSize := 4.0; + fRange.r := $FFFFFFFF; + fRange.g := $FFFFFFFF; + fRange.b := $FFFFFFFF; + fglFormat := GL_DEPTH_COMPONENT; fglDataFormat := GL_UNSIGNED_INT; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdR3G3B2.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -var - i: Integer; +constructor TfdAlpha4.Create; begin - aData^ := 0; - for i := 0 to 3 do - if (fRange.arr[i] > 0) then - aData^ := aData^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); - inc(aData); + inherited Create; + fFormat := tfAlpha4; + fWithAlpha := tfAlpha4; + fglInternalFormat := GL_ALPHA4; end; -procedure TfdR3G3B2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -var - i: Integer; +constructor TfdAlpha8.Create; begin - for i := 0 to 3 do - aPixel.Data.arr[i] := (aData^ shr fShift.arr[i]) and fRange.arr[i]; - inc(aData); + inherited Create; + fFormat := tfAlpha8; + fWithAlpha := tfAlpha8; + fglInternalFormat := GL_ALPHA8; +end; + +constructor TfdAlpha12.Create; +begin + inherited Create; + fFormat := tfAlpha12; + fWithAlpha := tfAlpha12; + fglInternalFormat := GL_ALPHA12; +end; + +constructor TfdAlpha16.Create; +begin + inherited Create; + fFormat := tfAlpha16; + fWithAlpha := tfAlpha16; + fglInternalFormat := GL_ALPHA16; +end; + +constructor TfdLuminance4.Create; +begin + inherited Create; + fFormat := tfLuminance4; + fWithAlpha := tfLuminance4Alpha4; + fWithoutAlpha := tfLuminance4; + fglInternalFormat := GL_LUMINANCE4; +end; + +constructor TfdLuminance8.Create; +begin + inherited Create; + fFormat := tfLuminance8; + fWithAlpha := tfLuminance8Alpha8; + fWithoutAlpha := tfLuminance8; + fglInternalFormat := GL_LUMINANCE8; +end; + +constructor TfdLuminance12.Create; +begin + inherited Create; + fFormat := tfLuminance12; + fWithAlpha := tfLuminance12Alpha12; + fWithoutAlpha := tfLuminance12; + fglInternalFormat := GL_LUMINANCE12; +end; + +constructor TfdLuminance16.Create; +begin + inherited Create; + fFormat := tfLuminance16; + fWithAlpha := tfLuminance16Alpha16; + fWithoutAlpha := tfLuminance16; + fglInternalFormat := GL_LUMINANCE16; +end; + +constructor TfdLuminance4Alpha4.Create; +begin + inherited Create; + fFormat := tfLuminance4Alpha4; + fWithAlpha := tfLuminance4Alpha4; + fWithoutAlpha := tfLuminance4; + fglInternalFormat := GL_LUMINANCE4_ALPHA4; +end; + +constructor TfdLuminance6Alpha2.Create; +begin + inherited Create; + fFormat := tfLuminance6Alpha2; + fWithAlpha := tfLuminance6Alpha2; + fWithoutAlpha := tfLuminance8; + fglInternalFormat := GL_LUMINANCE6_ALPHA2; +end; + +constructor TfdLuminance8Alpha8.Create; +begin + inherited Create; + fFormat := tfLuminance8Alpha8; + fWithAlpha := tfLuminance8Alpha8; + fWithoutAlpha := tfLuminance8; + fglInternalFormat := GL_LUMINANCE8_ALPHA8; +end; + +constructor TfdLuminance12Alpha4.Create; +begin + inherited Create; + fFormat := tfLuminance12Alpha4; + fWithAlpha := tfLuminance12Alpha4; + fWithoutAlpha := tfLuminance12; + fglInternalFormat := GL_LUMINANCE12_ALPHA4; +end; + +constructor TfdLuminance12Alpha12.Create; +begin + inherited Create; + fFormat := tfLuminance12Alpha12; + fWithAlpha := tfLuminance12Alpha12; + fWithoutAlpha := tfLuminance12; + fglInternalFormat := GL_LUMINANCE12_ALPHA12; +end; + +constructor TfdLuminance16Alpha16.Create; +begin + inherited Create; + fFormat := tfLuminance16Alpha16; + fWithAlpha := tfLuminance16Alpha16; + fWithoutAlpha := tfLuminance16; + fglInternalFormat := GL_LUMINANCE16_ALPHA16; end; constructor TfdR3G3B2.Create; begin inherited Create; - fPixelSize := 1.0; fFormat := tfR3G3B2; fWithAlpha := tfRGBA2; fWithoutAlpha := tfR3G3B2; @@ -2345,39 +2886,15 @@ begin fRange.b := $3; fShift.r := 0; fShift.g := 3; - fShift.b := 5; + fShift.b := 6; fglFormat := GL_RGB; fglInternalFormat := GL_R3_G3_B2; fglDataFormat := GL_UNSIGNED_BYTE_2_3_3_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGB4.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -var - i: Integer; -begin - PWord(aData)^ := 0; - for i := 0 to 3 do - if (fRange.arr[i] > 0) then - PWord(aData)^ := PWord(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); - inc(aData, 2); -end; - -procedure TfdRGB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -var - i: Integer; -begin - for i := 0 to 3 do - aPixel.Data.arr[i] := (PWord(aData)^ shr fShift.arr[i]) and fRange.arr[i]; - inc(aData, 2); -end; - constructor TfdRGB4.Create; begin inherited Create; - fPixelSize := 2.0; fFormat := tfRGB4; fWithAlpha := tfRGBA4; fWithoutAlpha := tfRGB4; @@ -2392,13 +2909,9 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdR5G6B5.Create; begin inherited Create; - fPixelSize := 2.0; fFormat := tfR5G6B5; fWithAlpha := tfRGBA4; fWithoutAlpha := tfR5G6B5; @@ -2409,17 +2922,13 @@ begin fShift.g := 5; fShift.b := 11; fglFormat := GL_RGB; - fglInternalFormat := GL_RGB8; + fglInternalFormat := GL_RGB565; fglDataFormat := GL_UNSIGNED_SHORT_5_6_5_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdRGB5.Create; begin inherited Create; - fPixelSize := 2.0; fFormat := tfRGB5; fWithAlpha := tfRGB5A1; fWithoutAlpha := tfRGB5; @@ -2434,75 +2943,18 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGB8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - aData^ := aPixel.Data.r; - inc(aData); - aData^ := aPixel.Data.g; - inc(aData); - aData^ := aPixel.Data.b; - inc(aData); -end; - -procedure TfdRGB8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -begin - aPixel.Data.r := aData^; - inc(aData); - aPixel.Data.g := aData^; - inc(aData); - aPixel.Data.b := aData^; - inc(aData); - aPixel.Data.a := 0; -end; - constructor TfdRGB8.Create; begin inherited Create; - fPixelSize := 3.0; fFormat := tfRGB8; fWithAlpha := tfRGBA8; - fWithoutAlpha := tfRGB8; - fRange.r := $FF; - fRange.g := $FF; - fRange.b := $FF; - fShift.r := 0; - fShift.g := 8; - fShift.b := 16; - fglFormat := GL_RGB; - fglInternalFormat := GL_RGB8; - fglDataFormat := GL_UNSIGNED_BYTE; -end; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGB10.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -var - i: Integer; -begin - PCardinal(aData)^ := 0; - for i := 0 to 3 do - if (fRange.arr[i] > 0) then - PCardinal(aData)^ := PCardinal(aData)^ or ((aPixel.Data.arr[i] and fRange.arr[i]) shl fShift.arr[i]); - inc(aData, 4); -end; - -procedure TfdRGB10.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -var - i: Integer; -begin - for i := 0 to 3 do - aPixel.Data.arr[i] := (PCardinal(aData)^ shr fShift.arr[i]) and fRange.arr[i]; - inc(aData, 4); + fWithoutAlpha := tfRGB8; + fglInternalFormat := GL_RGB8; end; constructor TfdRGB10.Create; begin inherited Create; - fPixelSize := 4.0; fFormat := tfRGB10; fWithAlpha := tfRGB10A2; fWithoutAlpha := tfRGB10; @@ -2512,78 +2964,38 @@ begin fShift.r := 0; fShift.g := 10; fShift.b := 20; - fglFormat := GL_RGB; + fglFormat := GL_RGBA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA fglInternalFormat := GL_RGB10; fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGB16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - PWord(aData)^ := aPixel.Data.r; - inc(aData, 2); - PWord(aData)^ := aPixel.Data.g; - inc(aData, 2); - PWord(aData)^ := aPixel.Data.b; - inc(aData, 2); -end; - -procedure TfdRGB16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +constructor TfdRGB12.Create; begin - aPixel.Data.r := PWord(aData)^; - inc(aData, 2); - aPixel.Data.g := PWord(aData)^; - inc(aData, 2); - aPixel.Data.b := PWord(aData)^; - inc(aData, 2); - aPixel.Data.a := 0; + inherited Create; + fFormat := tfRGB12; + fWithAlpha := tfRGBA12; + fWithoutAlpha := tfRGB12; + fglInternalFormat := GL_RGB12; end; constructor TfdRGB16.Create; begin inherited Create; - fPixelSize := 6.0; fFormat := tfRGB16; fWithAlpha := tfRGBA16; fWithoutAlpha := tfRGB16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fShift.r := 0; - fShift.g := 16; - fShift.b := 32; - fglFormat := GL_RGB; fglInternalFormat := GL_RGB16; - fglDataFormat := GL_UNSIGNED_SHORT; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdRGBA2.Create; begin inherited Create; fFormat := tfRGBA2; fWithAlpha := tfRGBA2; fWithoutAlpha := tfR3G3B2; - fRange.r := $3; - fRange.g := $3; - fRange.b := $3; - fRange.a := $3; - fShift.r := 0; - fShift.g := 2; - fShift.b := 4; - fShift.a := 6; - fglFormat := GL_RGBA; fglInternalFormat := GL_RGBA2; - fglDataFormat := GL_UNSIGNED_BYTE; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdRGBA4.Create; begin inherited Create; @@ -2603,9 +3015,6 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdRGB5A1.Create; begin inherited Create; @@ -2625,46 +3034,15 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGBA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - inherited Map(aPixel, aData, aMapData); - aData^ := aPixel.Data.a; - inc(aData); -end; - -procedure TfdRGBA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -begin - inherited Unmap(aData, aPixel, aMapData); - aPixel.Data.a := aData^; - inc(aData); -end; - constructor TfdRGBA8.Create; begin inherited Create; - fPixelSize := 4.0; fFormat := tfRGBA8; fWithAlpha := tfRGBA8; fWithoutAlpha := tfRGB8; - fRange.r := $FF; - fRange.g := $FF; - fRange.b := $FF; - fRange.a := $FF; - fShift.r := 0; - fShift.g := 8; - fShift.b := 16; - fShift.a := 24; - fglFormat := GL_RGBA; fglInternalFormat := GL_RGBA8; - fglDataFormat := GL_UNSIGNED_BYTE; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdRGB10A2.Create; begin inherited Create; @@ -2684,46 +3062,24 @@ begin fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdRGBA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - inherited Map(aPixel, aData, aMapData); - PWord(aData)^ := aPixel.Data.a; - inc(aData, 2); -end; - -procedure TfdRGBA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +constructor TfdRGBA12.Create; begin - inherited Unmap(aData, aPixel, aMapData); - aPixel.Data.a := PWord(aData)^; - inc(aData, 2); + inherited Create; + fFormat := tfRGBA12; + fWithAlpha := tfRGBA12; + fWithoutAlpha := tfRGB12; + fglInternalFormat := GL_RGBA12; end; constructor TfdRGBA16.Create; begin inherited Create; - fPixelSize := 8.0; fFormat := tfRGBA16; fWithAlpha := tfRGBA16; fWithoutAlpha := tfRGB16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fRange.a := $FFFF; - fShift.r := 0; - fShift.g := 16; - fShift.b := 32; - fShift.a := 48; - fglFormat := GL_RGBA; fglInternalFormat := GL_RGBA16; - fglDataFormat := GL_UNSIGNED_SHORT; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGR4.Create; begin inherited Create; @@ -2750,7 +3106,6 @@ end; constructor TfdB5G6R5.Create; begin inherited Create; - fPixelSize := 2.0; fFormat := tfB5G6R5; fWithAlpha := tfBGRA4; fWithoutAlpha := tfB5G6R5; @@ -2760,7 +3115,7 @@ begin fShift.r := 11; fShift.g := 5; fShift.b := 0; - fglFormat := GL_RGB; + fglFormat := GL_RGB; //B5G6R5 is only possible as R5G6B5 -> use reverted dataformat fglInternalFormat := GL_RGB8; fglDataFormat := GL_UNSIGNED_SHORT_5_6_5; end; @@ -2788,53 +3143,15 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdBGR8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - aData^ := aPixel.Data.b; - inc(aData); - aData^ := aPixel.Data.g; - inc(aData); - aData^ := aPixel.Data.r; - inc(aData); -end; - -procedure TfdBGR8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -begin - aPixel.Data.b := aData^; - inc(aData); - aPixel.Data.g := aData^; - inc(aData); - aPixel.Data.r := aData^; - inc(aData); - aPixel.Data.a := 0; -end; - constructor TfdBGR8.Create; begin inherited Create; - fPixelSize := 3.0; fFormat := tfBGR8; fWithAlpha := tfBGRA8; fWithoutAlpha := tfBGR8; - fRange.r := $FF; - fRange.g := $FF; - fRange.b := $FF; - fRange.a := $00; - fShift.r := 16; - fShift.g := 8; - fShift.b := 0; - fShift.a := 0; - fglFormat := GL_BGR; fglInternalFormat := GL_RGB8; - fglDataFormat := GL_UNSIGNED_BYTE; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGR10.Create; begin inherited Create; @@ -2849,80 +3166,38 @@ begin fShift.g := 10; fShift.b := 0; fShift.a := 0; - fglFormat := GL_BGR; + fglFormat := GL_BGRA; //GL_INVALID_OPERATION if not GL_BGRA or GL_RGBA fglInternalFormat := GL_RGB10; fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdBGR16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - PWord(aData)^ := aPixel.Data.b; - inc(aData, 2); - PWord(aData)^ := aPixel.Data.g; - inc(aData, 2); - PWord(aData)^ := aPixel.Data.r; - inc(aData, 2); -end; - -procedure TfdBGR16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +constructor TfdBGR12.Create; begin - aPixel.Data.b := PWord(aData)^; - inc(aData, 2); - aPixel.Data.g := PWord(aData)^; - inc(aData, 2); - aPixel.Data.r := PWord(aData)^; - inc(aData, 2); - aPixel.Data.a := 0; + inherited Create; + fFormat := tfBGR12; + fWithAlpha := tfBGRA12; + fWithoutAlpha := tfBGR12; + fglInternalFormat := GL_RGB12; end; constructor TfdBGR16.Create; begin inherited Create; - fPixelSize := 6.0; fFormat := tfBGR16; fWithAlpha := tfBGRA16; fWithoutAlpha := tfBGR16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fRange.a := $0000; - fShift.r := 32; - fShift.g := 16; - fShift.b := 0; - fShift.a := 0; - fglFormat := GL_BGR; fglInternalFormat := GL_RGB16; - fglDataFormat := GL_UNSIGNED_SHORT; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGRA2.Create; begin inherited Create; fFormat := tfBGRA2; fWithAlpha := tfBGRA4; fWithoutAlpha := tfBGR4; - fRange.r := $3; - fRange.g := $3; - fRange.b := $3; - fRange.a := $3; - fShift.r := 4; - fShift.g := 2; - fShift.b := 0; - fShift.a := 6; - fglFormat := GL_BGRA; fglInternalFormat := GL_RGBA2; - fglDataFormat := GL_UNSIGNED_BYTE; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGRA4.Create; begin inherited Create; @@ -2942,9 +3217,6 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_4_4_4_4_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGR5A1.Create; begin inherited Create; @@ -2964,46 +3236,15 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_1_5_5_5_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////s -procedure TfdBGRA8.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - inherited Map(aPixel, aData, aMapData); - aData^ := aPixel.Data.a; - inc(aData); -end; - -procedure TfdBGRA8.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); -begin - inherited Unmap(aData, aPixel, aMapData); - aPixel.Data.a := aData^; - inc(aData); -end; - constructor TfdBGRA8.Create; begin inherited Create; - fPixelSize := 4.0; fFormat := tfBGRA8; fWithAlpha := tfBGRA8; fWithoutAlpha := tfBGR8; - fRange.r := $FF; - fRange.g := $FF; - fRange.b := $FF; - fRange.a := $FF; - fShift.r := 16; - fShift.g := 8; - fShift.b := 0; - fShift.a := 24; - fglFormat := GL_BGRA; fglInternalFormat := GL_RGBA8; - fglDataFormat := GL_UNSIGNED_BYTE; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGR10A2.Create; begin inherited Create; @@ -3023,41 +3264,49 @@ begin fglDataFormat := GL_UNSIGNED_INT_2_10_10_10_REV; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TfdBGRA16.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); -begin - inherited Map(aPixel, aData, aMapData); - PWord(aData)^ := aPixel.Data.a; - inc(aData, 2); -end; - -procedure TfdBGRA16.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +constructor TfdBGRA12.Create; begin - inherited Unmap(aData, aPixel, aMapData); - aPixel.Data.a := PWord(aData)^; - inc(aData, 2); + inherited Create; + fFormat := tfBGRA12; + fWithAlpha := tfBGRA12; + fWithoutAlpha := tfBGR12; + fglInternalFormat := GL_RGBA12; end; constructor TfdBGRA16.Create; begin inherited Create; - fPixelSize := 8.0; fFormat := tfBGRA16; fWithAlpha := tfBGRA16; fWithoutAlpha := tfBGR16; - fRange.r := $FFFF; - fRange.g := $FFFF; - fRange.b := $FFFF; - fRange.a := $FFFF; - fShift.r := 32; - fShift.g := 16; - fShift.b := 0; - fShift.a := 48; - fglFormat := GL_BGRA; fglInternalFormat := GL_RGBA16; - fglDataFormat := GL_UNSIGNED_SHORT; +end; + +constructor TfdDepth16.Create; +begin + inherited Create; + fFormat := tfDepth16; + fWithAlpha := tfEmpty; + fWithoutAlpha := tfDepth16; + fglInternalFormat := GL_DEPTH_COMPONENT16; +end; + +constructor TfdDepth24.Create; +begin + inherited Create; + fFormat := tfDepth24; + fWithAlpha := tfEmpty; + fWithoutAlpha := tfDepth24; + fglInternalFormat := GL_DEPTH_COMPONENT24; +end; + +constructor TfdDepth32.Create; +begin + inherited Create; + fFormat := tfDepth32; + fWithAlpha := tfEmpty; + fWithoutAlpha := tfDepth32; + fglInternalFormat := GL_DEPTH_COMPONENT32; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4482,7 +4731,7 @@ var end; begin - if aFormat <> fFormat then begin + if (aFormat <> fFormat) and (aFormat <> tfEmpty) then begin SourceFD := TFormatDescriptor.Get(Format); DestFD := TFormatDescriptor.Get(aFormat); @@ -5919,33 +6168,28 @@ begin Info.biCompression := BMP_COMP_RGB; Info.biSizeImage := ImageSize; case Format of - //TODO tfAlpha8, ifLuminance8, ifDepth8: - tfLuminance8: - begin - Info.biBitCount := 8; + tfR3G3B2, tfLuminance8: begin + Info.biBitCount := 8; + Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); + end; - Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); - Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); + tfRGB5, tfRGB5A1, tfR5G6B5, tfRGB4, tfRGBA4, + tfBGR5, tfBGR5A1, tfB5G6R5, tfBGR4, tfBGRA4: begin + Info.biBitCount := 16; + Info.biCompression := BMP_COMP_BITFIELDS; + end; - Info.biClrUsed := 256; - Info.biClrImportant := 256; - end; - //TODO ifLuminance8Alpha8, tfRGBA4, ifR5G6B5, tfRGB5A1: - tfLuminance8Alpha8, tfRGB5A1: - begin - Info.biBitCount := 16; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - tfBGR8, tfRGB8: + tfBGR8, tfRGB8: begin Info.biBitCount := 24; - //TODO tfBGRA8, tfRGBA8, tfRGB10A2: - tfBGRA8, tfRGBA8: - begin - Info.biBitCount := 32; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - else - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); + end; + + tfRGB10, tfRGB10A2, tfRGBA8, + tfBGR10, tfBGR10A2, tfBGRA8: begin + Info.biBitCount := 32; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + else + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); end; Info.biXPelsPerMeter := 2835; Info.biYPelsPerMeter := 2835; From 7f2710a823a2f2eb01b49a58e3440ceaaf2b996c Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 3 Nov 2013 02:59:44 +0100 Subject: [PATCH 08/38] * SaveBMP for all supported formats --- glBitmap.pas | 399 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 275 insertions(+), 124 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 74b9233..68d9cde 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1411,7 +1411,7 @@ type end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TBitfieldFormat = class(TFormatDescriptor) + TbmpBitfieldFormat = class(TFormatDescriptor) private procedure SetRedMask (const aValue: UInt64); procedure SetGreenMask(const aValue: UInt64); @@ -1432,17 +1432,21 @@ type end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TColorTableEnty = packed record + TbmpColorTableEnty = packed record b, g, r, a: Byte; end; - TColorTable = array of TColorTableEnty; - TColorTableFormat = class(TFormatDescriptor) + TbmpColorTable = array of TbmpColorTableEnty; + TbmpColorTableFormat = class(TFormatDescriptor) private - fColorTable: TColorTable; + fColorTable: TbmpColorTable; public property PixelSize: Single read fPixelSize write fPixelSize; - property ColorTable: TColorTable read fColorTable write fColorTable; + property ColorTable: TbmpColorTable read fColorTable write fColorTable; property Range: TglBitmapColorRec read fRange write fRange; + property Shift: TShiftRec read fShift write fShift; + property Format: TglBitmapFormat read fFormat write fFormat; + + procedure CreateColorTable; procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; @@ -1549,11 +1553,41 @@ begin result.a := a; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec; +begin + result.r := r; + result.g := g; + result.b := b; + result.a := a; +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin + result := [ftDDS, ftTGA]; + + if (aFormat in [ + //4 bbp + tfLuminance4, + + //8bpp + tfR3G3B2, tfLuminance8, + + //16bpp + tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4, + tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4, + + //24bpp + tfBGR8, tfRGB8, + + //32bpp + tfRGB10, tfRGB10A2, tfRGBA8, + tfBGR10, tfBGR10A2, tfBGRA8]) then + result := result + [ftBMP]; + //TODO Supported File Formats! - result := [ftDDS, ftTGA, ftBMP]; + (* {$IFDEF GLB_SUPPORT_PNG_WRITE} if aFormat in [ @@ -3363,31 +3397,31 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TBitfieldFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetRedMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64); begin Update(aValue, fRange.r, fShift.r); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetGreenMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64); begin Update(aValue, fRange.g, fShift.g); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetBlueMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64); begin Update(aValue, fRange.b, fShift.b); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.SetAlphaMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64); begin Update(aValue, fRange.a, fShift.a); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out +procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte); begin aShift := 0; @@ -3409,7 +3443,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); var data: UInt64; s: Integer; @@ -3434,7 +3468,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TbmpBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); var data: UInt64; s, i: Integer; @@ -3458,12 +3492,90 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TColorTableFormat/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +procedure TbmpColorTableFormat.CreateColorTable; +var + bits: Byte; + len: Integer; + i: Integer; begin - raise EglBitmapException.Create('mapping of color table formats is not supported'); + if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then + raise EglBitmapException.Create(UNSUPPORTED_FORMAT); + + if (Format = tfLuminance4) then + SetLength(fColorTable, 16) + else + SetLength(fColorTable, 256); + + case Format of + tfLuminance4: begin + for i := 0 to High(fColorTable) do begin + fColorTable[i].r := 16 * i; + fColorTable[i].g := 16 * i; + fColorTable[i].b := 16 * i; + fColorTable[i].a := 0; + end; + end; + + tfLuminance8: begin + for i := 0 to High(fColorTable) do begin + fColorTable[i].r := i; + fColorTable[i].g := i; + fColorTable[i].b := i; + fColorTable[i].a := 0; + end; + end; + + tfR3G3B2: begin + for i := 0 to High(fColorTable) do begin + fColorTable[i].r := Round(((i shr Shift.r) and Range.r) / Range.r * 255); + fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255); + fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255); + fColorTable[i].a := 0; + + s := SysUtils.Format('%.2X%.2X%.2X' + sLineBreak, [fColorTable[i].r, fColorTable[i].g, fColorTable[i].b]); + fs.Write(s[1], Length(s)); + end; + end; + end; end; -procedure TColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TbmpColorTableFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); +var + d: Byte; +begin + if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then + raise EglBitmapException.Create(UNSUPPORTED_FORMAT); + + case Format of + tfLuminance4: begin + if (aMapData = nil) then + aData^ := 0; + d := LuminanceWeight(aPixel) and Range.r; + aData^ := aData^ or (d shl (4 - PtrInt(aMapData))); + inc(aMapData, 4); + if (PtrInt(aMapData) >= 8) then begin + inc(aData); + aMapData := nil; + end; + end; + + tfLuminance8: begin + aData^ := LuminanceWeight(aPixel) and Range.r; + inc(aData); + end; + + tfR3G3B2: begin + aData^ := Round( + ((aPixel.Data.r and Range.r) shl Shift.r) or + ((aPixel.Data.g and Range.g) shl Shift.g) or + ((aPixel.Data.b and Range.b) shl Shift.b)); + inc(aData); + end; + end; +end; + +procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); type PUInt64 = ^UInt64; var @@ -3500,7 +3612,7 @@ begin inc(aData, s); end; -destructor TColorTableFormat.Destroy; +destructor TbmpColorTableFormat.Destroy; begin SetLength(fColorTable, 0); inherited Destroy; @@ -5906,16 +6018,6 @@ type biClrImportant: Cardinal; end; - (* TODO: delete? - TBMPInfoOS = packed record - biSize: Cardinal; - biWidth: Longint; - biHeight: Longint; - biPlanes: Word; - biBitCount: Word; - end; - *) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadBMP(const aStream: TStream): Boolean; @@ -5952,10 +6054,10 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean; end; end; - function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TColorTableFormat; + function ReadColorTable(var aFormat: TglBitmapFormat; const aInfo: TBMPInfo): TbmpColorTableFormat; var i, c: Integer; - ColorTable: TColorTable; + ColorTable: TbmpColorTable; begin result := nil; if (aInfo.biBitCount >= 16) then @@ -5966,20 +6068,20 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean; c := 1 shl aInfo.biBitCount; SetLength(ColorTable, c); for i := 0 to c-1 do begin - aStream.Read(ColorTable[i], SizeOf(TColorTableEnty)); + aStream.Read(ColorTable[i], SizeOf(TbmpColorTableEnty)); if (ColorTable[i].r <> ColorTable[i].g) or (ColorTable[i].g <> ColorTable[i].b) then aFormat := tfRGB8; end; - result := TColorTableFormat.Create; + result := TbmpColorTableFormat.Create; result.PixelSize := aInfo.biBitCount / 8; result.ColorTable := ColorTable; - result.Range := glBitmapColorRec($FF, $FF, $FF, $00); + result.Range := glBitmapColorRec($FF, $FF, $FF, $00); end; ////////////////////////////////////////////////////////////////////////////////////////////////// function CheckBitfields(var aFormat: TglBitmapFormat; const aMask: TglBitmapColorRec; - const aInfo: TBMPInfo): TBitfieldFormat; + const aInfo: TBMPInfo): TbmpBitfieldFormat; var TmpFormat: TglBitmapFormat; FormatDesc: TFormatDescriptor; @@ -5999,7 +6101,7 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean; if (aMask.a <> 0) and not TFormatDescriptor.Get(aFormat).HasAlpha then aFormat := TFormatDescriptor.Get(aFormat).WithAlpha; - result := TBitfieldFormat.Create; + result := TbmpBitfieldFormat.Create; result.PixelSize := aInfo.biBitCount / 8; result.RedMask := aMask.r; result.GreenMask := aMask.g; @@ -6016,7 +6118,7 @@ var LineBuf, ImageData, TmpData: PByte; SourceMD, DestMD: Pointer; BmpFormat: TglBitmapFormat; - ColorTable: TColorTable; + ColorTable: TbmpColorTable; //records Mask: TglBitmapColorRec; @@ -6134,12 +6236,15 @@ procedure TglBitmap.SaveBMP(const aStream: TStream); var Header: TBMPHeader; Info: TBMPInfo; - pData, pTemp: pByte; + Converter: TbmpColorTableFormat; + FormatDesc: TFormatDescriptor; + SourceFD, DestFD: Pointer; + pData, srcData, dstData, ConvertBuffer: pByte; + Pixel: TglBitmapPixelData; PixelFormat: TglBitmapPixelData; - FormatDesc: TFormatDescriptor; - ImageSize, LineSize, Padding, LineIdx, ColorIdx: Integer; - Temp, RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; + ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx, i: Integer; + RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; PaddingBuff: Cardinal; @@ -6152,8 +6257,11 @@ begin if not (ftBMP in FormatGetSupportedFiles(Format)) then raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); - ImageSize := TFormatDescriptor.Get(Format).GetSize(Dimension); + Converter := nil; + FormatDesc := TFormatDescriptor.Get(Format); + ImageSize := FormatDesc.GetSize(Dimension); + FillChar(Header, SizeOf(Header), 0); Header.bfType := BMP_MAGIC; Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; Header.bfReserved1 := 0; @@ -6167,100 +6275,142 @@ begin Info.biPlanes := 1; Info.biCompression := BMP_COMP_RGB; Info.biSizeImage := ImageSize; - case Format of - tfR3G3B2, tfLuminance8: begin - Info.biBitCount := 8; - Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); - end; - - tfRGB5, tfRGB5A1, tfR5G6B5, tfRGB4, tfRGBA4, - tfBGR5, tfBGR5A1, tfB5G6R5, tfBGR4, tfBGRA4: begin - Info.biBitCount := 16; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - tfBGR8, tfRGB8: begin - Info.biBitCount := 24; - end; + try + case Format of + tfLuminance4: begin + Info.biBitCount := 4; + Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries + Converter := TbmpColorTableFormat.Create; + Converter.PixelSize := 0.5; + Converter.Format := Format; + Converter.Range := glBitmapColorRec($F, $F, $F, $0); + Converter.CreateColorTable; + end; - tfRGB10, tfRGB10A2, tfRGBA8, - tfBGR10, tfBGR10A2, tfBGRA8: begin - Info.biBitCount := 32; - Info.biCompression := BMP_COMP_BITFIELDS; - end; - else - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); - end; - Info.biXPelsPerMeter := 2835; - Info.biYPelsPerMeter := 2835; + tfR3G3B2, tfLuminance8: begin + Info.biBitCount := 8; + Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries + Converter := TbmpColorTableFormat.Create; + Converter.PixelSize := 1; + Converter.Format := Format; + if (Format = tfR3G3B2) then begin + Converter.Range := glBitmapColorRec($7, $7, $3, $0); + Converter.Shift := glBitmapShiftRec(0, 3, 6, 0); + end else + Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0); + Converter.CreateColorTable; + end; - // prepare bitmasks - if Info.biCompression = BMP_COMP_BITFIELDS then begin - Info.biSize := Info.biSize + 4 * SizeOf(Cardinal); - Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); - Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); + tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4, + tfBGR4, tfBGR5, tfB5G6R5, tfBGR5A1, tfBGRA4: begin + Info.biBitCount := 16; + Info.biCompression := BMP_COMP_BITFIELDS; + end; - FormatDesc := TFormatDescriptor.Get(Format); - RedMask := FormatDesc.RedMask; - GreenMask := FormatDesc.GreenMask; - BlueMask := FormatDesc.BlueMask; - AlphaMask := FormatDesc.AlphaMask; - end; + tfBGR8, tfRGB8: begin + Info.biBitCount := 24; + end; - // headers - aStream.Write(Header, SizeOf(Header)); - aStream.Write(Info, SizeOf(Info)); - - // colortable - if Info.biBitCount = 8 then begin - Temp := 0; - for ColorIdx := Low(Byte) to High(Byte) do begin - aStream.Write(Temp, 4); - Temp := Temp + $00010101; + tfRGB10, tfRGB10A2, tfRGBA8, + tfBGR10, tfBGR10A2, tfBGRA8: begin + Info.biBitCount := 32; + Info.biCompression := BMP_COMP_BITFIELDS; + end; + else + raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); + end; + Info.biXPelsPerMeter := 2835; + Info.biYPelsPerMeter := 2835; + + // prepare bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + Header.bfSize := Header.bfSize + 4 * SizeOf(Cardinal); + Header.bfOffBits := Header.bfOffBits + 4 * SizeOf(Cardinal); + + RedMask := FormatDesc.RedMask; + GreenMask := FormatDesc.GreenMask; + BlueMask := FormatDesc.BlueMask; + AlphaMask := FormatDesc.AlphaMask; end; - end; - - // bitmasks - if Info.biCompression = BMP_COMP_BITFIELDS then begin - aStream.Write(RedMask, SizeOf(Cardinal)); - aStream.Write(GreenMask, SizeOf(Cardinal)); - aStream.Write(BlueMask, SizeOf(Cardinal)); - aStream.Write(AlphaMask, SizeOf(Cardinal)); - end; - - // image data - LineSize := Trunc(Width * TFormatDescriptor.Get(Format).PixelSize); - Padding := GetLineWidth - LineSize; - PaddingBuff := 0; - pData := Data; - Inc(pData, (Height -1) * LineSize); + // headers + aStream.Write(Header, SizeOf(Header)); + aStream.Write(Info, SizeOf(Info)); + + // colortable + if Assigned(Converter) then + aStream.Write(Converter.ColorTable[0].b, + SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable)); + + // bitmasks + if Info.biCompression = BMP_COMP_BITFIELDS then begin + aStream.Write(RedMask, SizeOf(Cardinal)); + aStream.Write(GreenMask, SizeOf(Cardinal)); + aStream.Write(BlueMask, SizeOf(Cardinal)); + aStream.Write(AlphaMask, SizeOf(Cardinal)); + end; - // prepare row buffer. But only for RGB because RGBA supports color masks - // so it's possible to change color within the image. - if (Format = tfRGB8) then - GetMem(pTemp, fRowSize) - else - pTemp := nil; + // image data + rbLineSize := Round(Info.biWidth * FormatDesc.PixelSize); + wbLineSize := Round(Info.biWidth * Info.biBitCount / 8); + Padding := GetLineWidth - wbLineSize; + PaddingBuff := 0; + + pData := Data; + inc(pData, (Height-1) * rbLineSize); + + // prepare row buffer. But only for RGB because RGBA supports color masks + // so it's possible to change color within the image. + if Assigned(Converter) then begin + FormatDesc.PreparePixel(Pixel); + GetMem(ConvertBuffer, wbLineSize); + SourceFD := FormatDesc.CreateMappingData; + DestFD := Converter.CreateMappingData; + end else + ConvertBuffer := nil; - try - // write image data - for LineIdx := 0 to Height - 1 do begin - // preparing row - if Format = tfRGB8 then begin - Move(pData^, pTemp^, fRowSize); - SwapRGB(pTemp, Width, false); - end else - pTemp := pData; - aStream.Write(pTemp^, LineSize); - Dec(pData, LineSize); - if Padding > 0 then - aStream.Write(PaddingBuff, Padding); + try + for LineIdx := 0 to Height - 1 do begin + // preparing row + if Assigned(Converter) then begin + srcData := pData; + dstData := ConvertBuffer; + for PixelIdx := 0 to Info.biWidth-1 do begin + FormatDesc.Unmap(srcData, Pixel, SourceFD); + with FormatDesc do begin + //TODO use convert function + for i := 0 to 3 do + if (Converter.Range.arr[i] <> Range.arr[i]) then begin + if (Range.arr[i] > 0) then + Pixel.Data.arr[i] := Round(Pixel.Data.arr[i] / Range.arr[i] * Converter.Range.arr[i]) + else + Pixel.Data.arr[i] := 0; + end; + end; + Converter.Map(Pixel, dstData, DestFD); + end; + aStream.Write(ConvertBuffer^, wbLineSize); + end else begin + aStream.Write(pData^, rbLineSize); + end; + dec(pData, rbLineSize); + if (Padding > 0) then + aStream.Write(PaddingBuff, Padding); + end; + finally + // destroy row buffer + if Assigned(ConvertBuffer) then begin + FormatDesc.FreeMappingData(SourceFD); + Converter.FreeMappingData(DestFD); + FreeMem(ConvertBuffer); + end; end; finally - // destroy row buffer - if Format = tfRGB8 then - FreeMem(pTemp); + if Assigned(Converter) then + Converter.Free; end; end; @@ -7702,3 +7852,4 @@ finalization TFormatDescriptor.Finalize; end. + From f067ec08d69bd75acff660df64c05840ff457dfa Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Wed, 6 Nov 2013 20:01:24 +0100 Subject: [PATCH 09/38] * refactored LoadTGA --- glBitmap.pas | 543 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 330 insertions(+), 213 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 68d9cde..88724cf 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1004,6 +1004,7 @@ procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); function glBitmapPosition(X: Integer = -1; Y: Integer = -1): TglBitmapPixelPosition; function glBitmapColorRec(const r, g, b, a: Cardinal): TglBitmapColorRec; +function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean; var glBitmapDefaultDeleteTextureOnFree: Boolean; @@ -1052,6 +1053,7 @@ type fFormat: TglBitmapFormat; fWithAlpha: TglBitmapFormat; fWithoutAlpha: TglBitmapFormat; + fRGBInverted: TglBitmapFormat; fPixelSize: Single; fRange: TglBitmapColorRec; @@ -1066,6 +1068,7 @@ type property Format: TglBitmapFormat read fFormat; property WithAlpha: TglBitmapFormat read fWithAlpha; property WithoutAlpha: TglBitmapFormat read fWithoutAlpha; + property RGBInverted: TglBitmapFormat read fRGBInverted; property Components: Integer read GetComponents; property PixelSize: Single read fPixelSize; @@ -1553,6 +1556,18 @@ begin result.a := a; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function glBitmapColorRecCmp(const r1, r2: TglBitmapColorRec): Boolean; +var + i: Integer; +begin + result := false; + for i := 0 to high(r1.arr) do + if (r1.arr[i] <> r2.arr[i]) then + exit; + result := true; +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapShiftRec(const r, g, b, a: Byte): TShiftRec; begin @@ -1565,7 +1580,7 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin - result := [ftDDS, ftTGA]; + result := [ftDDS]; if (aFormat in [ //4 bbp @@ -1586,6 +1601,22 @@ begin tfBGR10, tfBGR10A2, tfBGRA8]) then result := result + [ftBMP]; + if (aFormat in [ + //8 bpp + tfLuminance8, tfAlpha8, + + //16 bpp + tfLuminance16, tfLuminance8Alpha8, + tfRGB5, tfRGB5A1, tfRGBA4, + tfBGR5, tfBGR5A1, tfBGRA4, + + //24 bpp + tfRGB8, tfBGR8, + + //32 bpp + tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then + result := result + [ftTGA]; + //TODO Supported File Formats! (* @@ -2204,6 +2235,7 @@ begin fFormat := tfEmpty; fWithAlpha := tfEmpty; fWithoutAlpha := tfEmpty; + fRGBInverted := tfEmpty; fPixelSize := 0.0; fglFormat := 0; @@ -2932,6 +2964,7 @@ begin fFormat := tfRGB4; fWithAlpha := tfRGBA4; fWithoutAlpha := tfRGB4; + fRGBInverted := tfBGR4; fRange.r := $F; fRange.g := $F; fRange.b := $F; @@ -2949,6 +2982,7 @@ begin fFormat := tfR5G6B5; fWithAlpha := tfRGBA4; fWithoutAlpha := tfR5G6B5; + fRGBInverted := tfB5G6R5; fRange.r := $1F; fRange.g := $3F; fRange.b := $1F; @@ -2966,6 +3000,7 @@ begin fFormat := tfRGB5; fWithAlpha := tfRGB5A1; fWithoutAlpha := tfRGB5; + fRGBInverted := tfBGR5; fRange.r := $1F; fRange.g := $1F; fRange.b := $1F; @@ -2983,6 +3018,7 @@ begin fFormat := tfRGB8; fWithAlpha := tfRGBA8; fWithoutAlpha := tfRGB8; + fRGBInverted := tfBGR8; fglInternalFormat := GL_RGB8; end; @@ -2992,6 +3028,7 @@ begin fFormat := tfRGB10; fWithAlpha := tfRGB10A2; fWithoutAlpha := tfRGB10; + fRGBInverted := tfBGR10; fRange.r := $3FF; fRange.g := $3FF; fRange.b := $3FF; @@ -3009,6 +3046,7 @@ begin fFormat := tfRGB12; fWithAlpha := tfRGBA12; fWithoutAlpha := tfRGB12; + fRGBInverted := tfBGR12; fglInternalFormat := GL_RGB12; end; @@ -3018,6 +3056,7 @@ begin fFormat := tfRGB16; fWithAlpha := tfRGBA16; fWithoutAlpha := tfRGB16; + fRGBInverted := tfBGR16; fglInternalFormat := GL_RGB16; end; @@ -3027,6 +3066,7 @@ begin fFormat := tfRGBA2; fWithAlpha := tfRGBA2; fWithoutAlpha := tfR3G3B2; + fRGBInverted := tfBGRA2; fglInternalFormat := GL_RGBA2; end; @@ -3036,6 +3076,7 @@ begin fFormat := tfRGBA4; fWithAlpha := tfRGBA4; fWithoutAlpha := tfRGB4; + fRGBInverted := tfBGRA4; fRange.r := $F; fRange.g := $F; fRange.b := $F; @@ -3055,6 +3096,7 @@ begin fFormat := tfRGB5A1; fWithAlpha := tfRGB5A1; fWithoutAlpha := tfRGB5; + fRGBInverted := tfBGR5A1; fRange.r := $1F; fRange.g := $1F; fRange.b := $1F; @@ -3074,6 +3116,7 @@ begin fFormat := tfRGBA8; fWithAlpha := tfRGBA8; fWithoutAlpha := tfRGB8; + fRGBInverted := tfBGRA8; fglInternalFormat := GL_RGBA8; end; @@ -3083,6 +3126,7 @@ begin fFormat := tfRGB10A2; fWithAlpha := tfRGB10A2; fWithoutAlpha := tfRGB10; + fRGBInverted := tfBGR10A2; fRange.r := $3FF; fRange.g := $3FF; fRange.b := $3FF; @@ -3102,6 +3146,7 @@ begin fFormat := tfRGBA12; fWithAlpha := tfRGBA12; fWithoutAlpha := tfRGB12; + fRGBInverted := tfBGRA12; fglInternalFormat := GL_RGBA12; end; @@ -3111,6 +3156,7 @@ begin fFormat := tfRGBA16; fWithAlpha := tfRGBA16; fWithoutAlpha := tfRGB16; + fRGBInverted := tfBGRA16; fglInternalFormat := GL_RGBA16; end; @@ -3121,6 +3167,7 @@ begin fFormat := tfBGR4; fWithAlpha := tfBGRA4; fWithoutAlpha := tfBGR4; + fRGBInverted := tfRGB4; fRange.r := $F; fRange.g := $F; fRange.b := $F; @@ -3143,6 +3190,7 @@ begin fFormat := tfB5G6R5; fWithAlpha := tfBGRA4; fWithoutAlpha := tfB5G6R5; + fRGBInverted := tfR5G6B5; fRange.r := $1F; fRange.g := $3F; fRange.b := $1F; @@ -3154,9 +3202,6 @@ begin fglDataFormat := GL_UNSIGNED_SHORT_5_6_5; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TfdBGR5.Create; begin inherited Create; @@ -3164,6 +3209,7 @@ begin fFormat := tfBGR5; fWithAlpha := tfBGR5A1; fWithoutAlpha := tfBGR5; + fRGBInverted := tfRGB5; fRange.r := $1F; fRange.g := $1F; fRange.b := $1F; @@ -3183,6 +3229,7 @@ begin fFormat := tfBGR8; fWithAlpha := tfBGRA8; fWithoutAlpha := tfBGR8; + fRGBInverted := tfRGB8; fglInternalFormat := GL_RGB8; end; @@ -3192,6 +3239,7 @@ begin fFormat := tfBGR10; fWithAlpha := tfBGR10A2; fWithoutAlpha := tfBGR10; + fRGBInverted := tfRGB10; fRange.r := $3FF; fRange.g := $3FF; fRange.b := $3FF; @@ -3211,6 +3259,7 @@ begin fFormat := tfBGR12; fWithAlpha := tfBGRA12; fWithoutAlpha := tfBGR12; + fRGBInverted := tfRGB12; fglInternalFormat := GL_RGB12; end; @@ -3220,6 +3269,7 @@ begin fFormat := tfBGR16; fWithAlpha := tfBGRA16; fWithoutAlpha := tfBGR16; + fRGBInverted := tfRGB16; fglInternalFormat := GL_RGB16; end; @@ -3229,6 +3279,7 @@ begin fFormat := tfBGRA2; fWithAlpha := tfBGRA4; fWithoutAlpha := tfBGR4; + fRGBInverted := tfRGBA2; fglInternalFormat := GL_RGBA2; end; @@ -3238,6 +3289,7 @@ begin fFormat := tfBGRA4; fWithAlpha := tfBGRA4; fWithoutAlpha := tfBGR4; + fRGBInverted := tfRGBA4; fRange.r := $F; fRange.g := $F; fRange.b := $F; @@ -3257,6 +3309,7 @@ begin fFormat := tfBGR5A1; fWithAlpha := tfBGR5A1; fWithoutAlpha := tfBGR5; + fRGBInverted := tfRGB5A1; fRange.r := $1F; fRange.g := $1F; fRange.b := $1F; @@ -3276,6 +3329,7 @@ begin fFormat := tfBGRA8; fWithAlpha := tfBGRA8; fWithoutAlpha := tfBGR8; + fRGBInverted := tfRGBA8; fglInternalFormat := GL_RGBA8; end; @@ -3285,6 +3339,7 @@ begin fFormat := tfBGR10A2; fWithAlpha := tfBGR10A2; fWithoutAlpha := tfBGR10; + fRGBInverted := tfRGB10A2; fRange.r := $3FF; fRange.g := $3FF; fRange.b := $3FF; @@ -3304,6 +3359,7 @@ begin fFormat := tfBGRA12; fWithAlpha := tfBGRA12; fWithoutAlpha := tfBGR12; + fRGBInverted := tfRGBA12; fglInternalFormat := GL_RGBA12; end; @@ -3313,6 +3369,7 @@ begin fFormat := tfBGRA16; fWithAlpha := tfBGRA16; fWithoutAlpha := tfBGR16; + fRGBInverted := tfRGBA16; fglInternalFormat := GL_RGBA16; end; @@ -3531,9 +3588,6 @@ begin fColorTable[i].g := Round(((i shr Shift.g) and Range.g) / Range.g * 255); fColorTable[i].b := Round(((i shr Shift.b) and Range.b) / Range.b * 255); fColorTable[i].a := 0; - - s := SysUtils.Format('%.2X%.2X%.2X' + sLineBreak, [fColorTable[i].r, fColorTable[i].g, fColorTable[i].b]); - fs.Write(s[1], Length(s)); end; end; end; @@ -4004,6 +4058,8 @@ procedure TglBitmap.LoadFromFile(const aFilename: String); var fs: TFileStream; begin + if not FileExists(aFilename) then + raise EglBitmapException.Create('file does not exist: ' + aFilename); fFilename := aFilename; fs := TFileStream.Create(fFilename, fmOpenRead); try @@ -6422,29 +6478,43 @@ type ImageID: Byte; ColorMapType: Byte; ImageType: Byte; - ColorMapSpec: Array[0..4] of Byte; + //ColorMapSpec: Array[0..4] of Byte; + ColorMapStart: Word; + ColorMapLength: Word; + ColorMapEntrySize: Byte; OrigX: Word; OrigY: Word; Width: Word; Height: Word; Bpp: Byte; - ImageDes: Byte; + ImageDesc: Byte; end; const - TGA_UNCOMPRESSED_RGB = 2; - TGA_UNCOMPRESSED_GRAY = 3; - TGA_COMPRESSED_RGB = 10; - TGA_COMPRESSED_GRAY = 11; + TGA_UNCOMPRESSED_COLOR_TABLE = 1; + TGA_UNCOMPRESSED_RGB = 2; + TGA_UNCOMPRESSED_GRAY = 3; + TGA_COMPRESSED_COLOR_TABLE = 9; + TGA_COMPRESSED_RGB = 10; + TGA_COMPRESSED_GRAY = 11; + + TGA_NONE_COLOR_TABLE = 0; + TGA_COLOR_TABLE = 1; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadTGA(const aStream: TStream): Boolean; var Header: TTGAHeader; - NewImage, pData: PByte; - StreamPos: Int64; - PixelSize, LineSize, YStart, YEnd, YInc: Integer; - Format: TglBitmapFormat; + ImageData: PByte; + StartPosition: Int64; + PixelSize, LineSize: Integer; + tgaFormat: TglBitmapFormat; + FormatDesc: TFormatDescriptor; + Counter: packed record + X, Y: packed record + low, high, dir: Integer; + end; + end; const CACHE_SIZE = $4000; @@ -6452,195 +6522,233 @@ const //////////////////////////////////////////////////////////////////////////////////////// procedure ReadUncompressed; var - RowSize: Integer; + i, j: Integer; + buf, tmp1, tmp2: PByte; begin - RowSize := Header.Width * PixelSize; - // copy line by line - while YStart <> YEnd + YInc do begin - pData := NewImage; - Inc(pData, YStart * LineSize); - aStream.Read(pData^, RowSize); - Inc(YStart, YInc); + buf := nil; + if (Counter.X.dir < 0) then + buf := GetMem(LineSize); + try + while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin + tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart + if (Counter.X.dir < 0) then begin //flip X + aStream.Read(buf^, LineSize); + tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line + for i := 0 to Header.Width-1 do begin //for all pixels in line + for j := 0 to PixelSize-1 do begin //for all bytes in pixel + tmp1^ := tmp2^; + inc(tmp1); + inc(tmp2); + end; + dec(tmp2, 2*PixelSize); //move 2 backwards, because j-loop moved 1 forward + end; + end else + aStream.Read(tmp1^, LineSize); + inc(Counter.Y.low, Counter.Y.dir); //move to next line index + end; + finally + if Assigned(buf) then + FreeMem(buf); end; end; //////////////////////////////////////////////////////////////////////////////////////// procedure ReadCompressed; - var - HeaderWidth, HeaderHeight: Integer; - LinePixelsRead, ImgPixelsRead, ImgPixelsToRead: Integer; - - Cache: PByte; - CacheSize, CachePos: Integer; - - Temp: Byte; - TempBuf: Array [0..15] of Byte; - - PixelRepeat: Boolean; - PixelToRead, TempPixels: Integer; ///////////////////////////////////////////////////////////////// + var + TmpData: PByte; + LinePixelsRead: Integer; procedure CheckLine; begin - if LinePixelsRead >= HeaderWidth then begin + if (LinePixelsRead >= Header.Width) then begin LinePixelsRead := 0; - pData := NewImage; - Inc(YStart, YInc); - Inc(pData, YStart * LineSize); + inc(Counter.Y.low, Counter.Y.dir); //next line index + TmpData := ImageData + Counter.Y.low * LineSize; //set line + if (Counter.X.dir < 0) then //if x flipped then + TmpData := TmpData + LineSize - PixelSize; //set last pixel end; end; ///////////////////////////////////////////////////////////////// + var + Cache: PByte; + CacheSize, CachePos: Integer; procedure CachedRead(out Buffer; Count: Integer); var BytesRead: Integer; begin - if (CachePos + Count) > CacheSize then begin + if (CachePos + Count > CacheSize) then begin + //if buffer overflow save non read bytes BytesRead := 0; - - // Read Data - if CacheSize - CachePos > 0 then begin + if (CacheSize - CachePos > 0) then begin BytesRead := CacheSize - CachePos; - Move(pByteArray(Cache)^[CachePos], Buffer, BytesRead); - Inc(CachePos, BytesRead); + Move(PByteArray(Cache)^[CachePos], Buffer, BytesRead); + inc(CachePos, BytesRead); end; - // Reload Data + //load cache from file CacheSize := Min(CACHE_SIZE, aStream.Size - aStream.Position); aStream.Read(Cache^, CacheSize); CachePos := 0; - // Read else - if Count - BytesRead > 0 then begin - Move(pByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead); - Inc(CachePos, Count - BytesRead); + //read rest of requested bytes + if (Count - BytesRead > 0) then begin + Move(PByteArray(Cache)^[CachePos], TByteArray(Buffer)[BytesRead], Count - BytesRead); + inc(CachePos, Count - BytesRead); end; end else begin - Move(pByteArray(Cache)^[CachePos], Buffer, Count); - Inc(CachePos, Count); + //if no buffer overflow just read the data + Move(PByteArray(Cache)^[CachePos], Buffer, Count); + inc(CachePos, Count); + end; + end; + + procedure PixelToBuffer(const aData: PByte; var aBuffer: PByte); + begin + case PixelSize of + 1: begin + aBuffer^ := aData^; + inc(aBuffer, Counter.X.dir); + end; + 2: begin + PWord(aBuffer)^ := PWord(aData)^; + inc(aBuffer, 2 * Counter.X.dir); + end; + 3: begin + PByteArray(aBuffer)^[0] := PByteArray(aData)^[0]; + PByteArray(aBuffer)^[1] := PByteArray(aData)^[1]; + PByteArray(aBuffer)^[2] := PByteArray(aData)^[2]; + inc(aBuffer, 3 * Counter.X.dir); + end; + 4: begin + PCardinal(aBuffer)^ := PCardinal(aData)^; + inc(aBuffer, 4 * Counter.X.dir); + end; end; end; + var + TotalPixelsToRead, TotalPixelsRead: Integer; + Temp: Byte; + buf: array [0..3] of Byte; //1 pixel is max 32bit long + PixelRepeat: Boolean; + PixelsToRead, PixelCount: Integer; begin CacheSize := 0; - CachePos := 0; + CachePos := 0; - HeaderWidth := Header.Width; - HeaderHeight := Header.Height; + TotalPixelsToRead := Header.Width * Header.Height; + TotalPixelsRead := 0; + LinePixelsRead := 0; - GetMem(Cache, CACHE_SIZE); // 16K Buffer + GetMem(Cache, CACHE_SIZE); try - ImgPixelsToRead := HeaderWidth * HeaderHeight; - ImgPixelsRead := 0; - LinePixelsRead := 0; + TmpData := ImageData + Counter.Y.low * LineSize; //set line + if (Counter.X.dir < 0) then //if x flipped then + TmpData := TmpData + LineSize - PixelSize; //set last pixel - pData := NewImage; - Inc(pData, YStart * LineSize); - - // Read until all Pixels repeat + //read CommandByte CachedRead(Temp, 1); - - PixelRepeat := Temp and $80 > 0; - PixelToRead := (Temp and $7F) + 1; - - Inc(ImgPixelsRead, PixelToRead); - - if PixelRepeat then begin - // repeat one pixel x times - CachedRead(TempBuf[0], PixelSize); - - // repeat Pixel - while PixelToRead > 0 do begin - CheckLine; - - TempPixels := HeaderWidth - LinePixelsRead; - if PixelToRead < TempPixels then - TempPixels := PixelToRead; - - Inc(LinePixelsRead, TempPixels); - Dec(PixelToRead, TempPixels); - - while TempPixels > 0 do begin - case PixelSize of - 1: begin - pData^ := TempBuf[0]; - Inc(pData); - end; - 2: begin - pWord(pData)^ := pWord(@TempBuf[0])^; - Inc(pData, 2); - end; - 3: begin - pWord(pData)^ := pWord(@TempBuf[0])^; - Inc(pData, 2); - pData^ := TempBuf[2]; - Inc(pData); - end; - 4: begin - pDWord(pData)^ := pDWord(@TempBuf[0])^; - Inc(pData, 4); - end; - end; - Dec(TempPixels); - end; - end; - end else begin - // copy x pixels - while PixelToRead > 0 do begin - CheckLine; - TempPixels := HeaderWidth - LinePixelsRead; - if PixelToRead < TempPixels then - TempPixels := PixelToRead; - CachedRead(pData^, PixelSize * TempPixels); - Inc(pData, PixelSize * TempPixels); - Inc(LinePixelsRead, TempPixels); - Dec(PixelToRead, TempPixels); + PixelRepeat := (Temp and $80) > 0; + PixelsToRead := (Temp and $7F) + 1; + inc(TotalPixelsRead, PixelsToRead); + + if PixelRepeat then + CachedRead(buf[0], PixelSize); + while (PixelsToRead > 0) do begin + CheckLine; + PixelCount := Min(Header.Width - LinePixelsRead, PixelsToRead); //max read to EOL or EOF + while (PixelCount > 0) do begin + if not PixelRepeat then + CachedRead(buf[0], PixelSize); + PixelToBuffer(@buf[0], TmpData); + inc(LinePixelsRead); + dec(PixelsToRead); + dec(PixelCount); end; end; - until ImgPixelsRead >= ImgPixelsToRead; + until (TotalPixelsRead >= TotalPixelsToRead); finally - FreeMem(Cache) + FreeMem(Cache); end; end; + function IsGrayFormat: Boolean; + begin + result := Header.ImageType in [TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_GRAY]; + end; + begin result := false; // reading header to test file and set cursor back to begin - StreamPos := aStream.Position; + StartPosition := aStream.Position; aStream.Read(Header, SizeOf(Header)); // no colormapped files - if (Header.ColorMapType = 0) then begin - if Header.ImageType in [TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY] then begin + if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [ + TGA_UNCOMPRESSED_RGB, TGA_UNCOMPRESSED_GRAY, TGA_COMPRESSED_RGB, TGA_COMPRESSED_GRAY]) then + begin + try + if Header.ImageID <> 0 then // skip image ID + aStream.Position := aStream.Position + Header.ImageID; + case Header.Bpp of - //TODO 8: Format := tfAlpha8; - 16: Format := tfLuminance8Alpha8; - 24: Format := tfBGR8; - 32: Format := tfBGRA8; - else - raise EglBitmapException.Create('LoadTga - unsupported BitsPerPixel found.'); + 8: if IsGrayFormat then case (Header.ImageDesc and $F) of + 0: tgaFormat := tfLuminance8; + 8: tgaFormat := tfAlpha8; + end; + + 16: if IsGrayFormat then case (Header.ImageDesc and $F) of + 0: tgaFormat := tfLuminance16; + 8: tgaFormat := tfLuminance8Alpha8; + end else case (Header.ImageDesc and $F) of + 0: tgaFormat := tfBGR5; + 1: tgaFormat := tfBGR5A1; + 4: tgaFormat := tfBGRA4; + end; + + 24: if not IsGrayFormat then case (Header.ImageDesc and $F) of + 0: tgaFormat := tfBGR8; + end; + + 32: if not IsGrayFormat then case (Header.ImageDesc and $F) of + 2: tgaFormat := tfBGR10A2; + 8: tgaFormat := tfBGRA8; + end; end; - // skip image ID - if Header.ImageID <> 0 then - aStream.Position := aStream.Position + Header.ImageID; + if (tgaFormat = tfEmpty) then + raise EglBitmapException.Create('LoadTga - unsupported format'); - PixelSize := TFormatDescriptor.Get(Format).GetSize(1, 1); - LineSize := Trunc(Header.Width * PixelSize); + FormatDesc := TFormatDescriptor.Get(tgaFormat); + PixelSize := FormatDesc.GetSize(1, 1); + LineSize := FormatDesc.GetSize(Header.Width, 1); - GetMem(NewImage, LineSize * Header.Height); + GetMem(ImageData, LineSize * Header.Height); try + //column direction + if ((Header.ImageDesc and (1 shl 4)) > 0) then begin + Counter.X.low := Header.Height-1;; + Counter.X.high := 0; + Counter.X.dir := -1; + end else begin + Counter.X.low := 0; + Counter.X.high := Header.Height-1; + Counter.X.dir := 1; + end; + // Row direction - if (Header.ImageDes and $20 > 0) then begin - YStart := 0; - YEnd := Header.Height -1; - YInc := 1; + if ((Header.ImageDesc and (1 shl 5)) > 0) then begin + Counter.Y.low := 0; + Counter.Y.high := Header.Height-1; + Counter.Y.dir := 1; end else begin - YStart := Header.Height -1; - YEnd := 0; - YInc := -1; + Counter.Y.low := Header.Height-1;; + Counter.Y.high := 0; + Counter.Y.dir := -1; end; // Read Image @@ -6651,97 +6759,106 @@ begin ReadCompressed; end; - SetDataPointer(NewImage, Format, Header.Width, Header.Height); + SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); result := true; except - FreeMem(NewImage); + FreeMem(ImageData); raise; end; - end - else aStream.Position := StreamPos; + finally + aStream.Position := StartPosition; + end; end - else aStream.Position := StreamPos; + else aStream.Position := StartPosition; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SaveTGA(const aStream: TStream); var Header: TTGAHeader; - Size: Integer; - pTemp: pByte; + LineSize, Size, x, y: Integer; + Pixel: TglBitmapPixelData; + LineBuf, SourceData, DestData: PByte; + SourceMD, DestMD: Pointer; FormatDesc: TFormatDescriptor; - - procedure ConvertData(pTemp: pByte); - var - Idx, PixelSize: Integer; - Temp: byte; - begin - PixelSize := fPixelSize; - for Idx := 1 to Height * Width do begin - Temp := pByteArray(pTemp)^[2]; - pByteArray(pTemp)^[2] := pByteArray(pTemp)^[0]; - pByteArray(pTemp)^[0] := Temp; - Inc(pTemp, PixelSize); - end; - end; - + Converter: TFormatDescriptor; begin if not (ftTGA in FormatGetSupportedFiles(Format)) then raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); + //prepare header FillChar(Header, SizeOf(Header), 0); - case Format of - //TODO ifAlpha8, ifLuminance8, ifDepth8: begin - tfLuminance8: begin - Header.ImageType := TGA_UNCOMPRESSED_GRAY; - Header.Bpp := 8; - end; - tfLuminance8Alpha8: begin - Header.ImageType := TGA_UNCOMPRESSED_GRAY; - Header.Bpp := 16; - end; - tfRGB8, tfBGR8: begin - Header.ImageType := TGA_UNCOMPRESSED_RGB; - Header.Bpp := 24; - end; - tfRGBA8, tfBGRA8: begin - Header.ImageType := TGA_UNCOMPRESSED_RGB; - Header.Bpp := 32; - end; - else - raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); - end; - Header.Width := Width; - Header.Height := Height; - Header.ImageDes := $20; - FormatDesc := TFormatDescriptor.Get(Format); + //set ImageType + if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8, + tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8]) then + Header.ImageType := TGA_UNCOMPRESSED_GRAY + else + Header.ImageType := TGA_UNCOMPRESSED_RGB; + + //set BitsPerPixel + if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8]) then + Header.Bpp := 8 + else if (Format in [tfLuminance16, tfLuminance12Alpha4, tfLuminance8Alpha8, + tfRGB5, tfBGR5, tfRGB5A1, tfBGR5A1, tfRGBA4, tfBGRA4]) then + Header.Bpp := 16 + else if (Format in [tfBGR8, tfRGB8]) then + Header.Bpp := 24 + else + Header.Bpp := 32; - if FormatDesc.HasAlpha then - Header.ImageDes := Header.ImageDes or $08; + //set AlphaBitCount + case Format of + tfRGB5A1, tfBGR5A1: + Header.ImageDesc := 1 and $F; + tfRGB10A2, tfBGR10A2: + Header.ImageDesc := 2 and $F; + tfRGBA4, tfBGRA4: + Header.ImageDesc := 4 and $F; + tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8: + Header.ImageDesc := 8 and $F; + end; + + Header.Width := Width; + Header.Height := Height; + Header.ImageDesc := Header.ImageDesc or $20; //flip y aStream.Write(Header, SizeOf(Header)); // convert RGB(A) to BGR(A) - Size := FormatDesc.GetSize(Dimension); - if Format in [tfRGB8, tfRGBA8] then begin - GetMem(pTemp, Size); - end else - pTemp := Data; - - try - // convert data - if Format in [tfRGB8, tfRGBA8] then begin - Move(Data^, pTemp^, Size); - ConvertData(pTemp); + Converter := nil; + FormatDesc := TFormatDescriptor.Get(Format); + Size := FormatDesc.GetSize(Dimension); + if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin + if (FormatDesc.RGBInverted = tfEmpty) then + raise EglBitmapException.Create('inverted RGB format is empty'); + Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted); + if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or + (Converter.PixelSize <> FormatDesc.PixelSize) then + raise EglBitmapException.Create('invalid inverted RGB format'); + end; + + if Assigned(Converter) then begin + LineSize := FormatDesc.GetSize(Width, 1); + LineBuf := GetMem(LineSize); + SourceMD := FormatDesc.CreateMappingData; + DestMD := Converter.CreateMappingData; + try + SourceData := Data; + for y := 0 to Height-1 do begin + DestData := LineBuf; + for x := 0 to Width-1 do begin + FormatDesc.Unmap(SourceData, Pixel, SourceMD); + Converter.Map(Pixel, DestData, DestMD); + end; + aStream.Write(LineBuf^, LineSize); + end; + finally + FreeMem(LineBuf); + FormatDesc.FreeMappingData(SourceMD); + FormatDesc.FreeMappingData(DestMD); end; - - // write data - aStream.Write(pTemp^, Size); - finally - // free tempdata - if Format in [tfRGB8, tfRGBA8] then - FreeMem(pTemp); - end; + end else + aStream.Write(Data^, Size); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// From ff9fe5a4282af64bf3d6fad22ce914c3124e49fa Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 10 Nov 2013 17:30:24 +0100 Subject: [PATCH 10/38] * refactored LoadDDS --- glBitmap.pas | 271 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 183 insertions(+), 88 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 88724cf..72c81e0 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -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; @@ -3400,6 +3431,84 @@ begin fglInternalFormat := GL_DEPTH_COMPONENT32; 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/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -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); From 475288680c6bdf18f91e97e17707c1553b070c01 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 12 Nov 2013 17:50:35 +0100 Subject: [PATCH 11/38] * Bitfield support for LoadDDS * refactored SaveDDS --- glBitmap.pas | 302 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 187 insertions(+), 115 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 72c81e0..e1e591d 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -591,7 +591,7 @@ type //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapFormat = ( - tfEmpty = 0, + tfEmpty = 0, //must be smallest value! tfAlpha4, tfAlpha8, @@ -1609,8 +1609,6 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin - result := [ftDDS]; - if (aFormat in [ //4 bbp tfLuminance4, @@ -1646,9 +1644,29 @@ begin tfRGB10A2, tfRGBA8, tfBGR10A2, tfBGRA8]) then result := result + [ftTGA]; - //TODO Supported File Formats! + if (aFormat in [ + //8 bpp + tfAlpha8, tfLuminance8, tfLuminance4Alpha4, tfLuminance6Alpha2, + tfR3G3B2, tfRGBA2, tfBGRA2, + + //16 bpp + tfAlpha16, tfLuminance16, tfLuminance8Alpha8, tfLuminance12Alpha4, + tfRGB4, tfR5G6B5, tfRGB5, tfRGBA4, tfRGB5A1, + tfBGR4, tfB5G6R5, tfBGR5, tfBGRA4, tfBGR5A1, - (* + //24 bpp + tfRGB8, tfBGR8, + + //32 bbp + tfLuminance16Alpha16, + tfRGBA8, tfRGB10A2, + tfBGRA8, tfBGR10A2, + + //compressed + tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then + result := result + [ftDDS]; + + (* TODO {$IFDEF GLB_SUPPORT_PNG_WRITE} if aFormat in [ tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, @@ -6974,7 +6992,7 @@ end; //DDS///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const - DDS_MAGIC = $20534444; + DDS_MAGIC: Cardinal = $20534444; // DDS_header.dwFlags DDSD_CAPS = $00000001; @@ -6988,6 +7006,7 @@ const // DDS_header.sPixelFormat.dwFlags DDPF_ALPHAPIXELS = $00000001; + DDPF_ALPHA = $00000002; DDPF_FOURCC = $00000004; DDPF_INDEXED = $00000020; DDPF_RGB = $00000040; @@ -7032,7 +7051,6 @@ type end; TDDSHeader = packed record - dwMagic: Cardinal; dwSize: Cardinal; dwFlags: Cardinal; dwHeight: Cardinal; @@ -7050,8 +7068,14 @@ type function TglBitmap.LoadDDS(const aStream: TStream): Boolean; var Header: TDDSHeader; + Converter: TbmpBitfieldFormat; function GetDDSFormat: TglBitmapFormat; + var + fd: TFormatDescriptor; + i: Integer; + Range: TglBitmapColorRec; + match: Boolean; begin result := tfEmpty; with Header.PixelFormat do begin @@ -7062,66 +7086,79 @@ var D3DFMT_DXT3: result := tfS3tcDtx3RGBA; D3DFMT_DXT5: result := tfS3tcDtx5RGBA; end; - end else - - // RGB - if (dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0 then begin - case dwRGBBitCount of - 8: begin - 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 - case CountSetBits(dwRBitMask) of - 5: result := tfRGB5A1; - 4: result := tfRGBA4; - else - result := tfLuminance8Alpha8; - end; - end else if (CountSetBits(dwGBitMask) = 6) then - result := tfR5G6B5 - else - result := tfRGB5; - end; + end else if ((Header.PixelFormat.dwFlags and (DDPF_RGB or DDPF_ALPHAPIXELS or DDPF_LUMINANCE)) > 0) then begin + + //find matching format + for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin + fd := TFormatDescriptor.Get(result); + if fd.MaskMatch(dwRBitMask, dwGBitMask, dwBBitMask, dwABitMask) and + (8 * fd.PixelSize = dwRGBBitCount) then + exit; + end; - 24: begin - result := tfRGB8; - end; + //find format with same Range + Range.r := dwRBitMask; + Range.g := dwGBitMask; + Range.b := dwBBitMask; + Range.a := dwABitMask; + for i := 0 to 3 do begin + while ((Range.arr[i] and 1) = 0) and (Range.arr[i] > 0) do + Range.arr[i] := Range.arr[i] shr 1; + end; + for result := High(TglBitmapFormat) downto Low(TglBitmapFormat) do begin + fd := TFormatDescriptor.Get(result); + match := true; + for i := 0 to 3 do + if (fd.Range.arr[i] <> Range.arr[i]) then begin + match := false; + break; + end; + if match then + break; + end; - 32: begin - if CountSetBits(dwRBitMask) = 10 then - result := tfRGB10A2 - else - result := tfRGBA8; - end; + //no format with same range found -> use default + if (result = tfEmpty) then begin + if (dwABitMask > 0) then + result := tfBGRA8 + else + result := tfBGR8; end; - if (dwRBitMask <> 0) and (dwBBitMask <> 0) and (dwRBitMask > dwBBitMask) then - result := TFormatDescriptor.Get(result).RGBInverted; + Converter := TbmpBitfieldFormat.Create; + Converter.RedMask := dwRBitMask; + Converter.GreenMask := dwGBitMask; + Converter.BlueMask := dwBBitMask; + Converter.AlphaMask := dwABitMask; + Converter.PixelSize := dwRGBBitCount / 8; end; end; end; var StreamPos: Int64; - Y, LineSize: Cardinal; - RowSize: Cardinal; - NewImage, TmpData: PByte; + x, y, j, LineSize, RowSize, Magic: Cardinal; + NewImage, TmpData, RowData, SrcData: PByte; + SourceMD, DestMD: Pointer; + Pixel: TglBitmapPixelData; ddsFormat: TglBitmapFormat; FormatDesc: TFormatDescriptor; begin - result := false; - - // Header + result := false; + Converter := nil; StreamPos := aStream.Position; - aStream.Read(Header, sizeof(Header)); - if (Header.dwMagic <> DDS_MAGIC) or (Header.dwSize <> 124) or + // Magic + aStream.Read(Magic, sizeof(Magic)); + if (Magic <> DDS_MAGIC) then begin + aStream.Position := StreamPos; + exit; + end; + + //Header + aStream.Read(Header, sizeof(Header)); + if (Header.dwSize <> SizeOf(Header)) 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 @@ -7133,39 +7170,74 @@ begin raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported'); ddsFormat := GetDDSFormat; - 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 - TmpData := NewImage; - - // Compressed - 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(TmpData^, RowSize); - Inc(TmpData, LineSize); - end; - end else - - // 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 + if (ddsFormat = tfEmpty) then raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); - SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); - result := true; - except - FreeMem(NewImage); - raise; + FormatDesc := TFormatDescriptor.Get(ddsFormat); + LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize); + GetMem(NewImage, Header.dwHeight * LineSize); + try + TmpData := NewImage; + + //Converter needed + if Assigned(Converter) then begin + RowSize := Round(Header.dwWidth * Header.PixelFormat.dwRGBBitCount / 8); + GetMem(RowData, RowSize); + SourceMD := Converter.CreateMappingData; + DestMD := FormatDesc.CreateMappingData; + try + for y := 0 to Header.dwHeight-1 do begin + TmpData := NewImage + y * LineSize; + SrcData := RowData; + aStream.Read(SrcData^, RowSize); + for x := 0 to Header.dwWidth-1 do begin + Converter.Unmap(SrcData, Pixel, SourceMD); + //TODO use converter function + for j := 0 to 3 do + if (Converter.Range.arr[j] <> FormatDesc.Range.arr[j]) then begin + if (Converter.Range.arr[j] > 0) then + Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / Converter.Range.arr[j] * FormatDesc.Range.arr[j]) + else + Pixel.Data.arr[j] := 0; + end; + FormatDesc.Map(Pixel, TmpData, DestMD); + end; + end; + finally + Converter.FreeMappingData(SourceMD); + FormatDesc.FreeMappingData(DestMD); + FreeMem(RowData); + end; + end else + + // Compressed + 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(TmpData^, RowSize); + Inc(TmpData, LineSize); + end; + end else + + // 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 EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + + SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); + result := true; + except + FreeMem(NewImage); + raise; + end; + finally + FreeAndNil(Converter); end; end; @@ -7173,55 +7245,55 @@ end; procedure TglBitmap.SaveDDS(const aStream: TStream); var Header: TDDSHeader; - Pix: TglBitmapPixelData; FormatDesc: TFormatDescriptor; begin - //if not FormatIsUncompressed(InternalFormat) then - // raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT); + if not (ftDDS in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT); - (* TODO if Format = tfAlpha8 then - FORMAT_DESCRIPTORS[tfLuminance8].PreparePixel(Pix); - else *) - TFormatDescriptor.Get(Format).PreparePixel(Pix); + FormatDesc := TFormatDescriptor.Get(Format); // Generell FillChar(Header, SizeOf(Header), 0); - Header.dwMagic := DDS_MAGIC; - Header.dwSize := 124; - Header.dwFlags := DDSD_PITCH or DDSD_CAPS or DDSD_PIXELFORMAT; - - if Width > 0 then begin - Header.dwWidth := Width; - Header.dwFlags := Header.dwFlags or DDSD_WIDTH; - end; - - if Height > 0 then begin - Header.dwHeight := Height; - Header.dwFlags := Header.dwFlags or DDSD_HEIGHT; - end; + Header.dwSize := SizeOf(Header); + Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT; - Header.dwPitchOrLinearSize := fRowSize; - Header.dwMipMapCount := 1; + Header.dwWidth := Max(1, Width); + Header.dwHeight := Max(1, Height); // Caps Header.Caps.dwCaps1 := DDSCAPS_TEXTURE; // Pixelformat - Header.PixelFormat.dwSize := Sizeof(Header.PixelFormat); - Header.PixelFormat.dwFlags := DDPF_RGB; + Header.PixelFormat.dwSize := sizeof(Header); + if (FormatDesc.IsCompressed) then begin + Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_FOURCC; + case Format of + tfS3tcDtx1RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT1; + tfS3tcDtx3RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT3; + tfS3tcDtx5RGBA: Header.PixelFormat.dwFourCC := D3DFMT_DXT5; + end; + end else if (Format in [tfAlpha8, tfAlpha16]) then begin + Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHA; + Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8); + Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask; + end else if (FormatDesc.RedMask = FormatDesc.GreenMask) and (FormatDesc.GreenMask = FormatDesc.BlueMask) then begin + Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_LUMINANCE; + Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8); + Header.PixelFormat.dwRBitMask := FormatDesc.RedMask; + Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask; + end else begin + Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_RGB; + Header.PixelFormat.dwRGBBitCount := Round(FormatDesc.PixelSize * 8); + Header.PixelFormat.dwRBitMask := FormatDesc.RedMask; + Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask; + Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask; + Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask; + end; - (* TODO tfAlpha8 - if FORMAT_DESCRIPTORS[Format].HasAlpha and (Format <> tfAlpha8) then + if (FormatDesc.HasAlpha) then Header.PixelFormat.dwFlags := Header.PixelFormat.dwFlags or DDPF_ALPHAPIXELS; - *) - - FormatDesc := TFormatDescriptor.Get(Format); - Header.PixelFormat.dwRGBBitCount := Trunc(FormatDesc.PixelSize * 8); - Header.PixelFormat.dwRBitMask := FormatDesc.RedMask; - Header.PixelFormat.dwGBitMask := FormatDesc.GreenMask; - Header.PixelFormat.dwBBitMask := FormatDesc.BlueMask; - Header.PixelFormat.dwABitMask := FormatDesc.AlphaMask; + aStream.Write(DDS_MAGIC, sizeof(DDS_MAGIC)); aStream.Write(Header, SizeOf(Header)); aStream.Write(Data^, FormatDesc.GetSize(Dimension)); end; From 7964d52cb7747906b6d450afbed3ff5b807ad780 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 18:16:15 +0100 Subject: [PATCH 12/38] * native OpenGL Support (dynamic or static linked) --- glBitmap.pas | 845 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 515 insertions(+), 330 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index e1e591d..1a547ac 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -218,58 +218,51 @@ unit glBitmap; // Please uncomment the defines below to configure the glBitmap to your preferences. // If you have configured the unit you can uncomment the warning above. -// ###### Start of preferences ################################################ - -{$DEFINE GLB_NO_NATIVE_GL} -// To enable the dglOpenGL.pas Header -// With native GL then bindings are staticlly declared to support other headers -// or use the glBitmap inside of DLLs (minimize codesize). +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Preferences /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// activate to enable build-in OpenGL support with statically linked methods +// use dglOpenGL.pas if not enabled +{$DEFINE GLB_NATIVE_OGL_STATIC} +// activate to enable build-in OpenGL support with dynamically linked methods +// use dglOpenGL.pas if not enabled +{$DEFINE GLB_NATIVE_OGL_DYNAMIC} +// activate to enable the support for SDL_surfaces {.$DEFINE GLB_SDL} -// To enable the support for SDL_surfaces +// activate to enable the support for TBitmap from Delphi (not lazarus) {.$DEFINE GLB_DELPHI} -// To enable the support for TBitmap from Delphi (not lazarus) -// *** image libs *** - -{.$DEFINE GLB_SDL_IMAGE} -// To enable the support of SDL_image to load files. (READ ONLY) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// activate to enable the support of SDL_image to load files. (READ ONLY) // If you enable SDL_image all other libraries will be ignored! +{.$DEFINE GLB_SDL_IMAGE} - -{.$DEFINE GLB_PNGIMAGE} -// to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ +// activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored +{.$DEFINE GLB_PNGIMAGE} -{.$DEFINE GLB_LIB_PNG} -// to use the libPNG http://www.libpng.org/ +// activate to use the libPNG http://www.libpng.org/ // You will need an aditional header. // http://www.opengl24.de/index.php?cat=header&file=libpng +{.$DEFINE GLB_LIB_PNG} -{.$DEFINE GLB_DELPHI_JPEG} // if you enable delphi jpegs the libJPEG will be ignored +{.$DEFINE GLB_DELPHI_JPEG} -{.$DEFINE GLB_LIB_JPEG} -// to use the libJPEG http://www.ijg.org/ +// activateto use the libJPEG http://www.ijg.org/ // You will need an aditional header. // http://www.opengl24.de/index.php?cat=header&file=libjpeg +{.$DEFINE GLB_LIB_JPEG} -// ###### End of preferences ################################################## - - -// ###### PRIVATE. Do not change anything. #################################### -// *** old defines for compatibility *** -{$IFDEF NO_NATIVE_GL} - {$DEFINE GLB_NO_NATIVE_GL} -{$ENDIF} -{$IFDEF pngimage} - {$definde GLB_PNGIMAGE} -{$ENDIF} -// *** Delphi Versions *** +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PRIVATE: DO not change anything! ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Delphi Versions {$IFDEF fpc} {$MODE Delphi} @@ -283,7 +276,20 @@ unit glBitmap; {$ENDIF} {$ENDIF} -// *** checking define combinations *** +// Operation System +{$IF DEFINED(WIN32) or DEFINED(WIN64)} + {$DEFINE GLB_WIN} +{$ELSEIF DEFINED(LINUX)} + {$DEFINE GLB_LINUX} +{$IFEND} + +// native OpenGL Support +{$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)} + {$DEFINE GLB_NATIVE_OGL} +{$IFEND} + +// checking define combinations +//SDL Image {$IFDEF GLB_SDL_IMAGE} {$IFNDEF GLB_SDL} {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'} @@ -310,6 +316,7 @@ unit glBitmap; {$DEFINE GLB_SUPPORT_JPEG_READ} {$ENDIF} +// PNG Image {$IFDEF GLB_PNGIMAGE} {$IFDEF GLB_LIB_PNG} {$MESSAGE warn 'The library libPNG will be ignored if you are using pngimage.'} @@ -320,11 +327,13 @@ unit glBitmap; {$DEFINE GLB_SUPPORT_PNG_WRITE} {$ENDIF} +// libPNG {$IFDEF GLB_LIB_PNG} {$DEFINE GLB_SUPPORT_PNG_READ} {$DEFINE GLB_SUPPORT_PNG_WRITE} {$ENDIF} +// JPEG Image {$IFDEF GLB_DELPHI_JPEG} {$IFDEF GLB_LIB_JPEG} {$MESSAGE warn 'The library libJPEG will be ignored if you are using the unit JPEG.'} @@ -335,12 +344,18 @@ unit glBitmap; {$DEFINE GLB_SUPPORT_JPEG_WRITE} {$ENDIF} +// libJPEG {$IFDEF GLB_LIB_JPEG} {$DEFINE GLB_SUPPORT_JPEG_READ} {$DEFINE GLB_SUPPORT_JPEG_WRITE} {$ENDIF} -// *** general options *** +// native OpenGL +{$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)} + {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'} +{$ENDIF} + +// general options {$EXTENDEDSYNTAX ON} {$LONGSTRINGS ON} {$ALIGN ON} @@ -351,18 +366,21 @@ unit glBitmap; interface uses - {$IFDEF GLB_NO_NATIVE_GL} dglOpenGL, {$ENDIF} + {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} + {$IF DEFINED(GLB_WIN) AND + DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} + + {$IFDEF GLB_SDL} SDL, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} - {$IFDEF GLB_SDL} SDL, {$ENDIF} - {$IFDEF GLB_DELPHI} Dialogs, Windows, Graphics, {$ENDIF} + {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} - {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} + {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} + {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} - {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} - {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} + {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} - {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} - {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} Classes, SysUtils; {$IFNDEF GLB_DELPHI} @@ -379,209 +397,285 @@ type end; {$ENDIF} -(* TODO dglOpenGL -{$IFNDEF GLB_NO_NATIVE_GL} -// Native OpenGL Implementation -type - PByteBool = ^ByteBool; - -{$IFDEF GLB_DELPHI} -var - gLastContext: HGLRC; -{$ENDIF} - +{$IFDEF GLB_NATIVE_OGL} const - // Generell - GL_VERSION = $1F02; + GL_TRUE = 1; + GL_FALSE = 0; + + GL_VERSION = $1F02; GL_EXTENSIONS = $1F03; - GL_TRUE = 1; - GL_FALSE = 0; - - GL_TEXTURE_1D = $0DE0; - GL_TEXTURE_2D = $0DE1; - - GL_MAX_TEXTURE_SIZE = $0D33; - GL_PACK_ALIGNMENT = $0D05; - GL_UNPACK_ALIGNMENT = $0CF5; - - // Textureformats - GL_RGB = $1907; - GL_RGB4 = $804F; - GL_RGB8 = $8051; - GL_RGBA = $1908; - GL_RGBA4 = $8056; - GL_RGBA8 = $8058; - GL_BGR = $80E0; - GL_BGRA = $80E1; - GL_ALPHA4 = $803B; - GL_ALPHA8 = $803C; - GL_LUMINANCE4 = $803F; - GL_LUMINANCE8 = $8040; - GL_LUMINANCE4_ALPHA4 = $8043; - GL_LUMINANCE8_ALPHA8 = $8045; - GL_DEPTH_COMPONENT = $1902; - - GL_UNSIGNED_BYTE = $1401; - GL_ALPHA = $1906; - GL_LUMINANCE = $1909; - GL_LUMINANCE_ALPHA = $190A; - - GL_TEXTURE_WIDTH = $1000; - GL_TEXTURE_HEIGHT = $1001; - GL_TEXTURE_INTERNAL_FORMAT = $1003; - GL_TEXTURE_RED_SIZE = $805C; - GL_TEXTURE_GREEN_SIZE = $805D; - GL_TEXTURE_BLUE_SIZE = $805E; - GL_TEXTURE_ALPHA_SIZE = $805F; - GL_TEXTURE_LUMINANCE_SIZE = $8060; - - // Dataformats - GL_UNSIGNED_SHORT_5_6_5 = $8363; - GL_UNSIGNED_SHORT_5_6_5_REV = $8364; + GL_TEXTURE_1D = $0DE0; + GL_TEXTURE_2D = $0DE1; + GL_TEXTURE_RECTANGLE = $84F5; + + GL_TEXTURE_WIDTH = $1000; + GL_TEXTURE_HEIGHT = $1001; + GL_TEXTURE_INTERNAL_FORMAT = $1003; + + GL_ALPHA = $1906; + GL_ALPHA4 = $803B; + GL_ALPHA8 = $803C; + GL_ALPHA12 = $803D; + GL_ALPHA16 = $803E; + + GL_LUMINANCE = $1909; + GL_LUMINANCE4 = $803F; + GL_LUMINANCE8 = $8040; + GL_LUMINANCE12 = $8041; + GL_LUMINANCE16 = $8042; + + GL_LUMINANCE_ALPHA = $190A; + GL_LUMINANCE4_ALPHA4 = $8043; + GL_LUMINANCE6_ALPHA2 = $8044; + GL_LUMINANCE8_ALPHA8 = $8045; + GL_LUMINANCE12_ALPHA4 = $8046; + GL_LUMINANCE12_ALPHA12 = $8047; + GL_LUMINANCE16_ALPHA16 = $8048; + + GL_RGB = $1907; + GL_BGR = $80E0; + GL_R3_G3_B2 = $2A10; + GL_RGB4 = $804F; + GL_RGB5 = $8050; + GL_RGB565 = $8D62; + GL_RGB8 = $8051; + GL_RGB10 = $8052; + GL_RGB12 = $8053; + GL_RGB16 = $8054; + + GL_RGBA = $1908; + GL_BGRA = $80E1; + GL_RGBA2 = $8055; + GL_RGBA4 = $8056; + GL_RGB5_A1 = $8057; + GL_RGBA8 = $8058; + GL_RGB10_A2 = $8059; + GL_RGBA12 = $805A; + GL_RGBA16 = $805B; + + GL_DEPTH_COMPONENT = $1902; + GL_DEPTH_COMPONENT16 = $81A5; + GL_DEPTH_COMPONENT24 = $81A6; + GL_DEPTH_COMPONENT32 = $81A7; + + GL_COMPRESSED_RGB = $84ED; + GL_COMPRESSED_RGBA = $84EE; + GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0; + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1; + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2; + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3; + + GL_UNSIGNED_BYTE = $1401; + GL_UNSIGNED_BYTE_3_3_2 = $8032; + GL_UNSIGNED_BYTE_2_3_3_REV = $8362; + + GL_UNSIGNED_SHORT = $1403; + GL_UNSIGNED_SHORT_5_6_5 = $8363; + GL_UNSIGNED_SHORT_4_4_4_4 = $8033; + GL_UNSIGNED_SHORT_5_5_5_1 = $8034; + GL_UNSIGNED_SHORT_5_6_5_REV = $8364; GL_UNSIGNED_SHORT_4_4_4_4_REV = $8365; GL_UNSIGNED_SHORT_1_5_5_5_REV = $8366; - GL_UNSIGNED_INT_2_10_10_10_REV = $8368; - // Filter - GL_NEAREST = $2600; - GL_LINEAR = $2601; + GL_UNSIGNED_INT = $1405; + GL_UNSIGNED_INT_8_8_8_8 = $8035; + GL_UNSIGNED_INT_10_10_10_2 = $8036; + GL_UNSIGNED_INT_8_8_8_8_REV = $8367; + GL_UNSIGNED_INT_2_10_10_10_REV = $8368; + + { Texture Filter } + GL_TEXTURE_MAG_FILTER = $2800; + GL_TEXTURE_MIN_FILTER = $2801; + GL_NEAREST = $2600; GL_NEAREST_MIPMAP_NEAREST = $2700; - GL_LINEAR_MIPMAP_NEAREST = $2701; - GL_NEAREST_MIPMAP_LINEAR = $2702; - GL_LINEAR_MIPMAP_LINEAR = $2703; - GL_TEXTURE_MAG_FILTER = $2800; - GL_TEXTURE_MIN_FILTER = $2801; - - // Wrapmodes - GL_TEXTURE_WRAP_S = $2802; - GL_TEXTURE_WRAP_T = $2803; - GL_CLAMP = $2900; - GL_REPEAT = $2901; - GL_CLAMP_TO_EDGE = $812F; - GL_CLAMP_TO_BORDER = $812D; - GL_TEXTURE_WRAP_R = $8072; - - GL_MIRRORED_REPEAT = $8370; - - // Border Color + GL_NEAREST_MIPMAP_LINEAR = $2702; + GL_LINEAR = $2601; + GL_LINEAR_MIPMAP_NEAREST = $2701; + GL_LINEAR_MIPMAP_LINEAR = $2703; + + { Texture Wrap } + GL_TEXTURE_WRAP_S = $2802; + GL_TEXTURE_WRAP_T = $2803; + GL_TEXTURE_WRAP_R = $8072; + GL_CLAMP = $2900; + GL_REPEAT = $2901; + GL_CLAMP_TO_EDGE = $812F; + GL_CLAMP_TO_BORDER = $812D; + GL_MIRRORED_REPEAT = $8370; + + { Other } + GL_GENERATE_MIPMAP = $8191; GL_TEXTURE_BORDER_COLOR = $1004; + GL_MAX_TEXTURE_SIZE = $0D33; + GL_PACK_ALIGNMENT = $0D05; + GL_UNPACK_ALIGNMENT = $0CF5; - // Texgen - GL_NORMAL_MAP = $8511; - GL_REFLECTION_MAP = $8512; - GL_S = $2000; - GL_T = $2001; - GL_R = $2002; - GL_TEXTURE_GEN_MODE = $2500; - GL_TEXTURE_GEN_S = $0C60; - GL_TEXTURE_GEN_T = $0C61; - GL_TEXTURE_GEN_R = $0C62; - - // Cubemaps - GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C; - GL_TEXTURE_CUBE_MAP = $8513; - GL_TEXTURE_BINDING_CUBE_MAP = $8514; - GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515; - GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516; - GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518; - GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519; - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A; - - GL_TEXTURE_RECTANGLE_ARB = $84F5; - - // GL_SGIS_generate_mipmap - GL_GENERATE_MIPMAP = $8191; - - // GL_EXT_texture_compression_s3tc - GL_COMPRESSED_RGB_S3TC_DXT1_EXT = $83F0; - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = $83F1; - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = $83F2; - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = $83F3; - - // GL_EXT_texture_filter_anisotropic - GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; + GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; - // GL_ARB_texture_compression - GL_COMPRESSED_RGB = $84ED; - GL_COMPRESSED_RGBA = $84EE; - GL_COMPRESSED_ALPHA = $84E9; - GL_COMPRESSED_LUMINANCE = $84EA; - GL_COMPRESSED_LUMINANCE_ALPHA = $84EB; +{$ifdef LINUX} + libglu = 'libGLU.so.1'; + libopengl = 'libGL.so.1'; +{$else} + libglu = 'glu32.dll'; + libopengl = 'opengl32.dll'; +{$endif} + +type + GLboolean = BYTEBOOL; + GLint = Integer; + GLsizei = Integer; + GLuint = Cardinal; + GLfloat = Single; + GLenum = Cardinal; + + PGLvoid = Pointer; + PGLboolean = ^GLboolean; + PGLint = ^GLint; + PGLuint = ^GLuint; + PGLfloat = ^GLfloat; + + TglCompressedTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + +{$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)} + TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TglGetString = function(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TglAreTexturesResident = function(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglReadPixels = procedure(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglPixelStorei = procedure(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TglTexImage1D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglGetTexImage = procedure(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + + {$IFDEF GLB_LINUX} + TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl; + {$ELSE} + TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall; + {$ENDIF} + +{$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)} + procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + function glGetString(name: GLenum): PAnsiChar; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + function glAreTexturesResident(n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF DGL_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glReadPixels(x: GLint; y: GLint; width: GLsizei; height: GLsizei; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glPixelStorei(pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + procedure glTexImage1D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glTexImage2D(target: GLenum; level: GLint; internalformat: GLint; width: GLsizei; height: GLsizei; border: GLint; format: GLenum; _type: GLenum; const pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glGetTexImage(target: GLenum; level: GLint; format: GLenum; _type: GLenum; pixels: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + + function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu; + function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu; +{$ENDIF} - // Extensions var GL_VERSION_1_2, GL_VERSION_1_3, GL_VERSION_1_4, GL_VERSION_2_0, + GL_SGIS_generate_mipmap, + GL_ARB_texture_border_clamp, - GL_ARB_texture_cube_map, - GL_ARB_texture_compression, - GL_ARB_texture_non_power_of_two, - GL_ARB_texture_rectangle, GL_ARB_texture_mirrored_repeat, - GL_EXT_bgra, - GL_EXT_texture_edge_clamp, - GL_EXT_texture_cube_map, - GL_EXT_texture_compression_s3tc, - GL_EXT_texture_filter_anisotropic, - GL_EXT_texture_rectangle, - GL_NV_texture_rectangle, + GL_ARB_texture_rectangle, + GL_ARB_texture_non_power_of_two, + GL_IBM_texture_mirrored_repeat, - GL_SGIS_generate_mipmap: Boolean; -const -{$IFDEF LINUX} - libglu = 'libGLU.so.1'; - libopengl = 'libGL.so.1'; -{$else} - libglu = 'glu32.dll'; - libopengl = 'opengl32.dll'; -{$ENDIF} + GL_NV_texture_rectangle, -{$IFDEF LINUX} - function glXGetProcAddress(ProcName: PAnsiChar): Pointer; cdecl; external libopengl; -{$else} - function wglGetProcAddress(ProcName: PAnsiChar): Pointer; stdcall; external libopengl; + GL_EXT_texture_edge_clamp, + GL_EXT_texture_rectangle, + GL_EXT_texture_filter_anisotropic: Boolean; + + glCompressedTexImage1D: TglCompressedTexImage1D; + glCompressedTexImage2D: TglCompressedTexImage2D; + glGetCompressedTexImage: TglGetCompressedTexImage; + +{$IFDEF GLB_NATIVE_OGL_DYNAMIC} + glEnable: TglEnable; + glDisable: TglDisable; + + glGetString: TglGetString; + glGetIntegerv: TglGetIntegerv; + + glTexParameteri: TglTexParameteri; + glTexParameterfv: TglTexParameterfv; + glGetTexParameteriv: TglGetTexParameteriv; + glGetTexParameterfv: TglGetTexParameterfv; + glGetTexLevelParameteriv: TglGetTexLevelParameteriv; + glGetTexLevelParameterfv: TglGetTexLevelParameterfv; + + glGenTextures: TglGenTextures; + glBindTexture: TglBindTexture; + glDeleteTextures: TglDeleteTextures; + + glAreTexturesResident: TglAreTexturesResident; + glReadPixels: TglReadPixels; + glPixelStorei: TglPixelStorei; + + glTexImage1D: TglTexImage1D; + glTexImage2D: TglTexImage2D; + glGetTexImage: TglGetTexImage; + + gluBuild1DMipmaps: TgluBuild1DMipmaps; + gluBuild2DMipmaps: TgluBuild2DMipmaps; + + {$IF DEFINED(GLB_WIN)} + wglGetProcAddress: TwglGetProcAddress; + {$ELSEIF DEFINED(GLB_LINUX)} + glXGetProcAddress: TglXGetProcAddress; + glXGetProcAddressARB: TglXGetProcAddressARB; + {$ENDIF} {$ENDIF} - function glGetString(name: Cardinal): PAnsiChar; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - procedure glEnable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glDisable(cap: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glGetIntegerv(pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - procedure glTexImage1D(target: Cardinal; level, internalformat, width, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glTexImage2D(target: Cardinal; level, internalformat, width, height, border: Integer; format, atype: Cardinal; const pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - procedure glGenTextures(n: Integer; Textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glBindTexture(target: Cardinal; Texture: Cardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glDeleteTextures(n: Integer; const textures: PCardinal); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - procedure glReadPixels(x, y: Integer; width, height: Integer; format, atype: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glPixelStorei(pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glGetTexImage(target: Cardinal; level: Integer; format: Cardinal; _type: Cardinal; pixels: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - function glAreTexturesResident(n: Integer; const Textures: PCardinal; residences: PByteBool): ByteBool; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glTexParameteri(target: Cardinal; pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glTexParameterfv(target: Cardinal; pname: Cardinal; const params: PSingle); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glGetTexLevelParameteriv(target: Cardinal; level: Integer; pname: Cardinal; params: PInteger); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - procedure glTexGeni(coord, pname: Cardinal; param: Integer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libopengl; - - function gluBuild1DMipmaps(Target: Cardinal; Components, Width: Integer; Format, atype: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu; - function gluBuild2DMipmaps(Target: Cardinal; Components, Width, Height: Integer; Format, aType: Cardinal; Data: Pointer): Integer; {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} external libglu; - +(* +{$IFDEF GLB_DELPHI} var - glCompressedTexImage2D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width, height: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} - glCompressedTexImage1D : procedure(target: Cardinal; level: Integer; internalformat: Cardinal; width: Integer; border: Integer; imageSize: Integer; const data: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} - glGetCompressedTexImage : procedure(target: Cardinal; level: Integer; img: Pointer); {$IFDEF WINDOWS}stdcall; {$else}cdecl; {$ENDIF} + gLastContext: HGLRC; {$ENDIF} *) +{$ENDIF} + type //////////////////////////////////////////////////////////////////////////////////////////////////// EglBitmapException = class(Exception); @@ -1104,7 +1198,7 @@ type function HasAlpha: Boolean; virtual; function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; - procedure PreparePixel(var aPixel: TglBitmapPixelData); virtual; + procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual; constructor Create; virtual; public @@ -1609,6 +1703,8 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function FormatGetSupportedFiles(const aFormat: TglBitmapFormat): TglBitmapFileTypes; begin + result := []; + if (aFormat in [ //4 bbp tfLuminance4, @@ -1739,6 +1835,7 @@ begin LUMINANCE_WEIGHT_B * aPixel.Data.b); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function DepthWeight(const aPixel: TglBitmapPixelData): Cardinal; begin result := Trunc( @@ -1747,11 +1844,137 @@ begin DEPTH_WEIGHT_B * aPixel.Data.b); end; -//TODO check _ARB functions and constants +{$IFDEF GLB_NATIVE_OGL} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//OpenGLInitialization/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +var + GL_LibHandle: Pointer = nil; + +function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer; +begin + result := nil; + + if not Assigned(aLibHandle) then + aLibHandle := GL_LibHandle; + +{$IF DEFINED(GLB_WIN)} + result := GetProcAddress(HMODULE(aLibHandle), aProcName); + if Assigned(result) then + exit; + + if Assigned(wglGetProcAddress) then + result := wglGetProcAddress(aProcName); +{$ELSEIF DEFINED(GLB_LINUX)} + if Assigned(glXGetProcAddress) then begin + result := glXGetProcAddress(aProcName); + if Assigned(result) then + exit; + end; + + if Assigned(glXGetProcAddressARB) then begin + result := glXGetProcAddressARB(aProcName); + if Assigned(result) then + exit; + end; + + result := dlsym(aLibHandle, aProcName); +{$ENDIF} + if not Assigned(result) then + raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName); +end; + +{$IFDEF GLB_NATIVE_OGL_DYNAMIC} +var + GLU_LibHandle: Pointer = nil; + OpenGLInitialized: Boolean; + InitOpenGLCS: TCriticalSection; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glbInitOpenGL; + + //////////////////////////////////////////////////////////////////////////////// + function glbLoadLibrary(const aName: PChar): Pointer; + begin + {$IF DEFINED(GLB_WIN)} + result := Pointer(LoadLibrary(aName)); + {$ELSEIF DEFINED(GLB_LINUX)} + result := dlopen(Name, RTLD_LAZY); + {$ELSE} + result := nil; + {$ENDIF} + end; + + //////////////////////////////////////////////////////////////////////////////// + function glbFreeLibrary(const aLibHandle: Pointer): Boolean; + begin + result := false; + if not Assigned(aLibHandle) then + exit; + + {$IF DEFINED(GLB_WIN)} + Result := FreeLibrary(HINST(aLibHandle)); + {$ELSEIF DEFINED(GLB_LINUX)} + Result := dlclose(aLibHandle) = 0; + {$ENDIF} + end; -(* GLB_NO_NATIVE_GL -{$IFNDEF GLB_NO_NATIVE_GL} -procedure ReadOpenGLExtensions; +var + p: Pointer; +begin + if Assigned(GL_LibHandle) then + glbFreeLibrary(GL_LibHandle); + + if Assigned(GLU_LibHandle) then + glbFreeLibrary(GLU_LibHandle); + + GL_LibHandle := glbLoadLibrary(libopengl); + if not Assigned(GL_LibHandle) then + raise EglBitmapException.Create('unable to load library: ' + libopengl); + + GLU_LibHandle := glbLoadLibrary(libglu); + if not Assigned(GLU_LibHandle) then + raise EglBitmapException.Create('unable to load library: ' + libglu); + + try + {$IF DEFINED(GLB_WIN)} + wglGetProcAddress := glbGetProcAddress('wglGetProcAddress'); + {$ELSEIF DEFINED(GLB_LINUX)} + glXGetProcAddress := glbGetProcAddress('glXGetProcAddress'); + glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB'); + {$ENDIF} + + glEnable := glbGetProcAddress('glEnable'); + glDisable := glbGetProcAddress('glDisable'); + glGetString := glbGetProcAddress('glGetString'); + glGetIntegerv := glbGetProcAddress('glGetIntegerv'); + glTexParameteri := glbGetProcAddress('glTexParameteri'); + glTexParameterfv := glbGetProcAddress('glTexParameterfv'); + glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv'); + glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv'); + glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv'); + glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv'); + glGenTextures := glbGetProcAddress('glGenTextures'); + glBindTexture := glbGetProcAddress('glBindTexture'); + glDeleteTextures := glbGetProcAddress('glDeleteTextures'); + glAreTexturesResident := glbGetProcAddress('glAreTexturesResident'); + glReadPixels := glbGetProcAddress('glReadPixels'); + glPixelStorei := glbGetProcAddress('glPixelStorei'); + glTexImage1D := glbGetProcAddress('glTexImage1D'); + glTexImage2D := glbGetProcAddress('glTexImage2D'); + glGetTexImage := glbGetProcAddress('glGetTexImage'); + + gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle); + gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle); + finally + glbFreeLibrary(GL_LibHandle); + glbFreeLibrary(GLU_LibHandle); + end; +end; +{$ENDIF} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glbReadOpenGLExtensions; var {$IFDEF GLB_DELPHI} Context: HGLRC; @@ -1759,7 +1982,7 @@ var Buffer: AnsiString; MajorVersion, MinorVersion: Integer; - + /////////////////////////////////////////////////////////////////////////////////////////// procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer); var Separator: Integer; @@ -1768,7 +1991,6 @@ var Major := 0; Separator := Pos(AnsiString('.'), Buffer); - if (Separator > 1) and (Separator < Length(Buffer)) and (Buffer[Separator - 1] in ['0'..'9']) and (Buffer[Separator + 1] in ['0'..'9']) then begin @@ -1791,36 +2013,35 @@ var end; end; - + /////////////////////////////////////////////////////////////////////////////////////////// function CheckExtension(const Extension: AnsiString): Boolean; var ExtPos: Integer; begin ExtPos := Pos(Extension, Buffer); result := ExtPos > 0; - if result then result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']); end; - - function glLoad (aFunc: pAnsiChar): pointer; - begin - {$IFDEF LINUX} - result := glXGetProcAddress(aFunc); - {$else} - result := wglGetProcAddress(aFunc); - {$ENDIF} +begin +{$IFDEF GLB_NATIVE_OGL_DYNAMIC} + InitOpenGLCS.Enter; + try + if not OpenGLInitialized then begin + glbInitOpenGL; + OpenGLInitialized := true; + end; + finally + InitOpenGLCS.Leave; end; +{$ENDIF} - -begin - {$IFDEF GLB_DELPHI} +{$IFDEF GLB_DELPHI} Context := wglGetCurrentContext; - - if Context <> gLastContext then begin + if (Context <> gLastContext) then begin gLastContext := Context; - {$ENDIF} +{$ENDIF} // Version Buffer := glGetString(GL_VERSION); @@ -1830,21 +2051,16 @@ begin GL_VERSION_1_3 := false; GL_VERSION_1_4 := false; GL_VERSION_2_0 := false; - if MajorVersion = 1 then begin - if MinorVersion >= 1 then begin - if MinorVersion >= 2 then - GL_VERSION_1_2 := true; + if MinorVersion >= 2 then + GL_VERSION_1_2 := true; - if MinorVersion >= 3 then - GL_VERSION_1_3 := true; + if MinorVersion >= 3 then + GL_VERSION_1_3 := true; - if MinorVersion >= 4 then - GL_VERSION_1_4 := true; - end; - end; - - if MajorVersion >= 2 then begin + if MinorVersion >= 4 then + GL_VERSION_1_4 := true; + end else if MajorVersion >= 2 then begin GL_VERSION_1_2 := true; GL_VERSION_1_3 := true; GL_VERSION_1_4 := true; @@ -1854,41 +2070,30 @@ begin // Extensions Buffer := glGetString(GL_EXTENSIONS); GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp'); - GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map'); - GL_ARB_texture_compression := CheckExtension('GL_ARB_texture_compression'); GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two'); GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle'); GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat'); - GL_EXT_bgra := CheckExtension('GL_EXT_bgra'); GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp'); - GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map'); - GL_EXT_texture_compression_s3tc := CheckExtension('GL_EXT_texture_compression_s3tc'); GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic'); GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle'); GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle'); GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat'); GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap'); - // Funtions if GL_VERSION_1_3 then begin - // Loading Core - glCompressedTexImage1D := glLoad('glCompressedTexImage1D'); - glCompressedTexImage2D := glLoad('glCompressedTexImage2D'); - glGetCompressedTexImage := glLoad('glGetCompressedTexImage'); - end else - - begin - // Try loading Extension - glCompressedTexImage1D := glLoad('glCompressedTexImage1DARB'); - glCompressedTexImage2D := glLoad('glCompressedTexImage2DARB'); - glGetCompressedTexImage := glLoad('glGetCompressedTexImageARB'); + glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D'); + glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D'); + glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage'); + end else begin + glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB'); + glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB'); + glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB'); end; - {$IFDEF GLB_DELPHI} +{$IFDEF GLB_DELPHI} end; - {$ENDIF} +{$ENDIF} end; {$ENDIF} -*) (* TODO GLB_DELPHI {$IFDEF GLB_DELPHI} @@ -2266,7 +2471,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TFormatDescriptor.PreparePixel(var aPixel: TglBitmapPixelData); +procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData); begin FillChar(aPixel, SizeOf(aPixel), 0); aPixel.Data := fRange; @@ -3756,6 +3961,7 @@ begin end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); type PUInt64 = ^UInt64; @@ -3801,6 +4007,21 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap - Helper////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapConvertPixel(var aPixel: TglBitmapPixelData; const aSourceFD, aDestFD: TFormatDescriptor); +var + i: Integer; +begin + for i := 0 to 3 do begin + if (aSourceFD.Range.arr[i] <> aDestFD.Range.arr[i]) then begin + if (aSourceFD.Range.arr[i] > 0) then + aPixel.Data.arr[i] := Round(aPixel.Data.arr[i] / aSourceFD.Range.arr[i] * aDestFD.Range.arr[i]) + else + aPixel.Data.arr[i] := aDestFD.Range.arr[i]; + end; + end; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapConvertCopyFunc(var aFuncRec: TglBitmapFunctionRec); begin @@ -3851,10 +4072,7 @@ end; procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec); begin with aFuncRec do begin - Dest.Data.r := Source.Data.r; - Dest.Data.g := Source.Data.g; - Dest.Data.b := Source.Data.b; - Dest.Data.a := Source.Data.a; + Dest.Data := Source.Data; if (Args and $1 > 0) then begin Dest.Data.r := Dest.Data.r xor Dest.Range.r; Dest.Data.g := Dest.Data.g xor Dest.Range.g; @@ -4935,7 +5153,7 @@ begin result := false; FormatDesc := TFormatDescriptor.Get(Format); if Assigned(Data) then begin - if not ({FormatDesc.IsUncompressed or }FormatDesc.HasAlpha) then + if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT); result := ConvertTo(FormatDesc.WithoutAlpha); end; @@ -5246,8 +5464,8 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TglBitmap.Create; begin -{$IFNDEF GLB_NO_NATIVE_GL} - ReadOpenGLExtensions; +{$IFDEF GLB_NATIVE_OGL} + glbReadOpenGLExtensions; {$ENDIF} if (ClassType = TglBitmap) then raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); @@ -6322,16 +6540,7 @@ var SpecialFormat.PreparePixel(Pixel); for i := 0 to Info.biWidth-1 do begin SpecialFormat.Unmap(aLineBuf, Pixel, SourceMD); - with FormatDesc do begin - //TODO: use convert function - for j := 0 to 3 do - if (SpecialFormat.Range.arr[j] <> Range.arr[j]) then begin - if (SpecialFormat.Range.arr[j] > 0) then - Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / SpecialFormat.Range.arr[j] * Range.arr[j]) - else - Pixel.Data.arr[j] := 0; - end; - end; + glBitmapConvertPixel(Pixel, SpecialFormat, FormatDesc); FormatDesc.Map(Pixel, aData, DestMD); end; end; @@ -6563,16 +6772,7 @@ begin dstData := ConvertBuffer; for PixelIdx := 0 to Info.biWidth-1 do begin FormatDesc.Unmap(srcData, Pixel, SourceFD); - with FormatDesc do begin - //TODO use convert function - for i := 0 to 3 do - if (Converter.Range.arr[i] <> Range.arr[i]) then begin - if (Range.arr[i] > 0) then - Pixel.Data.arr[i] := Round(Pixel.Data.arr[i] / Range.arr[i] * Converter.Range.arr[i]) - else - Pixel.Data.arr[i] := 0; - end; - end; + glBitmapConvertPixel(Pixel, FormatDesc, Converter); Converter.Map(Pixel, dstData, DestFD); end; aStream.Write(ConvertBuffer^, wbLineSize); @@ -6618,15 +6818,12 @@ type end; const - TGA_UNCOMPRESSED_COLOR_TABLE = 1; - TGA_UNCOMPRESSED_RGB = 2; - TGA_UNCOMPRESSED_GRAY = 3; - TGA_COMPRESSED_COLOR_TABLE = 9; - TGA_COMPRESSED_RGB = 10; - TGA_COMPRESSED_GRAY = 11; + TGA_UNCOMPRESSED_RGB = 2; + TGA_UNCOMPRESSED_GRAY = 3; + TGA_COMPRESSED_RGB = 10; + TGA_COMPRESSED_GRAY = 11; - TGA_NONE_COLOR_TABLE = 0; - TGA_COLOR_TABLE = 1; + TGA_NONE_COLOR_TABLE = 0; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadTGA(const aStream: TStream): Boolean; @@ -6998,34 +7195,20 @@ const DDSD_CAPS = $00000001; DDSD_HEIGHT = $00000002; DDSD_WIDTH = $00000004; - DDSD_PITCH = $00000008; DDSD_PIXELFORMAT = $00001000; - DDSD_MIPMAPCOUNT = $00020000; - DDSD_LINEARSIZE = $00080000; - DDSD_DEPTH = $00800000; // DDS_header.sPixelFormat.dwFlags DDPF_ALPHAPIXELS = $00000001; DDPF_ALPHA = $00000002; DDPF_FOURCC = $00000004; - DDPF_INDEXED = $00000020; DDPF_RGB = $00000040; DDPF_LUMINANCE = $00020000; // DDS_header.sCaps.dwCaps1 - DDSCAPS_COMPLEX = $00000008; DDSCAPS_TEXTURE = $00001000; - DDSCAPS_MIPMAP = $00400000; // DDS_header.sCaps.dwCaps2 DDSCAPS2_CUBEMAP = $00000200; - DDSCAPS2_CUBEMAP_POSITIVEX = $00000400; - DDSCAPS2_CUBEMAP_NEGATIVEX = $00000800; - DDSCAPS2_CUBEMAP_POSITIVEY = $00001000; - DDSCAPS2_CUBEMAP_NEGATIVEY = $00002000; - DDSCAPS2_CUBEMAP_POSITIVEZ = $00004000; - DDSCAPS2_CUBEMAP_NEGATIVEZ = $00008000; - DDSCAPS2_VOLUME = $00200000; D3DFMT_DXT1 = $31545844; D3DFMT_DXT3 = $33545844; @@ -7193,14 +7376,7 @@ begin aStream.Read(SrcData^, RowSize); for x := 0 to Header.dwWidth-1 do begin Converter.Unmap(SrcData, Pixel, SourceMD); - //TODO use converter function - for j := 0 to 3 do - if (Converter.Range.arr[j] <> FormatDesc.Range.arr[j]) then begin - if (Converter.Range.arr[j] > 0) then - Pixel.Data.arr[j] := Round(Pixel.Data.arr[j] / Converter.Range.arr[j] * FormatDesc.Range.arr[j]) - else - Pixel.Data.arr[j] := 0; - end; + glBitmapConvertPixel(Pixel, Converter, FormatDesc); FormatDesc.Map(Pixel, TmpData, DestMD); end; end; @@ -7461,7 +7637,7 @@ begin raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width); - TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE_ARB); + TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE); if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); @@ -8132,8 +8308,17 @@ initialization TFormatDescriptor.Init; +{$IFDEF GLB_NATIVE_OGL_DYNAMIC} + OpenGLInitialized := false; + InitOpenGLCS := TCriticalSection.Create; +{$ENDIF} + finalization TFormatDescriptor.Finalize; +{$IFDEF GLB_NATIVE_OGL_DYNAMIC} + FreeAndNil(InitOpenGLCS); +{$ENDIF} + end. From d52e74ca500daaa05e33e05b53d16317a2990e88 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 18:53:48 +0100 Subject: [PATCH 13/38] * fixed Compiler Warnings and Hints --- glBitmap.pas | 297 ++++++++++++++++++++++++--------------------------- 1 file changed, 137 insertions(+), 160 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 1a547ac..d39e7c5 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -223,7 +223,7 @@ unit glBitmap; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // activate to enable build-in OpenGL support with statically linked methods // use dglOpenGL.pas if not enabled -{$DEFINE GLB_NATIVE_OGL_STATIC} +{.$DEFINE GLB_NATIVE_OGL_STATIC} // activate to enable build-in OpenGL support with dynamically linked methods // use dglOpenGL.pas if not enabled @@ -794,7 +794,7 @@ type Position: TglBitmapPixelPosition; Source: TglBitmapPixelData; Dest: TglBitmapPixelData; - Args: PtrInt; + Args: Pointer; end; TglBitmapFunction = procedure(var FuncRec: TglBitmapFunctionRec); @@ -853,7 +853,7 @@ type procedure SetAnisotropic(const aValue: Integer); procedure CreateID; - procedure SetupParameters(var aBuildWithGlu: Boolean); + procedure SetupParameters(out aBuildWithGlu: Boolean); procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract; @@ -893,7 +893,7 @@ type procedure LoadFromFile(const aFilename: String); procedure LoadFromStream(const aStream: TStream); virtual; procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; - const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0); + const aFormat: TglBitmapFormat; const aArgs: Pointer = nil); {$IFDEF GLB_DELPHI} procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); @@ -904,9 +904,9 @@ type procedure SaveToStream(const aStream: TStream; const aFileType: TglBitmapFileType); virtual; //Convert - function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt = 0): Boolean; overload; + function AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer = nil): Boolean; overload; function AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean; - const aFormat: TglBitmapFormat; const aArgs: PtrInt = 0): Boolean; overload; + const aFormat: TglBitmapFormat; const aArgs: Pointer = nil): Boolean; overload; public //Alpha & Co {$IFDEF GLB_SDL} @@ -914,7 +914,7 @@ type function AssignFromSurface(const aSurface: PSDL_Surface): Boolean; function AssignAlphaToSurface(out aSurface: PSDL_Surface): Boolean; function AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; - const aArgs: PtrInt = 0): Boolean; + const aArgs: Pointer = nil): Boolean; {$ENDIF} {$IFDEF GLB_DELPHI} @@ -922,17 +922,17 @@ type function AssignFromBitmap(const aBitmap: TBitmap): Boolean; function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean; function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; - const aArgs: PtrInt = 0): Boolean; + const aArgs: Pointer = nil): Boolean; function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil; - const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; - const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; {$ENDIF} - function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0): Boolean; virtual; - function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; - function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: PtrInt = 0): Boolean; + function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual; + function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; + function AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; + function AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; function AddAlphaFromColorKey(const aRed, aGreen, aBlue: Byte; const aDeviation: Byte = 0): Boolean; function AddAlphaFromColorKeyRange(const aRed, aGreen, aBlue: Cardinal; const aDeviation: Cardinal = 0): Boolean; @@ -963,9 +963,6 @@ type const T: Cardinal = GL_CLAMP_TO_EDGE; const R: Cardinal = GL_CLAMP_TO_EDGE); - procedure GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); virtual; - procedure SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); virtual; - procedure Bind(const aEnableTextureUnit: Boolean = true); virtual; procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual; @@ -974,7 +971,7 @@ type constructor Create(const aFileName: String); overload; constructor Create(const aStream: TStream); overload; constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload; - constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: PtrInt = 0); overload; + constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload; {$IFDEF GLB_DELPHI} constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload; constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload; @@ -1186,7 +1183,7 @@ type property AlphaMask: UInt64 read GetAlphaMask; procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload; function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload; @@ -1215,117 +1212,117 @@ type ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TfdAlpha_UB1 = class(TFormatDescriptor) //1* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdLuminance_UB1 = class(TFormatDescriptor) //1* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdUniversal_UB1 = class(TFormatDescriptor) //1* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdLuminanceAlpha_UB2 = class(TfdLuminance_UB1) //2* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdRGB_UB3 = class(TFormatDescriptor) //3* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdBGR_UB3 = class(TFormatDescriptor) //3* unsigned byte (inverse) procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdRGBA_UB4 = class(TfdRGB_UB3) //4* unsigned byte procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdBGRA_UB4 = class(TfdBGR_UB3) //4* unsigned byte (inverse) procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TfdAlpha_US1 = class(TFormatDescriptor) //1* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdLuminance_US1 = class(TFormatDescriptor) //1* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdUniversal_US1 = class(TFormatDescriptor) //1* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdDepth_US1 = class(TFormatDescriptor) //1* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdLuminanceAlpha_US2 = class(TfdLuminance_US1) //2* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdRGB_US3 = class(TFormatDescriptor) //3* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdBGR_US3 = class(TFormatDescriptor) //3* unsigned short (inverse) procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdRGBA_US4 = class(TfdRGB_US3) //4* unsigned short procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdBGRA_US4 = class(TfdBGR_US3) //4* unsigned short (inverse) procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TfdUniversal_UI1 = class(TFormatDescriptor) //1* unsigned int procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; TfdDepth_UI1 = class(TFormatDescriptor) //1* unsigned int procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; @@ -1516,19 +1513,19 @@ type 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; + procedure Unmap(var aData: PByte; out 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; + procedure Unmap(var aData: PByte; out 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; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; constructor Create; override; end; @@ -1550,7 +1547,7 @@ type property PixelSize: Single read fPixelSize write fPixelSize; procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1571,7 +1568,7 @@ type procedure CreateColorTable; procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); override; - procedure Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); override; + procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); override; destructor Destroy; override; end; @@ -1859,7 +1856,7 @@ begin aLibHandle := GL_LibHandle; {$IF DEFINED(GLB_WIN)} - result := GetProcAddress(HMODULE(aLibHandle), aProcName); + result := GetProcAddress({%H-}HMODULE(aLibHandle), aProcName); if Assigned(result) then exit; @@ -1897,7 +1894,7 @@ procedure glbInitOpenGL; function glbLoadLibrary(const aName: PChar): Pointer; begin {$IF DEFINED(GLB_WIN)} - result := Pointer(LoadLibrary(aName)); + result := {%H-}Pointer(LoadLibrary(aName)); {$ELSEIF DEFINED(GLB_LINUX)} result := dlopen(Name, RTLD_LAZY); {$ELSE} @@ -1913,14 +1910,12 @@ procedure glbInitOpenGL; exit; {$IF DEFINED(GLB_WIN)} - Result := FreeLibrary(HINST(aLibHandle)); + Result := FreeLibrary({%H-}HINST(aLibHandle)); {$ELSEIF DEFINED(GLB_LINUX)} Result := dlclose(aLibHandle) = 0; {$ENDIF} end; -var - p: Pointer; begin if Assigned(GL_LibHandle) then glbFreeLibrary(GL_LibHandle); @@ -1983,33 +1978,33 @@ var MajorVersion, MinorVersion: Integer; /////////////////////////////////////////////////////////////////////////////////////////// - procedure TrimVersionString(Buffer: AnsiString; var Major, Minor: Integer); + procedure TrimVersionString(aBuffer: AnsiString; out aMajor, aMinor: Integer); var Separator: Integer; begin - Minor := 0; - Major := 0; + aMinor := 0; + aMajor := 0; - Separator := Pos(AnsiString('.'), Buffer); - if (Separator > 1) and (Separator < Length(Buffer)) and - (Buffer[Separator - 1] in ['0'..'9']) and - (Buffer[Separator + 1] in ['0'..'9']) then begin + Separator := Pos(AnsiString('.'), aBuffer); + if (Separator > 1) and (Separator < Length(aBuffer)) and + (aBuffer[Separator - 1] in ['0'..'9']) and + (aBuffer[Separator + 1] in ['0'..'9']) then begin Dec(Separator); - while (Separator > 0) and (Buffer[Separator] in ['0'..'9']) do + while (Separator > 0) and (aBuffer[Separator] in ['0'..'9']) do Dec(Separator); - Delete(Buffer, 1, Separator); - Separator := Pos(AnsiString('.'), Buffer) + 1; + Delete(aBuffer, 1, Separator); + Separator := Pos(AnsiString('.'), aBuffer) + 1; - while (Separator <= Length(Buffer)) and (AnsiChar(Buffer[Separator]) in ['0'..'9']) do + while (Separator <= Length(aBuffer)) and (AnsiChar(aBuffer[Separator]) in ['0'..'9']) do Inc(Separator); - Delete(Buffer, Separator, 255); - Separator := Pos(AnsiString('.'), Buffer); + Delete(aBuffer, Separator, 255); + Separator := Pos(AnsiString('.'), aBuffer); - Major := StrToInt(Copy(String(Buffer), 1, Separator - 1)); - Minor := StrToInt(Copy(String(Buffer), Separator + 1, 1)); + aMajor := StrToInt(Copy(String(aBuffer), 1, Separator - 1)); + aMinor := StrToInt(Copy(String(aBuffer), Separator + 1, 1)); end; end; @@ -2473,7 +2468,7 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TFormatDescriptor.PreparePixel(out aPixel: TglBitmapPixelData); begin - FillChar(aPixel, SizeOf(aPixel), 0); + FillChar(aPixel{%H-}, SizeOf(aPixel), 0); aPixel.Data := fRange; aPixel.Range := fRange; aPixel.Format := fFormat; @@ -2509,7 +2504,7 @@ begin inc(aData); end; -procedure TfdAlpha_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdAlpha_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := 0; aPixel.Data.g := 0; @@ -2536,7 +2531,7 @@ begin inc(aData); end; -procedure TfdLuminance_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdLuminance_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := aData^; aPixel.Data.g := aData^; @@ -2570,7 +2565,7 @@ begin inc(aData); end; -procedure TfdUniversal_UB1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdUniversal_UB1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); var i: Integer; begin @@ -2595,7 +2590,7 @@ begin inc(aData); end; -procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdLuminanceAlpha_UB2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := aData^; @@ -2625,7 +2620,7 @@ begin inc(aData); end; -procedure TfdRGB_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdRGB_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := aData^; inc(aData); @@ -2663,7 +2658,7 @@ begin inc(aData); end; -procedure TfdBGR_UB3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdBGR_UB3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.b := aData^; inc(aData); @@ -2697,7 +2692,7 @@ begin inc(aData); end; -procedure TfdRGBA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdRGBA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := aData^; @@ -2724,7 +2719,7 @@ begin inc(aData); end; -procedure TfdBGRA_UB4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdBGRA_UB4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := aData^; @@ -2750,7 +2745,7 @@ begin inc(aData, 2); end; -procedure TfdAlpha_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdAlpha_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := 0; aPixel.Data.g := 0; @@ -2777,7 +2772,7 @@ begin inc(aData, 2); end; -procedure TfdLuminance_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdLuminance_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := PWord(aData)^; aPixel.Data.g := PWord(aData)^; @@ -2811,7 +2806,7 @@ begin inc(aData, 2); end; -procedure TfdUniversal_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdUniversal_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); var i: Integer; begin @@ -2835,7 +2830,7 @@ begin inc(aData, 2); end; -procedure TfdDepth_US1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdDepth_US1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := PWord(aData)^; aPixel.Data.g := PWord(aData)^; @@ -2865,7 +2860,7 @@ begin inc(aData, 2); end; -procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdLuminanceAlpha_US2.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := PWord(aData)^; @@ -2895,7 +2890,7 @@ begin inc(aData, 2); end; -procedure TfdRGB_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdRGB_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := PWord(aData)^; inc(aData, 2); @@ -2933,7 +2928,7 @@ begin inc(aData, 2); end; -procedure TfdBGR_US3.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdBGR_US3.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.b := PWord(aData)^; inc(aData, 2); @@ -2968,7 +2963,7 @@ begin inc(aData, 2); end; -procedure TfdRGBA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdRGBA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := PWord(aData)^; @@ -2995,7 +2990,7 @@ begin inc(aData, 2); end; -procedure TfdBGRA_US4.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdBGRA_US4.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin inherited Unmap(aData, aPixel, aMapData); aPixel.Data.a := PWord(aData)^; @@ -3026,7 +3021,7 @@ begin inc(aData, 4); end; -procedure TfdUniversal_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdUniversal_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); var i: Integer; begin @@ -3050,7 +3045,7 @@ begin inc(aData, 4); end; -procedure TfdDepth_UI1.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdDepth_UI1.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin aPixel.Data.r := PCardinal(aData)^; aPixel.Data.g := PCardinal(aData)^; @@ -3662,7 +3657,7 @@ begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; -procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; @@ -3688,7 +3683,7 @@ begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; -procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; @@ -3714,7 +3709,7 @@ begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; -procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin raise EglBitmapException.Create('mapping for compressed formats is not supported'); end; @@ -3857,7 +3852,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); var data: UInt64; s, i: Integer; @@ -3883,8 +3878,6 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TbmpColorTableFormat.CreateColorTable; var - bits: Byte; - len: Integer; i: Integer; begin if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then @@ -3938,9 +3931,9 @@ begin if (aMapData = nil) then aData^ := 0; d := LuminanceWeight(aPixel) and Range.r; - aData^ := aData^ or (d shl (4 - PtrInt(aMapData))); + aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData))); inc(aMapData, 4); - if (PtrInt(aMapData) >= 8) then begin + if ({%H-}PtrUInt(aMapData) >= 8) then begin inc(aData); aMapData := nil; end; @@ -3962,7 +3955,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpColorTableFormat.Unmap(var aData: PByte; var aPixel: TglBitmapPixelData; var aMapData: Pointer); +procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); type PUInt64 = ^UInt64; var @@ -3975,7 +3968,7 @@ begin f := fPixelSize - s; bits := Round(8 * f); case s of - 0: idx := (aData^ shr (8 - bits - PtrInt(aMapData))) and ((1 shl bits) - 1); + 0: idx := (aData^ shr (8 - bits - {%H-}PtrUInt(aMapData))) and ((1 shl bits) - 1); 1: idx := aData^; 2: idx := PWord(aData)^; 4: idx := PCardinal(aData)^; @@ -3992,7 +3985,7 @@ begin aPixel.Data.a := a; end; inc(aMapData, bits); - if (PtrInt(aMapData) >= 8) then begin + if ({%H-}PtrUInt(aMapData) >= 8) then begin inc(aData, 1); dec(aMapData, 8); end; @@ -4073,12 +4066,12 @@ procedure glBitmapInvertFunc(var aFuncRec: TglBitmapFunctionRec); begin with aFuncRec do begin Dest.Data := Source.Data; - if (Args and $1 > 0) then begin + if ({%H-}PtrUInt(Args) and $1 > 0) then begin Dest.Data.r := Dest.Data.r xor Dest.Range.r; Dest.Data.g := Dest.Data.g xor Dest.Range.g; Dest.Data.b := Dest.Data.b xor Dest.Range.b; end; - if (Args and $2 > 0) then begin + if ({%H-}PtrUInt(Args) and $2 > 0) then begin Dest.Data.a := Dest.Data.a xor Dest.Range.a; end; end; @@ -4101,7 +4094,7 @@ var Temp: Single; begin with FuncRec do begin - if (FuncRec.Args = 0) then begin //source has no alpha + if (FuncRec.Args = nil) then begin //source has no alpha Temp := Source.Data.r / Source.Range.r * ALPHA_WEIGHT_R + Source.Data.g / Source.Range.g * ALPHA_WEIGHT_G + @@ -4134,8 +4127,6 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapValueAlphaFunc(var FuncRec: TglBitmapFunctionRec); -type - PglBitmapPixelData = ^TglBitmapPixelData; begin with FuncRec do begin Dest.Data.r := Source.Data.r; @@ -4303,7 +4294,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SetupParameters(var aBuildWithGlu: Boolean); +procedure TglBitmap.SetupParameters(out aBuildWithGlu: Boolean); begin // Set Up Parameters SetWrap(fWrapS, fWrapT, fWrapR); @@ -4432,7 +4423,7 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; - const aFormat: TglBitmapFormat; const aArgs: PtrInt); + const aFormat: TglBitmapFormat; const aArgs: Pointer); var tmpData: PByte; size: Integer; @@ -4519,14 +4510,14 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: PtrInt): Boolean; +function TglBitmap.AddFunc(const aFunc: TglBitmapFunction; const aCreateTemp: Boolean; const aArgs: Pointer): Boolean; begin result := AddFunc(Self, aFunc, aCreateTemp, Format, aArgs); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AddFunc(const aSource: TglBitmap; const aFunc: TglBitmapFunction; aCreateTemp: Boolean; - const aFormat: TglBitmapFormat; const aArgs: PtrInt): Boolean; + const aFormat: TglBitmapFormat; const aArgs: Pointer): Boolean; var DestData, TmpData, SourceData: pByte; TempHeight, TempWidth: Integer; @@ -4974,7 +4965,7 @@ end; {$ENDIF} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; begin (* TODO if not FormatIsUncompressed(InternalFormat) then @@ -4984,7 +4975,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; var FS: TFileStream; begin @@ -4997,7 +4988,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromStream(const aStream: TStream; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; var tex: TglBitmap2D; begin @@ -5010,7 +5001,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromGlBitmap(const aBitmap: TglBitmap; aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; var DestData, DestData2, SourceData: pByte; TempHeight, TempWidth: Integer; @@ -5027,21 +5018,23 @@ begin if ((aBitmap.Width = Width) and (aBitmap.Height = Height)) then begin result := ConvertTo(TFormatDescriptor.Get(Format).WithAlpha); - if not Assigned(aFunc) then - aFunc := glBitmapAlphaFunc; SourceFD := TFormatDescriptor.Get(aBitmap.Format); DestFD := TFormatDescriptor.Get(Format); + if not Assigned(aFunc) then begin + aFunc := glBitmapAlphaFunc; + FuncRec.Args := {%H-}Pointer(SourceFD.HasAlpha); + end else + FuncRec.Args := aArgs; + // Values TempHeight := aBitmap.FileHeight; TempWidth := aBitmap.FileWidth; FuncRec.Sender := Self; - FuncRec.Args := aArgs; FuncRec.Size := Dimension; FuncRec.Position.Fields := FuncRec.Size.Fields; - FuncRec.Args := PtrInt(SourceFD.HasAlpha) and 1; DestData := Data; DestData2 := Data; @@ -5116,7 +5109,7 @@ begin Data.a := 0; Range.a := 0; end; - result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, PtrInt(@PixelData)); + result := AddAlphaFromFunc(glBitmapColorKeyAlphaFunc, @PixelData); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5142,7 +5135,7 @@ begin TFormatDescriptor.GetWithAlpha(Format).PreparePixel(PixelData); with PixelData do Data.a := Min(Range.a, Max(0, Round(Range.a * aAlpha))); - result := AddAlphaFromFunc(glBitmapValueAlphaFunc, PtrInt(@PixelData.Data.a)); + result := AddAlphaFromFunc(glBitmapValueAlphaFunc, @PixelData.Data.a); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5258,7 +5251,7 @@ begin ShiftData.g := GetShift(SourcePD.Range.g, DestPD.Range.g); ShiftData.b := GetShift(SourcePD.Range.b, DestPD.Range.b); ShiftData.a := GetShift(SourcePD.Range.a, DestPD.Range.a); - result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, PtrInt(@ShiftData)); + result := AddFunc(Self, glBitmapConvertShiftRGBAFunc, false, aFormat, @ShiftData); end else result := AddFunc(Self, glBitmapConvertCalculateRGBAFunc, false, aFormat); end else @@ -5269,7 +5262,9 @@ end; procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean); begin if aUseRGB or aUseAlpha then - AddFunc(glBitmapInvertFunc, false, ((PtrInt(aUseAlpha) and 1) shl 1) or (PtrInt(aUseRGB) and 1)); + AddFunc(glBitmapInvertFunc, false, {%H-}Pointer( + ((PtrInt(aUseAlpha) and 1) shl 1) or + (PtrInt(aUseRGB) and 1) )); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5323,7 +5318,7 @@ begin Data.b := Max(0, Min(Range.b, Trunc(Range.b * aBlue))); Data.a := Max(0, Min(Range.a, Trunc(Range.a * aAlpha))); end; - AddFunc(glBitmapFillWithColorFunc, false, PtrInt(@PixelData)); + AddFunc(glBitmapFillWithColorFunc, false, @PixelData); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5426,24 +5421,6 @@ begin end; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.GetPixel(const aPos: TglBitmapPixelPosition; var aPixel: TglBitmapPixelData); -begin - { TODO delete? - if Assigned (fGetPixelFunc) then - fGetPixelFunc(aPos, aPixel); - } -end; - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SetPixel(const aPos: TglBitmapPixelPosition; const aPixel: TglBitmapPixelData); -begin - {TODO delete? - if Assigned (fSetPixelFunc) then - fSetPixelFuc(aPos, aPixel); - } -end; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean); begin @@ -5493,7 +5470,7 @@ var ImageSize: Integer; begin Create; - TFormatDescriptor.Get(aFormat).GetSize(aSize); + ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize); GetMem(Image, ImageSize); try FillChar(Image^, ImageSize, #$FF); @@ -5506,7 +5483,7 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; - const aFunc: TglBitmapFunction; const aArgs: PtrInt); + const aFunc: TglBitmapFunction; const aArgs: Pointer); begin Create; LoadFromFunc(aSize, aFunc, aFormat, aArgs); @@ -6423,11 +6400,11 @@ type function TglBitmap.LoadBMP(const aStream: TStream): Boolean; ////////////////////////////////////////////////////////////////////////////////////////////////// - function ReadInfo(var aInfo: TBMPInfo; var aMask: TglBitmapColorRec): TglBitmapFormat; + function ReadInfo(out aInfo: TBMPInfo; out aMask: TglBitmapColorRec): TglBitmapFormat; begin result := tfEmpty; - aStream.Read(aInfo, SizeOf(aInfo)); - FillChar(aMask, SizeOf(aMask), 0); + aStream.Read(aInfo{%H-}, SizeOf(aInfo)); + FillChar(aMask{%H-}, SizeOf(aMask), 0); //Read Compression case aInfo.biCompression of @@ -6519,7 +6496,6 @@ var LineBuf, ImageData, TmpData: PByte; SourceMD, DestMD: Pointer; BmpFormat: TglBitmapFormat; - ColorTable: TbmpColorTable; //records Mask: TglBitmapColorRec; @@ -6533,7 +6509,7 @@ var ////////////////////////////////////////////////////////////////////////////////////////////////// procedure SpecialFormatReadLine(aData: PByte; aLineBuf: PByte); var - i, j: Integer; + i: Integer; Pixel: TglBitmapPixelData; begin aStream.Read(aLineBuf^, rbLineSize); @@ -6555,7 +6531,7 @@ begin // Header StartPos := aStream.Position; - aStream.Read(Header, SizeOf(Header)); + aStream.Read(Header{%H-}, SizeOf(Header)); if Header.bfType = BMP_MAGIC then begin try try @@ -6595,7 +6571,7 @@ begin dec(TmpData, wbLineSize) else inc(TmpData, wbLineSize); - aStream.Read(PaddingBuff, Padding); + aStream.Read(PaddingBuff{%H-}, Padding); end; SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); result := true; @@ -6634,8 +6610,7 @@ var pData, srcData, dstData, ConvertBuffer: pByte; Pixel: TglBitmapPixelData; - PixelFormat: TglBitmapPixelData; - ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx, i: Integer; + ImageSize, wbLineSize, rbLineSize, Padding, LineIdx, PixelIdx: Integer; RedMask, GreenMask, BlueMask, AlphaMask: Cardinal; PaddingBuff: Cardinal; @@ -6653,14 +6628,14 @@ begin FormatDesc := TFormatDescriptor.Get(Format); ImageSize := FormatDesc.GetSize(Dimension); - FillChar(Header, SizeOf(Header), 0); + FillChar(Header{%H-}, SizeOf(Header), 0); Header.bfType := BMP_MAGIC; Header.bfSize := SizeOf(Header) + SizeOf(Info) + ImageSize; Header.bfReserved1 := 0; Header.bfReserved2 := 0; Header.bfOffBits := SizeOf(Header) + SizeOf(Info); - FillChar(Info, SizeOf(Info), 0); + FillChar(Info{%H-}, SizeOf(Info), 0); Info.biSize := SizeOf(Info); Info.biWidth := Width; Info.biHeight := Height; @@ -6907,7 +6882,7 @@ const BytesRead := 0; if (CacheSize - CachePos > 0) then begin BytesRead := CacheSize - CachePos; - Move(PByteArray(Cache)^[CachePos], Buffer, BytesRead); + Move(PByteArray(Cache)^[CachePos], Buffer{%H-}, BytesRead); inc(CachePos, BytesRead); end; @@ -7009,7 +6984,7 @@ begin // reading header to test file and set cursor back to begin StartPosition := aStream.Position; - aStream.Read(Header, SizeOf(Header)); + aStream.Read(Header{%H-}, SizeOf(Header)); // no colormapped files if (Header.ColorMapType = TGA_NONE_COLOR_TABLE) and (Header.ImageType in [ @@ -7111,7 +7086,7 @@ begin raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); //prepare header - FillChar(Header, SizeOf(Header), 0); + FillChar(Header{%H-}, SizeOf(Header), 0); //set ImageType if (Format in [tfLuminance8, tfLuminance6Alpha2, tfLuminance4Alpha4, tfAlpha8, @@ -7320,7 +7295,7 @@ var var StreamPos: Int64; - x, y, j, LineSize, RowSize, Magic: Cardinal; + x, y, LineSize, RowSize, Magic: Cardinal; NewImage, TmpData, RowData, SrcData: PByte; SourceMD, DestMD: Pointer; Pixel: TglBitmapPixelData; @@ -7333,14 +7308,14 @@ begin StreamPos := aStream.Position; // Magic - aStream.Read(Magic, sizeof(Magic)); + aStream.Read(Magic{%H-}, sizeof(Magic)); if (Magic <> DDS_MAGIC) then begin aStream.Position := StreamPos; exit; end; //Header - aStream.Read(Header, sizeof(Header)); + aStream.Read(Header{%H-}, sizeof(Header)); if (Header.dwSize <> SizeOf(Header)) 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 @@ -7429,7 +7404,7 @@ begin FormatDesc := TFormatDescriptor.Get(Format); // Generell - FillChar(Header, SizeOf(Header), 0); + FillChar(Header{%H-}, SizeOf(Header), 0); Header.dwSize := SizeOf(Header); Header.dwFlags := DDSD_WIDTH or DDSD_HEIGHT or DDSD_CAPS or DDSD_PIXELFORMAT; @@ -7589,7 +7564,7 @@ procedure TglBitmap2D.GetDataFromTexture; var Temp: PByte; TempWidth, TempHeight: Integer; - TempType, TempIntFormat: Cardinal; + TempIntFormat: Cardinal; IntFormat, f: TglBitmapFormat; FormatDesc: TFormatDescriptor; begin @@ -7601,11 +7576,13 @@ begin glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); IntFormat := tfEmpty; - for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do - if (TFormatDescriptor.Get(f).glInternalFormat = TempIntFormat) then begin + for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin + FormatDesc := TFormatDescriptor.Get(f); + if (FormatDesc.glInternalFormat = TempIntFormat) then begin IntFormat := FormatDesc.Format; break; end; + end; // Getting data from OpenGL FormatDesc := TFormatDescriptor.Get(IntFormat); @@ -7925,10 +7902,10 @@ begin // Daten Sammeln if aUseAlpha and TFormatDescriptor.Get(Format).HasAlpha then - AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, PtrInt(@Rec)) + AddFunc(glBitmapToNormalMapPrepareAlphaFunc, false, @Rec) else - AddFunc(glBitmapToNormalMapPrepareFunc, false, PtrInt(@Rec)); - AddFunc(glBitmapToNormalMapFunc, false, PtrInt(@Rec)); + AddFunc(glBitmapToNormalMapPrepareFunc, false, @Rec); + AddFunc(glBitmapToNormalMapFunc, false, @Rec); finally SetLength(Rec.Heights, 0); end; From 68113a32f56cd82b376d2006a0c696d22555057a Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 21:10:37 +0100 Subject: [PATCH 14/38] * added SDL support --- glBitmap.pas | 241 +++++++++++++++++++-------------------------------- 1 file changed, 89 insertions(+), 152 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index d39e7c5..19dba74 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -227,10 +227,10 @@ unit glBitmap; // activate to enable build-in OpenGL support with dynamically linked methods // use dglOpenGL.pas if not enabled -{$DEFINE GLB_NATIVE_OGL_DYNAMIC} +{.$DEFINE GLB_NATIVE_OGL_DYNAMIC} // activate to enable the support for SDL_surfaces -{.$DEFINE GLB_SDL} +{$DEFINE GLB_SDL} // activate to enable the support for TBitmap from Delphi (not lazarus) {.$DEFINE GLB_DELPHI} @@ -239,7 +239,7 @@ unit glBitmap; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // activate to enable the support of SDL_image to load files. (READ ONLY) // If you enable SDL_image all other libraries will be ignored! -{.$DEFINE GLB_SDL_IMAGE} +{$DEFINE GLB_SDL_IMAGE} // activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored @@ -681,7 +681,7 @@ type EglBitmapException = class(Exception); EglBitmapSizeToLargeException = class(EglBitmapException); EglBitmapNonPowerOfTwoException = class(EglBitmapException); - EglBitmapUnsupportedFormatFormat = class(EglBitmapException); + EglBitmapUnsupportedFormat = class(EglBitmapException); //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapFormat = ( @@ -977,14 +977,12 @@ type constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload; {$ENDIF} private - {$IFDEF GLB_SUPPORT_PNG_READ} - function LoadPNG(const aStream: TStream): Boolean; virtual; - procedure SavePNG(const aStream: TStream); virtual; - {$ENDIF} - {$IFDEF GLB_SUPPORT_JPEG_READ} - function LoadJPEG(const aStream: TStream): Boolean; virtual; - procedure SaveJPEG(const aStream: TStream); virtual; - {$ENDIF} + {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF} + {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF} + + {$IFDEF GLB_SUPPORT_JPEG_READ} function LoadJPEG(const aStream: TStream): Boolean; virtual; {$ENDIF} + {$IFDEF GLB_SUPPORT_JPEG_WRITE} procedure SaveJPEG(const aStream: TStream); virtual; {$ENDIF} + function LoadBMP(const aStream: TStream): Boolean; virtual; procedure SaveBMP(const aStream: TStream); virtual; @@ -1140,10 +1138,10 @@ type TFormatDescriptor = class(TObject) private - function GetRedMask: UInt64; - function GetGreenMask: UInt64; - function GetBlueMask: UInt64; - function GetAlphaMask: UInt64; + function GetRedMask: QWord; + function GetGreenMask: QWord; + function GetBlueMask: QWord; + function GetAlphaMask: QWord; protected fFormat: TglBitmapFormat; fWithAlpha: TglBitmapFormat; @@ -1177,10 +1175,10 @@ type property Range: TglBitmapColorRec read fRange; property Shift: TShiftRec read fShift; - property RedMask: UInt64 read GetRedMask; - property GreenMask: UInt64 read GetGreenMask; - property BlueMask: UInt64 read GetBlueMask; - property AlphaMask: UInt64 read GetAlphaMask; + property RedMask: QWord read GetRedMask; + property GreenMask: QWord read GetGreenMask; + property BlueMask: QWord read GetBlueMask; + property AlphaMask: QWord read GetAlphaMask; procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract; procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; @@ -1193,7 +1191,7 @@ type function IsEmpty: Boolean; virtual; function HasAlpha: Boolean; virtual; - function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; virtual; + function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual; procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual; @@ -1532,17 +1530,17 @@ type ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TbmpBitfieldFormat = class(TFormatDescriptor) private - procedure SetRedMask (const aValue: UInt64); - procedure SetGreenMask(const aValue: UInt64); - procedure SetBlueMask (const aValue: UInt64); - procedure SetAlphaMask(const aValue: UInt64); + procedure SetRedMask (const aValue: QWord); + procedure SetGreenMask(const aValue: QWord); + procedure SetBlueMask (const aValue: QWord); + procedure SetAlphaMask(const aValue: QWord); - procedure Update(aMask: UInt64; out aRange: Cardinal; out aShift: Byte); + procedure Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte); public - property RedMask: UInt64 read GetRedMask write SetRedMask; - property GreenMask: UInt64 read GetGreenMask write SetGreenMask; - property BlueMask: UInt64 read GetBlueMask write SetBlueMask; - property AlphaMask: UInt64 read GetAlphaMask write SetAlphaMask; + property RedMask: QWord read GetRedMask write SetRedMask; + property GreenMask: QWord read GetGreenMask write SetGreenMask; + property BlueMask: QWord read GetBlueMask write SetBlueMask; + property AlphaMask: QWord read GetAlphaMask write SetAlphaMask; property PixelSize: Single read fPixelSize write fPixelSize; @@ -1803,7 +1801,7 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function GetTopMostBit(aBitSet: UInt64): Integer; +function GetTopMostBit(aBitSet: QWord): Integer; begin result := 0; while aBitSet > 0 do begin @@ -1813,7 +1811,7 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function CountSetBits(aBitSet: UInt64): Integer; +function CountSetBits(aBitSet: QWord): Integer; begin result := 0; while aBitSet > 0 do begin @@ -2126,8 +2124,10 @@ end; {$ENDIF} *) -(* TODO GLB_SDL_IMAGE {$IFDEF GLB_SDL_IMAGE} +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SDL Image Helper ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapRWseek(context: PSDL_RWops; offset: Integer; whence: Integer): Integer; cdecl; begin result := TStream(context^.unknown.data1).Seek(offset, whence); @@ -2162,7 +2162,6 @@ begin result^.unknown.data1 := Stream; end; {$ENDIF} -*) (* TODO LoadFuncs function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; @@ -2366,25 +2365,25 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.GetRedMask: UInt64; +function TFormatDescriptor.GetRedMask: QWord; begin result := fRange.r shl fShift.r; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.GetGreenMask: UInt64; +function TFormatDescriptor.GetGreenMask: QWord; begin result := fRange.g shl fShift.g; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.GetBlueMask: UInt64; +function TFormatDescriptor.GetBlueMask: QWord; begin result := fRange.b shl fShift.b; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.GetAlphaMask: UInt64; +function TFormatDescriptor.GetAlphaMask: QWord; begin result := fRange.a shl fShift.a; end; @@ -2447,7 +2446,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: UInt64): Boolean; +function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; begin result := false; @@ -3781,31 +3780,31 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TBitfieldFormat///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.SetRedMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetRedMask(const aValue: QWord); begin Update(aValue, fRange.r, fShift.r); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.SetGreenMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetGreenMask(const aValue: QWord); begin Update(aValue, fRange.g, fShift.g); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.SetBlueMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetBlueMask(const aValue: QWord); begin Update(aValue, fRange.b, fShift.b); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: UInt64); +procedure TbmpBitfieldFormat.SetAlphaMask(const aValue: QWord); begin Update(aValue, fRange.a, fShift.a); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TbmpBitfieldFormat.Update(aMask: UInt64; out aRange: Cardinal; out +procedure TbmpBitfieldFormat.Update(aMask: QWord; out aRange: Cardinal; out aShift: Byte); begin aShift := 0; @@ -3829,10 +3828,8 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TbmpBitfieldFormat.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); var - data: UInt64; + data: QWord; s: Integer; -type - PUInt64 = ^UInt64; begin data := ((aPixel.Data.r and fRange.r) shl fShift.r) or @@ -3844,7 +3841,7 @@ begin 1: aData^ := data; 2: PWord(aData)^ := data; 4: PCardinal(aData)^ := data; - 8: PUInt64(aData)^ := data; + 8: PQWord(aData)^ := data; else raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; @@ -3854,17 +3851,15 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TbmpBitfieldFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); var - data: UInt64; + data: QWord; s, i: Integer; -type - PUInt64 = ^UInt64; begin s := Round(fPixelSize); case s of 1: data := aData^; 2: data := PWord(aData)^; 4: data := PCardinal(aData)^; - 8: data := PUInt64(aData)^; + 8: data := PQWord(aData)^; else raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; @@ -3956,10 +3951,8 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TbmpColorTableFormat.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); -type - PUInt64 = ^UInt64; var - idx: UInt64; + idx: QWord; s: Integer; bits: Byte; f: Single; @@ -3972,7 +3965,7 @@ begin 1: idx := aData^; 2: idx := PWord(aData)^; 4: idx := PCardinal(aData)^; - 8: idx := PUInt64(aData)^; + 8: idx := PQWord(aData)^; else raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]); end; @@ -4227,7 +4220,7 @@ begin if fFormat = aValue then exit; if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then - raise EglBitmapUnsupportedFormatFormat.Create('SetInternalFormat - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('SetFormat'); SetDataPointer(Data, aValue, Width, Height); end; @@ -4603,42 +4596,37 @@ var Row, RowSize: Integer; SourceData, TmpData: PByte; TempDepth: Integer; - Pix: TglBitmapPixelData; - FormatDesc: TglBitmapFormatDescriptor; + FormatDesc: TFormatDescriptor; function GetRowPointer(Row: Integer): pByte; begin - result := Surface.pixels; + result := aSurface.pixels; Inc(result, Row * RowSize); end; begin result := false; - (* TODO - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedInternalFormat.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); - *) + FormatDesc := TFormatDescriptor.Get(Format); + if FormatDesc.IsCompressed then + raise EglBitmapUnsupportedFormat.Create('AssignToSurface'); - FormatDesc := FORMAT_DESCRIPTORS[Format]; if Assigned(Data) then begin - case Trunc(FormatDesc.GetSize) of + case Trunc(FormatDesc.PixelSize) of 1: TempDepth := 8; 2: TempDepth := 16; 3: TempDepth := 24; 4: TempDepth := 32; else - raise EglBitmapException.Create('AssignToSurface - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormat.Create('AssignToSurface'); end; - FormatDesc.PreparePixel(Pix); - with Pix.PixelDesc do - Surface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, - RedRange shl RedShift, GreenRange shl GreenShift, BlueRange shl BlueShift, AlphaRange shl AlphaShift); + aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, + FormatDesc.RedMask, FormatDesc.GreenMask, FormatDesc.BlueMask, FormatDesc.AlphaMask); SourceData := Data; - RowSize := Ceil(FileWidth * FormatDesc.GetSize); + RowSize := FormatDesc.GetSize(FileWidth, 1); - for Row := 0 to FileHeight -1 do begin + for Row := 0 to FileHeight-1 do begin TmpData := GetRowPointer(Row); if Assigned(TmpData) then begin Move(SourceData^, TmpData^, RowSize); @@ -4654,34 +4642,31 @@ function TglBitmap.AssignFromSurface(const aSurface: PSDL_Surface): Boolean; var pSource, pData, pTempData: PByte; Row, RowSize, TempWidth, TempHeight: Integer; - IntFormat, f: TglBitmapInternalFormat; - FormatDesc: TglBitmapFormatDescriptor; + IntFormat: TglBitmapFormat; + FormatDesc: TFormatDescriptor; function GetRowPointer(Row: Integer): pByte; begin - result := Surface^.pixels; + result := aSurface^.pixels; Inc(result, Row * RowSize); end; begin result := false; - if (Assigned(Surface)) then begin - with Surface^.format^ do begin - IntFormat := tfEmpty; - for f := Low(f) to High(f) do begin - if FORMAT_DESCRIPTORS[f].MaskMatch(RMask, GMask, BMask, AMask) then begin - IntFormat := f; + if (Assigned(aSurface)) then begin + with aSurface^.format^ do begin + for IntFormat := High(TglBitmapFormat) to Low(TglBitmapFormat) do begin + FormatDesc := TFormatDescriptor.Get(IntFormat); + if (FormatDesc.MaskMatch(RMask, GMask, BMask, AMask)) then break; - end; end; if (IntFormat = tfEmpty) then raise EglBitmapException.Create('AssignFromSurface - Invalid Pixelformat.'); end; - FormatDesc := FORMAT_DESCRIPTORS[IntFormat]; - TempWidth := Surface^.w; - TempHeight := Surface^.h; - RowSize := Trunc(TempWidth * FormatDesc.GetSize); + TempWidth := aSurface^.w; + TempHeight := aSurface^.h; + RowSize := FormatDesc.GetSize(TempWidth, 1); GetMem(pData, TempHeight * RowSize); try pTempData := pData; @@ -4721,9 +4706,9 @@ begin AlphaInterleave := 0; case Format of - ifLuminance8Alpha8: + tfLuminance8Alpha8: AlphaInterleave := 1; - ifBGRA8, ifRGBA8: + tfBGRA8, tfRGBA8: AlphaInterleave := 3; end; @@ -4745,14 +4730,14 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromSurface(const aSurface: PSDL_Surface; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; var bmp: TglBitmap2D; begin bmp := TglBitmap2D.Create; try - bmp.AssignFromSurface(Surface); - result := AddAlphaFromGlBitmap(bmp, Func, CustomData); + bmp.AssignFromSurface(aSurface); + result := AddAlphaFromGlBitmap(bmp, aFunc, aArgs); finally bmp.Free; end; @@ -5147,7 +5132,7 @@ begin FormatDesc := TFormatDescriptor.Get(Format); if Assigned(Data) then begin if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then - raise EglBitmapUnsupportedFormatFormat.Create('RemoveAlpha - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('RemoveAlpha'); result := ConvertTo(FormatDesc.WithoutAlpha); end; end; @@ -5522,7 +5507,7 @@ begin Surface := IMG_LoadPNG_RW(RWops); try AssignFromSurface(Surface); - Rresult := true; + result := true; finally SDL_FreeSurface(Surface); end; @@ -5922,40 +5907,6 @@ type DestBuffer: array [1..4096] of byte; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{ -procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl; -var - Msg: String; -begin - SetLength(Msg, 256); - cinfo^.err^.format_message(cinfo, pChar(Msg)); - Writeln('ERROR [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); - cinfo^.global_state := 0; - jpeg_abort(cinfo); -end; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{ -procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl; -var - Msg: String; -begin - SetLength(Msg, 256); - cinfo^.err^.format_message(cinfo, pChar(Msg)); - Writeln('OUTPUT [' + IntToStr(cinfo^.err^.msg_code) + '] ' + Msg); - cinfo^.global_state := 0; -end; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{ -procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl; -begin -end; -} - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl; var @@ -5997,20 +5948,6 @@ begin end; end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{ -procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl; -begin -end; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -{ -procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl; -begin -end; -} - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmap_libJPEG_empty_output_buffer(cinfo: j_compress_ptr): boolean; cdecl; var @@ -6062,7 +5999,7 @@ var begin result := false; - RWops := glBitmapCreateRWops(Stream); + RWops := glBitmapCreateRWops(aStream); try if IMG_isJPG(RWops) > 0 then begin Surface := IMG_LoadJPG_RW(RWops); @@ -6622,7 +6559,7 @@ var begin if not (ftBMP in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('SaveBMP'); Converter := nil; FormatDesc := TFormatDescriptor.Get(Format); @@ -6687,7 +6624,7 @@ begin Info.biCompression := BMP_COMP_BITFIELDS; end; else - raise EglBitmapUnsupportedFormatFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); end; Info.biXPelsPerMeter := 2835; Info.biYPelsPerMeter := 2835; @@ -6804,7 +6741,7 @@ const function TglBitmap.LoadTGA(const aStream: TStream): Boolean; var Header: TTGAHeader; - ImageData: PByte; + ImageData: System.PByte; StartPosition: Int64; PixelSize, LineSize: Integer; tgaFormat: TglBitmapFormat; @@ -6822,7 +6759,7 @@ const procedure ReadUncompressed; var i, j: Integer; - buf, tmp1, tmp2: PByte; + buf, tmp1, tmp2: System.PByte; begin buf := nil; if (Counter.X.dir < 0) then @@ -6856,7 +6793,7 @@ const ///////////////////////////////////////////////////////////////// var - TmpData: PByte; + TmpData: System.PByte; LinePixelsRead: Integer; procedure CheckLine; begin @@ -7083,7 +7020,7 @@ var Converter: TFormatDescriptor; begin if not (ftTGA in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveTGA - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('SaveTGA'); //prepare header FillChar(Header{%H-}, SizeOf(Header), 0); @@ -7296,7 +7233,7 @@ var var StreamPos: Int64; x, y, LineSize, RowSize, Magic: Cardinal; - NewImage, TmpData, RowData, SrcData: PByte; + NewImage, TmpData, RowData, SrcData: System.PByte; SourceMD, DestMD: Pointer; Pixel: TglBitmapPixelData; ddsFormat: TglBitmapFormat; @@ -7399,7 +7336,7 @@ var FormatDesc: TFormatDescriptor; begin if not (ftDDS in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormatFormat.Create('SaveDDS - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('SaveDDS'); FormatDesc := TFormatDescriptor.Get(Format); @@ -7542,7 +7479,7 @@ var begin FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.IsCompressed then - raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.GrabScreen - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create('TglBitmap2D.GrabScreen'); w := aRight - aLeft; h := aBottom - aTop; From 77bababf6dbb72075657d5c12282462a96f7b854 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 22:06:11 +0100 Subject: [PATCH 15/38] * added LibPNG Support --- glBitmap.pas | 125 +++++++++++++++++++++++++-------------------------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 19dba74..5bfb8e7 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1,6 +1,10 @@ {*********************************************************** glBitmap by Steffen Xonna aka Lossy eX (2003-2008) http://www.opengl24.de/index.php?cat=header&file=glbitmap + +modified by Delphi OpenGL Community (http://delphigl.com/) + + ------------------------------------------------------------ The contents of this file are used with permission, subject to the Mozilla Public License Version 1.1 (the "License"); you may @@ -230,7 +234,7 @@ unit glBitmap; {.$DEFINE GLB_NATIVE_OGL_DYNAMIC} // activate to enable the support for SDL_surfaces -{$DEFINE GLB_SDL} +{.$DEFINE GLB_SDL} // activate to enable the support for TBitmap from Delphi (not lazarus) {.$DEFINE GLB_DELPHI} @@ -239,7 +243,7 @@ unit glBitmap; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // activate to enable the support of SDL_image to load files. (READ ONLY) // If you enable SDL_image all other libraries will be ignored! -{$DEFINE GLB_SDL_IMAGE} +{.$DEFINE GLB_SDL_IMAGE} // activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored @@ -248,7 +252,7 @@ unit glBitmap; // activate to use the libPNG http://www.libpng.org/ // You will need an aditional header. // http://www.opengl24.de/index.php?cat=header&file=libpng -{.$DEFINE GLB_LIB_PNG} +{$DEFINE GLB_LIB_PNG} // if you enable delphi jpegs the libJPEG will be ignored {.$DEFINE GLB_DELPHI_JPEG} @@ -260,7 +264,7 @@ unit glBitmap; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PRIVATE: DO not change anything! ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PRIVATE: do not change anything! ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Delphi Versions {$IFDEF fpc} @@ -677,12 +681,6 @@ var {$ENDIF} type -//////////////////////////////////////////////////////////////////////////////////////////////////// - EglBitmapException = class(Exception); - EglBitmapSizeToLargeException = class(EglBitmapException); - EglBitmapNonPowerOfTwoException = class(EglBitmapException); - EglBitmapUnsupportedFormat = class(EglBitmapException); - //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapFormat = ( tfEmpty = 0, //must be smallest value! @@ -765,6 +763,14 @@ type nm3x3, nm5x5); + //////////////////////////////////////////////////////////////////////////////////////////////////// + EglBitmapException = class(Exception); + EglBitmapSizeToLargeException = class(EglBitmapException); + EglBitmapNonPowerOfTwoException = class(EglBitmapException); + EglBitmapUnsupportedFormat = class(EglBitmapException) + constructor Create(const aFormat: TglBitmapFormat); + end; + //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapColorRec = packed record case Integer of @@ -1126,7 +1132,7 @@ implementation *) uses - Math, syncobjs; + Math, syncobjs, typinfo; type //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1651,6 +1657,12 @@ var FormatDescriptorCS: TCriticalSection; FormatDescriptors: array[TglBitmapFormat] of TFormatDescriptor; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat); +begin + inherited Create(GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat))); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; begin @@ -1757,19 +1769,15 @@ begin tfS3tcDtx1RGBA, tfS3tcDtx3RGBA, tfS3tcDtx5RGBA]) then result := result + [ftDDS]; - (* TODO {$IFDEF GLB_SUPPORT_PNG_WRITE} if aFormat in [ - tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, - tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, - tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16, - tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, - tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16, - tfDepth16, tfDepth24, tfDepth32] - then + tfAlpha8, tfLuminance8, tfLuminance8Alpha8, + tfRGB8, tfRGBA8, + tfBGR8, tfBGRA8] then result := result + [ftPNG]; {$ENDIF} +(* TODO {$IFDEF GLB_SUPPORT_JPEG_WRITE} if Format in [ tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, @@ -1779,16 +1787,6 @@ begin then result := result + [ftJPEG]; {$ENDIF} - - if aFormat in [ - tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, - tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, - tfuminance4Alpha4, tfLuminance6Alpha2, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16, - tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, - tfRGBA2, tfRGBA4, tfRGB5A1, tfRGBA8, tfRGB10A2, tfRGBA12, tfRGBA16, - tfDepth16, tfDepth24, tfDepth32] - then - result := result + [ftDDS, ftTGA, ftBMP]; *) end; @@ -4220,7 +4218,7 @@ begin if fFormat = aValue then exit; if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then - raise EglBitmapUnsupportedFormat.Create('SetFormat'); + raise EglBitmapUnsupportedFormat.Create(Format); SetDataPointer(Data, aValue, Width, Height); end; @@ -4491,7 +4489,7 @@ procedure TglBitmap.SaveToStream(const aStream: TStream; const aFileType: TglBit begin case aFileType of {$IFDEF GLB_SUPPORT_PNG_WRITE} - ftPNG: SavePng(aStream); + ftPNG: SavePNG(aStream); {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} ftJPEG: SaveJPEG(aStream); @@ -4609,7 +4607,7 @@ begin FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.IsCompressed then - raise EglBitmapUnsupportedFormat.Create('AssignToSurface'); + raise EglBitmapUnsupportedFormat.Create(Format); if Assigned(Data) then begin case Trunc(FormatDesc.PixelSize) of @@ -4618,7 +4616,7 @@ begin 3: TempDepth := 24; 4: TempDepth := 32; else - raise EglBitmapUnsupportedFormat.Create('AssignToSurface'); + raise EglBitmapUnsupportedFormat.Create(Format); end; aSurface := SDL_CreateRGBSurface(SDL_SWSURFACE, Width, Height, TempDepth, @@ -4952,10 +4950,8 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; begin - (* TODO - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('AddAlphaFromFunc - ' + UNSUPPORTED_FORMAT); - *) + if TFormatDescriptor.Get(Format).IsCompressed then + raise EglBitmapUnsupportedFormat.Create(Format); result := AddFunc(Self, aFunc, false, TFormatDescriptor.Get(Format).WithAlpha, aArgs); end; @@ -5132,7 +5128,7 @@ begin FormatDesc := TFormatDescriptor.Get(Format); if Assigned(Data) then begin if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then - raise EglBitmapUnsupportedFormat.Create('RemoveAlpha'); + raise EglBitmapUnsupportedFormat.Create(Format); result := ConvertTo(FormatDesc.WithoutAlpha); end; end; @@ -5533,7 +5529,7 @@ var png_info: png_infop; TempHeight, TempWidth: Integer; - Format: TglBitmapInternalFormat; + Format: TglBitmapFormat; png_data: pByte; png_rows: array of pByte; @@ -5546,9 +5542,9 @@ begin try // signature - StreamPos := Stream.Position; - Stream.Read(signature, 8); - Stream.Position := StreamPos; + StreamPos := aStream.Position; + aStream.Read(signature, 8); + aStream.Position := StreamPos; if png_check_sig(@signature, 8) <> 0 then begin // png read struct @@ -5564,7 +5560,7 @@ begin end; // set read callback - png_set_read_fn(png, stream, glBitmap_libPNG_read_func); + png_set_read_fn(png, aStream, glBitmap_libPNG_read_func); // read informations png_read_info(png, png_info); @@ -5742,27 +5738,30 @@ var LineSize: Integer; ColorType: Integer; Row: Integer; + FormatDesc: TFormatDescriptor; begin - if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + if not (ftPNG in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedFormat.Create(Format); if not init_libPNG then - raise Exception.Create('SavePNG - unable to initialize libPNG.'); + raise Exception.Create('unable to initialize libPNG.'); try - case FInternalFormat of - ifAlpha, ifLuminance, ifDepth8: + case Format of + tfAlpha8, tfLuminance8: ColorType := PNG_COLOR_TYPE_GRAY; - ifLuminanceAlpha: + tfLuminance8Alpha8: ColorType := PNG_COLOR_TYPE_GRAY_ALPHA; - ifBGR8, ifRGB8: + tfBGR8, tfRGB8: ColorType := PNG_COLOR_TYPE_RGB; - ifBGRA8, ifRGBA8: + tfBGRA8, tfRGBA8: ColorType := PNG_COLOR_TYPE_RGBA; else - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormat.Create(Format); end; - LineSize := Trunc(FormatGetSize(FInternalFormat) * Width); + + FormatDesc := TFormatDescriptor.Get(Format); + LineSize := FormatDesc.GetSize(Width, 1); // creating array for scanline SetLength(png_rows, Height); @@ -5785,12 +5784,12 @@ begin end; // set read callback - png_set_write_fn(png, stream, glBitmap_libPNG_write_func, nil); + png_set_write_fn(png, aStream, glBitmap_libPNG_write_func, nil); // set compression png_set_compression_level(png, 6); - if InternalFormat in [ifBGR8, ifBGRA8] then + if Format in [tfBGR8, tfBGRA8] then png_set_bgr(png); png_set_IHDR(png, png_info, Width, Height, 8, ColorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); @@ -6559,7 +6558,7 @@ var begin if not (ftBMP in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormat.Create('SaveBMP'); + raise EglBitmapUnsupportedFormat.Create(Format); Converter := nil; FormatDesc := TFormatDescriptor.Get(Format); @@ -6624,7 +6623,7 @@ begin Info.biCompression := BMP_COMP_BITFIELDS; end; else - raise EglBitmapUnsupportedFormat.Create('SaveBMP - ' + UNSUPPORTED_FORMAT); + raise EglBitmapUnsupportedFormat.Create(Format); end; Info.biXPelsPerMeter := 2835; Info.biYPelsPerMeter := 2835; @@ -7020,7 +7019,7 @@ var Converter: TFormatDescriptor; begin if not (ftTGA in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormat.Create('SaveTGA'); + raise EglBitmapUnsupportedFormat.Create(Format); //prepare header FillChar(Header{%H-}, SizeOf(Header), 0); @@ -7336,7 +7335,7 @@ var FormatDesc: TFormatDescriptor; begin if not (ftDDS in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedFormat.Create('SaveDDS'); + raise EglBitmapUnsupportedFormat.Create(Format); FormatDesc := TFormatDescriptor.Get(Format); @@ -7479,7 +7478,7 @@ var begin FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.IsCompressed then - raise EglBitmapUnsupportedFormat.Create('TglBitmap2D.GrabScreen'); + raise EglBitmapUnsupportedFormat.Create(Format); w := aRight - aLeft; h := aBottom - aTop; @@ -7729,10 +7728,8 @@ var end; begin - (* TODO Compression - if not FormatIsUncompressed(InternalFormat) then - raise EglBitmapUnsupportedFormatFormat.Create('TglBitmap2D.ToNormalMap - ' + UNSUPPORTED_FORMAT); - *) + if TFormatDescriptor.Get(Format).IsCompressed then + raise EglBitmapUnsupportedFormat.Create(Format); if aScale > 100 then Rec.Scale := 100 From 3abbe3ab4b2faa2f817a2d99085009467e1aadbe Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 22:22:22 +0100 Subject: [PATCH 16/38] * added LibJPEG Support --- glBitmap.pas | 116 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 5bfb8e7..32ee575 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -245,22 +245,22 @@ unit glBitmap; // If you enable SDL_image all other libraries will be ignored! {.$DEFINE GLB_SDL_IMAGE} -// activate to enable png support with the unit pngimage. You can download it from http://pngdelphi.sourceforge.net/ +// PNG ///////////////////////////////////////////////////////////////////////////////////////////// +// activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored {.$DEFINE GLB_PNGIMAGE} -// activate to use the libPNG http://www.libpng.org/ -// You will need an aditional header. -// http://www.opengl24.de/index.php?cat=header&file=libpng -{$DEFINE GLB_LIB_PNG} +// activate to use the libPNG -> http://www.libpng.org/ +// You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng +{.$DEFINE GLB_LIB_PNG} +// JPEG //////////////////////////////////////////////////////////////////////////////////////////// // if you enable delphi jpegs the libJPEG will be ignored {.$DEFINE GLB_DELPHI_JPEG} -// activateto use the libJPEG http://www.ijg.org/ -// You will need an aditional header. -// http://www.opengl24.de/index.php?cat=header&file=libjpeg -{.$DEFINE GLB_LIB_JPEG} +// activate to use the libJPEG -> http://www.ijg.org/ +// You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg +{$DEFINE GLB_LIB_JPEG} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1777,17 +1777,10 @@ begin result := result + [ftPNG]; {$ENDIF} -(* TODO {$IFDEF GLB_SUPPORT_JPEG_WRITE} - if Format in [ - tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, - tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, - tfR3G3B2, tfRGB4, tfRGB5, tfRGB8, tfRGB10, tfRGB12, tfRGB16, - tfDepth16, tfDepth24, tfDepth32] - then + if aFormat in [tfAlpha8, tfLuminance8, tfRGB8, tfBGR8] then result := result + [ftJPEG]; {$ENDIF} - *) end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5543,7 +5536,7 @@ begin try // signature StreamPos := aStream.Position; - aStream.Read(signature, 8); + aStream.Read(signature{%H-}, 8); aStream.Position := StreamPos; if png_check_sig(@signature, 8) <> 0 then begin @@ -5906,6 +5899,35 @@ type DestBuffer: array [1..4096] of byte; end; +procedure glBitmap_libJPEG_error_exit(cinfo: j_common_ptr); cdecl; +begin + //DUMMY +end; + + +procedure glBitmap_libJPEG_output_message(cinfo: j_common_ptr); cdecl; +begin + //DUMMY +end; + + +procedure glBitmap_libJPEG_init_source(cinfo: j_decompress_ptr); cdecl; +begin + //DUMMY +end; + +procedure glBitmap_libJPEG_term_source(cinfo: j_decompress_ptr); cdecl; +begin + //DUMMY +end; + + +procedure glBitmap_libJPEG_init_destination(cinfo: j_compress_ptr); cdecl; +begin + //DUMMY +end; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmap_libJPEG_fill_input_buffer(cinfo: j_decompress_ptr): boolean; cdecl; var @@ -6024,12 +6046,14 @@ var jpeg: jpeg_decompress_struct; jpeg_err: jpeg_error_mgr; - IntFormat: TglBitmapInternalFormat; + IntFormat: TglBitmapFormat; pImage: pByte; TempHeight, TempWidth: Integer; pTemp: pByte; Row: Integer; + + FormatDesc: TFormatDescriptor; begin result := false; @@ -6038,18 +6062,18 @@ begin try // reading first two bytes to test file and set cursor back to begin - StreamPos := Stream.Position; - Stream.Read(Temp[0], 2); - Stream.Position := StreamPos; + StreamPos := aStream.Position; + aStream.Read({%H-}Temp[0], 2); + aStream.Position := StreamPos; // if Bitmap then read file. if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin - FillChar(jpeg, SizeOf(jpeg_decompress_struct), $00); - FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); + FillChar(jpeg{%H-}, SizeOf(jpeg_decompress_struct), $00); + FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00); // error managment jpeg.err := jpeg_std_error(@jpeg_err); - jpeg_err.error_exit := glBitmap_libJPEG_error_exit; + jpeg_err.error_exit := glBitmap_libJPEG_error_exit; jpeg_err.output_message := glBitmap_libJPEG_output_message; // decompression struct @@ -6069,7 +6093,7 @@ begin pub.bytes_in_buffer := 0; // forces fill_input_buffer on first read pub.next_input_byte := nil; // until buffer loaded - SrcStream := Stream; + SrcStream := aStream; end; // set global decoding state @@ -6083,11 +6107,11 @@ begin JCS_GRAYSCALE: begin jpeg.out_color_space := JCS_GRAYSCALE; - IntFormat := ifLuminance; + IntFormat := tfLuminance8; end; else jpeg.out_color_space := JCS_RGB; - IntFormat := ifRGB8; + IntFormat := tfRGB8; end; // reading image @@ -6096,14 +6120,16 @@ begin TempHeight := jpeg.output_height; TempWidth := jpeg.output_width; + FormatDesc := TFormatDescriptor.Get(IntFormat); + // creating new image - GetMem(pImage, FormatGetImageSize(glBitmapPosition(TempWidth, TempHeight), IntFormat)); + GetMem(pImage, FormatDesc.GetSize(TempWidth, TempHeight)); try pTemp := pImage; for Row := 0 to TempHeight -1 do begin jpeg_read_scanlines(@jpeg, @pTemp, 1); - Inc(pTemp, Trunc(FormatGetSize(IntFormat) * TempWidth)); + Inc(pTemp, FormatDesc.GetSize(TempWidth, 1)); end; // finish decompression @@ -6162,9 +6188,9 @@ end; {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} -{$IF DEFEFINED(GLB_LIB_JPEG)} +{$IF DEFINED(GLB_LIB_JPEG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SaveJPEG(Stream: TStream); +procedure TglBitmap.SaveJPEG(const aStream: TStream); var jpeg: jpeg_compress_struct; jpeg_err: jpeg_error_mgr; @@ -6186,18 +6212,18 @@ var begin if not (ftJPEG in FormatGetSupportedFiles(Format)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormat.Create(Format); if not init_libJPEG then raise Exception.Create('SaveJPG - unable to initialize libJPEG.'); try - FillChar(jpeg, SizeOf(jpeg_compress_struct), $00); - FillChar(jpeg_err, SizeOf(jpeg_error_mgr), $00); + FillChar(jpeg{%H-}, SizeOf(jpeg_compress_struct), $00); + FillChar(jpeg_err{%H-}, SizeOf(jpeg_error_mgr), $00); // error managment jpeg.err := jpeg_std_error(@jpeg_err); - jpeg_err.error_exit := glBitmap_libJPEG_error_exit; + jpeg_err.error_exit := glBitmap_libJPEG_error_exit; jpeg_err.output_message := glBitmap_libJPEG_output_message; // compression struct @@ -6215,21 +6241,21 @@ begin pub.next_output_byte := @DestBuffer[1]; pub.free_in_buffer := Length(DestBuffer); - DestStream := Stream; + DestStream := aStream; end; // very important state jpeg.global_state := CSTATE_START; jpeg.image_width := Width; jpeg.image_height := Height; - case InternalFormat of - ifAlpha, ifLuminance, ifDepth8: begin + case Format of + tfAlpha8, tfLuminance8: begin jpeg.input_components := 1; - jpeg.in_color_space := JCS_GRAYSCALE; + jpeg.in_color_space := JCS_GRAYSCALE; end; - ifRGB8, ifBGR8: begin + tfRGB8, tfBGR8: begin jpeg.input_components := 3; - jpeg.in_color_space := JCS_RGB; + jpeg.in_color_space := JCS_RGB; end; end; @@ -6238,7 +6264,7 @@ begin jpeg_start_compress(@jpeg, true); pTemp := Data; - if InternalFormat = ifBGR8 then + if Format = tfBGR8 then GetMem(pTemp2, fRowSize) else pTemp2 := pTemp; @@ -6246,7 +6272,7 @@ begin try for Row := 0 to jpeg.image_height -1 do begin // prepare row - if InternalFormat = ifBGR8 then + if Format = tfBGR8 then CopyRow(pTemp2, pTemp) else pTemp2 := pTemp; @@ -6257,7 +6283,7 @@ begin end; finally // free memory - if InternalFormat = ifBGR8 then + if Format = tfBGR8 then FreeMem(pTemp2); end; jpeg_finish_compress(@jpeg); From ecbecb3fd9069e1610d889ff5d96300cca65615a Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 16 Nov 2013 22:42:31 +0100 Subject: [PATCH 17/38] * added pngimage Support --- glBitmap.pas | 72 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 32ee575..f745956 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -248,7 +248,7 @@ unit glBitmap; // PNG ///////////////////////////////////////////////////////////////////////////////////////////// // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored -{.$DEFINE GLB_PNGIMAGE} +{$DEFINE GLB_PNGIMAGE} // activate to use the libPNG -> http://www.libpng.org/ // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng @@ -260,7 +260,7 @@ unit glBitmap; // activate to use the libJPEG -> http://www.ijg.org/ // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libjpeg -{$DEFINE GLB_LIB_JPEG} +{.$DEFINE GLB_LIB_JPEG} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1660,7 +1660,7 @@ var ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor EglBitmapUnsupportedFormat.Create(const aFormat: TglBitmapFormat); begin - inherited Create(GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat))); + inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat))); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5625,42 +5625,44 @@ function TglBitmap.LoadPNG(const aStream: TStream): Boolean; var StreamPos: Int64; Png: TPNGObject; - Header: Array[0..7] of Byte; + Header: String[8]; Row, Col, PixSize, LineSize: Integer; NewImage, pSource, pDest, pAlpha: pByte; - Format: TglBitmapInternalFormat; + PngFormat: TglBitmapFormat; + FormatDesc: TFormatDescriptor; const - PngHeader: Array[0..7] of Byte = (#137, #80, #78, #71, #13, #10, #26, #10); + PngHeader: String[8] = #137#80#78#71#13#10#26#10; begin result := false; - StreamPos := Stream.Position; - Stream.Read(Header[0], SizeOf(Header)); - Stream.Position := StreamPos; + StreamPos := aStream.Position; + aStream.Read(Header[0], SizeOf(Header)); + aStream.Position := StreamPos; {Test if the header matches} if Header = PngHeader then begin Png := TPNGObject.Create; try - Png.LoadFromStream(Stream); + Png.LoadFromStream(aStream); case Png.Header.ColorType of COLOR_GRAYSCALE: - Format := ifLuminance; + PngFormat := tfLuminance8; COLOR_GRAYSCALEALPHA: - Format := ifLuminanceAlpha; + PngFormat := tfLuminance8Alpha8; COLOR_RGB: - Format := ifBGR8; + PngFormat := tfBGR8; COLOR_RGBALPHA: - Format := ifBGRA8; + PngFormat := tfBGRA8; else raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); end; - PixSize := Trunc(FormatGetSize(Format)); - LineSize := Integer(Png.Header.Width) * PixSize; + FormatDesc := TFormatDescriptor.Get(PngFormat); + PixSize := Round(FormatDesc.PixelSize); + LineSize := FormatDesc.GetSize(Png.Header.Width, 1); GetMem(NewImage, LineSize * Integer(Png.Header.Height)); try @@ -5697,7 +5699,7 @@ begin raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); end; - SetDataPointer(NewImage, Format, Png.Header.Width, Png.Header.Height); + SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); result := true; except @@ -5812,32 +5814,32 @@ var pTemp: pByte; Temp: Byte; begin - if not (ftPNG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + if not (ftPNG in FormatGetSupportedFiles (Format)) then + raise EglBitmapUnsupportedFormat.Create(Format); - case FInternalFormat of - ifAlpha, ifLuminance, ifDepth8: begin + case Format of + tfAlpha8, tfLuminance8: begin ColorType := COLOR_GRAYSCALE; - PixSize := 1; - Alpha := false; + PixSize := 1; + Alpha := false; end; - ifLuminanceAlpha: begin + tfLuminance8Alpha8: begin ColorType := COLOR_GRAYSCALEALPHA; - PixSize := 1; - Alpha := true; + PixSize := 1; + Alpha := true; end; - ifBGR8, ifRGB8: begin + tfBGR8, tfRGB8: begin ColorType := COLOR_RGB; - PixSize := 3; - Alpha := false; + PixSize := 3; + Alpha := false; end; - ifBGRA8, ifRGBA8: begin + tfBGRA8, tfRGBA8: begin ColorType := COLOR_RGBALPHA; - PixSize := 3; - Alpha := true + PixSize := 3; + Alpha := true end; else - raise EglBitmapUnsupportedInternalFormat.Create('SavePng - ' + UNSUPPORTED_INTERNAL_FORMAT); + raise EglBitmapUnsupportedFormat.Create(Format); end; Png := TPNGObject.CreateBlank(ColorType, 8, Width, Height); @@ -5857,7 +5859,7 @@ begin end; // convert RGB line to BGR - if InternalFormat in [ifRGB8, ifRGBA8] then begin + if Format in [tfRGB8, tfRGBA8] then begin pTemp := png.ScanLine[Y]; for X := 0 to Width -1 do begin Temp := pByteArray(pTemp)^[0]; @@ -5870,7 +5872,7 @@ begin // Save to Stream Png.CompressionLevel := 6; - Png.SaveToStream(Stream); + Png.SaveToStream(aStream); finally FreeAndNil(Png); end; From 5707b04adc5d25bab079597637ac3a52c92336e7 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 17 Nov 2013 18:06:31 +0100 Subject: [PATCH 18/38] * added LazIntfImage Support --- glBitmap.pas | 506 +++++++++++++++++++++++++++------------------------ 1 file changed, 271 insertions(+), 235 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index f745956..debcd36 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -218,9 +218,9 @@ History ***********************************************************} unit glBitmap; -{.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} // Please uncomment the defines below to configure the glBitmap to your preferences. // If you have configured the unit you can uncomment the warning above. +{$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Preferences /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -233,28 +233,33 @@ unit glBitmap; // use dglOpenGL.pas if not enabled {.$DEFINE GLB_NATIVE_OGL_DYNAMIC} + // activate to enable the support for SDL_surfaces {.$DEFINE GLB_SDL} // activate to enable the support for TBitmap from Delphi (not lazarus) {.$DEFINE GLB_DELPHI} +// activate to enable the support for TLazIntfImage from Lazarus +{$DEFINE GLB_LAZARUS} + -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // activate to enable the support of SDL_image to load files. (READ ONLY) // If you enable SDL_image all other libraries will be ignored! {.$DEFINE GLB_SDL_IMAGE} -// PNG ///////////////////////////////////////////////////////////////////////////////////////////// + + // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored -{$DEFINE GLB_PNGIMAGE} +{.$DEFINE GLB_PNGIMAGE} // activate to use the libPNG -> http://www.libpng.org/ // You will need an aditional header -> http://www.opengl24.de/index.php?cat=header&file=libpng {.$DEFINE GLB_LIB_PNG} -// JPEG //////////////////////////////////////////////////////////////////////////////////////////// + + // if you enable delphi jpegs the libJPEG will be ignored {.$DEFINE GLB_DELPHI_JPEG} @@ -285,12 +290,12 @@ unit glBitmap; {$DEFINE GLB_WIN} {$ELSEIF DEFINED(LINUX)} {$DEFINE GLB_LINUX} -{$IFEND} +{$ENDIF} // native OpenGL Support {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)} {$DEFINE GLB_NATIVE_OGL} -{$IFEND} +{$ENDIF} // checking define combinations //SDL Image @@ -370,20 +375,21 @@ unit glBitmap; interface uses - {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} + {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} {$IF DEFINED(GLB_WIN) AND - DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} + DEFINED(GLB_NATIVE_OGL)} windows, {$ENDIF} - {$IFDEF GLB_SDL} SDL, {$ENDIF} - {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} + {$IFDEF GLB_SDL} SDL, {$ENDIF} + {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} - {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} + {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} - {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} - {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} + {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} + {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} - {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} - {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} + {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} Classes, SysUtils; @@ -575,8 +581,9 @@ type {$IFDEF GLB_LINUX} TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl; + TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl; {$ELSE} - TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall; + TwglGetProcAddress = function(ProcName: PAnsiChar): Pointer; stdcall; {$ENDIF} {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)} @@ -768,7 +775,8 @@ type EglBitmapSizeToLargeException = class(EglBitmapException); EglBitmapNonPowerOfTwoException = class(EglBitmapException); EglBitmapUnsupportedFormat = class(EglBitmapException) - constructor Create(const aFormat: TglBitmapFormat); + constructor Create(const aFormat: TglBitmapFormat); overload; + constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload; end; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -895,15 +903,15 @@ type procedure AfterConstruction; override; procedure BeforeDestruction; override; + procedure PrepareResType(var aResource: String; var aResType: PChar); + //Load procedure LoadFromFile(const aFilename: String); procedure LoadFromStream(const aStream: TStream); virtual; procedure LoadFromFunc(const aSize: TglBitmapPixelPosition; const aFunc: TglBitmapFunction; const aFormat: TglBitmapFormat; const aArgs: Pointer = nil); - {$IFDEF GLB_DELPHI} - procedure LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); - procedure LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); - {$ENDIF} + procedure LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil); + procedure LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); //Save procedure SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); @@ -929,11 +937,20 @@ type function AssignAlphaToBitmap(const aBitmap: TBitmap): Boolean; function AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; - function AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil; + {$ENDIF} + + {$IFDEF GLB_LAZARUS} + function AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean; + function AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean; + function AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean; + function AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction = nil; + const aArgs: Pointer = nil): Boolean; + {$ENDIF} + + function AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar = nil; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; function AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; - {$ENDIF} function AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer = nil): Boolean; virtual; function AddAlphaFromFile(const aFileName: String; const aFunc: TglBitmapFunction = nil; const aArgs: Pointer = nil): Boolean; @@ -978,10 +995,8 @@ type constructor Create(const aStream: TStream); overload; constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload; constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload; - {$IFDEF GLB_DELPHI} constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload; constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload; - {$ENDIF} private {$IFDEF GLB_SUPPORT_PNG_READ} function LoadPNG(const aStream: TStream): Boolean; virtual; {$ENDIF} {$ifdef GLB_SUPPORT_PNG_WRITE} procedure SavePNG(const aStream: TStream); virtual; {$ENDIF} @@ -1005,15 +1020,6 @@ type // Bildeinstellungen fLines: array of PByte; - (* TODO - procedure GetDXTColorBlock(pData: pByte; relX, relY: Integer; var Pixel: TglBitmapPixelData); - procedure GetPixel2DDXT1(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - procedure GetPixel2DDXT3(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - procedure GetPixel2DDXT5(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - procedure GetPixel2DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - procedure SetPixel2DUnmap(const Pos: TglBitmapPixelPosition; const Pixel: TglBitmapPixelData); - *) - function GetScanline(const aIndex: Integer): Pointer; procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer = - 1; const aHeight: Integer = - 1); override; @@ -1122,15 +1128,6 @@ function CreateGrayPalette: HPALETTE; implementation - - (* TODO - function FormatIsCompressed(Format: TglBitmapInternalFormat): boolean; - function FormatIsUncompressed(Format: TglBitmapInternalFormat): boolean; - function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; - function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal = 0{$ENDIF}): Boolean; - function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; - *) - uses Math, syncobjs, typinfo; @@ -1663,6 +1660,12 @@ begin inherited Create('unsupported format: ' + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat))); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor EglBitmapUnsupportedFormat.Create(const aMsg: String; const aFormat: TglBitmapFormat); +begin + inherited Create(aMsg + GetEnumName(TypeInfo(TglBitmapFormat), Integer(aFormat))); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapPosition(X, Y: Integer): TglBitmapPixelPosition; begin @@ -2154,127 +2157,6 @@ begin end; {$ENDIF} -(* TODO LoadFuncs -function LoadTexture(Filename: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; -var - glBitmap: TglBitmap2D; -begin - result := false; - Texture := 0; - - {$IFDEF GLB_DELPHI} - if Instance = 0 then - Instance := HInstance; - - if (LoadFromRes) then - glBitmap := TglBitmap2D.CreateFromResourceName(Instance, FileName) - else - {$ENDIF} - glBitmap := TglBitmap2D.Create(FileName); - - try - glBitmap.DeleteTextureOnFree := false; - glBitmap.FreeDataAfterGenTexture := false; - glBitmap.GenTexture(true); - if (glBitmap.ID > 0) then begin - Texture := glBitmap.ID; - result := true; - end; - finally - glBitmap.Free; - end; -end; - -function LoadCubeMap(PositiveX, NegativeX, PositiveY, NegativeY, PositiveZ, NegativeZ: String; var Texture: Cardinal{$IFDEF GLB_DELPHI}; LoadFromRes : Boolean; Instance: Cardinal{$ENDIF}): Boolean; -var - CM: TglBitmapCubeMap; -begin - Texture := 0; - - {$IFDEF GLB_DELPHI} - if Instance = 0 then - Instance := HInstance; - {$ENDIF} - - CM := TglBitmapCubeMap.Create; - try - CM.DeleteTextureOnFree := false; - - // Maps - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveX) - else - {$ENDIF} - CM.LoadFromFile(PositiveX); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeX) - else - {$ENDIF} - CM.LoadFromFile(NegativeX); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveY) - else - {$ENDIF} - CM.LoadFromFile(PositiveY); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeY) - else - {$ENDIF} - CM.LoadFromFile(NegativeY); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, PositiveZ) - else - {$ENDIF} - CM.LoadFromFile(PositiveZ); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z); - - {$IFDEF GLB_DELPHI} - if (LoadFromRes) then - CM.LoadFromResource(Instance, NegativeZ) - else - {$ENDIF} - CM.LoadFromFile(NegativeZ); - CM.GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); - - Texture := CM.ID; - result := true; - finally - CM.Free; - end; -end; - -function LoadNormalMap(Size: Integer; var Texture: Cardinal): Boolean; -var - NM: TglBitmapNormalMap; -begin - Texture := 0; - - NM := TglBitmapNormalMap.Create; - try - NM.DeleteTextureOnFree := false; - NM.GenerateNormalMap(Size); - - Texture := NM.ID; - result := true; - finally - NM.Free; - end; -end; -*) - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapSetDefaultDeleteTextureOnFree(const aDeleteTextureOnFree: Boolean); begin @@ -2440,10 +2322,8 @@ end; function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; begin result := false; - if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); - if (aRedMask <> RedMask) then exit; if (aGreenMask <> GreenMask) then @@ -2500,7 +2380,7 @@ begin aPixel.Data.g := 0; aPixel.Data.b := 0; aPixel.Data.a := aData^; - inc(aData^); + inc(aData); end; constructor TfdAlpha_UB1.Create; @@ -3952,7 +3832,7 @@ begin f := fPixelSize - s; bits := Round(8 * f); case s of - 0: idx := (aData^ shr (8 - bits - {%H-}PtrUInt(aMapData))) and ((1 shl bits) - 1); + 0: idx := (aData^ shr (8 - bits - {%H-}PtrInt(aMapData))) and ((1 shl bits) - 1); 1: idx := aData^; 2: idx := PWord(aData)^; 4: idx := PCardinal(aData)^; @@ -4373,6 +4253,18 @@ begin inherited BeforeDestruction; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.PrepareResType(var aResource: String; var aResType: PChar); +var + TempPos: Integer; +begin + if not Assigned(aResType) then begin + TempPos := Pos('.', aResource); + aResType := PChar(UpperCase(Copy(aResource, TempPos + 1, Length(aResource) - TempPos))); + aResource := UpperCase(Copy(aResource, 0, TempPos -1)); + end; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.LoadFromFile(const aFilename: String); var @@ -4424,24 +4316,13 @@ begin AddFunc(Self, aFunc, false, Format, aArgs); end; -{$IFDEF GLB_DELPHI} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); +procedure TglBitmap.LoadFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar); var rs: TResourceStream; - TempPos: Integer; - ResTypeStr: String; - TempResType: PChar; -begin - if not Assigned(ResType) then begin - TempPos := Pos('.', Resource); - ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); - Resource := UpperCase(Copy(Resource, 0, TempPos -1)); - TempResType := PChar(ResTypeStr); - end else - TempResType := ResType - - rs := TResourceStream.Create(Instance, Resource, TempResType); +begin + PrepareResType(aResource, aResType); + rs := TResourceStream.Create(aInstance, aResource, aResType); try LoadFromStream(rs); finally @@ -4450,18 +4331,17 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.LoadFromResourceID(const sInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); +procedure TglBitmap.LoadFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); var rs: TResourceStream; begin - rs := TResourceStream.CreateFromID(Instance, ResourceID, ResType); + rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType); try LoadFromStream(rs); finally rs.Free; end; end; -{$ENDIF} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SaveToFile(const aFileName: String; const aFileType: TglBitmapFileType); @@ -4519,6 +4399,11 @@ begin SourceFD := TFormatDescriptor.Get(aSource.Format); DestFD := TFormatDescriptor.Get(aFormat); + if (SourceFD.IsCompressed) then + raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', SourceFD.Format); + if (DestFD.IsCompressed) then + raise EglBitmapUnsupportedFormat.Create('compressed formats are not supported: ', DestFD.Format); + // inkompatible Formats so CreateTemp if (SourceFD.PixelSize <> DestFD.PixelSize) then aCreateTemp := true; @@ -4532,7 +4417,7 @@ begin TmpData := nil; if aCreateTemp then begin - GetMem(TmpData, TFormatDescriptor.Get(aFormat).GetSize(TempWidth, TempHeight)); + GetMem(TmpData, DestFD.GetSize(TempWidth, TempHeight)); DestData := TmpData; end else DestData := Data; @@ -4897,49 +4782,220 @@ begin tex.Free; end; end; +{$ENDIF} +{$IFDEF GLB_LAZARUS} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; const aResource: String; const aResType: PChar; - const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AssignToLazIntfImage(const aImage: TLazIntfImage): Boolean; var - RS: TResourceStream; - TempPos: Integer; - ResTypeStr: String; - TempResType: PChar; + rid: TRawImageDescription; + FormatDesc: TFormatDescriptor; begin - if Assigned(ResType) then - TempResType := ResType + result := false; + if not Assigned(aImage) or (Format = tfEmpty) then + exit; + FormatDesc := TFormatDescriptor.Get(Format); + if FormatDesc.IsCompressed then + exit; + + FillChar(rid{%H-}, SizeOf(rid), 0); + if (Format in [ + tfAlpha4, tfAlpha8, tfAlpha12, tfAlpha16, + tfLuminance4, tfLuminance8, tfLuminance12, tfLuminance16, + tfLuminance4Alpha4, tfLuminance8Alpha8, tfLuminance12Alpha4, tfLuminance12Alpha12, tfLuminance16Alpha16]) then + rid.Format := ricfGray else - begin - TempPos := Pos('.', Resource); - ResTypeStr := UpperCase(Copy(Resource, TempPos + 1, Length(Resource) - TempPos)); - Resource := UpperCase(Copy(Resource, 0, TempPos -1)); - TempResType := PChar(ResTypeStr); - end; + rid.Format := ricfRGBA; + + rid.Width := Width; + rid.Height := Height; + rid.Depth := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a); + rid.BitOrder := riboBitsInOrder; + rid.ByteOrder := riboLSBFirst; + rid.LineOrder := riloTopToBottom; + rid.LineEnd := rileTight; + rid.BitsPerPixel := Round(8 * FormatDesc.PixelSize); + rid.RedPrec := CountSetBits(FormatDesc.Range.r); + rid.GreenPrec := CountSetBits(FormatDesc.Range.g); + rid.BluePrec := CountSetBits(FormatDesc.Range.b); + rid.AlphaPrec := CountSetBits(FormatDesc.Range.a); + rid.RedShift := FormatDesc.Shift.r; + rid.GreenShift := FormatDesc.Shift.g; + rid.BlueShift := FormatDesc.Shift.b; + rid.AlphaShift := FormatDesc.Shift.a; + + rid.MaskBitsPerPixel := 0; + rid.PaletteColorCount := 0; + + aImage.DataDescription := rid; + aImage.CreateData; + + Move(Data^, aImage.PixelData^, FormatDesc.GetSize(Dimension)); + + result := true; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignFromLazIntfImage(const aImage: TLazIntfImage): Boolean; +var + f: TglBitmapFormat; + FormatDesc: TFormatDescriptor; + ImageData: PByte; + ImageSize: Integer; +begin + result := false; + if not Assigned(aImage) then + exit; + for f := High(f) downto Low(f) do begin + FormatDesc := TFormatDescriptor.Get(f); + with aImage.DataDescription do + if FormatDesc.MaskMatch( + (QWord(1 shl RedPrec )-1) shl RedShift, + (QWord(1 shl GreenPrec)-1) shl GreenShift, + (QWord(1 shl BluePrec )-1) shl BlueShift, + (QWord(1 shl AlphaPrec)-1) shl AlphaShift) then + break; + end; + + if (f = tfEmpty) then + exit; + + ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height); + ImageData := GetMem(ImageSize); + try + Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3); + SetDataPointer(ImageData, f, aImage.Width, aImage.Height); + except + FreeMem(ImageData); + raise; + end; + + result := true; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AssignAlphaToLazIntfImage(const aImage: TLazIntfImage): Boolean; +var + rid: TRawImageDescription; + FormatDesc: TFormatDescriptor; + Pixel: TglBitmapPixelData; + x, y: Integer; + srcMD: Pointer; + src, dst: PByte; +begin + result := false; + if not Assigned(aImage) or (Format = tfEmpty) then + exit; + FormatDesc := TFormatDescriptor.Get(Format); + if FormatDesc.IsCompressed or not FormatDesc.HasAlpha then + exit; - RS := TResourceStream.Create(Instance, Resource, TempResType); + FillChar(rid{%H-}, SizeOf(rid), 0); + rid.Format := ricfGray; + rid.Width := Width; + rid.Height := Height; + rid.Depth := CountSetBits(FormatDesc.Range.a); + rid.BitOrder := riboBitsInOrder; + rid.ByteOrder := riboLSBFirst; + rid.LineOrder := riloTopToBottom; + rid.LineEnd := rileTight; + rid.BitsPerPixel := 8 * Ceil(rid.Depth / 8); + rid.RedPrec := CountSetBits(FormatDesc.Range.a); + rid.GreenPrec := 0; + rid.BluePrec := 0; + rid.AlphaPrec := 0; + rid.RedShift := 0; + rid.GreenShift := 0; + rid.BlueShift := 0; + rid.AlphaShift := 0; + + rid.MaskBitsPerPixel := 0; + rid.PaletteColorCount := 0; + + aImage.DataDescription := rid; + aImage.CreateData; + + srcMD := FormatDesc.CreateMappingData; try - result := AddAlphaFromStream(RS, Func, CustomData); + FormatDesc.PreparePixel(Pixel); + src := Data; + dst := aImage.PixelData; + for y := 0 to Height-1 do + for x := 0 to Width-1 do begin + FormatDesc.Unmap(src, Pixel, srcMD); + case rid.BitsPerPixel of + 8: begin + dst^ := Pixel.Data.a; + inc(dst); + end; + 16: begin + PWord(dst)^ := Pixel.Data.a; + inc(dst, 2); + end; + 24: begin + PByteArray(dst)^[0] := PByteArray(@Pixel.Data.a)^[0]; + PByteArray(dst)^[1] := PByteArray(@Pixel.Data.a)^[1]; + PByteArray(dst)^[2] := PByteArray(@Pixel.Data.a)^[2]; + inc(dst, 3); + end; + 32: begin + PCardinal(dst)^ := Pixel.Data.a; + inc(dst, 4); + end; + else + raise EglBitmapUnsupportedFormat.Create(Format); + end; + end; finally - RS.Free; + FormatDesc.FreeMappingData(srcMD); end; + result := true; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; - const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromLazIntfImage(const aImage: TLazIntfImage; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; var - RS: TResourceStream; + tex: TglBitmap2D; begin - RS := TResourceStream.CreateFromID(Instance, ResourceID, ResType); + tex := TglBitmap2D.Create; try - result := AddAlphaFromStream(RS, Func, CustomData); + tex.AssignFromLazIntfImage(aImage); + result := AddAlphaFromglBitmap(tex, aFunc, aArgs); finally - RS.Free; + tex.Free; end; end; {$ENDIF} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromResource(const aInstance: Cardinal; aResource: String; aResType: PChar; + const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; +var + rs: TResourceStream; +begin + PrepareResType(aResource, aResType); + rs := TResourceStream.Create(aInstance, aResource, aResType); + try + result := AddAlphaFromStream(rs, aFunc, aArgs); + finally + rs.Free; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.AddAlphaFromResourceID(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar; + const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; +var + rs: TResourceStream; +begin + rs := TResourceStream.CreateFromID(aInstance, aResourceID, aResType); + try + result := AddAlphaFromStream(rs, aFunc, aArgs); + finally + rs.Free; + end; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AddAlphaFromFunc(const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; begin @@ -5463,7 +5519,6 @@ begin LoadFromFunc(aSize, aFunc, aFormat, aArgs); end; -{$IFDEF GLB_DELPHI} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TglBitmap.Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar); begin @@ -5477,7 +5532,6 @@ begin Create; LoadFromResourceID(aInstance, aResourceID, aResType); end; -{$ENDIF} {$IFDEF GLB_SUPPORT_PNG_READ} {$IF DEFINED(GLB_SDL_IMAGE)} @@ -5711,7 +5765,7 @@ begin end; end; end; -{$IFEND} +{$ENDIF} {$ENDIF} {$IFDEF GLB_SUPPORT_PNG_WRITE} @@ -5877,7 +5931,7 @@ begin FreeAndNil(Png); end; end; -{$IFEND} +{$ENDIF} {$ENDIF} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -6186,7 +6240,7 @@ begin end; end; end; -{$IFEND} +{$ENDIF} {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} @@ -7433,16 +7487,12 @@ begin inherited SetDataPointer(aData, aFormat, aWidth, aHeight); if not TFormatDescriptor.Get(aFormat).IsCompressed then begin - (* TODO PixelFuncs - fGetPixelFunc := GetPixel2DUnmap; - fSetPixelFunc := SetPixel2DUnmap; - *) // Assigning Data if Assigned(Data) then begin SetLength(fLines, GetHeight); LineWidth := Trunc(GetWidth * TFormatDescriptor.Get(Format).PixelSize); - for Idx := 0 to GetHeight -1 do begin + for Idx := 0 to GetHeight-1 do begin fLines[Idx] := Data; Inc(fLines[Idx], Idx * LineWidth); end; @@ -7450,20 +7500,6 @@ begin else SetLength(fLines, 0); end else begin SetLength(fLines, 0); - (* - fSetPixelFunc := nil; - - case Format of - ifDXT1: - fGetPixelFunc := GetPixel2DDXT1; - ifDXT3: - fGetPixelFunc := GetPixel2DDXT3; - ifDXT5: - fGetPixelFunc := GetPixel2DDXT5; - else - fGetPixelFunc := nil; - end; - *) end; end; From 483a3227ccbeb78fc52d371f1ae36b22db07becc Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 17 Nov 2013 18:41:15 +0100 Subject: [PATCH 19/38] * added Delphi Support --- glBitmap.pas | 377 +++++++++++++++++++++++++-------------------------- 1 file changed, 181 insertions(+), 196 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index debcd36..38ddefd 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -241,7 +241,7 @@ unit glBitmap; {.$DEFINE GLB_DELPHI} // activate to enable the support for TLazIntfImage from Lazarus -{$DEFINE GLB_LAZARUS} +{.$DEFINE GLB_LAZARUS} // activate to enable the support of SDL_image to load files. (READ ONLY) @@ -286,16 +286,16 @@ unit glBitmap; {$ENDIF} // Operation System -{$IF DEFINED(WIN32) or DEFINED(WIN64)} +{$IF DEFINED(WIN32) or DEFINED(WIN64) or DEFINED(WINDOWS)} {$DEFINE GLB_WIN} {$ELSEIF DEFINED(LINUX)} {$DEFINE GLB_LINUX} -{$ENDIF} +{$IFEND} // native OpenGL Support {$IF DEFINED(GLB_NATIVE_OGL_STATIC) OR DEFINED(GLB_NATIVE_OGL_DYNAMIC)} {$DEFINE GLB_NATIVE_OGL} -{$ENDIF} +{$IFEND} // checking define combinations //SDL Image @@ -362,7 +362,7 @@ unit glBitmap; // native OpenGL {$IF DEFINED(GLB_NATIVE_OGL_STATIC) AND DEFINED(GLB_NATIVE_OGL_DYNAMIC)} {$MESSAGE warn 'GLB_NATIVE_OGL_STATIC will be ignored because you enabled GLB_NATIVE_OGL_DYNAMIC'} -{$ENDIF} +{$IFEND} // general options {$EXTENDEDSYNTAX ON} @@ -377,7 +377,7 @@ interface uses {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} {$IF DEFINED(GLB_WIN) AND - DEFINED(GLB_NATIVE_OGL)} windows, {$ENDIF} + DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} {$IFDEF GLB_SDL} SDL, {$ENDIF} {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF} @@ -393,20 +393,6 @@ uses Classes, SysUtils; -{$IFNDEF GLB_DELPHI} -type - HGLRC = Cardinal; - DWORD = Cardinal; - PDWORD = ^DWORD; - - TRGBQuad = packed record - rgbBlue: Byte; - rgbGreen: Byte; - rgbRed: Byte; - rgbReserved: Byte; - end; -{$ENDIF} - {$IFDEF GLB_NATIVE_OGL} const GL_TRUE = 1; @@ -524,13 +510,13 @@ const GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; -{$ifdef LINUX} - libglu = 'libGLU.so.1'; - libopengl = 'libGL.so.1'; -{$else} +{$IF DEFINED(GLB_WIN)} libglu = 'glu32.dll'; libopengl = 'opengl32.dll'; -{$endif} +{$ELSEIF DEFINED(GLB_LINUX)} + libglu = 'libGLU.so.1'; + libopengl = 'libGL.so.1'; +{$IFEND} type GLboolean = BYTEBOOL; @@ -550,6 +536,13 @@ type TglCompressedTexImage2D = procedure(target: GLenum; level: GLint; internalformat: GLenum; width: GLsizei; height: GLsizei; border: GLint; imageSize: GLsizei; const data: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGetCompressedTexImage = procedure(target: GLenum; level: GLint; img: PGLvoid); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} +{$IF DEFINED(GLB_WIN)} + TwglGetProcAddress = function (ProcName: PAnsiChar): Pointer; stdcall; +{$ELSEIF DEFINED(GLB_LINUX)} + TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl; + TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl; +{$IFEND} + {$IF DEFINED(GLB_NATIVE_OGL_DYNAMIC)} TglEnable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglDisable = procedure(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} @@ -579,13 +572,6 @@ type TgluBuild1DMipmaps = function(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TgluBuild2DMipmaps = function(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} - {$IFDEF GLB_LINUX} - TglXGetProcAddress = function(ProcName: PAnsiChar): Pointer; cdecl; - TglXGetProcAddressARB = function(const name: PAnsiChar): pointer; cdecl; - {$ELSE} - TwglGetProcAddress = function(ProcName: PAnsiChar): Pointer; stdcall; - {$ENDIF} - {$ELSEIF DEFINED(GLB_NATIVE_OGL_STATIC)} procedure glEnable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glDisable(cap: GLenum); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; @@ -614,7 +600,7 @@ type function gluBuild1DMipmaps(target: GLEnum; components, width: GLint; format, atype: GLEnum; const data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu; function gluBuild2DMipmaps(target: GLEnum; components, width, height: GLint; format, atype: GLEnum; const Data: Pointer): GLint; {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libglu; -{$ENDIF} +{$IFEND} var GL_VERSION_1_2, @@ -641,6 +627,13 @@ var glCompressedTexImage2D: TglCompressedTexImage2D; glGetCompressedTexImage: TglGetCompressedTexImage; +{$IF DEFINED(GLB_WIN)} + wglGetProcAddress: TwglGetProcAddress; +{$ELSEIF DEFINED(GLB_LINUX)} + glXGetProcAddress: TglXGetProcAddress; + glXGetProcAddressARB: TglXGetProcAddress; +{$IFEND} + {$IFDEF GLB_NATIVE_OGL_DYNAMIC} glEnable: TglEnable; glDisable: TglDisable; @@ -669,22 +662,7 @@ var gluBuild1DMipmaps: TgluBuild1DMipmaps; gluBuild2DMipmaps: TgluBuild2DMipmaps; - - {$IF DEFINED(GLB_WIN)} - wglGetProcAddress: TwglGetProcAddress; - {$ELSEIF DEFINED(GLB_LINUX)} - glXGetProcAddress: TglXGetProcAddress; - glXGetProcAddressARB: TglXGetProcAddressARB; - {$ENDIF} -{$ENDIF} - -(* -{$IFDEF GLB_DELPHI} -var - gLastContext: HGLRC; {$ENDIF} -*) - {$ENDIF} type @@ -1132,6 +1110,14 @@ uses Math, syncobjs, typinfo; type +{$IFNDEF fpc} + QWord = System.UInt64; + PQWord = ^QWord; + + PtrInt = Longint; + PtrUInt = DWord; +{$ENDIF} + //////////////////////////////////////////////////////////////////////////////////////////////////// TShiftRec = packed record case Integer of @@ -1186,8 +1172,8 @@ type procedure Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); virtual; abstract; procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; - function GetSize(const aSize: TglBitmapPixelPosition): Integer; virtual; overload; - function GetSize(const aWidth, aHeight: Integer): Integer; virtual; overload; + function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual; + function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual; function CreateMappingData: Pointer; virtual; procedure FreeMappingData(var aMappingData: Pointer); virtual; @@ -1842,8 +1828,6 @@ var function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer; begin - result := nil; - if not Assigned(aLibHandle) then aLibHandle := GL_LibHandle; @@ -1868,7 +1852,7 @@ begin end; result := dlsym(aLibHandle, aProcName); -{$ENDIF} +{$IFEND} if not Assigned(result) then raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName); end; @@ -1891,7 +1875,7 @@ procedure glbInitOpenGL; result := dlopen(Name, RTLD_LAZY); {$ELSE} result := nil; - {$ENDIF} + {$IFEND} end; //////////////////////////////////////////////////////////////////////////////// @@ -1905,7 +1889,7 @@ procedure glbInitOpenGL; Result := FreeLibrary({%H-}HINST(aLibHandle)); {$ELSEIF DEFINED(GLB_LINUX)} Result := dlclose(aLibHandle) = 0; - {$ENDIF} + {$IFEND} end; begin @@ -1928,8 +1912,8 @@ begin wglGetProcAddress := glbGetProcAddress('wglGetProcAddress'); {$ELSEIF DEFINED(GLB_LINUX)} glXGetProcAddress := glbGetProcAddress('glXGetProcAddress'); - glXGetProcAddressARB := dglGetProcAddress('glXGetProcAddressARB'); - {$ENDIF} + glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB'); + {$IFEND} glEnable := glbGetProcAddress('glEnable'); glDisable := glbGetProcAddress('glDisable'); @@ -1963,9 +1947,6 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glbReadOpenGLExtensions; var - {$IFDEF GLB_DELPHI} - Context: HGLRC; - {$ENDIF} Buffer: AnsiString; MajorVersion, MinorVersion: Integer; @@ -2024,61 +2005,52 @@ begin end; {$ENDIF} -{$IFDEF GLB_DELPHI} - Context := wglGetCurrentContext; - if (Context <> gLastContext) then begin - gLastContext := Context; -{$ENDIF} - - // Version - Buffer := glGetString(GL_VERSION); - TrimVersionString(Buffer, MajorVersion, MinorVersion); + // Version + Buffer := glGetString(GL_VERSION); + TrimVersionString(Buffer, MajorVersion, MinorVersion); - GL_VERSION_1_2 := false; - GL_VERSION_1_3 := false; - GL_VERSION_1_4 := false; - GL_VERSION_2_0 := false; - if MajorVersion = 1 then begin - if MinorVersion >= 2 then - GL_VERSION_1_2 := true; - - if MinorVersion >= 3 then - GL_VERSION_1_3 := true; - - if MinorVersion >= 4 then - GL_VERSION_1_4 := true; - end else if MajorVersion >= 2 then begin + GL_VERSION_1_2 := false; + GL_VERSION_1_3 := false; + GL_VERSION_1_4 := false; + GL_VERSION_2_0 := false; + if MajorVersion = 1 then begin + if MinorVersion >= 2 then GL_VERSION_1_2 := true; + + if MinorVersion >= 3 then GL_VERSION_1_3 := true; - GL_VERSION_1_4 := true; - GL_VERSION_2_0 := true; - end; - // Extensions - Buffer := glGetString(GL_EXTENSIONS); - GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp'); - GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two'); - GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle'); - GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat'); - GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp'); - GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic'); - GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle'); - GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle'); - GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat'); - GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap'); - - if GL_VERSION_1_3 then begin - glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D'); - glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D'); - glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage'); - end else begin - glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB'); - glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB'); - glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB'); - end; -{$IFDEF GLB_DELPHI} + if MinorVersion >= 4 then + GL_VERSION_1_4 := true; + end else if MajorVersion >= 2 then begin + GL_VERSION_1_2 := true; + GL_VERSION_1_3 := true; + GL_VERSION_1_4 := true; + GL_VERSION_2_0 := true; + end; + + // Extensions + Buffer := glGetString(GL_EXTENSIONS); + GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp'); + GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two'); + GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle'); + GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat'); + GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp'); + GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic'); + GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle'); + GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle'); + GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat'); + GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap'); + + if GL_VERSION_1_3 then begin + glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1D'); + glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D'); + glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage'); + end else begin + glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB'); + glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB'); + glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB'); end; -{$ENDIF} end; {$ENDIF} @@ -3798,7 +3770,7 @@ begin aData^ := 0; d := LuminanceWeight(aPixel) and Range.r; aData^ := aData^ or (d shl (4 - {%H-}PtrUInt(aMapData))); - inc(aMapData, 4); + inc(PByte(aMapData), 4); if ({%H-}PtrUInt(aMapData) >= 8) then begin inc(aData); aMapData := nil; @@ -3848,10 +3820,10 @@ begin aPixel.Data.b := b; aPixel.Data.a := a; end; - inc(aMapData, bits); + inc(PByte(aMapData), bits); if ({%H-}PtrUInt(aMapData) >= 8) then begin inc(aData, 1); - dec(aMapData, 8); + dec(PByte(aMapData), 8); end; inc(aData, s); end; @@ -4621,7 +4593,27 @@ end; {$ENDIF} {$IFDEF GLB_DELPHI} -//TODO rework & test +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function CreateGrayPalette: HPALETTE; +var + Idx: Integer; + Pal: PLogPalette; +begin + GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256)); + + Pal.palVersion := $300; + Pal.palNumEntries := 256; + + for Idx := 0 to Pal.palNumEntries - 1 do begin + Pal.palPalEntry[Idx].peRed := Idx; + Pal.palPalEntry[Idx].peGreen := Idx; + Pal.palPalEntry[Idx].peBlue := Idx; + Pal.palPalEntry[Idx].peFlags := 0; + end; + Result := CreatePalette(Pal^); + FreeMem(Pal); +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.AssignToBitmap(const aBitmap: TBitmap): Boolean; var @@ -4635,35 +4627,30 @@ begin aBitmap.Height := Height; case Format of - tfAlpha8, ifLuminance, ifDepth8: - begin - Bitmap.PixelFormat := pf8bit; - Bitmap.Palette := CreateGrayPalette; - end; - ifRGB5A1: - Bitmap.PixelFormat := pf15bit; - ifR5G6B5: - Bitmap.PixelFormat := pf16bit; - ifRGB8, ifBGR8: - Bitmap.PixelFormat := pf24bit; - ifRGBA8, ifBGRA8: - Bitmap.PixelFormat := pf32bit; - else - raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); + tfAlpha8, tfLuminance8: begin + aBitmap.PixelFormat := pf8bit; + aBitmap.Palette := CreateGrayPalette; + end; + tfRGB5A1: + aBitmap.PixelFormat := pf15bit; + tfR5G6B5: + aBitmap.PixelFormat := pf16bit; + tfRGB8, tfBGR8: + aBitmap.PixelFormat := pf24bit; + tfRGBA8, tfBGRA8: + aBitmap.PixelFormat := pf32bit; + else + raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); end; pSource := Data; for Row := 0 to FileHeight -1 do begin - pData := Bitmap.Scanline[Row]; - + pData := aBitmap.Scanline[Row]; Move(pSource^, pData^, fRowSize); Inc(pSource, fRowSize); - - // swap RGB(A) to BGR(A) - if InternalFormat in [ifRGB8, ifRGBA8] then - SwapRGB(pData, FileWidth, InternalFormat = ifRGBA8); + if (Format in [tfRGB8, tfRGBA8]) then // swap RGB(A) to BGR(A) + SwapRGB(pData, FileWidth, Format = tfRGBA8); end; - result := true; end; end; @@ -4674,46 +4661,40 @@ function TglBitmap.AssignFromBitmap(const aBitmap: TBitmap): Boolean; var pSource, pData, pTempData: PByte; Row, RowSize, TempWidth, TempHeight: Integer; - IntFormat: TglBitmapInternalFormat; + IntFormat: TglBitmapFormat; begin result := false; - if (Assigned(Bitmap)) then begin - case Bitmap.PixelFormat of + if (Assigned(aBitmap)) then begin + case aBitmap.PixelFormat of pf8bit: - IntFormat := ifLuminance; + IntFormat := tfLuminance8; pf15bit: - IntFormat := ifRGB5A1; + IntFormat := tfRGB5A1; pf16bit: - IntFormat := ifR5G6B5; + IntFormat := tfR5G6B5; pf24bit: - IntFormat := ifBGR8; + IntFormat := tfBGR8; pf32bit: - IntFormat := ifBGRA8; - else - raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.'); + IntFormat := tfBGRA8; + else + raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.'); end; - TempWidth := Bitmap.Width; - TempHeight := Bitmap.Height; - - RowSize := Trunc(TempWidth * FormatGetSize(IntFormat)); - + TempWidth := aBitmap.Width; + TempHeight := aBitmap.Height; + RowSize := TFormatDescriptor.Get(IntFormat).GetSize(TempWidth, 1); GetMem(pData, TempHeight * RowSize); try pTempData := pData; - for Row := 0 to TempHeight -1 do begin - pSource := Bitmap.Scanline[Row]; - + pSource := aBitmap.Scanline[Row]; if (Assigned(pSource)) then begin Move(pSource^, pTempData^, RowSize); Inc(pTempData, RowSize); end; end; - SetDataPointer(pData, IntFormat, TempWidth, TempHeight); - result := true; except FreeMem(pData); @@ -4731,17 +4712,17 @@ begin result := false; if Assigned(Data) then begin - if InternalFormat in [ifAlpha, ifLuminanceAlpha, ifRGBA8, ifBGRA8] then begin - if Assigned(Bitmap) then begin - Bitmap.PixelFormat := pf8bit; - Bitmap.Palette := CreateGrayPalette; - Bitmap.Width := Width; - Bitmap.Height := Height; - - case InternalFormat of - ifLuminanceAlpha: + if (Format in [tfAlpha8, tfLuminance8Alpha8, tfRGBA8, tfBGRA8]) then begin + if Assigned(aBitmap) then begin + aBitmap.PixelFormat := pf8bit; + aBitmap.Palette := CreateGrayPalette; + aBitmap.Width := Width; + aBitmap.Height := Height; + + case Format of + tfLuminance8Alpha8: AlphaInterleave := 1; - ifRGBA8, ifBGRA8: + tfRGBA8, tfBGRA8: AlphaInterleave := 3; else AlphaInterleave := 0; @@ -4751,8 +4732,7 @@ begin pSource := Data; for Row := 0 to Height -1 do begin - pDest := Bitmap.Scanline[Row]; - + pDest := aBitmap.Scanline[Row]; if Assigned(pDest) then begin for Col := 0 to Width -1 do begin Inc(pSource, AlphaInterleave); @@ -4761,8 +4741,7 @@ begin Inc(pSource); end; end; - end; - + end; result := true; end; end; @@ -4770,14 +4749,14 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: PtrInt): Boolean; +function TglBitmap.AddAlphaFromBitmap(const aBitmap: TBitmap; const aFunc: TglBitmapFunction; const aArgs: Pointer): Boolean; var tex: TglBitmap2D; begin tex := TglBitmap2D.Create; try - tex.AssignFromBitmap(Bitmap); - result := AddAlphaFromglBitmap(tex, Func, CustomData); + tex.AssignFromBitmap(ABitmap); + result := AddAlphaFromglBitmap(tex, aFunc, aArgs); finally tex.Free; end; @@ -5765,7 +5744,7 @@ begin end; end; end; -{$ENDIF} +{$IFEND} {$ENDIF} {$IFDEF GLB_SUPPORT_PNG_WRITE} @@ -5931,7 +5910,7 @@ begin FreeAndNil(Png); end; end; -{$ENDIF} +{$IFEND} {$ENDIF} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -6219,9 +6198,9 @@ begin result := false; // reading first two bytes to test file and set cursor back to begin - StreamPos := Stream.Position; - Stream.Read(Temp[0], 2); - Stream.Position := StreamPos; + StreamPos := aStream.Position; + aStream.Read(Temp[0], 2); + aStream.Position := StreamPos; // if Bitmap then read file. if ((Temp[0] = $FF) and (Temp[1] = $D8)) then begin @@ -6229,7 +6208,7 @@ begin try jpg := TJPEGImage.Create; try - jpg.LoadFromStream(Stream); + jpg.LoadFromStream(aStream); bmp.Assign(jpg); result := AssignFromBitmap(bmp); finally @@ -6240,7 +6219,7 @@ begin end; end; end; -{$ENDIF} +{$IFEND} {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} @@ -6351,25 +6330,25 @@ end; {$ELSEIF DEFINED(GLB_DELPHI_JPEG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SaveJPEG(Stream: TStream); +procedure TglBitmap.SaveJPEG(const aStream: TStream); var Bmp: TBitmap; Jpg: TJPEGImage; begin - if not (ftJPEG in FormatGetSupportedFiles (InternalFormat)) then - raise EglBitmapUnsupportedInternalFormat.Create('SaveJpg - ' + UNSUPPORTED_INTERNAL_FORMAT); + if not (ftJPEG in FormatGetSupportedFiles(Format)) then + raise EglBitmapUnsupportedFormat.Create(Format); Bmp := TBitmap.Create; try Jpg := TJPEGImage.Create; try AssignToBitmap(Bmp); - if FInternalFormat in [ifAlpha, ifLuminance, ifDepth8] then begin - Jpg.Grayscale := true; + if (Format in [tfAlpha8, tfLuminance8]) then begin + Jpg.Grayscale := true; Jpg.PixelFormat := jf8Bit; end; Jpg.Assign(Bmp); - Jpg.SaveToStream(Stream); + Jpg.SaveToStream(aStream); finally FreeAndNil(Jpg); end; @@ -6377,7 +6356,7 @@ begin FreeAndNil(Bmp); end; end; -{$ENDIF} +{$IFEND} {$ENDIF} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -6844,13 +6823,15 @@ const begin buf := nil; if (Counter.X.dir < 0) then - buf := GetMem(LineSize); + GetMem(buf, LineSize); try while (Counter.Y.low <> Counter.Y.high + counter.Y.dir) do begin - tmp1 := ImageData + (Counter.Y.low * LineSize); //pointer to LineStart + tmp1 := ImageData; + inc(tmp1, (Counter.Y.low * LineSize)); //pointer to LineStart if (Counter.X.dir < 0) then begin //flip X aStream.Read(buf^, LineSize); - tmp2 := buf + LineSize - PixelSize; //pointer to last pixel in line + tmp2 := buf; + inc(tmp2, LineSize - PixelSize); //pointer to last pixel in line for i := 0 to Header.Width-1 do begin //for all pixels in line for j := 0 to PixelSize-1 do begin //for all bytes in pixel tmp1^ := tmp2^; @@ -6881,9 +6862,10 @@ const if (LinePixelsRead >= Header.Width) then begin LinePixelsRead := 0; inc(Counter.Y.low, Counter.Y.dir); //next line index - TmpData := ImageData + Counter.Y.low * LineSize; //set line + TmpData := ImageData; + inc(TmpData, Counter.Y.low * LineSize); //set line if (Counter.X.dir < 0) then //if x flipped then - TmpData := TmpData + LineSize - PixelSize; //set last pixel + inc(TmpData, LineSize - PixelSize); //set last pixel end; end; @@ -6961,9 +6943,10 @@ const GetMem(Cache, CACHE_SIZE); try - TmpData := ImageData + Counter.Y.low * LineSize; //set line + TmpData := ImageData; + inc(TmpData, Counter.Y.low * LineSize); //set line if (Counter.X.dir < 0) then //if x flipped then - TmpData := TmpData + LineSize - PixelSize; //set last pixel + inc(TmpData, LineSize - PixelSize); //set last pixel repeat //read CommandByte @@ -7012,6 +6995,7 @@ begin if Header.ImageID <> 0 then // skip image ID aStream.Position := aStream.Position + Header.ImageID; + tgaFormat := tfEmpty; case Header.Bpp of 8: if IsGrayFormat then case (Header.ImageDesc and $F) of 0: tgaFormat := tfLuminance8; @@ -7156,7 +7140,7 @@ begin if Assigned(Converter) then begin LineSize := FormatDesc.GetSize(Width, 1); - LineBuf := GetMem(LineSize); + GetMem(LineBuf, LineSize); SourceMD := FormatDesc.CreateMappingData; DestMD := Converter.CreateMappingData; try @@ -7364,7 +7348,8 @@ begin DestMD := FormatDesc.CreateMappingData; try for y := 0 to Header.dwHeight-1 do begin - TmpData := NewImage + y * LineSize; + TmpData := NewImage; + inc(TmpData, y * LineSize); SrcData := RowData; aStream.Read(SrcData^, RowSize); for x := 0 to Header.dwWidth-1 do begin From df5f73ad097033eb6fd4442ba0d1953eb1147865 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 19 Nov 2013 18:53:26 +0100 Subject: [PATCH 20/38] * implemented TglBitmap1D * fixed some memory issues --- glBitmap.pas | 430 +++++++++++++++++++++++---------------------------- 1 file changed, 196 insertions(+), 234 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 38ddefd..0b4d037 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -4,7 +4,6 @@ http://www.opengl24.de/index.php?cat=header&file=glbitmap modified by Delphi OpenGL Community (http://delphigl.com/) - ------------------------------------------------------------ The contents of this file are used with permission, subject to the Mozilla Public License Version 1.1 (the "License"); you may @@ -241,7 +240,8 @@ unit glBitmap; {.$DEFINE GLB_DELPHI} // activate to enable the support for TLazIntfImage from Lazarus -{.$DEFINE GLB_LAZARUS} +{$DEFINE GLB_LAZARUS} + // activate to enable the support of SDL_image to load files. (READ ONLY) @@ -846,8 +846,8 @@ type procedure CreateID; procedure SetupParameters(out aBuildWithGlu: Boolean); - procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; - const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; + procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer = -1; const aHeight: Integer = -1); virtual; //be careful, aData could be freed by this method procedure GenTexture(const aTestTextureSize: Boolean = true); virtual; abstract; function FlipHorz: Boolean; virtual; @@ -992,6 +992,19 @@ type procedure SaveDDS(const aStream: TStream); virtual; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TglBitmap1D = class(TglBitmap) + protected + procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer = - 1; const aHeight: Integer = - 1); override; + procedure UploadData(const aBuildWithGlu: Boolean); + public + property Width; + procedure AfterConstruction; override; + function FlipHorz: Boolean; override; + procedure GenTexture(const aTestTextureSize: Boolean = true); override; + end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap2D = class(TglBitmap) protected @@ -999,9 +1012,9 @@ type fLines: array of PByte; function GetScanline(const aIndex: Integer): Pointer; - procedure SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; + procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer = - 1; const aHeight: Integer = - 1); override; - procedure UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean); + procedure UploadData(const aBuildWithGlu: Boolean); public property Width; property Height; @@ -1045,24 +1058,7 @@ type end; - TglBitmap1D = class(TglBitmap) - protected - procedure GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); - - procedure SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width: Integer = -1; Height: Integer = -1); override; - procedure UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); - public - // propertys - property Width; - - procedure AfterConstruction; override; - - // Other - function FlipHorz: Boolean; override; - // Generation - procedure GenTexture(TestTextureSize: Boolean = true); override; - end; *) const @@ -2054,42 +2050,6 @@ begin end; {$ENDIF} -(* TODO GLB_DELPHI -{$IFDEF GLB_DELPHI} -function CreateGrayPalette: HPALETTE; -var - Idx: Integer; - Pal: PLogPalette; -begin - GetMem(Pal, SizeOf(TLogPalette) + (SizeOf(TPaletteEntry) * 256)); - - Pal.palVersion := $300; - Pal.palNumEntries := 256; - - {$IFOPT R+} - {$DEFINE GLB_TEMPRANGECHECK} - {$R-} - {$ENDIF} - - for Idx := 0 to 256 - 1 do begin - Pal.palPalEntry[Idx].peRed := Idx; - Pal.palPalEntry[Idx].peGreen := Idx; - Pal.palPalEntry[Idx].peBlue := Idx; - Pal.palPalEntry[Idx].peFlags := 0; - end; - - {$IFDEF GLB_TEMPRANGECHECK} - {$UNDEF GLB_TEMPRANGECHECK} - {$R+} - {$ENDIF} - - result := CreatePalette(Pal^); - - FreeMem(Pal); -end; -{$ENDIF} -*) - {$IFDEF GLB_SDL_IMAGE} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SDL Image Helper ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4064,7 +4024,7 @@ begin exit; if TFormatDescriptor.Get(Format).PixelSize <> TFormatDescriptor.Get(aValue).PixelSize then raise EglBitmapUnsupportedFormat.Create(Format); - SetDataPointer(Data, aValue, Width, Height); + SetDataPointer(fData, aValue, Width, Height); //be careful, Data could be freed by this method end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4150,7 +4110,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; +procedure TglBitmap.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer; const aHeight: Integer); var s: Single; @@ -4218,8 +4178,11 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.BeforeDestruction; +var + NewData: PByte; begin - SetDataPointer(nil, tfEmpty); + NewData := nil; + SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method if (fID > 0) and fDeleteTextureOnFree then glDeleteTextures(1, @fID); inherited BeforeDestruction; @@ -4280,9 +4243,10 @@ begin GetMem(tmpData, size); try FillChar(tmpData^, size, #$FF); - SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); + SetDataPointer(tmpData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method except - FreeMem(tmpData); + if Assigned(tmpData) then + FreeMem(tmpData); raise; end; AddFunc(Self, aFunc, false, Format, aArgs); @@ -4420,7 +4384,7 @@ begin // Updating Image or InternalFormat if aCreateTemp then - SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) + SetDataPointer(TmpData, aFormat, aSource.Width, aSource.Height) //be careful, Data could be freed by this method else if (aFormat <> fFormat) then Format := aFormat; @@ -4430,7 +4394,7 @@ begin DestFD.FreeMappingData(DestMD); end; except - if aCreateTemp then + if aCreateTemp and Assigned(TmpData) then FreeMem(TmpData); raise; end; @@ -4525,10 +4489,11 @@ begin Inc(pTempData, RowSize); end; end; - SetDataPointer(pData, IntFormat, TempWidth, TempHeight); + SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method result := true; except - FreeMem(pData); + if Assigned(pData) then + FreeMem(pData); raise; end; end; @@ -4694,10 +4659,11 @@ begin Inc(pTempData, RowSize); end; end; - SetDataPointer(pData, IntFormat, TempWidth, TempHeight); + SetDataPointer(pData, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method result := true; except - FreeMem(pData); + if Assigned(pData) then + FreeMem(pData); raise; end; end; @@ -4843,9 +4809,10 @@ begin ImageData := GetMem(ImageSize); try Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3); - SetDataPointer(ImageData, f, aImage.Width, aImage.Height); + SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method except - FreeMem(ImageData); + if Assigned(ImageData) then + FreeMem(ImageData); raise; end; @@ -5177,13 +5144,16 @@ begin GetMem(TempPtr, Size); try Move(Data^, TempPtr^, Size); - Temp.SetDataPointer(TempPtr, Format, Width, Height); + Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method except - FreeMem(TempPtr); + if Assigned(TempPtr) then + FreeMem(TempPtr); raise; end; - end else - Temp.SetDataPointer(nil, Format, Width, Height); + end else begin + TempPtr := nil; + Temp.SetDataPointer(TempPtr, Format, Width, Height); //be careful, Data could be freed by this method + end; // copy properties Temp.fID := ID; @@ -5291,8 +5261,11 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.FreeData; +var + TempPtr: PByte; begin - SetDataPointer(nil, tfEmpty); + TempPtr := nil; + SetDataPointer(TempPtr, tfEmpty); //be careful, Data could be freed by this method end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5450,11 +5423,11 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TglBitmap.Create; begin + if (ClassType = TglBitmap) then + raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); {$IFDEF GLB_NATIVE_OGL} glbReadOpenGLExtensions; {$ENDIF} - if (ClassType = TglBitmap) then - raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); inherited Create; end; @@ -5483,9 +5456,10 @@ begin GetMem(Image, ImageSize); try FillChar(Image^, ImageSize, #$FF); - SetDataPointer(Image, aFormat, aSize.X, aSize.Y); + SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method except - FreeMem(Image); + if Assigned(Image) then + FreeMem(Image); raise; end; end; @@ -5639,11 +5613,12 @@ begin SetLength(png_rows, 0); // set new data - SetDataPointer(png_data, Format, TempWidth, TempHeight); + SetDataPointer(png_data, Format, TempWidth, TempHeight); //be careful, Data could be freed by this method result := true; except - FreeMem(png_data); + if Assigned(png_data) then + FreeMem(png_data); raise; end; end; @@ -5732,11 +5707,12 @@ begin raise EglBitmapException.Create ('LoadPng - Unsupported Colortype found.'); end; - SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); + SetDataPointer(NewImage, PngFormat, Png.Header.Width, Png.Header.Height); //be careful, Data could be freed by this method result := true; except - FreeMem(NewImage); + if Assigned(NewImage) then + FreeMem(NewImage); raise; end; finally @@ -6173,11 +6149,12 @@ begin // destroy decompression jpeg_destroy_decompress(@jpeg); - SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); + SetDataPointer(pImage, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method result := true; except - FreeMem(pImage); + if Assigned(pImage) then + FreeMem(pImage); raise; end; end; @@ -6570,7 +6547,7 @@ begin inc(TmpData, wbLineSize); aStream.Read(PaddingBuff{%H-}, Padding); end; - SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); + SetDataPointer(ImageData, BmpFormat, Info.biWidth, abs(Info.biHeight)); //be careful, Data could be freed by this method result := true; finally if Assigned(LineBuf) then @@ -6580,7 +6557,8 @@ begin FormatDesc.FreeMappingData(DestMD); end; except - FreeMem(ImageData); + if Assigned(ImageData) then + FreeMem(ImageData); raise; end; end else @@ -7060,10 +7038,11 @@ begin ReadCompressed; end; - SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); + SetDataPointer(ImageData, tgaFormat, Header.Width, Header.Height); //be careful, Data could be freed by this method result := true; except - FreeMem(ImageData); + if Assigned(ImageData) then + FreeMem(ImageData); raise; end; finally @@ -7384,10 +7363,11 @@ begin end else raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); - SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); + SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method result := true; except - FreeMem(NewImage); + if Assigned(NewImage) then + FreeMem(NewImage); raise; end; finally @@ -7452,6 +7432,112 @@ begin aStream.Write(Data^, FormatDesc.GetSize(Dimension)); end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmap1D///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap1D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; + const aWidth: Integer; const aHeight: Integer); +var + pTemp: pByte; + Size: Integer; +begin + if (aHeight > 1) then begin + Size := TFormatDescriptor.Get(aFormat).GetSize(aWidth, 1); + GetMem(pTemp, Size); + try + Move(aData^, pTemp^, Size); + FreeMem(aData); + aData := nil; + except + FreeMem(pTemp); + raise; + end; + end else + pTemp := aData; + inherited SetDataPointer(pTemp, aFormat, aWidth); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap1D.FlipHorz: Boolean; +var + Col: Integer; + pTempDest, pDest, pSource: PByte; +begin + result := inherited FlipHorz; + if Assigned(Data) and not TFormatDescriptor.Get(Format).IsCompressed then begin + pSource := Data; + GetMem(pDest, fRowSize); + try + pTempDest := pDest; + Inc(pTempDest, fRowSize); + for Col := 0 to Width-1 do begin + dec(pTempDest, fPixelSize); //dec before, because ptr is behind last byte of data + Move(pSource^, pTempDest^, fPixelSize); + Inc(pSource, fPixelSize); + end; + SetDataPointer(pDest, Format, Width); //be careful, Data could be freed by this method + result := true; + except + if Assigned(pDest) then + FreeMem(pDest); + raise; + end; + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap1D.UploadData(const aBuildWithGlu: Boolean); +var + FormatDesc: TFormatDescriptor; +begin + // Upload data + FormatDesc := TFormatDescriptor.Get(Format); + if FormatDesc.IsCompressed then + glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data) + else if aBuildWithGlu then + gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data) + else + glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data); + + // Free Data + if (FreeDataAfterGenTexture) then + FreeData; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap1D.GenTexture(const aTestTextureSize: Boolean); +var + BuildWithGlu, TexRec: Boolean; + TexSize: Integer; +begin + if Assigned(Data) then begin + // Check Texture Size + if (aTestTextureSize) then begin + glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); + + if (Width > TexSize) then + raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); + + TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and + (Target = GL_TEXTURE_RECTANGLE_ARB); + if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then + raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.'); + end; + + CreateId; + SetupParameters(BuildWithGlu); + UploadData(BuildWithGlu); + glAreTexturesResident(1, @fID, @fIsResident); + end; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap1D.AfterConstruction; +begin + inherited; + Target := GL_TEXTURE_1D; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap2D///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -7464,7 +7550,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap2D.SetDataPointer(const aData: PByte; const aFormat: TglBitmapFormat; +procedure TglBitmap2D.SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer; const aHeight: Integer); var Idx, LineWidth: Integer; @@ -7489,7 +7575,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap2D.UploadData(const aTarget: Cardinal; const aBuildWithGlu: Boolean); +procedure TglBitmap2D.UploadData(const aBuildWithGlu: Boolean); var FormatDesc: TFormatDescriptor; begin @@ -7499,10 +7585,10 @@ begin 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, + gluBuild2DMipmaps(Target, FormatDesc.Components, Width, Height, FormatDesc.glFormat, FormatDesc.glDataFormat, Data) end else begin - glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, + glTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data); end; @@ -7536,10 +7622,11 @@ begin try glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp); - SetDataPointer(Temp, Format, w, h); + SetDataPointer(Temp, Format, w, h); //be careful, Data could be freed by this method FlipVert; except - FreeMem(Temp); + if Assigned(Temp) then + FreeMem(Temp); raise; end; end; @@ -7577,9 +7664,10 @@ begin glGetCompressedTexImage(Target, 0, Temp) else glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp); - SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); + SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method except - FreeMem(Temp); + if Assigned(Temp) then + FreeMem(Temp); raise; end; end; @@ -7600,14 +7688,13 @@ begin PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width); TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE); - if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); end; CreateId; SetupParameters(BuildWithGlu); - UploadData(Target, BuildWithGlu); + UploadData(BuildWithGlu); glAreTexturesResident(1, @fID, @fIsResident); end; end; @@ -7635,10 +7722,11 @@ begin Dec(TempDestData, fPixelSize); end; end; - SetDataPointer(DestData, Format); + SetDataPointer(DestData, Format); //be careful, Data could be freed by this method result := true; except - FreeMem(DestData); + if Assigned(DestData) then + FreeMem(DestData); raise; end; end; @@ -7662,10 +7750,11 @@ begin Dec(TempDestData, fRowSize); Inc(SourceData, fRowSize); end; - SetDataPointer(DestData, Format); + SetDataPointer(DestData, Format); //be careful, Data could be freed by this method result := true; except - FreeMem(DestData); + if Assigned(DestData) then + FreeMem(DestData); raise; end; end; @@ -7903,134 +7992,7 @@ end; (* -procedure TglBitmap1D.SetDataPointer(Data: pByte; Format: TglBitmapInternalFormat; Width, Height: Integer); -var - pTemp: pByte; - Size: Integer; -begin - if Height > 1 then begin - // extract first line of the data - Size := FormatGetImageSize(glBitmapPosition(Width), Format); - GetMem(pTemp, Size); - Move(Data^, pTemp^, Size); - - FreeMem(Data); - end else - pTemp := Data; - - // set data pointer - inherited SetDataPointer(pTemp, Format, Width); - - if FormatIsUncompressed(Format) then begin - fUnmapFunc := FormatGetUnMapFunc(Format); - fGetPixelFunc := GetPixel1DUnmap; - end; -end; - - -procedure TglBitmap1D.GetPixel1DUnmap(const Pos: TglBitmapPixelPosition; var Pixel: TglBitmapPixelData); -var - pTemp: pByte; -begin - pTemp := Data; - Inc(pTemp, Pos.X * fPixelSize); - - fUnmapFunc(pTemp, Pixel); -end; - - -function TglBitmap1D.FlipHorz: Boolean; -var - Col: Integer; - pTempDest, pDest, pSource: pByte; -begin - result := inherited FlipHorz; - - if Assigned(Data) and FormatIsUncompressed(InternalFormat) then begin - pSource := Data; - - GetMem(pDest, fRowSize); - try - pTempDest := pDest; - - Inc(pTempDest, fRowSize); - for Col := 0 to Width -1 do begin - Move(pSource^, pTempDest^, fPixelSize); - - Inc(pSource, fPixelSize); - Dec(pTempDest, fPixelSize); - end; - - SetDataPointer(pDest, InternalFormat); - - result := true; - finally - FreeMem(pDest); - end; - end; -end; - - -procedure TglBitmap1D.UploadData (Target, Format, InternalFormat, Typ: Cardinal; BuildWithGlu: Boolean); -begin - // Upload data - if Self.InternalFormat in [ifDXT1, ifDXT3, ifDXT5] then - glCompressedTexImage1D(Target, 0, InternalFormat, Width, 0, Trunc(Width * FormatGetSize(Self.InternalFormat)), Data) - else - - // Upload data - if BuildWithGlu then - gluBuild1DMipmaps(Target, InternalFormat, Width, Format, Typ, Data) - else - glTexImage1D(Target, 0, InternalFormat, Width, 0, Format, Typ, Data); - - // Freigeben - if (FreeDataAfterGenTexture) then - FreeData; -end; - - -procedure TglBitmap1D.GenTexture(TestTextureSize: Boolean); -var - BuildWithGlu, TexRec: Boolean; - glFormat, glInternalFormat, glType: Cardinal; - TexSize: Integer; -begin - if Assigned(Data) then begin - // Check Texture Size - if (TestTextureSize) then begin - glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); - - if (Width > TexSize) then - raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); - - TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and - (Target = GL_TEXTURE_RECTANGLE_ARB); - - if not (IsPowerOfTwo (Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then - raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.'); - end; - - CreateId; - - SetupParameters(BuildWithGlu); - SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); - - UploadData(Target, glFormat, glInternalFormat, glType, BuildWithGlu); - - // Infos sammeln - glAreTexturesResident(1, @fID, @fIsResident); - end; -end; - - -procedure TglBitmap1D.AfterConstruction; -begin - inherited; - - Target := GL_TEXTURE_1D; -end; { TglBitmapCubeMap } From 5bce73c91972f2b2974b3cef61b5354f517d6b97 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 19 Nov 2013 19:40:02 +0100 Subject: [PATCH 21/38] * implemented CubeMaps --- glBitmap.pas | 245 ++++++++++++++++++++++----------------------------- 1 file changed, 105 insertions(+), 140 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 0b4d037..513a9e6 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1008,13 +1008,11 @@ type ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap2D = class(TglBitmap) protected - // Bildeinstellungen fLines: array of PByte; - function GetScanline(const aIndex: Integer): Pointer; procedure SetDataPointer(var aData: PByte; const aFormat: TglBitmapFormat; const aWidth: Integer = - 1; const aHeight: Integer = - 1); override; - procedure UploadData(const aBuildWithGlu: Boolean); + procedure UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean); public property Width; property Height; @@ -1033,34 +1031,25 @@ type const aScale: Single = 2; const aUseAlpha: Boolean = false); end; -(* TODO +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapCubeMap = class(TglBitmap2D) protected fGenMode: Integer; - - // Hide GenTexture - procedure GenTexture(TestTextureSize: Boolean = true); reintroduce; + procedure GenTexture(const aTestTextureSize: Boolean = true); reintroduce; public procedure AfterConstruction; override; - - procedure GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean = true); - - procedure Unbind(DisableTexCoordsGen: Boolean = true; DisableTextureUnit: Boolean = true); reintroduce; virtual; - procedure Bind(EnableTexCoordsGen: Boolean = true; EnableTextureUnit: Boolean = true); reintroduce; virtual; + procedure GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean = true); + procedure Bind(const aEnableTexCoordsGen: Boolean = true; const aEnableTextureUnit: Boolean = true); reintroduce; virtual; + procedure Unbind(const aDisableTexCoordsGen: Boolean = true; const aDisableTextureUnit: Boolean = true); reintroduce; virtual; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmapNormalMap = class(TglBitmapCubeMap) public procedure AfterConstruction; override; - - procedure GenerateNormalMap(Size: Integer = 32; TestTextureSize: Boolean = true); + procedure GenerateNormalMap(const aSize: Integer = 32; const aTestTextureSize: Boolean = true); end; - - -*) - const NULL_SIZE: TglBitmapPixelPosition = (Fields: []; X: 0; Y: 0); @@ -7575,7 +7564,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap2D.UploadData(const aBuildWithGlu: Boolean); +procedure TglBitmap2D.UploadData(const aTarget: GLenum; const aBuildWithGlu: Boolean); var FormatDesc: TFormatDescriptor; begin @@ -7583,12 +7572,12 @@ begin FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.IsCompressed then begin - glCompressedTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data) + glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data) end else if aBuildWithGlu then begin - gluBuild2DMipmaps(Target, FormatDesc.Components, Width, Height, + gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height, FormatDesc.glFormat, FormatDesc.glDataFormat, Data) end else begin - glTexImage2D(Target, 0, FormatDesc.glInternalFormat, Width, Height, 0, + glTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data); end; @@ -7694,7 +7683,7 @@ begin CreateId; SetupParameters(BuildWithGlu); - UploadData(BuildWithGlu); + UploadData(Target, BuildWithGlu); glAreTexturesResident(1, @fID, @fIsResident); end; end; @@ -7983,20 +7972,15 @@ begin end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmapCubeMap//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmapCubeMap.GenTexture(const aTestTextureSize: Boolean); +begin + Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.'); +end; - - - - - - - -(* - - - -{ TglBitmapCubeMap } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmapCubeMap.AfterConstruction; begin inherited; @@ -8004,80 +7988,64 @@ begin if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.'); - SetWrap; // set all to GL_CLAMP_TO_EDGE - Target := GL_TEXTURE_CUBE_MAP; + SetWrap; + Target := GL_TEXTURE_CUBE_MAP; fGenMode := GL_REFLECTION_MAP; end; - -procedure TglBitmapCubeMap.Bind(EnableTexCoordsGen, EnableTextureUnit: Boolean); -begin - inherited Bind (EnableTextureUnit); - - if EnableTexCoordsGen then begin - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode); - glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glEnable(GL_TEXTURE_GEN_R); - end; -end; - - -procedure TglBitmapCubeMap.GenerateCubeMap(CubeTarget: Cardinal; TestTextureSize: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmapCubeMap.GenerateCubeMap(const aCubeTarget: Cardinal; const aTestTextureSize: Boolean); var - glFormat, glInternalFormat, glType: Cardinal; BuildWithGlu: Boolean; TexSize: Integer; begin - // Check Texture Size - if (TestTextureSize) then begin + if (aTestTextureSize) then begin glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize); - if ((Height > TexSize) or (Width > TexSize)) then + if (Height > TexSize) or (Width > TexSize) then raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.'); - if not ((IsPowerOfTwo (Height) and IsPowerOfTwo (Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then + if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.'); end; - // create Texture - if ID = 0 then begin + if (ID = 0) then CreateID; - SetupParameters(BuildWithGlu); - end; - - SelectFormat(InternalFormat, glFormat, glInternalFormat, glType); - - UploadData (CubeTarget, glFormat, glInternalFormat, glType, BuildWithGlu); + SetupParameters(BuildWithGlu); + UploadData(aCubeTarget, BuildWithGlu); end; - -procedure TglBitmapCubeMap.GenTexture(TestTextureSize: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmapCubeMap.Bind(const aEnableTexCoordsGen: Boolean; const aEnableTextureUnit: Boolean); begin - Assert(false, 'TglBitmapCubeMap.GenTexture - Don''t call GenTextures directly.'); + inherited Bind (aEnableTextureUnit); + if aEnableTexCoordsGen then begin + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, fGenMode); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, fGenMode); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, fGenMode); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + end; end; - -procedure TglBitmapCubeMap.Unbind(DisableTexCoordsGen, - DisableTextureUnit: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmapCubeMap.Unbind(const aDisableTexCoordsGen: Boolean; const aDisableTextureUnit: Boolean); begin - inherited Unbind (DisableTextureUnit); - - if DisableTexCoordsGen then begin + inherited Unbind(aDisableTextureUnit); + if aDisableTexCoordsGen then begin glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_GEN_R); end; end; - -{ TglBitmapNormalMap } - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmapNormalMap////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// type TVec = Array[0..2] of Single; - TglBitmapNormalMapGetVectorFunc = procedure (var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); + TglBitmapNormalMapGetVectorFunc = procedure (out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); PglBitmapNormalMapRec = ^TglBitmapNormalMapRec; TglBitmapNormalMapRec = record @@ -8085,62 +8053,63 @@ type Func: TglBitmapNormalMapGetVectorFunc; end; - -procedure glBitmapNormalMapPosX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapPosX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := HalfSize; - Vec[1] := - (Position.Y + 0.5 - HalfSize); - Vec[2] := - (Position.X + 0.5 - HalfSize); + aVec[0] := aHalfSize; + aVec[1] := - (aPosition.Y + 0.5 - aHalfSize); + aVec[2] := - (aPosition.X + 0.5 - aHalfSize); end; - -procedure glBitmapNormalMapNegX(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapNegX(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := - HalfSize; - Vec[1] := - (Position.Y + 0.5 - HalfSize); - Vec[2] := Position.X + 0.5 - HalfSize; + aVec[0] := - aHalfSize; + aVec[1] := - (aPosition.Y + 0.5 - aHalfSize); + aVec[2] := aPosition.X + 0.5 - aHalfSize; end; - -procedure glBitmapNormalMapPosY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapPosY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := Position.X + 0.5 - HalfSize; - Vec[1] := HalfSize; - Vec[2] := Position.Y + 0.5 - HalfSize; + aVec[0] := aPosition.X + 0.5 - aHalfSize; + aVec[1] := aHalfSize; + aVec[2] := aPosition.Y + 0.5 - aHalfSize; end; - -procedure glBitmapNormalMapNegY(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapNegY(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := Position.X + 0.5 - HalfSize; - Vec[1] := - HalfSize; - Vec[2] := - (Position.Y + 0.5 - HalfSize); + aVec[0] := aPosition.X + 0.5 - aHalfSize; + aVec[1] := - aHalfSize; + aVec[2] := - (aPosition.Y + 0.5 - aHalfSize); end; - -procedure glBitmapNormalMapPosZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapPosZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := Position.X + 0.5 - HalfSize; - Vec[1] := - (Position.Y + 0.5 - HalfSize); - Vec[2] := HalfSize; + aVec[0] := aPosition.X + 0.5 - aHalfSize; + aVec[1] := - (aPosition.Y + 0.5 - aHalfSize); + aVec[2] := aHalfSize; end; - -procedure glBitmapNormalMapNegZ(var Vec: TVec; const Position: TglBitmapPixelPosition; const HalfSize: Integer); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapNormalMapNegZ(out aVec: TVec; const aPosition: TglBitmapPixelPosition; const aHalfSize: Integer); begin - Vec[0] := - (Position.X + 0.5 - HalfSize); - Vec[1] := - (Position.Y + 0.5 - HalfSize); - Vec[2] := - HalfSize; + aVec[0] := - (aPosition.X + 0.5 - aHalfSize); + aVec[1] := - (aPosition.Y + 0.5 - aHalfSize); + aVec[2] := - aHalfSize; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure glBitmapNormalMapFunc(var FuncRec: TglBitmapFunctionRec); var - Vec : TVec; + i: Integer; + Vec: TVec; Len: Single; begin with FuncRec do begin - with PglBitmapNormalMapRec (CustomData)^ do begin + with PglBitmapNormalMapRec(Args)^ do begin Func(Vec, Position, HalfSize); // Normalize @@ -8158,66 +8127,62 @@ begin end; // Set Color - Dest.Red := Round(Vec[0] * 255); - Dest.Green := Round(Vec[1] * 255); - Dest.Blue := Round(Vec[2] * 255); + for i := 0 to 2 do + Dest.Data.arr[i] := Round(Vec[i] * 255); end; end; - +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmapNormalMap.AfterConstruction; begin inherited; - fGenMode := GL_NORMAL_MAP; end; - -procedure TglBitmapNormalMap.GenerateNormalMap(Size: Integer; - TestTextureSize: Boolean); +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmapNormalMap.GenerateNormalMap(const aSize: Integer; const aTestTextureSize: Boolean); var Rec: TglBitmapNormalMapRec; SizeRec: TglBitmapPixelPosition; begin - Rec.HalfSize := Size div 2; - + Rec.HalfSize := aSize div 2; FreeDataAfterGenTexture := false; SizeRec.Fields := [ffX, ffY]; - SizeRec.X := Size; - SizeRec.Y := Size; + SizeRec.X := aSize; + SizeRec.Y := aSize; // Positive X Rec.Func := glBitmapNormalMapPosX; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_X, aTestTextureSize); // Negative X Rec.Func := glBitmapNormalMapNegX; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, aTestTextureSize); // Positive Y Rec.Func := glBitmapNormalMapPosY; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, aTestTextureSize); // Negative Y Rec.Func := glBitmapNormalMapNegY; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, aTestTextureSize); // Positive Z Rec.Func := glBitmapNormalMapPosZ; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, aTestTextureSize); // Negative Z Rec.Func := glBitmapNormalMapNegZ; - LoadFromFunc (SizeRec, glBitmapNormalMapFunc, ifBGR8, @Rec); - GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, TestTextureSize); + LoadFromFunc(SizeRec, glBitmapNormalMapFunc, tfBGR8, @Rec); + GenerateCubeMap(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, aTestTextureSize); end; -*) + initialization glBitmapSetDefaultFormat(tfEmpty); From 370c0fbe8e0f0c44042cb08e367521e3a73097f4 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Tue, 19 Nov 2013 20:34:00 +0100 Subject: [PATCH 22/38] * added Swizzle Support * updated native OpenGL Support --- glBitmap.pas | 276 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 184 insertions(+), 92 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 513a9e6..675d5f9 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -375,21 +375,19 @@ unit glBitmap; interface uses - {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} + {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} {$IF DEFINED(GLB_WIN) AND - DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} + DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} - {$IFDEF GLB_SDL} SDL, {$ENDIF} - {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF} - {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} + {$IFDEF GLB_SDL} SDL, {$ENDIF} + {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} - {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} - - {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} - {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} - - {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} - {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} + {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} + {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} + {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} + {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} Classes, SysUtils; @@ -398,6 +396,9 @@ const GL_TRUE = 1; GL_FALSE = 0; + GL_ZERO = 0; + GL_ONE = 1; + GL_VERSION = $1F02; GL_EXTENSIONS = $1F03; @@ -405,9 +406,34 @@ const GL_TEXTURE_2D = $0DE1; GL_TEXTURE_RECTANGLE = $84F5; + GL_NORMAL_MAP = $8511; + GL_TEXTURE_CUBE_MAP = $8513; + GL_REFLECTION_MAP = $8512; + GL_TEXTURE_CUBE_MAP_POSITIVE_X = $8515; + GL_TEXTURE_CUBE_MAP_NEGATIVE_X = $8516; + GL_TEXTURE_CUBE_MAP_POSITIVE_Y = $8517; + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = $8518; + GL_TEXTURE_CUBE_MAP_POSITIVE_Z = $8519; + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = $851A; + GL_TEXTURE_WIDTH = $1000; GL_TEXTURE_HEIGHT = $1001; GL_TEXTURE_INTERNAL_FORMAT = $1003; + GL_TEXTURE_SWIZZLE_RGBA = $8E46; + + GL_S = $2000; + GL_T = $2001; + GL_R = $2002; + GL_Q = $2003; + + GL_TEXTURE_GEN_S = $0C60; + GL_TEXTURE_GEN_T = $0C61; + GL_TEXTURE_GEN_R = $0C62; + GL_TEXTURE_GEN_Q = $0C63; + + GL_RED = $1903; + GL_GREEN = $1904; + GL_BLUE = $1905; GL_ALPHA = $1906; GL_ALPHA4 = $803B; @@ -509,6 +535,8 @@ const GL_TEXTURE_MAX_ANISOTROPY_EXT = $84FE; GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = $84FF; + GL_MAX_CUBE_MAP_TEXTURE_SIZE = $851C; + GL_TEXTURE_GEN_MODE = $2500; {$IF DEFINED(GLB_WIN)} libglu = 'glu32.dll'; @@ -551,12 +579,14 @@ type TglGetIntegerv = procedure(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglTexParameteri = procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglTexParameteriv = procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglTexParameterfv = procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGetTexParameteriv = procedure(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGetTexParameterfv = procedure(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGetTexLevelParameteriv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGetTexLevelParameterfv = procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} + TglTexGeni = procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglGenTextures = procedure(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglBindTexture = procedure(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} TglDeleteTextures = procedure(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} @@ -580,12 +610,14 @@ type procedure glGetIntegerv(pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glTexParameteriv(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glTexParameterfv(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glGetTexParameteriv(target: GLenum; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glGetTexParameterfv(target: GLenum; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glGetTexLevelParameteriv(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glGetTexLevelParameterfv(target: GLenum; level: GLint; pname: GLenum; params: PGLfloat); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; + procedure glTexGeni(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glGenTextures(n: GLsizei; textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glBindTexture(target: GLenum; texture: GLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; procedure glDeleteTextures(n: GLsizei; const textures: PGLuint); {$IFDEF GLB_WIN}stdcall; {$ELSE}cdecl; {$ENDIF} external libopengl; @@ -607,6 +639,7 @@ var GL_VERSION_1_3, GL_VERSION_1_4, GL_VERSION_2_0, + GL_VERSION_3_3, GL_SGIS_generate_mipmap, @@ -614,6 +647,8 @@ var GL_ARB_texture_mirrored_repeat, GL_ARB_texture_rectangle, GL_ARB_texture_non_power_of_two, + GL_ARB_texture_swizzle, + GL_ARB_texture_cube_map, GL_IBM_texture_mirrored_repeat, @@ -621,6 +656,8 @@ var GL_EXT_texture_edge_clamp, GL_EXT_texture_rectangle, + GL_EXT_texture_swizzle, + GL_EXT_texture_cube_map, GL_EXT_texture_filter_anisotropic: Boolean; glCompressedTexImage1D: TglCompressedTexImage1D; @@ -642,12 +679,14 @@ var glGetIntegerv: TglGetIntegerv; glTexParameteri: TglTexParameteri; + glTexParameteriv: TglTexParameteriv; glTexParameterfv: TglTexParameterfv; glGetTexParameteriv: TglGetTexParameteriv; glGetTexParameterfv: TglGetTexParameterfv; glGetTexLevelParameteriv: TglGetTexLevelParameteriv; glGetTexLevelParameterfv: TglGetTexLevelParameterfv; + glTexGeni: TglTexGeni; glGenTextures: TglGenTextures; glBindTexture: TglBindTexture; glDeleteTextures: TglDeleteTextures; @@ -749,10 +788,11 @@ type nm5x5); //////////////////////////////////////////////////////////////////////////////////////////////////// - EglBitmapException = class(Exception); - EglBitmapSizeToLargeException = class(EglBitmapException); - EglBitmapNonPowerOfTwoException = class(EglBitmapException); - EglBitmapUnsupportedFormat = class(EglBitmapException) + EglBitmap = class(Exception); + EglBitmapNotSupported = class(Exception); + EglBitmapSizeToLarge = class(EglBitmap); + EglBitmapNonPowerOfTwo = class(EglBitmap); + EglBitmapUnsupportedFormat = class(EglBitmap) constructor Create(const aFormat: TglBitmapFormat); overload; constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload; end; @@ -811,13 +851,16 @@ type fRowSize: Integer; // Filtering - fFilterMin: Cardinal; - fFilterMag: Cardinal; + fFilterMin: GLenum; + fFilterMag: GLenum; // TexturWarp - fWrapS: Cardinal; - fWrapT: Cardinal; - fWrapR: Cardinal; + fWrapS: GLenum; + fWrapT: GLenum; + fWrapR: GLenum; + + //Swizzle + fSwizzle: array[0..3] of GLenum; // CustomData fFilename: String; @@ -958,11 +1001,12 @@ type procedure FillWithColorFloat(const aRed, aGreen, aBlue: Single; const aAlpha : Single = 1); //TexParameters - procedure SetFilter(const aMin, aMag: Cardinal); + procedure SetFilter(const aMin, aMag: GLenum); procedure SetWrap( - const S: Cardinal = GL_CLAMP_TO_EDGE; - const T: Cardinal = GL_CLAMP_TO_EDGE; - const R: Cardinal = GL_CLAMP_TO_EDGE); + const S: GLenum = GL_CLAMP_TO_EDGE; + const T: GLenum = GL_CLAMP_TO_EDGE; + const R: GLenum = GL_CLAMP_TO_EDGE); + procedure SetSwizzle(const r, g, b, a: GLenum); procedure Bind(const aEnableTextureUnit: Boolean = true); virtual; procedure Unbind(const aDisableTextureUnit: Boolean = true); virtual; @@ -1084,6 +1128,7 @@ var glBitmapDefaultWrapS: Cardinal; glBitmapDefaultWrapT: Cardinal; glBitmapDefaultWrapR: Cardinal; + glDefaultSwizzle: array[0..3] of GLenum; {$IFDEF GLB_DELPHI} function CreateGrayPalette: HPALETTE; @@ -1839,7 +1884,7 @@ begin result := dlsym(aLibHandle, aProcName); {$IFEND} if not Assigned(result) then - raise EglBitmapException.Create('unable to load procedure form library: ' + aProcName); + raise EglBitmap.Create('unable to load procedure form library: ' + aProcName); end; {$IFDEF GLB_NATIVE_OGL_DYNAMIC} @@ -1886,11 +1931,11 @@ begin GL_LibHandle := glbLoadLibrary(libopengl); if not Assigned(GL_LibHandle) then - raise EglBitmapException.Create('unable to load library: ' + libopengl); + raise EglBitmap.Create('unable to load library: ' + libopengl); GLU_LibHandle := glbLoadLibrary(libglu); if not Assigned(GLU_LibHandle) then - raise EglBitmapException.Create('unable to load library: ' + libglu); + raise EglBitmap.Create('unable to load library: ' + libglu); try {$IF DEFINED(GLB_WIN)} @@ -1905,11 +1950,13 @@ begin glGetString := glbGetProcAddress('glGetString'); glGetIntegerv := glbGetProcAddress('glGetIntegerv'); glTexParameteri := glbGetProcAddress('glTexParameteri'); + glTexParameteriv := glbGetProcAddress('glTexParameteriv'); glTexParameterfv := glbGetProcAddress('glTexParameterfv'); glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv'); glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv'); glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv'); glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv'); + glTexGeni := glbGetProcAddress('glTexGeni'); glGenTextures := glbGetProcAddress('glGenTextures'); glBindTexture := glbGetProcAddress('glBindTexture'); glDeleteTextures := glbGetProcAddress('glDeleteTextures'); @@ -1977,6 +2024,12 @@ var result := ((ExtPos + Length(Extension) - 1) = Length(Buffer)) or not (Buffer[ExtPos + Length(Extension)] in ['_', 'A'..'Z', 'a'..'z']); end; + /////////////////////////////////////////////////////////////////////////////////////////// + function CheckVersion(const aMajor, aMinor: Integer): Boolean; + begin + result := (MajorVersion > aMajor) or ((MajorVersion = aMajor) and (MinorVersion >= aMinor)); + end; + begin {$IFDEF GLB_NATIVE_OGL_DYNAMIC} InitOpenGLCS.Enter; @@ -1994,35 +2047,25 @@ begin Buffer := glGetString(GL_VERSION); TrimVersionString(Buffer, MajorVersion, MinorVersion); - GL_VERSION_1_2 := false; - GL_VERSION_1_3 := false; - GL_VERSION_1_4 := false; - GL_VERSION_2_0 := false; - if MajorVersion = 1 then begin - if MinorVersion >= 2 then - GL_VERSION_1_2 := true; - - if MinorVersion >= 3 then - GL_VERSION_1_3 := true; - - if MinorVersion >= 4 then - GL_VERSION_1_4 := true; - end else if MajorVersion >= 2 then begin - GL_VERSION_1_2 := true; - GL_VERSION_1_3 := true; - GL_VERSION_1_4 := true; - GL_VERSION_2_0 := true; - end; + GL_VERSION_1_2 := CheckVersion(1, 2); + GL_VERSION_1_3 := CheckVersion(1, 3); + GL_VERSION_1_4 := CheckVersion(1, 4); + GL_VERSION_2_0 := CheckVersion(2, 0); + GL_VERSION_3_3 := CheckVersion(3, 3); // Extensions Buffer := glGetString(GL_EXTENSIONS); GL_ARB_texture_border_clamp := CheckExtension('GL_ARB_texture_border_clamp'); GL_ARB_texture_non_power_of_two := CheckExtension('GL_ARB_texture_non_power_of_two'); + GL_ARB_texture_swizzle := CheckExtension('GL_ARB_texture_swizzle'); + GL_ARB_texture_cube_map := CheckExtension('GL_ARB_texture_cube_map'); GL_ARB_texture_rectangle := CheckExtension('GL_ARB_texture_rectangle'); GL_ARB_texture_mirrored_repeat := CheckExtension('GL_ARB_texture_mirrored_repeat'); GL_EXT_texture_edge_clamp := CheckExtension('GL_EXT_texture_edge_clamp'); GL_EXT_texture_filter_anisotropic := CheckExtension('GL_EXT_texture_filter_anisotropic'); GL_EXT_texture_rectangle := CheckExtension('GL_EXT_texture_rectangle'); + GL_EXT_texture_swizzle := CheckExtension('GL_EXT_texture_swizzle'); + GL_EXT_texture_cube_map := CheckExtension('GL_EXT_texture_cube_map'); GL_NV_texture_rectangle := CheckExtension('GL_NV_texture_rectangle'); GL_IBM_texture_mirrored_repeat := CheckExtension('GL_IBM_texture_mirrored_repeat'); GL_SGIS_generate_mipmap := CheckExtension('GL_SGIS_generate_mipmap'); @@ -2117,6 +2160,15 @@ begin glBitmapDefaultWrapR := R; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapSetDefaultSwizzle(const r: GLenum = GL_RED; g: GLenum = GL_GREEN; b: GLenum = GL_BLUE; a: GLenum = GL_ALPHA); +begin + glDefaultSwizzle[0] := r; + glDefaultSwizzle[1] := g; + glDefaultSwizzle[2] := b; + glDefaultSwizzle[3] := a; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function glBitmapGetDefaultDeleteTextureOnFree: Boolean; begin @@ -2142,20 +2194,29 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure glBitmapGetDefaultFilter(var aMin, aMag: Cardinal); +procedure glBitmapGetDefaultFilter(var aMin, aMag: GLenum); begin aMin := glBitmapDefaultFilterMin; aMag := glBitmapDefaultFilterMag; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure glBitmapGetDefaultTextureWrap(var S, T, R: Cardinal); +procedure glBitmapGetDefaultTextureWrap(var S, T, R: GLenum); begin S := glBitmapDefaultWrapS; T := glBitmapDefaultWrapT; R := glBitmapDefaultWrapR; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure glBitmapGetDefaultSwizzle(var r, g, b, a: GLenum); +begin + r := glDefaultSwizzle[0]; + g := glDefaultSwizzle[1]; + b := glDefaultSwizzle[2]; + a := glDefaultSwizzle[3]; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -2244,7 +2305,7 @@ function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlp begin result := false; if (aRedMask = 0) and (aGreenMask = 0) and (aBlueMask = 0) and (aAlphaMask = 0) then - raise EglBitmapException.Create('FormatCheckFormat - All Masks are 0'); + raise EglBitmap.Create('FormatCheckFormat - All Masks are 0'); if (aRedMask <> RedMask) then exit; if (aGreenMask <> GreenMask) then @@ -3445,12 +3506,12 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TfdS3tcDtx1RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; procedure TfdS3tcDtx1RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; constructor TfdS3tcDtx1RGBA.Create; @@ -3471,12 +3532,12 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TfdS3tcDtx3RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; procedure TfdS3tcDtx3RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; constructor TfdS3tcDtx3RGBA.Create; @@ -3497,12 +3558,12 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TfdS3tcDtx5RGBA.Map(const aPixel: TglBitmapPixelData; var aData: PByte; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; procedure TfdS3tcDtx5RGBA.Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); begin - raise EglBitmapException.Create('mapping for compressed formats is not supported'); + raise EglBitmap.Create('mapping for compressed formats is not supported'); end; constructor TfdS3tcDtx5RGBA.Create; @@ -3635,7 +3696,7 @@ begin 4: PCardinal(aData)^ := data; 8: PQWord(aData)^ := data; else - raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); + raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; inc(aData, s); end; @@ -3653,7 +3714,7 @@ begin 4: data := PCardinal(aData)^; 8: data := PQWord(aData)^; else - raise EglBitmapException.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); + raise EglBitmap.CreateFmt('invalid pixel size: %.1f', [fPixelSize]); end; for i := 0 to 3 do aPixel.Data.arr[i] := (data shr fShift.arr[i]) and fRange.arr[i]; @@ -3668,7 +3729,7 @@ var i: Integer; begin if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then - raise EglBitmapException.Create(UNSUPPORTED_FORMAT); + raise EglBitmap.Create(UNSUPPORTED_FORMAT); if (Format = tfLuminance4) then SetLength(fColorTable, 16) @@ -3711,7 +3772,7 @@ var d: Byte; begin if not (Format in [tfLuminance4, tfLuminance8, tfR3G3B2]) then - raise EglBitmapException.Create(UNSUPPORTED_FORMAT); + raise EglBitmap.Create(UNSUPPORTED_FORMAT); case Format of tfLuminance4: begin @@ -3759,10 +3820,10 @@ begin 4: idx := PCardinal(aData)^; 8: idx := PQWord(aData)^; else - raise EglBitmapException.CreateFmt('invalid pixel size: %.3f', [fPixelSize]); + raise EglBitmap.CreateFmt('invalid pixel size: %.3f', [fPixelSize]); end; if (idx >= Length(fColorTable)) then - raise EglBitmapException.CreateFmt('invalid color index: %d', [idx]); + raise EglBitmap.CreateFmt('invalid color index: %d', [idx]); with fColorTable[idx] do begin aPixel.Data.r := r; aPixel.Data.g := g; @@ -4087,6 +4148,9 @@ begin SetAnisotropic(fAnisotropic); SetBorderColor(fBorderColor[0], fBorderColor[1], fBorderColor[2], fBorderColor[3]); + if (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then + SetSwizzle(fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]); + // Mip Maps Generation Mode aBuildWithGlu := false; if (MipMap = mmMipmap) then begin @@ -4163,6 +4227,7 @@ begin glBitmapGetDefaultFilter (fFilterMin, fFilterMag); glBitmapGetDefaultTextureWrap(fWrapS, fWrapT, fWrapR); + glBitmapGetDefaultSwizzle (fSwizzle[0], fSwizzle[1], fSwizzle[2], fSwizzle[3]); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -4195,7 +4260,7 @@ var fs: TFileStream; begin if not FileExists(aFilename) then - raise EglBitmapException.Create('file does not exist: ' + aFilename); + raise EglBitmap.Create('file does not exist: ' + aFilename); fFilename := aFilename; fs := TFileStream.Create(fFilename, fmOpenRead); try @@ -4218,7 +4283,7 @@ begin if not LoadDDS(aStream) then if not LoadTGA(aStream) then if not LoadBMP(aStream) then - raise EglBitmapException.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.'); + raise EglBitmap.Create('LoadFromStream - Couldn''t load Stream. It''s possible to be an unknow Streamtype.'); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5293,7 +5358,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SetFilter(const aMin, aMag: Cardinal); +procedure TglBitmap.SetFilter(const aMin, aMag: GLenum); begin //check MIN filter case aMin of @@ -5310,7 +5375,7 @@ begin GL_LINEAR_MIPMAP_LINEAR: fFilterMin := GL_LINEAR_MIPMAP_LINEAR; else - raise EglBitmapException.Create('SetFilter - Unknow MIN filter.'); + raise EglBitmap.Create('SetFilter - Unknow MIN filter.'); end; //check MAG filter @@ -5320,7 +5385,7 @@ begin GL_LINEAR: fFilterMag := GL_LINEAR; else - raise EglBitmapException.Create('SetFilter - Unknow MAG filter.'); + raise EglBitmap.Create('SetFilter - Unknow MAG filter.'); end; //apply filter @@ -5343,7 +5408,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardinal); +procedure TglBitmap.SetWrap(const S: GLenum; const T: GLenum; const R: GLenum); procedure CheckAndSetWrap(const aValue: Cardinal; var aTarget: Cardinal); begin @@ -5372,10 +5437,10 @@ procedure TglBitmap.SetWrap(const S: Cardinal; const T: Cardinal; const R: Cardi if GL_VERSION_1_4 or GL_ARB_texture_mirrored_repeat or GL_IBM_texture_mirrored_repeat then aTarget := GL_MIRRORED_REPEAT else - raise EglBitmapException.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).'); + raise EglBitmap.Create('SetWrap - Unsupported Texturewrap GL_MIRRORED_REPEAT (S).'); end; else - raise EglBitmapException.Create('SetWrap - Unknow Texturewrap (S).'); + raise EglBitmap.Create('SetWrap - Unknow Texturewrap'); end; end; @@ -5392,6 +5457,32 @@ begin end; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetSwizzle(const r, g, b, a: GLenum); + + procedure CheckAndSetValue(const aValue: GLenum; const aIndex: Integer); + begin + if (aValue = GL_ZERO) or (aValue = GL_ONE) or (aValue = GL_ALPHA) or + (aValue = GL_RED) or (aValue = GL_GREEN) or (aValue = GL_BLUE) then + fSwizzle[aIndex] := aValue + else + raise EglBitmap.Create('SetSwizzle - Unknow Swizle Value'); + end; + +begin + if not (GL_ARB_texture_swizzle or GL_EXT_texture_swizzle or GL_VERSION_3_3) then + raise EglBitmapNotSupported.Create('texture swizzle is not supported'); + CheckAndSetValue(r, 0); + CheckAndSetValue(g, 1); + CheckAndSetValue(b, 2); + CheckAndSetValue(a, 3); + + if (ID > 0) then begin + Bind(false); + glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]); + end; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.Bind(const aEnableTextureUnit: Boolean); begin @@ -5413,7 +5504,7 @@ end; constructor TglBitmap.Create; begin if (ClassType = TglBitmap) then - raise EglBitmapException.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); + raise EglBitmap.Create('Don''t create TglBitmap directly. Use one of the deviated classes (TglBitmap2D) instead.'); {$IFDEF GLB_NATIVE_OGL} glbReadOpenGLExtensions; {$ENDIF} @@ -6373,7 +6464,7 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean; case aInfo.biCompression of BMP_COMP_RLE4, BMP_COMP_RLE8: begin - raise EglBitmapException.Create('RLE compression is not supported'); + raise EglBitmap.Create('RLE compression is not supported'); end; BMP_COMP_BITFIELDS: begin if (aInfo.biBitCount = 16) or (aInfo.biBitCount = 32) then begin @@ -6382,7 +6473,7 @@ function TglBitmap.LoadBMP(const aStream: TStream): Boolean; aStream.Read(aMask.b, SizeOf(aMask.b)); aStream.Read(aMask.a, SizeOf(aMask.a)); end else - raise EglBitmapException.Create('Bitfields are only supported for 16bit and 32bit formats'); + raise EglBitmap.Create('Bitfields are only supported for 16bit and 32bit formats'); end; end; @@ -6551,7 +6642,7 @@ begin raise; end; end else - raise EglBitmapException.Create('LoadBMP - No suitable format found'); + raise EglBitmap.Create('LoadBMP - No suitable format found'); except aStream.Position := StartPos; raise; @@ -6989,7 +7080,7 @@ begin end; if (tgaFormat = tfEmpty) then - raise EglBitmapException.Create('LoadTga - unsupported format'); + raise EglBitmap.Create('LoadTga - unsupported format'); FormatDesc := TFormatDescriptor.Get(tgaFormat); PixelSize := FormatDesc.GetSize(1, 1); @@ -7099,11 +7190,11 @@ begin Size := FormatDesc.GetSize(Dimension); if Format in [tfRGB5, tfRGB5A1, tfRGBA4, tfRGB8, tfRGB10A2, tfRGBA8] then begin if (FormatDesc.RGBInverted = tfEmpty) then - raise EglBitmapException.Create('inverted RGB format is empty'); + raise EglBitmap.Create('inverted RGB format is empty'); Converter := TFormatDescriptor.Get(FormatDesc.RGBInverted); if not glBitmapColorRecCmp(Converter.Range, FormatDesc.Range) or (Converter.PixelSize <> FormatDesc.PixelSize) then - raise EglBitmapException.Create('invalid inverted RGB format'); + raise EglBitmap.Create('invalid inverted RGB format'); end; if Assigned(Converter) then begin @@ -7295,12 +7386,12 @@ begin end; if ((Header.Caps.dwCaps1 and DDSCAPS2_CUBEMAP) > 0) then - raise EglBitmapException.Create('LoadDDS - CubeMaps are not supported'); + raise EglBitmap.Create('LoadDDS - CubeMaps are not supported'); ddsFormat := GetDDSFormat; try if (ddsFormat = tfEmpty) then - raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.'); FormatDesc := TFormatDescriptor.Get(ddsFormat); LineSize := Trunc(Header.dwWidth * FormatDesc.PixelSize); @@ -7350,7 +7441,7 @@ begin Inc(TmpData, LineSize); end; end else - raise EglBitmapException.Create('LoadDDS - unsupported Pixelformat found.'); + raise EglBitmap.Create('LoadDDS - unsupported Pixelformat found.'); SetDataPointer(NewImage, ddsFormat, Header.dwWidth, Header.dwHeight); //be careful, Data could be freed by this method result := true; @@ -7505,12 +7596,12 @@ begin glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); if (Width > TexSize) then - raise EglBitmapSizeToLargeException.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); + raise EglBitmapSizeToLarge.Create('TglBitmap1D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and - (Target = GL_TEXTURE_RECTANGLE_ARB); + (Target = GL_TEXTURE_RECTANGLE); if not (IsPowerOfTwo(Width) or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then - raise EglBitmapNonPowerOfTwoException.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.'); + raise EglBitmapNonPowerOfTwo.Create('TglBitmap1D.GenTexture - Rendercontex dosn''t support non power of two texture.'); end; CreateId; @@ -7673,12 +7764,12 @@ begin glGetIntegerv(GL_MAX_TEXTURE_SIZE, @TexSize); if ((Height > TexSize) or (Width > TexSize)) then - raise EglBitmapSizeToLargeException.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); + raise EglBitmapSizeToLarge.Create('TglBitmap2D.GenTexture - The size for the texture is to large. It''s may be not conform with the Hardware.'); PotTex := IsPowerOfTwo(Height) and IsPowerOfTwo(Width); TexRec := (GL_ARB_texture_rectangle or GL_EXT_texture_rectangle or GL_NV_texture_rectangle) and (Target = GL_TEXTURE_RECTANGLE); if not (PotTex or GL_ARB_texture_non_power_of_two or GL_VERSION_2_0 or TexRec) then - raise EglBitmapNonPowerOfTwoException.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); + raise EglBitmapNonPowerOfTwo.Create('TglBitmap2D.GenTexture - Rendercontex dosn''t support non power of two texture.'); end; CreateId; @@ -7986,7 +8077,7 @@ begin inherited; if not (GL_VERSION_1_3 or GL_ARB_texture_cube_map or GL_EXT_texture_cube_map) then - raise EglBitmapException.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.'); + raise EglBitmap.Create('TglBitmapCubeMap.AfterConstruction - CubeMaps are unsupported.'); SetWrap; Target := GL_TEXTURE_CUBE_MAP; @@ -8003,10 +8094,10 @@ begin glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, @TexSize); if (Height > TexSize) or (Width > TexSize) then - raise EglBitmapSizeToLargeException.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.'); + raise EglBitmapSizeToLarge.Create('TglBitmapCubeMap.GenTexture - The size for the Cubemap is to large. It''s may be not conform with the Hardware.'); if not ((IsPowerOfTwo(Height) and IsPowerOfTwo(Width)) or GL_VERSION_2_0 or GL_ARB_texture_non_power_of_two) then - raise EglBitmapNonPowerOfTwoException.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.'); + raise EglBitmapNonPowerOfTwo.Create('TglBitmapCubeMap.GenTexture - Cubemaps dosn''t support non power of two texture.'); end; if (ID = 0) then @@ -8185,10 +8276,11 @@ end; initialization - glBitmapSetDefaultFormat(tfEmpty); - glBitmapSetDefaultMipmap(mmMipmap); - glBitmapSetDefaultFilter(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); - glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + glBitmapSetDefaultFormat (tfEmpty); + glBitmapSetDefaultMipmap (mmMipmap); + glBitmapSetDefaultFilter (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR); + glBitmapSetDefaultWrap (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); + glBitmapSetDefaultSwizzle(GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA); glBitmapSetDefaultFreeDataAfterGenTexture(true); glBitmapSetDefaultDeleteTextureOnFree (true); From e406e4032c083428590a055600e5946e892674d4 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 21 Nov 2013 20:28:44 +0100 Subject: [PATCH 23/38] * moved parts from TFormatDescriptor to public abstract class to get information outside of glBitmap --- glBitmap.pas | 100 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 23 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 675d5f9..1a2f7d6 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -2,7 +2,7 @@ glBitmap by Steffen Xonna aka Lossy eX (2003-2008) http://www.opengl24.de/index.php?cat=header&file=glbitmap -modified by Delphi OpenGL Community (http://delphigl.com/) +modified by Delphi OpenGL Community (http://delphigl.com/) (2013) ------------------------------------------------------------ The contents of this file are used with permission, subject to @@ -11,9 +11,11 @@ not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html ------------------------------------------------------------ -Version 2.0.3 +Version 3.0.0 unstable ------------------------------------------------------------ History +20-11-2013 +- refactoring of the complete library 21-03-2010 - The define GLB_DELPHI dosn't check versions anymore. If you say you are using delphi then it's your problem if that isn't true. This prevents the unit for incompatibility @@ -818,6 +820,23 @@ type Y : Word; end; + TglBitmapFormatDescriptor = class(TObject) + protected + function GetIsCompressed: Boolean; virtual; abstract; + function GetHasAlpha: Boolean; virtual; abstract; + + function GetglDataFormat: GLenum; virtual; abstract; + function GetglFormat: GLenum; virtual; abstract; + function GetglInternalFormat: GLenum; virtual; abstract; + public + property IsCompressed: Boolean read GetIsCompressed; + property HasAlpha: Boolean read GetHasAlpha; + + property glFormat: GLenum read GetglFormat; + property glInternalFormat: GLenum read GetglInternalFormat; + property glDataFormat: GLenum read GetglDataFormat; + end; + //////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class; TglBitmapFunctionRec = record @@ -832,6 +851,8 @@ type ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TglBitmap = class + private + function GetFormatDesc: TglBitmapFormatDescriptor; protected fID: GLuint; fTarget: GLuint; @@ -909,6 +930,8 @@ type property MipMap: TglBitmapMipMap read fMipMap write SetMipMap; property Anisotropic: Integer read fAnisotropic write SetAnisotropic; + property FormatDesc: TglBitmapFormatDescriptor read GetFormatDesc; + property Filename: String read fFilename; property CustomName: String read fCustomName write SetCustomName; property CustomNameW: WideString read fCustomNameW write SetCustomNameW; @@ -1155,7 +1178,7 @@ type 1: (arr: array[0..3] of Byte); end; - TFormatDescriptor = class(TObject) + TFormatDescriptor = class(TglBitmapFormatDescriptor) private function GetRedMask: QWord; function GetGreenMask: QWord; @@ -1173,9 +1196,16 @@ type fRange: TglBitmapColorRec; fShift: TShiftRec; - fglFormat: Cardinal; - fglInternalFormat: Cardinal; - fglDataFormat: Cardinal; + fglFormat: GLenum; + fglInternalFormat: GLenum; + fglDataFormat: GLenum; + + function GetIsCompressed: Boolean; override; + function GetHasAlpha: Boolean; override; + + function GetglFormat: GLenum; override; + function GetglInternalFormat: GLenum; override; + function GetglDataFormat: GLenum; override; function GetComponents: Integer; virtual; public @@ -1185,11 +1215,6 @@ 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; - property glDataFormat: Cardinal read fglDataFormat; property Range: TglBitmapColorRec read fRange; property Shift: TShiftRec read fShift; @@ -1209,7 +1234,6 @@ type procedure FreeMappingData(var aMappingData: Pointer); virtual; function IsEmpty: Boolean; virtual; - function HasAlpha: Boolean; virtual; function MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; virtual; procedure PreparePixel(out aPixel: TglBitmapPixelData); virtual; @@ -2243,6 +2267,36 @@ begin result := fRange.a shl fShift.a; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetIsCompressed: Boolean; +begin + result := fIsCompressed; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetHasAlpha: Boolean; +begin + result := (fRange.a > 0); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetglFormat: GLenum; +begin + result := fglFormat; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetglInternalFormat: GLenum; +begin + result := fglInternalFormat; +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetglDataFormat: GLenum; +begin + result := fglDataFormat; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TFormatDescriptor.GetComponents: Integer; var @@ -2294,12 +2348,6 @@ begin result := (fFormat = tfEmpty); end; -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TFormatDescriptor.HasAlpha: Boolean; -begin - result := (fRange.a > 0); -end; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TFormatDescriptor.MaskMatch(const aRedMask, aGreenMask, aBlueMask, aAlphaMask: QWord): Boolean; begin @@ -4005,6 +4053,12 @@ end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TglBitmap - PROTECTED/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.GetFormatDesc: TglBitmapFormatDescriptor; +begin + result := TFormatDescriptor.Get(Format); +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.GetWidth: Integer; begin @@ -5009,7 +5063,7 @@ function TglBitmap.AddAlphaFromFile(const aFileName: String; const aFunc: TglBit var FS: TFileStream; begin - FS := TFileStream.Create(FileName, fmOpenRead); + FS := TFileStream.Create(aFileName, fmOpenRead); try result := AddAlphaFromStream(FS, aFunc, aArgs); finally @@ -5515,7 +5569,7 @@ end; constructor TglBitmap.Create(const aFileName: String); begin Create; - LoadFromFile(FileName); + LoadFromFile(aFileName); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -7691,9 +7745,9 @@ var Size, w, h: Integer; FormatDesc: TFormatDescriptor; begin - FormatDesc := TFormatDescriptor.Get(Format); + FormatDesc := TFormatDescriptor.Get(aFormat); if FormatDesc.IsCompressed then - raise EglBitmapUnsupportedFormat.Create(Format); + raise EglBitmapUnsupportedFormat.Create(aFormat); w := aRight - aLeft; h := aBottom - aTop; @@ -7702,7 +7756,7 @@ begin try glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(aLeft, aTop, w, h, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp); - SetDataPointer(Temp, Format, w, h); //be careful, Data could be freed by this method + SetDataPointer(Temp, aFormat, w, h); //be careful, Data could be freed by this method FlipVert; except if Assigned(Temp) then From 9dad15b306ffd7460232ddbbe4ffecd7e35bf866 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 21 Nov 2013 21:32:48 +0100 Subject: [PATCH 24/38] * JPEG and PNG support with Lazarus Graphics unit --- glBitmap.pas | 201 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 187 insertions(+), 14 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 1a2f7d6..0221b4d 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -252,6 +252,10 @@ unit glBitmap; +// activate to enable Lazarus TPortableNetworkGraphic support +// if you enable this pngImage and libPNG will be ignored +{$DEFINE GLB_LAZ_PNG} + // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored {.$DEFINE GLB_PNGIMAGE} @@ -262,6 +266,10 @@ unit glBitmap; +// activate to enable Lazarus TJPEGImage support +// if you enable this delphi jpegs and libJPEG will be ignored +{$DEFINE GLB_LAZ_JPEG} + // if you enable delphi jpegs the libJPEG will be ignored {.$DEFINE GLB_DELPHI_JPEG} @@ -306,18 +314,32 @@ unit glBitmap; {$MESSAGE warn 'SDL_image won''t work without SDL. SDL will be activated.'} {$DEFINE GLB_SDL} {$ENDIF} + + {$IFDEF GLB_LAZ_PNG} + {$MESSAGE warn 'The Lazarus TPortableNetworkGraphics will be ignored because you are using SDL_image.'} + {$undef GLB_LAZ_PNG} + {$ENDIF} + {$IFDEF GLB_PNGIMAGE} {$MESSAGE warn 'The unit pngimage will be ignored because you are using SDL_image.'} {$undef GLB_PNGIMAGE} {$ENDIF} + + {$IFDEF GLB_LAZ_JPEG} + {$MESSAGE warn 'The Lazarus TJPEGImage will be ignored because you are using SDL_image.'} + {$undef GLB_LAZ_JPEG} + {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} {$MESSAGE warn 'The unit JPEG will be ignored because you are using SDL_image.'} {$undef GLB_DELPHI_JPEG} {$ENDIF} + {$IFDEF GLB_LIB_PNG} {$MESSAGE warn 'The library libPNG will be ignored because you are using SDL_image.'} {$undef GLB_LIB_PNG} {$ENDIF} + {$IFDEF GLB_LIB_JPEG} {$MESSAGE warn 'The library libJPEG will be ignored because you are using SDL_image.'} {$undef GLB_LIB_JPEG} @@ -327,6 +349,27 @@ unit glBitmap; {$DEFINE GLB_SUPPORT_JPEG_READ} {$ENDIF} +// Lazarus TPortableNetworkGraphic +{$IFDEF GLB_LAZ_PNG} + {$IFNDEF GLB_LAZARUS} + {$MESSAGE warn 'Lazarus TPortableNetworkGraphic won''t work without Lazarus. Lazarus will be activated.'} + {$DEFINE GLB_LAZARUS} + {$ENDIF} + + {$IFDEF GLB_PNGIMAGE} + {$MESSAGE warn 'The pngimage will be ignored if you are using Lazarus TPortableNetworkGraphic.'} + {$undef GLB_PNGIMAGE} + {$ENDIF} + + {$IFDEF GLB_LIB_PNG} + {$MESSAGE warn 'The library libPNG will be ignored if you are using Lazarus TPortableNetworkGraphic.'} + {$undef GLB_LIB_PNG} + {$ENDIF} + + {$DEFINE GLB_SUPPORT_PNG_READ} + {$DEFINE GLB_SUPPORT_PNG_WRITE} +{$ENDIF} + // PNG Image {$IFDEF GLB_PNGIMAGE} {$IFDEF GLB_LIB_PNG} @@ -344,6 +387,27 @@ unit glBitmap; {$DEFINE GLB_SUPPORT_PNG_WRITE} {$ENDIF} +// Lazarus TJPEGImage +{$IFDEF GLB_LAZ_JPEG} + {$IFNDEF GLB_LAZARUS} + {$MESSAGE warn 'Lazarus TJPEGImage won''t work without Lazarus. Lazarus will be activated.'} + {$DEFINE GLB_LAZARUS} + {$ENDIF} + + {$IFDEF GLB_DELPHI_JPEG} + {$MESSAGE warn 'The Delphi JPEGImage will be ignored if you are using the Lazarus TJPEGImage.'} + {$undef GLB_DELPHI_JPEG} + {$ENDIF} + + {$IFDEF GLB_LIB_JPEG} + {$MESSAGE warn 'The library libJPEG will be ignored if you are using the Lazarus TJPEGImage.'} + {$undef GLB_LIB_JPEG} + {$ENDIF} + + {$DEFINE GLB_SUPPORT_JPEG_READ} + {$DEFINE GLB_SUPPORT_JPEG_WRITE} +{$ENDIF} + // JPEG Image {$IFDEF GLB_DELPHI_JPEG} {$IFDEF GLB_LIB_JPEG} @@ -377,19 +441,19 @@ unit glBitmap; interface uses - {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} + {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} {$IF DEFINED(GLB_WIN) AND - DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} + DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} - {$IFDEF GLB_SDL} SDL, {$ENDIF} - {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, {$ENDIF} - {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} + {$IFDEF GLB_SDL} SDL, {$ENDIF} + {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} - {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} - {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} - {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} - {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} - {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} + {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} + {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} + {$IFDEF GLB_LIB_PNG} libPNG, {$ENDIF} + {$IFDEF GLB_DELPHI_JPEG} JPEG, {$ENDIF} + {$IFDEF GLB_LIB_JPEG} libJPEG, {$ENDIF} Classes, SysUtils; @@ -5621,11 +5685,45 @@ begin end; {$IFDEF GLB_SUPPORT_PNG_READ} -{$IF DEFINED(GLB_SDL_IMAGE)} +{$IF DEFINED(GLB_LAZ_PNG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //PNG///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadPNG(const aStream: TStream): Boolean; +var + png: TPortableNetworkGraphic; + intf: TLazIntfImage; + StreamPos: Int64; +begin + result := true; + StreamPos := aStream.Position; + png := TPortableNetworkGraphic.Create; + try try + png.LoadFromStream(aStream); + intf := png.CreateIntfImage; + try try + AssignFromLazIntfImage(intf); + except + result := false; + aStream.Position := StreamPos; + exit; + end; + finally + intf.Free; + end; + except + result := false; + aStream.Position := StreamPos; + exit; + end; + finally + png.Free; + end; +end; + +{$ELSEIF DEFINED(GLB_SDL_IMAGE)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadPNG(const aStream: TStream): Boolean; var Surface: PSDL_Surface; RWops: PSDL_RWops; @@ -5866,7 +5964,27 @@ begin end; {$ENDIF} -{$IF DEFINED(GLB_LIB_PNG)} +{$IF DEFINED(GLB_LAZ_PNG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SavePNG(const aStream: TStream); +var + png: TPortableNetworkGraphic; + intf: TLazIntfImage; +begin + png := TPortableNetworkGraphic.Create; + intf := TLazIntfImage.Create(0, 0); + try + if not AssignToLazIntfImage(intf) then + raise EglBitmap.Create('unable to create LazIntfImage from glBitmap'); + png.LoadFromIntfImage(intf); + png.SaveToStream(aStream); + finally + png.Free; + intf.Free; + end; +end; + +{$ELSEIF DEFINED(GLB_LIB_PNG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SavePNG(const aStream: TStream); var @@ -6156,7 +6274,42 @@ end; {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_READ} -{$IF DEFINED(GLB_SDL_IMAGE)} +{$IF DEFINED(GLB_LAZ_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; +var + jpeg: TJPEGImage; + intf: TLazIntfImage; + StreamPos: Int64; +begin + result := true; + StreamPos := aStream.Position; + jpeg := TJPEGImage.Create; + try try + jpeg.LoadFromStream(aStream); + intf := TLazIntfImage.Create(0, 0); + try try + intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle); + AssignFromLazIntfImage(intf); + except + result := false; + aStream.Position := StreamPos; + exit; + end; + finally + intf.Free; + end; + except + result := false; + aStream.Position := StreamPos; + exit; + end; + finally + jpeg.Free; + end; +end; + +{$ELSEIF DEFINED(GLB_SDL_IMAGE)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; var @@ -6334,7 +6487,27 @@ end; {$ENDIF} {$IFDEF GLB_SUPPORT_JPEG_WRITE} -{$IF DEFINED(GLB_LIB_JPEG)} +{$IF DEFINED(GLB_LAZ_JPEG)} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SaveJPEG(const aStream: TStream); +var + jpeg: TJPEGImage; + intf: TLazIntfImage; +begin + jpeg := TJPEGImage.Create; + intf := TLazIntfImage.Create(0, 0); + try + if not AssignToLazIntfImage(intf) then + raise EglBitmap.Create('unable to create LazIntfImage from glBitmap'); + jpeg.LoadFromIntfImage(intf); + jpeg.SaveToStream(aStream); + finally + intf.Free; + jpeg.Free; + end; +end; + +{$ELSEIF DEFINED(GLB_LIB_JPEG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SaveJPEG(const aStream: TStream); var From 65e2aac8d0705d7c501a6723ab77e3f9cc8c0ff8 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 23 Nov 2013 14:04:52 +0100 Subject: [PATCH 25/38] * Delphi XE5 fixes * PNG and JPEG magic number check * some small bufixes --- glBitmap.pas | 182 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 75 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 0221b4d..04297fa 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1292,7 +1292,7 @@ type procedure Unmap(var aData: PByte; out aPixel: TglBitmapPixelData; var aMapData: Pointer); virtual; abstract; function GetSize(const aSize: TglBitmapPixelPosition): Integer; overload; virtual; - function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual; + function GetSize(const aWidth, aHeight: Integer): Integer; overload; virtual; function CreateMappingData: Pointer; virtual; procedure FreeMappingData(var aMappingData: Pointer); virtual; @@ -1944,7 +1944,7 @@ end; var GL_LibHandle: Pointer = nil; -function glbGetProcAddress(aProcName: PChar; aLibHandle: Pointer = nil): Pointer; +function glbGetProcAddress(aProcName: PAnsiChar; aLibHandle: Pointer = nil; const aRaiseOnErr: Boolean = true): Pointer; begin if not Assigned(aLibHandle) then aLibHandle := GL_LibHandle; @@ -1971,7 +1971,7 @@ begin result := dlsym(aLibHandle, aProcName); {$IFEND} - if not Assigned(result) then + if not Assigned(result) and aRaiseOnErr then raise EglBitmap.Create('unable to load procedure form library: ' + aProcName); end; @@ -2025,42 +2025,37 @@ begin if not Assigned(GLU_LibHandle) then raise EglBitmap.Create('unable to load library: ' + libglu); - try - {$IF DEFINED(GLB_WIN)} - wglGetProcAddress := glbGetProcAddress('wglGetProcAddress'); - {$ELSEIF DEFINED(GLB_LINUX)} - glXGetProcAddress := glbGetProcAddress('glXGetProcAddress'); - glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB'); - {$IFEND} - - glEnable := glbGetProcAddress('glEnable'); - glDisable := glbGetProcAddress('glDisable'); - glGetString := glbGetProcAddress('glGetString'); - glGetIntegerv := glbGetProcAddress('glGetIntegerv'); - glTexParameteri := glbGetProcAddress('glTexParameteri'); - glTexParameteriv := glbGetProcAddress('glTexParameteriv'); - glTexParameterfv := glbGetProcAddress('glTexParameterfv'); - glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv'); - glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv'); - glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv'); - glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv'); - glTexGeni := glbGetProcAddress('glTexGeni'); - glGenTextures := glbGetProcAddress('glGenTextures'); - glBindTexture := glbGetProcAddress('glBindTexture'); - glDeleteTextures := glbGetProcAddress('glDeleteTextures'); - glAreTexturesResident := glbGetProcAddress('glAreTexturesResident'); - glReadPixels := glbGetProcAddress('glReadPixels'); - glPixelStorei := glbGetProcAddress('glPixelStorei'); - glTexImage1D := glbGetProcAddress('glTexImage1D'); - glTexImage2D := glbGetProcAddress('glTexImage2D'); - glGetTexImage := glbGetProcAddress('glGetTexImage'); - - gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle); - gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle); - finally - glbFreeLibrary(GL_LibHandle); - glbFreeLibrary(GLU_LibHandle); - end; +{$IF DEFINED(GLB_WIN)} + wglGetProcAddress := glbGetProcAddress('wglGetProcAddress'); +{$ELSEIF DEFINED(GLB_LINUX)} + glXGetProcAddress := glbGetProcAddress('glXGetProcAddress'); + glXGetProcAddressARB := glbGetProcAddress('glXGetProcAddressARB'); +{$IFEND} + + glEnable := glbGetProcAddress('glEnable'); + glDisable := glbGetProcAddress('glDisable'); + glGetString := glbGetProcAddress('glGetString'); + glGetIntegerv := glbGetProcAddress('glGetIntegerv'); + glTexParameteri := glbGetProcAddress('glTexParameteri'); + glTexParameteriv := glbGetProcAddress('glTexParameteriv'); + glTexParameterfv := glbGetProcAddress('glTexParameterfv'); + glGetTexParameteriv := glbGetProcAddress('glGetTexParameteriv'); + glGetTexParameterfv := glbGetProcAddress('glGetTexParameterfv'); + glGetTexLevelParameteriv := glbGetProcAddress('glGetTexLevelParameteriv'); + glGetTexLevelParameterfv := glbGetProcAddress('glGetTexLevelParameterfv'); + glTexGeni := glbGetProcAddress('glTexGeni'); + glGenTextures := glbGetProcAddress('glGenTextures'); + glBindTexture := glbGetProcAddress('glBindTexture'); + glDeleteTextures := glbGetProcAddress('glDeleteTextures'); + glAreTexturesResident := glbGetProcAddress('glAreTexturesResident'); + glReadPixels := glbGetProcAddress('glReadPixels'); + glPixelStorei := glbGetProcAddress('glPixelStorei'); + glTexImage1D := glbGetProcAddress('glTexImage1D'); + glTexImage2D := glbGetProcAddress('glTexImage2D'); + glGetTexImage := glbGetProcAddress('glGetTexImage'); + + gluBuild1DMipmaps := glbGetProcAddress('gluBuild1DMipmaps', GLU_LibHandle); + gluBuild2DMipmaps := glbGetProcAddress('gluBuild2DMipmaps', GLU_LibHandle); end; {$ENDIF} @@ -2163,9 +2158,9 @@ begin glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2D'); glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImage'); end else begin - glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB'); - glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB'); - glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB'); + glCompressedTexImage1D := glbGetProcAddress('glCompressedTexImage1DARB', nil, false); + glCompressedTexImage2D := glbGetProcAddress('glCompressedTexImage2DARB', nil, false); + glGetCompressedTexImage := glbGetProcAddress('glGetCompressedTexImageARB', nil, false); end; end; {$ENDIF} @@ -4292,12 +4287,11 @@ begin fData := aData; end; - FillChar(fDimension, SizeOf(fDimension), 0); if not Assigned(fData) then begin - fFormat := tfEmpty; fPixelSize := 0; fRowSize := 0; end else begin + FillChar(fDimension, SizeOf(fDimension), 0); if aWidth <> -1 then begin fDimension.Fields := fDimension.Fields + [ffX]; fDimension.X := aWidth; @@ -4777,7 +4771,7 @@ begin tfRGBA8, tfBGRA8: aBitmap.PixelFormat := pf32bit; else - raise EglBitmapException.Create('AssignToBitmap - Invalid Pixelformat.'); + raise EglBitmap.Create('AssignToBitmap - Invalid Pixelformat.'); end; pSource := Data; @@ -4815,7 +4809,7 @@ begin pf32bit: IntFormat := tfBGRA8; else - raise EglBitmapException.Create('AssignFromBitmap - Invalid Pixelformat.'); + raise EglBitmap.Create('AssignFromBitmap - Invalid Pixelformat.'); end; TempWidth := aBitmap.Width; @@ -4879,7 +4873,7 @@ begin Inc(pSource); end; end; - end; + end; result := true; end; end; @@ -5414,8 +5408,8 @@ procedure TglBitmap.Invert(const aUseRGB: Boolean; const aUseAlpha: Boolean); begin if aUseRGB or aUseAlpha then AddFunc(glBitmapInvertFunc, false, {%H-}Pointer( - ((PtrInt(aUseAlpha) and 1) shl 1) or - (PtrInt(aUseRGB) and 1) )); + ((Byte(aUseAlpha) and 1) shl 1) or + (Byte(aUseRGB) and 1) )); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5690,13 +5684,26 @@ end; //PNG///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadPNG(const aStream: TStream): Boolean; +const + MAGIC_LEN = 8; + PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A; var png: TPortableNetworkGraphic; intf: TLazIntfImage; StreamPos: Int64; + magic: String[MAGIC_LEN]; begin result := true; StreamPos := aStream.Position; + + SetLength(magic, MAGIC_LEN); + aStream.Read(magic[1], MAGIC_LEN); + aStream.Position := StreamPos; + if (magic <> PNG_MAGIC) then begin + result := false; + exit; + end; + png := TPortableNetworkGraphic.Create; try try png.LoadFromStream(aStream); @@ -5797,7 +5804,7 @@ begin // read informations png_read_info(png, png_info); - // size + // size TempHeight := png_get_image_height(png, png_info); TempWidth := png_get_image_width(png, png_info); @@ -6277,13 +6284,26 @@ end; {$IF DEFINED(GLB_LAZ_JPEG)} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TglBitmap.LoadJPEG(const aStream: TStream): Boolean; +const + MAGIC_LEN = 2; + JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8; var jpeg: TJPEGImage; intf: TLazIntfImage; StreamPos: Int64; + magic: String[MAGIC_LEN]; begin result := true; StreamPos := aStream.Position; + + SetLength(magic, MAGIC_LEN); + aStream.Read(magic[1], MAGIC_LEN); + aStream.Position := StreamPos; + if (magic <> JPEG_MAGIC) then begin + result := false; + exit; + end; + jpeg := TJPEGImage.Create; try try jpeg.LoadFromStream(aStream); @@ -6886,7 +6906,7 @@ procedure TglBitmap.SaveBMP(const aStream: TStream); var Header: TBMPHeader; Info: TBMPInfo; - Converter: TbmpColorTableFormat; + Converter: TFormatDescriptor; FormatDesc: TFormatDescriptor; SourceFD, DestFD: Pointer; pData, srcData, dstData, ConvertBuffer: pByte; @@ -6931,26 +6951,30 @@ begin Info.biBitCount := 4; Header.bfSize := Header.bfSize + 16 * SizeOf(Cardinal); Header.bfOffBits := Header.bfOffBits + 16 * SizeOf(Cardinal); //16 ColorTable entries - Converter := TbmpColorTableFormat.Create; - Converter.PixelSize := 0.5; - Converter.Format := Format; - Converter.Range := glBitmapColorRec($F, $F, $F, $0); - Converter.CreateColorTable; + Converter := TbmpColorTableFormat.Create; + with (Converter as TbmpColorTableFormat) do begin + PixelSize := 0.5; + Format := Format; + Range := glBitmapColorRec($F, $F, $F, $0); + CreateColorTable; + end; end; tfR3G3B2, tfLuminance8: begin Info.biBitCount := 8; Header.bfSize := Header.bfSize + 256 * SizeOf(Cardinal); Header.bfOffBits := Header.bfOffBits + 256 * SizeOf(Cardinal); //256 ColorTable entries - Converter := TbmpColorTableFormat.Create; - Converter.PixelSize := 1; - Converter.Format := Format; - if (Format = tfR3G3B2) then begin - Converter.Range := glBitmapColorRec($7, $7, $3, $0); - Converter.Shift := glBitmapShiftRec(0, 3, 6, 0); - end else - Converter.Range := glBitmapColorRec($FF, $FF, $FF, $0); - Converter.CreateColorTable; + Converter := TbmpColorTableFormat.Create; + with (Converter as TbmpColorTableFormat) do begin + PixelSize := 1; + Format := Format; + if (Format = tfR3G3B2) then begin + Range := glBitmapColorRec($7, $7, $3, $0); + Shift := glBitmapShiftRec(0, 3, 6, 0); + end else + Range := glBitmapColorRec($FF, $FF, $FF, $0); + CreateColorTable; + end; end; tfRGB4, tfRGB5, tfR5G6B5, tfRGB5A1, tfRGBA4, @@ -6961,6 +6985,8 @@ begin tfBGR8, tfRGB8: begin Info.biBitCount := 24; + if (Format = tfRGB8) then + Converter := TfdBGR8.Create; //use BGR8 Format Descriptor to Swap RGB Values end; tfRGB10, tfRGB10A2, tfRGBA8, @@ -6990,9 +7016,10 @@ begin aStream.Write(Info, SizeOf(Info)); // colortable - if Assigned(Converter) then - aStream.Write(Converter.ColorTable[0].b, - SizeOf(TbmpColorTableEnty) * Length(Converter.ColorTable)); + if Assigned(Converter) and (Converter is TbmpColorTableFormat) then + with (Converter as TbmpColorTableFormat) do + aStream.Write(ColorTable[0].b, + SizeOf(TbmpColorTableEnty) * Length(ColorTable)); // bitmasks if Info.biCompression = BMP_COMP_BITFIELDS then begin @@ -7280,7 +7307,7 @@ begin if Header.ImageID <> 0 then // skip image ID aStream.Position := aStream.Position + Header.ImageID; - tgaFormat := tfEmpty; + tgaFormat := tfEmpty; case Header.Bpp of 8: if IsGrayFormat then case (Header.ImageDesc and $F) of 0: tgaFormat := tfLuminance8; @@ -7799,9 +7826,11 @@ var begin // Upload data FormatDesc := TFormatDescriptor.Get(Format); - if FormatDesc.IsCompressed then + if FormatDesc.IsCompressed then begin + if not Assigned(glCompressedTexImage1D) then + raise EglBitmap.Create('compressed formats not supported by video adapter'); glCompressedTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.GetSize(Width, 1), Data) - else if aBuildWithGlu then + end else if aBuildWithGlu then gluBuild1DMipmaps(Target, FormatDesc.glInternalFormat, Width, FormatDesc.glFormat, FormatDesc.glDataFormat, Data) else glTexImage1D(Target, 0, FormatDesc.glInternalFormat, Width, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Data); @@ -7890,6 +7919,8 @@ begin FormatDesc := TFormatDescriptor.Get(Format); if FormatDesc.IsCompressed then begin + if not Assigned(glCompressedTexImage2D) then + raise EglBitmap.Create('compressed formats not supported by video adapter'); glCompressedTexImage2D(aTarget, 0, FormatDesc.glInternalFormat, Width, Height, 0, FormatDesc.GetSize(fDimension), Data) end else if aBuildWithGlu then begin gluBuild2DMipmaps(aTarget, FormatDesc.Components, Width, Height, @@ -7967,10 +7998,12 @@ begin FormatDesc := TFormatDescriptor.Get(IntFormat); GetMem(Temp, FormatDesc.GetSize(TempWidth, TempHeight)); try - if FormatDesc.IsCompressed then + if FormatDesc.IsCompressed then begin + if not Assigned(glGetCompressedTexImage) then + raise EglBitmap.Create('compressed formats not supported by video adapter'); glGetCompressedTexImage(Target, 0, Temp) - else - glGetTexImage(Target, 0, FormatDesc.glInternalFormat, FormatDesc.glDataFormat, Temp); + end else + glGetTexImage(Target, 0, FormatDesc.glFormat, FormatDesc.glDataFormat, Temp); SetDataPointer(Temp, IntFormat, TempWidth, TempHeight); //be careful, Data could be freed by this method except if Assigned(Temp) then @@ -8527,4 +8560,3 @@ finalization {$ENDIF} end. - From d5c49ccbaf8da189f750c0577eee4ac2ac5a3abc Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 24 Nov 2013 01:59:55 +0100 Subject: [PATCH 26/38] * fixed Bug in Lazarus PNG/JPEG export: swapped red and blue values when saving RGB* Formats --- glBitmap.pas | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 04297fa..7c6e840 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -4920,7 +4920,7 @@ begin rid.Width := Width; rid.Height := Height; - rid.Depth := CountSetBits(FormatDesc.Range.r or FormatDesc.Range.g or FormatDesc.Range.b or FormatDesc.Range.a); + rid.Depth := CountSetBits(FormatDesc.RedMask or FormatDesc.GreenMask or FormatDesc.BlueMask or FormatDesc.AlphaMask); rid.BitOrder := riboBitsInOrder; rid.ByteOrder := riboLSBFirst; rid.LineOrder := riloTopToBottom; @@ -5977,13 +5977,15 @@ procedure TglBitmap.SavePNG(const aStream: TStream); var png: TPortableNetworkGraphic; intf: TLazIntfImage; + raw: TRawImage; begin png := TPortableNetworkGraphic.Create; intf := TLazIntfImage.Create(0, 0); try if not AssignToLazIntfImage(intf) then raise EglBitmap.Create('unable to create LazIntfImage from glBitmap'); - png.LoadFromIntfImage(intf); + intf.GetRawImage(raw); + png.LoadFromRawImage(raw, false); png.SaveToStream(aStream); finally png.Free; @@ -6513,13 +6515,15 @@ procedure TglBitmap.SaveJPEG(const aStream: TStream); var jpeg: TJPEGImage; intf: TLazIntfImage; + raw: TRawImage; begin jpeg := TJPEGImage.Create; intf := TLazIntfImage.Create(0, 0); try if not AssignToLazIntfImage(intf) then raise EglBitmap.Create('unable to create LazIntfImage from glBitmap'); - jpeg.LoadFromIntfImage(intf); + intf.GetRawImage(raw); + jpeg.LoadFromRawImage(raw, false); jpeg.SaveToStream(aStream); finally intf.Free; @@ -8559,4 +8563,4 @@ finalization FreeAndNil(InitOpenGLCS); {$ENDIF} -end. +end. \ No newline at end of file From baac1343d396a4a1cfdab8a0cef937981c91efdf Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 24 Nov 2013 15:49:09 +0100 Subject: [PATCH 27/38] * free lib handles on finalization --- glBitmap.pas | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/glBitmap.pas b/glBitmap.pas index 7c6e840..07317a3 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -8559,8 +8559,15 @@ initialization finalization TFormatDescriptor.Finalize; +{$IFDEF GLB_NATIVE_OGL} + if Assigned(GL_LibHandle) then + glbFreeLibrary(GL_LibHandle); + {$IFDEF GLB_NATIVE_OGL_DYNAMIC} + if Assigned(GLU_LibHandle) then + glbFreeLibrary(GLU_LibHandle); FreeAndNil(InitOpenGLCS); {$ENDIF} +{$ENDIF} -end. \ No newline at end of file +end. From aff95a0de81627a22330ffe57a4d2c6dd0535277 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Fri, 29 Nov 2013 12:10:11 +0100 Subject: [PATCH 28/38] * some fixes to support Delphi (thanks at Jens01) --- glBitmap.pas | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 07317a3..b5e8f2e 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -242,7 +242,7 @@ unit glBitmap; {.$DEFINE GLB_DELPHI} // activate to enable the support for TLazIntfImage from Lazarus -{$DEFINE GLB_LAZARUS} +{.$DEFINE GLB_LAZARUS} @@ -254,7 +254,7 @@ unit glBitmap; // activate to enable Lazarus TPortableNetworkGraphic support // if you enable this pngImage and libPNG will be ignored -{$DEFINE GLB_LAZ_PNG} +{.$DEFINE GLB_LAZ_PNG} // activate to enable png support with the unit pngimage -> http://pngdelphi.sourceforge.net/ // if you enable pngimage the libPNG will be ignored @@ -268,7 +268,7 @@ unit glBitmap; // activate to enable Lazarus TJPEGImage support // if you enable this delphi jpegs and libJPEG will be ignored -{$DEFINE GLB_LAZ_JPEG} +{.$DEFINE GLB_LAZ_JPEG} // if you enable delphi jpegs the libJPEG will be ignored {.$DEFINE GLB_DELPHI_JPEG} @@ -443,11 +443,12 @@ interface uses {$IFNDEF GLB_NATIVE_OGL} dglOpenGL, {$ENDIF} {$IF DEFINED(GLB_WIN) AND - DEFINED(GLB_NATIVE_OGL)} windows, {$IFEND} + (DEFINED(GLB_NATIVE_OGL) OR + DEFINED(GLB_DELPHI))} windows, {$IFEND} {$IFDEF GLB_SDL} SDL, {$ENDIF} {$IFDEF GLB_LAZARUS} IntfGraphics, GraphType, Graphics, {$ENDIF} - {$IFDEF GLB_DELPHI} Dialogs, Graphics, {$ENDIF} + {$IFDEF GLB_DELPHI} Dialogs, Graphics, Types, {$ENDIF} {$IFDEF GLB_SDL_IMAGE} SDL_image, {$ENDIF} {$IFDEF GLB_PNGIMAGE} pngimage, {$ENDIF} @@ -1224,7 +1225,8 @@ function CreateGrayPalette: HPALETTE; implementation uses - Math, syncobjs, typinfo; + Math, syncobjs, typinfo + {$IFDEF GLB_DELPHI}, Types{$ENDIF}; type {$IFNDEF fpc} From ff53bc1bee76288fe2fe5daef580d1ce197f2020 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Fri, 29 Nov 2013 14:56:06 +0100 Subject: [PATCH 29/38] * public constructor for EglBitmapUnsupportedFormat (thanks at Jens01) --- glBitmap.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/glBitmap.pas b/glBitmap.pas index b5e8f2e..a2884da 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -860,6 +860,7 @@ type EglBitmapSizeToLarge = class(EglBitmap); EglBitmapNonPowerOfTwo = class(EglBitmap); EglBitmapUnsupportedFormat = class(EglBitmap) + public constructor Create(const aFormat: TglBitmapFormat); overload; constructor Create(const aMsg: String; const aFormat: TglBitmapFormat); overload; end; From a6c7400293c7553d7d1c0bb59152e591344e07cf Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 21 Dec 2013 23:10:08 +0100 Subject: [PATCH 30/38] * pass TextureData as Argument in Constructor --- glBitmap.pas | 53 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index a2884da..2bbc6c1 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -924,6 +924,7 @@ type fTarget: GLuint; fAnisotropic: Integer; fDeleteTextureOnFree: Boolean; + fFreeDataOnDestroy: Boolean; fFreeDataAfterGenTexture: Boolean; fData: PByte; fIsResident: Boolean; @@ -966,6 +967,7 @@ type procedure SetCustomData(const aValue: Pointer); procedure SetCustomName(const aValue: String); procedure SetCustomNameW(const aValue: WideString); + procedure SetFreeDataOnDestroy(const aValue: Boolean); procedure SetDeleteTextureOnFree(const aValue: Boolean); procedure SetFormat(const aValue: TglBitmapFormat); procedure SetFreeDataAfterGenTexture(const aValue: Boolean); @@ -1004,6 +1006,7 @@ type property CustomData: Pointer read fCustomData write SetCustomData; property DeleteTextureOnFree: Boolean read fDeleteTextureOnFree write SetDeleteTextureOnFree; + property FreeDataOnDestroy: Boolean read fFreeDataOnDestroy write SetFreeDataOnDestroy; property FreeDataAfterGenTexture: Boolean read fFreeDataAfterGenTexture write SetFreeDataAfterGenTexture; property Dimension: TglBitmapPixelPosition read fDimension; @@ -1104,7 +1107,7 @@ type constructor Create; overload; constructor Create(const aFileName: String); overload; constructor Create(const aStream: TStream); overload; - constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); overload; + constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte = nil); overload; constructor Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer = nil); overload; constructor Create(const aInstance: Cardinal; const aResource: String; const aResType: PChar = nil); overload; constructor Create(const aInstance: Cardinal; const aResourceID: Integer; const aResType: PChar); overload; @@ -4175,6 +4178,14 @@ begin fCustomNameW := aValue; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TglBitmap.SetFreeDataOnDestroy(const aValue: Boolean); +begin + if fFreeDataOnDestroy = aValue then + exit; + fFreeDataOnDestroy := aValue; +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TglBitmap.SetDeleteTextureOnFree(const aValue: Boolean); begin @@ -4335,7 +4346,6 @@ begin fTarget := 0; fIsResident := false; - fFormat := glBitmapGetDefaultFormat; fMipMap := glBitmapDefaultMipmap; fFreeDataAfterGenTexture := glBitmapGetDefaultFreeDataAfterGenTexture; fDeleteTextureOnFree := glBitmapGetDefaultDeleteTextureOnFree; @@ -4350,8 +4360,10 @@ procedure TglBitmap.BeforeDestruction; var NewData: PByte; begin - NewData := nil; - SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method + if fFreeDataOnDestroy then begin + NewData := nil; + SetDataPointer(NewData, tfEmpty); //be careful, Data could be freed by this method + end; if (fID > 0) and fDeleteTextureOnFree then glDeleteTextures(1, @fID); inherited BeforeDestruction; @@ -4418,7 +4430,7 @@ begin FreeMem(tmpData); raise; end; - AddFunc(Self, aFunc, false, Format, aArgs); + AddFunc(Self, aFunc, false, aFormat, aArgs); end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5624,6 +5636,8 @@ begin glbReadOpenGLExtensions; {$ENDIF} inherited Create; + fFormat := glBitmapGetDefaultFormat; + fFreeDataOnDestroy := true; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5641,27 +5655,30 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat); +constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; aData: PByte); var - Image: PByte; ImageSize: Integer; begin Create; - ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize); - GetMem(Image, ImageSize); - try - FillChar(Image^, ImageSize, #$FF); - SetDataPointer(Image, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method - except - if Assigned(Image) then - FreeMem(Image); - raise; + if not Assigned(aData) then begin + ImageSize := TFormatDescriptor.Get(aFormat).GetSize(aSize); + GetMem(aData, ImageSize); + try + FillChar(aData^, ImageSize, #$FF); + SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method + except + if Assigned(aData) then + FreeMem(aData); + raise; + end; + end else begin + SetDataPointer(aData, aFormat, aSize.X, aSize.Y); //be careful, Data could be freed by this method + fFreeDataOnDestroy := false; end; end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; - const aFunc: TglBitmapFunction; const aArgs: Pointer); +constructor TglBitmap.Create(const aSize: TglBitmapPixelPosition; const aFormat: TglBitmapFormat; const aFunc: TglBitmapFunction; const aArgs: Pointer); begin Create; LoadFromFunc(aSize, aFunc, aFormat, aArgs); From 899463e5066c0e0e141bbc7aa93296c9318b8bc0 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 2 Feb 2014 17:10:53 +0100 Subject: [PATCH 31/38] * fixed MemLeak in AssignFromLazIntfImage --- glBitmap.pas | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/glBitmap.pas b/glBitmap.pas index 2bbc6c1..1e95efa 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -4968,6 +4968,42 @@ var FormatDesc: TFormatDescriptor; ImageData: PByte; ImageSize: Integer; + CanCopy: Boolean; + + procedure CopyConvert; + var + bfFormat: TbmpBitfieldFormat; + pSourceLine, pDestLine: PByte; + pSourceMD, pDestMD: Pointer; + x, y: Integer; + pixel: TglBitmapPixelData; + begin + bfFormat := TbmpBitfieldFormat.Create; + with aImage.DataDescription do begin + bfFormat.RedMask := ((1 shl RedPrec) - 1) shl RedShift; + bfFormat.GreenMask := ((1 shl GreenPrec) - 1) shl GreenShift; + bfFormat.BlueMask := ((1 shl BluePrec) - 1) shl BlueShift; + bfFormat.AlphaMask := ((1 shl AlphaPrec) - 1) shl AlphaShift; + bfFormat.PixelSize := BitsPerPixel / 8; + end; + pSourceMD := bfFormat.CreateMappingData; + pDestMD := FormatDesc.CreateMappingData; + try + for y := 0 to aImage.Height-1 do begin + pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine; + pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width); + for x := 0 to aImage.Width-1 do begin + bfFormat.Unmap(pSourceLine, pixel, pSourceMD); + FormatDesc.Map(pixel, pDestLine, pDestMD); + end; + end; + finally + FormatDesc.FreeMappingData(pDestMD); + bfFormat.FreeMappingData(pSourceMD); + bfFormat.Free; + end; + end; + begin result := false; if not Assigned(aImage) then @@ -4986,10 +5022,17 @@ begin if (f = tfEmpty) then exit; + CanCopy := + (Round(FormatDesc.PixelSize * 8) = aImage.DataDescription.Depth) and + (aImage.DataDescription.BitsPerPixel = aImage.DataDescription.Depth); + ImageSize := FormatDesc.GetSize(aImage.Width, aImage.Height); ImageData := GetMem(ImageSize); try - Move(aImage.PixelData^, ImageData^, (aImage.Width * aImage.Height * aImage.DataDescription.BitsPerPixel) shr 3); + if CanCopy then + Move(aImage.PixelData^, ImageData^, ImageSize) + else + CopyConvert; SetDataPointer(ImageData, f, aImage.Width, aImage.Height); //be careful, Data could be freed by this method except if Assigned(ImageData) then From eec4c8208622e8c3f5aa421cdb1631576d4c08d2 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 6 Feb 2014 17:50:40 +0100 Subject: [PATCH 32/38] * load PNG direct over TLazIntfImage and TLazReaderPNG instead of TPortableNetworkGraphic --- glBitmap.pas | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index 1e95efa..ea47607 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -5751,7 +5751,7 @@ const MAGIC_LEN = 8; PNG_MAGIC: String[MAGIC_LEN] = #$89#$50#$4E#$47#$0D#$0A#$1A#$0A; var - png: TPortableNetworkGraphic; + reader: TLazReaderPNG; intf: TLazIntfImage; StreamPos: Int64; magic: String[MAGIC_LEN]; @@ -5767,27 +5767,20 @@ begin exit; end; - png := TPortableNetworkGraphic.Create; + intf := TLazIntfImage.Create(0, 0); + reader := TLazReaderPNG.Create; try try - png.LoadFromStream(aStream); - intf := png.CreateIntfImage; - try try - AssignFromLazIntfImage(intf); - except - result := false; - aStream.Position := StreamPos; - exit; - end; - finally - intf.Free; - end; + reader.UpdateDescription := true; + reader.ImageRead(aStream, intf); + AssignFromLazIntfImage(intf); except result := false; aStream.Position := StreamPos; exit; end; finally - png.Free; + reader.Free; + intf.Free; end; end; From 95537170b0fcafff3246a1c03d6eb1b1449221cd Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 9 Feb 2014 13:30:58 +0100 Subject: [PATCH 33/38] * load JPEG direct over TLazIntfImage and TReadJPEG instead of TJPEGImage --- glBitmap.pas | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index ea47607..fdeaae1 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -1230,7 +1230,8 @@ implementation uses Math, syncobjs, typinfo - {$IFDEF GLB_DELPHI}, Types{$ENDIF}; + {$IFDEF GLB_DELPHI}, Types{$ENDIF} + {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND}; type {$IFNDEF fpc} @@ -6348,6 +6349,7 @@ const var jpeg: TJPEGImage; intf: TLazIntfImage; + reader: TFPReaderJPEG; StreamPos: Int64; magic: String[MAGIC_LEN]; begin @@ -6362,28 +6364,20 @@ begin exit; end; - jpeg := TJPEGImage.Create; + reader := TFPReaderJPEG.Create; + intf := TLazIntfImage.Create(0, 0); try try - jpeg.LoadFromStream(aStream); - intf := TLazIntfImage.Create(0, 0); - try try - intf.LoadFromBitmap(jpeg.BitmapHandle, jpeg.MaskHandle); - AssignFromLazIntfImage(intf); - except - result := false; - aStream.Position := StreamPos; - exit; - end; - finally - intf.Free; - end; + intf.DataDescription := GetDescriptionFromDevice(0, 0, 0); + reader.ImageRead(aStream, intf); + AssignFromLazIntfImage(intf); except result := false; aStream.Position := StreamPos; exit; end; finally - jpeg.Free; + reader.Free; + intf.Free; end; end; From 39d0b4a3cc4b5d49c02b79eac4f7fa7d40691c9e Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 3 May 2014 18:32:27 +0200 Subject: [PATCH 34/38] * Format: implemented HasRed, HasGreen and HasBlue * fixed some compiler hints and warnings --- glBitmap.pas | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index fdeaae1..b181705 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -24,7 +24,7 @@ History - GetPixel isn't set if you are loading textures inside the constructor (Thanks Wilson) 10-08-2008 - AddAlphaFromglBitmap used the custom pointer instead the imagedatapointer (Thanks Wilson) -- Additional Datapointer for functioninterface now has the name CustomData +- Additional Datapointer for functioninterface now has the name CustomData 24-07-2008 - AssigneAlphaToBitmap overwrites his own palette (Thanks Wilson) - If you load an texture from an file the property Filename will be set to the name of the file @@ -53,7 +53,7 @@ History - Property DataPtr now has the name Data - Functions are more flexible between RGB(A) and BGR(A). RGB can be saved as Bitmap and will be saved as BGR - Unused Depth removed -- Function FreeData to freeing image data added +- Function FreeData to freeing image data added 24-10-2007 - ImageID flag of TGAs was ignored. (Thanks Zwoetzen) 15-11-2006 @@ -221,7 +221,7 @@ unit glBitmap; // Please uncomment the defines below to configure the glBitmap to your preferences. // If you have configured the unit you can uncomment the warning above. -{$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} +{.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Preferences /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -889,6 +889,9 @@ type TglBitmapFormatDescriptor = class(TObject) protected function GetIsCompressed: Boolean; virtual; abstract; + function GetHasRed: Boolean; virtual; abstract; + function GetHasGreen: Boolean; virtual; abstract; + function GetHasBlue: Boolean; virtual; abstract; function GetHasAlpha: Boolean; virtual; abstract; function GetglDataFormat: GLenum; virtual; abstract; @@ -896,6 +899,9 @@ type function GetglInternalFormat: GLenum; virtual; abstract; public property IsCompressed: Boolean read GetIsCompressed; + property HasRed: Boolean read GetHasRed; + property HasGreen: Boolean read GetHasGreen; + property HasBlue: Boolean read GetHasBlue; property HasAlpha: Boolean read GetHasAlpha; property glFormat: GLenum read GetglFormat; @@ -927,7 +933,7 @@ type fFreeDataOnDestroy: Boolean; fFreeDataAfterGenTexture: Boolean; fData: PByte; - fIsResident: Boolean; + fIsResident: GLboolean; fBorderColor: array[0..3] of Single; fDimension: TglBitmapPixelPosition; @@ -1011,7 +1017,7 @@ type property Dimension: TglBitmapPixelPosition read fDimension; property Data: PByte read fData; - property IsResident: Boolean read fIsResident; + property IsResident: GLboolean read fIsResident; procedure AfterConstruction; override; procedure BeforeDestruction; override; @@ -1272,6 +1278,9 @@ type fglDataFormat: GLenum; function GetIsCompressed: Boolean; override; + function GetHasRed: Boolean; override; + function GetHasGreen: Boolean; override; + function GetHasBlue: Boolean; override; function GetHasAlpha: Boolean; override; function GetglFormat: GLenum; override; @@ -2308,7 +2317,7 @@ begin end; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TFormatDescriptor.GetRedMask: QWord; begin @@ -2339,6 +2348,24 @@ begin result := fIsCompressed; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetHasRed: Boolean; +begin + result := (fRange.r > 0); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetHasGreen: Boolean; +begin + result := (fRange.g > 0); +end; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TFormatDescriptor.GetHasBlue: Boolean; +begin + result := (fRange.b > 0); +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TFormatDescriptor.GetHasAlpha: Boolean; begin @@ -5650,7 +5677,7 @@ begin if (ID > 0) then begin Bind(false); - glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, @fSwizzle[0]); + glTexParameteriv(Target, GL_TEXTURE_SWIZZLE_RGBA, PGLint(@fSwizzle[0])); end; end; @@ -6347,7 +6374,6 @@ const MAGIC_LEN = 2; JPEG_MAGIC: String[MAGIC_LEN] = #$FF#$D8; var - jpeg: TJPEGImage; intf: TLazIntfImage; reader: TFPReaderJPEG; StreamPos: Int64; @@ -8028,7 +8054,7 @@ procedure TglBitmap2D.GetDataFromTexture; var Temp: PByte; TempWidth, TempHeight: Integer; - TempIntFormat: Cardinal; + TempIntFormat: GLint; IntFormat, f: TglBitmapFormat; FormatDesc: TFormatDescriptor; begin From 060ca52f8c439e9a7f52c49b8e5d3eec0790b039 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 3 May 2014 18:48:22 +0200 Subject: [PATCH 35/38] * removed duplicated unit usage * better description for delphi support compiler flag --- glBitmap.pas | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index b181705..d366652 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -221,7 +221,7 @@ unit glBitmap; // Please uncomment the defines below to configure the glBitmap to your preferences. // If you have configured the unit you can uncomment the warning above. -{.$MESSAGE warn 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} +{$MESSAGE error 'Hey. I''m the glBitmap.pas and i need to be configured. My master tell me your preferences! ;)'} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Preferences /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -238,7 +238,7 @@ unit glBitmap; // activate to enable the support for SDL_surfaces {.$DEFINE GLB_SDL} -// activate to enable the support for TBitmap from Delphi (not lazarus) +// activate to enable the support for Delphi (including support for Delphi's (not Lazarus') TBitmap) {.$DEFINE GLB_DELPHI} // activate to enable the support for TLazIntfImage from Lazarus @@ -1236,7 +1236,6 @@ implementation uses Math, syncobjs, typinfo - {$IFDEF GLB_DELPHI}, Types{$ENDIF} {$IF DEFINED(GLB_SUPPORT_JPEG_READ) AND DEFINED(GLB_LAZ_JPEG)}, FPReadJPEG{$IFEND}; type From 440a36866275f5510c9df2d630bedaca2e043514 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sat, 3 May 2014 19:00:56 +0200 Subject: [PATCH 36/38] * fixed some compiler hints in delphi 7 * version incremented to 3.0.1 --- glBitmap.pas | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index d366652..b1b4c65 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -11,7 +11,7 @@ not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html ------------------------------------------------------------ -Version 3.0.0 unstable +Version 3.0.1 ------------------------------------------------------------ History 20-11-2013 @@ -5002,7 +5002,7 @@ var bfFormat: TbmpBitfieldFormat; pSourceLine, pDestLine: PByte; pSourceMD, pDestMD: Pointer; - x, y: Integer; + x, y: Cardinal; pixel: TglBitmapPixelData; begin bfFormat := TbmpBitfieldFormat.Create; @@ -5386,7 +5386,6 @@ var TempPtr: PByte; Size: Integer; begin - result := nil; Temp := (ClassType.Create as TglBitmap); try // copy texture data if assigned @@ -8052,8 +8051,8 @@ end; procedure TglBitmap2D.GetDataFromTexture; var Temp: PByte; - TempWidth, TempHeight: Integer; - TempIntFormat: GLint; + TempWidth, TempHeight: GLint; + TempIntFormat: GLenum; IntFormat, f: TglBitmapFormat; FormatDesc: TFormatDescriptor; begin @@ -8062,7 +8061,7 @@ begin // Request Data glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth); glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, PGLint(@TempIntFormat)); IntFormat := tfEmpty; for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin From 84f22cf88183bb324b71e1181c4ade2f22b2447a Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 4 May 2014 02:23:55 +0200 Subject: [PATCH 37/38] * fixed bug in FlipHorz and FlipVert --- glBitmap.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index b1b4c65..c13d85c 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -8140,7 +8140,7 @@ begin Dec(TempDestData, fPixelSize); end; end; - SetDataPointer(DestData, Format); //be careful, Data could be freed by this method + SetDataPointer(DestData, Format, Width, Height); //be careful, Data could be freed by this method result := true; except if Assigned(DestData) then @@ -8168,7 +8168,7 @@ begin Dec(TempDestData, fRowSize); Inc(SourceData, fRowSize); end; - SetDataPointer(DestData, Format); //be careful, Data could be freed by this method + SetDataPointer(DestData, Format, Width, Height); //be careful, Data could be freed by this method result := true; except if Assigned(DestData) then From 401bba6efa010fd58c8bd2f5d5e6067b3a7aaf97 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Sun, 21 Sep 2014 17:34:53 +0200 Subject: [PATCH 38/38] * added function to get FormatDescriptor from internal OpenGL Format * fixed some hints / warnings --- glBitmap.pas | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/glBitmap.pas b/glBitmap.pas index c13d85c..1be10f8 100644 --- a/glBitmap.pas +++ b/glBitmap.pas @@ -907,6 +907,8 @@ type property glFormat: GLenum read GetglFormat; property glInternalFormat: GLenum read GetglInternalFormat; property glDataFormat: GLenum read GetglDataFormat; + public + class function GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor; end; //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -3719,6 +3721,21 @@ begin fglDataFormat := GL_UNSIGNED_BYTE; end; +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TglBitmapFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +class function TglBitmapFormatDescriptor.GetByFormat(const aInternalFormat: GLenum): TglBitmapFormatDescriptor; +var + f: TglBitmapFormat; +begin + for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin + result := TFormatDescriptor.Get(f); + if (result.glInternalFormat = aInternalFormat) then + exit; + end; + result := TFormatDescriptor.Get(tfEmpty); +end; + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TFormatDescriptor/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -5002,7 +5019,7 @@ var bfFormat: TbmpBitfieldFormat; pSourceLine, pDestLine: PByte; pSourceMD, pDestMD: Pointer; - x, y: Cardinal; + x, y: Integer; pixel: TglBitmapPixelData; begin bfFormat := TbmpBitfieldFormat.Create; @@ -5017,7 +5034,7 @@ var pDestMD := FormatDesc.CreateMappingData; try for y := 0 to aImage.Height-1 do begin - pSourceLine := aImage.PixelData + y * aImage.DataDescription.BytesPerLine; + pSourceLine := aImage.PixelData + y {%H-}* aImage.DataDescription.BytesPerLine; pDestLine := ImageData + y * Round(FormatDesc.PixelSize * aImage.Width); for x := 0 to aImage.Width-1 do begin bfFormat.Unmap(pSourceLine, pixel, pSourceMD); @@ -5386,6 +5403,7 @@ var TempPtr: PByte; Size: Integer; begin + result := nil; Temp := (ClassType.Create as TglBitmap); try // copy texture data if assigned @@ -8051,9 +8069,9 @@ end; procedure TglBitmap2D.GetDataFromTexture; var Temp: PByte; - TempWidth, TempHeight: GLint; - TempIntFormat: GLenum; - IntFormat, f: TglBitmapFormat; + TempWidth, TempHeight: Integer; + TempIntFormat: GLint; + IntFormat: TglBitmapFormat; FormatDesc: TFormatDescriptor; begin Bind; @@ -8061,16 +8079,11 @@ begin // Request Data glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_WIDTH, @TempWidth); glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_HEIGHT, @TempHeight); - glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, PGLint(@TempIntFormat)); + glGetTexLevelParameteriv(Target, 0, GL_TEXTURE_INTERNAL_FORMAT, @TempIntFormat); - IntFormat := tfEmpty; - for f := Low(TglBitmapFormat) to High(TglBitmapFormat) do begin - FormatDesc := TFormatDescriptor.Get(f); - if (FormatDesc.glInternalFormat = TempIntFormat) then begin - IntFormat := FormatDesc.Format; - break; - end; - end; + IntFormat := tfEmpty; + FormatDesc := (TglBitmapFormatDescriptor.GetByFormat(TempIntFormat) as TFormatDescriptor); + IntFormat := FormatDesc.Format; // Getting data from OpenGL FormatDesc := TFormatDescriptor.Get(IntFormat);