C2OGLRender.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:105k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  @Abstract(CAST Engine OpenGL render unit (incomplete) )
  3.  (C) 2009 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  Unit contains OpenGL-based renderer implementation classes
  6. *)
  7. {$Include GDefines.inc}
  8. {$Include C2Defines.inc}
  9. unit C2OGLRender;
  10. interface
  11. uses
  12.   BaseTypes, Basics, Base3D, Collisions, OSUtils,
  13.   TextFile,
  14.   BaseClasses,
  15.   C2Types, CAST2, C2Res, C2Visual, C2Render, C2Materials,
  16.   OpenGL12, MyOpenGL,
  17.   SysUtils, Windows, Messages;
  18. const
  19.   // Usage flags for dynamic and static vertex buffers
  20. //  BufferUsage: array[Boolean] of Cardinal = (D3DUSAGE_DYNAMIC or D3DUSAGE_WRITEONLY,         // Dynamic buffer usage
  21. //                                             D3DUSAGE_WRITEONLY);                            // Static buffer usage
  22.   // Flags for dynamic and static vertex buffers lock with keeping contents or without
  23. //  BufferLockFlags: array[Boolean, Boolean] of Cardinal =
  24. //   ((D3DLOCK_NOOVERWRITE*1 or 0*D3DLOCK_DISCARD or 0*D3DLOCK_NOSYSLOCK,   // Dynamic non-discard lock
  25. //     D3DLOCK_DISCARD*1 or 0*D3DLOCK_NOSYSLOCK),                           // Dynamic discard lock
  26. //     (D3DLOCK_NOOVERWRITE*0, 1*D3DLOCK_DISCARD));                         // Static non-discard and discard lock
  27. //  VertexDataTypeToD3DVSDT: array[vdtFloat1..vdtInt16_4] of Cardinal =
  28. //    (D3DVSDT_FLOAT1, D3DVSDT_FLOAT2, D3DVSDT_FLOAT3, D3DVSDT_FLOAT4, D3DVSDT_D3DCOLOR, D3DVSDT_UBYTE4, D3DVSDT_SHORT2, D3DVSDT_SHORT4);
  29. //     D3DVSDT_UBYTE4, D3DVSDT_FLOAT1, D3DVSDT_FLOAT2);           // Unsupported by OGL
  30. type
  31.   TOGLVertexBuffer = record
  32.     VertexSize, BufferSize: Integer;
  33.     Static: Boolean;
  34.     BufferID: Cardinal;
  35.     Data: Pointer;
  36.   end;
  37.   TOGLIndexBuffer = record
  38.     BufferSize: Integer;
  39.     Static: Boolean;
  40.     BufferID: Cardinal;
  41.     Data: Pointer;
  42.   end;
  43.   // @Abstract(OpenGL implementation of vertex and index buffers management class)
  44.   TOGLBuffers = class(TAPIBuffers)
  45.   private
  46.     VertexBuffers: array of TOGLVertexBuffer;
  47.     IndexBuffers: array of TOGLIndexBuffer;
  48.   public
  49. //    destructor Destroy; override;
  50.     { Creates a vertex buffer with the given size in bytes and returns its internal index or -1 if creation fails.
  51.       If <b>Static</b> is <b>False</b> the buffer will be optimized to store dynamic geometry. }
  52.     function CreateVertexBuffer(Size: Integer; Static: Boolean): Integer; override;
  53.     { Creates an index buffer with the given size in bytes and returns its internal index or -1 if creation fails
  54.       If <b>Static</b> is <b>False</b> the buffer will be optimized to store dynamic data. }
  55.     function CreateIndexBuffer(Size: Integer; Static: Boolean): Integer; override;
  56.     // Changes size of the given vertex buffer to the given size and returns <b>True</b> if success
  57.     function ResizeVertexBuffer(Index: Integer; NewSize: Integer): Boolean; override;
  58.     // Changes size of the given index buffer to the given size and returns <b>True</b> if success
  59.     function ResizeIndexBuffer(Index: Integer; NewSize: Integer): Boolean; override;
  60.     { Locks the given range in a vertex buffer with the given index and returns a write-only pointer to the range data or <b>nil</b> if lock fails.
  61.       If <b>DiscardExisting</b> is <b>True</b> existing data in the buffer will be discarded to avoid stalls. }
  62.     function LockVertexBuffer(Index: Integer; Offset, Size: Integer; DiscardExisting: Boolean): Pointer; override;
  63.     { Locks the given range in a index buffer with the given index and returns a write-only pointer to the range data or <b>nil</b> if lock fails.
  64.       If <b>DiscardExisting</b> is <b>True</b> existing data in the buffer will be discarded to avoid stalls. }
  65.     function LockIndexBuffer(Index: Integer; Offset, Size: Integer; DiscardExisting: Boolean): Pointer; override;
  66.     // Unlocks a previously locked vertex buffer
  67.     procedure UnlockVertexBuffer(Index: Integer); override;
  68.     // Unlocks a previously locked index buffer
  69.     procedure UnlockIndexBuffer(Index: Integer); override;
  70.     // Attaches a vertex buffer to the specified data stream and returns <b>True</b> if success. <b>VertexSize</b> should match the size of the data in the buffer.
  71.     function AttachVertexBuffer(Index, StreamIndex: Integer; VertexSize: Integer): Boolean; override;
  72.     // Attaches an index buffer and returns <b>True</b> if success. <b>StartingVertex</b> will be added to all indices read from the index buffer.
  73.     function AttachIndexBuffer(Index: Integer; StartingVertex: Integer): Boolean; override;
  74.     // Frees all allocated buffers. All internal indices returned before this call become invalid.
  75.     procedure Clear; override;
  76.   end;
  77.   TOGLTextures = class(C2Render.TTextures)
  78.   private
  79.     Direct3DDevice: IDirect3DDevice8;
  80.     APITextures: array of IDirect3DTexture8;
  81.   protected  
  82.     function APICreateTexture(Index: Integer): Boolean; override;
  83.   public
  84.     procedure Unload(Index: Integer); override;
  85.     function Update(Index: Integer; Src: Pointer; Rect: BaseTypes.PRect3D): Boolean; override;
  86.     function Read(Index: Integer; Dest: Pointer; Rect: BaseTypes.PRect3D): Boolean; override;
  87.     procedure Delete(Index: Integer); override;
  88.     procedure Apply(Stage, Index: Integer); override;
  89.     function Lock(AIndex, AMipLevel: Integer; const ARect: BaseTypes.PRect; out LockRectData: TLockedRectData; LockFlags: TLockFlags): Boolean; override;
  90.     procedure UnLock(AIndex, AMipLevel: Integer); override;
  91.   end;
  92.   TOGLStateWrapper = class(C2Render.TAPIStateWrapper)
  93.   private
  94.     Direct3DDevice: IDirect3DDevice8;
  95.     CurrentRenderTarget, CurrentDepthStencil, MainRenderTarget, MainDepthStencil: IDirect3DSurface8;
  96.     // Converts an FVF vertex format to a OGL vertex declaration. Result should be allocated by caller
  97.     procedure FVFToDeclaration(VertexFormat: Cardinal; var Result: POGLVertexDeclaration);
  98.     procedure DeclarationToAPI(Declaration: TVertexDeclaration; ConstantsData: Pointer; ConstantsSize: Integer; var Result: POGLVertexDeclaration);
  99.   protected
  100.     function APICreateRenderTarget(Index, Width, Height: Integer; AColorFormat, ADepthFormat: Cardinal): Boolean; override;
  101.     procedure DestroyRenderTarget(Index: Integer); override;
  102.     // Calls an API to set a shader constant
  103.     procedure APISetShaderConstant(const Constant: TShaderConstant); overload; override;
  104.     // Calls an API to set a shader constant. <b>ShaderKind</b> - kind of shader, <b>ShaderRegister</b> - index of 4-component vector register to set, <b>Vector</b> - new value of the register.
  105.     procedure APISetShaderConstant(ShaderKind: TShaderKind; ShaderRegister: Integer; const Vector: TShaderRegisterType); overload; override;
  106.     function APIValidatePass(const Pass: TRenderPass; out ResultStr: string): Boolean; override;
  107.     procedure ApplyTextureMatrices(const Pass: TRenderPass); override;
  108.     procedure CleanUpNonManaged;
  109.     procedure RestoreNonManaged;
  110.     procedure ObtainRenderTargetSurfaces;
  111.   public
  112.     function SetRenderTarget(const Camera: TCamera; TextureTarget: Boolean): Boolean; override;
  113.     function CreateVertexShader(Item: TShaderResource; Declaration: TVertexDeclaration): Integer; override;
  114.     function CreatePixelShader(Item: TShaderResource): Integer; override;
  115.     procedure SetFog(Kind: Cardinal; Color: BaseTypes.TColor; AFogStart, AFogEnd, ADensity: Single); override;
  116.     procedure SetBlending(Enabled: Boolean; SrcBlend, DestBlend, AlphaRef, ATestFunc, Operation: Integer); override;
  117.     procedure SetZBuffer(ZTestFunc, ZBias: Integer; ZWrite: Boolean); override;
  118.     procedure SetCullAndFillMode(FillMode, ShadeMode, CullMode: Integer; ColorMask: Cardinal); override;
  119.     procedure SetStencilState(SFailOp, ZFailOp, PassOp, STestFunc: Integer); override;
  120.     procedure SetStencilValues(SRef, SMask, SWriteMask: Integer); override;
  121.     procedure SetTextureWrap(const CoordSet: TTWrapCoordSet); override;
  122.     procedure SetLighting(Enable: Boolean; AAmbient: BaseTypes.TColor; SpecularMode: Integer; NormalizeNormals: Boolean); override;
  123.     procedure SetEdgePoint(PointSprite, PointScale, EdgeAntialias: Boolean); override;
  124.     procedure SetTextureFactor(ATextureFactor: BaseTypes.TColor); override;
  125.     procedure SetMaterial(const AAmbient, ADiffuse, ASpecular, AEmissive: BaseTypes.TColor4S; APower: Single); override;
  126.     procedure SetPointValues(APointSize, AMinPointSize, AMaxPointSize, APointScaleA, APointScaleB, APointScaleC: Single); override;
  127.     procedure SetLinePattern(ALinePattern: Longword); override;
  128.     procedure SetClipPlane(Index: Cardinal; Plane: PPlane); override;
  129.     procedure ApplyPass(const Pass: TRenderPass); override;
  130.     procedure ApplyCustomTextureMatrices(const Pass: TRenderPass; Item: TVisible); override;
  131.   end;
  132.   TOGLRenderer = class(TRenderer)
  133.   private
  134.     MixedVPMode,
  135.     LastFullScreen: Boolean;
  136.     CurrentDeviceType: TD3DDevType;
  137.     function FindDepthStencilFormat(iAdapter: Word; DeviceType: TD3DDEVTYPE; TargetFormat: TD3DFORMAT; var DepthStencilFormat: TD3DFORMAT) : Boolean;
  138.     function FillPresentPars(var D3DPP: TD3DPresent_Parameters): Boolean;
  139.     // Clean up non-managed resources
  140.     procedure CleanUpNonManaged;
  141.     // Restore non-managed resources after device restoration
  142.     procedure RestoreNonManaged;
  143.     // Converts a general vertex declaration to API-specific vartex declaration. Result should be allocated by caller
  144.     procedure GetAPIDeclaration(Declaration: TVertexDeclaration; Result: POGLVertexDeclaration);
  145.   protected
  146.     function APICheckFormat(const Format, Usage, RTFormat: Cardinal): Boolean; override;
  147.     procedure APIPrepareFVFStates(Item: TVisible); override;
  148.     procedure InternalDeInit; override;
  149.   public
  150.     DXRenderTargetTexture: IDirect3DTexture8;
  151.     Direct3D: IDirect3D8;
  152.     Direct3DDevice: IDirect3DDevice8;
  153.     Mat: TD3DMATERIAL8;
  154.     constructor Create(Manager: TItemsManager); override;
  155.     procedure SetDeviceType(DevType: Cardinal);
  156.     procedure BuildModeList; override;
  157.     procedure SetGamma(Gamma, Contrast, Brightness: Single); override;
  158.     procedure CheckCaps; override;
  159.     procedure CheckTextureFormats; override;
  160.     function APICreateDevice(WindowHandle, AVideoMode: Cardinal; AFullScreen: Boolean): Boolean; override;
  161.     function RestoreDevice(AVideoMode: Cardinal; AFullScreen: Boolean): Boolean; override;
  162.     procedure StartFrame; override;
  163.     procedure FinishFrame; override;
  164.     procedure Clear(Flags: TClearFlagsSet; Color: BaseTypes.TColor; Z: Single; Stencil: Cardinal); override;
  165.     procedure ApplyLight(Index: Integer; const ALight: TLight); override;
  166.     procedure ApplyCamera(Camera: TCamera); override;
  167.     procedure SetViewPort(const X, Y, Width, Height: Integer; const MinZ, MaxZ: Single); override;
  168.     procedure APIRenderStrip(Tesselator: TTesselator; StripIndex: Integer); override;
  169.     procedure APIRenderIndexedStrip(Tesselator: TTesselator; StripIndex: Integer); override;
  170.     procedure RenderItemBox(Item: TProcessing; Color: BaseTypes.TColor); override;
  171.     procedure RenderItemDebug(Item: TProcessing); override;
  172.   end;
  173.   function HResultToStr(Res: HResult): string;
  174.   function FVFToVertexFormat(FVF: Cardinal): Cardinal;
  175. implementation
  176. { TOGLBuffers }
  177. function TOGLBuffers.CreateVertexBuffer(Size: Integer; Static: Boolean): Integer;
  178. var Res: HResult; D3DBuf: IDirect3DVertexBuffer8;
  179. begin
  180.   Result := -1;
  181.   {$IFDEF DEBUGMODE}
  182.   Log.Log('TOGLBuffers.CreateVertexBuffer: Creating a vertex buffer', lkDebug);
  183.   {$ENDIF}
  184.   Res := (Renderer as TOGLRenderer).Direct3DDevice.CreateVertexBuffer(Size, BufferUsage[Static], 0, BufferPool[(Renderer as TOGLRenderer).MixedVPMode], D3DBuf);
  185.   if Failed(Res) then begin
  186.     Log.Log('TOGLBuffers.CreateVertexBuffer: Error creating vertex buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  187.     Exit;
  188.   end;
  189.   SetLength(VertexBuffers, Length(VertexBuffers)+1);
  190.   Result := High(VertexBuffers);
  191.   VertexBuffers[Result].BufferSize := Size;
  192.   VertexBuffers[Result].Buffer     := D3DBuf;
  193.   VertexBuffers[Result].Static     := Static;
  194. end;
  195. function TOGLBuffers.CreateIndexBuffer(Size: Integer; Static: Boolean): Integer;
  196. var Res: HResult; D3DBuf: IDirect3DIndexBuffer8;
  197. begin
  198.   Result := -1;
  199.   {$IFDEF DEBUGMODE}
  200.   Log.Log('TOGLBuffers.CreateIndexBuffer: Creating an index buffer', lkDebug);
  201.   {$ENDIF}                                              
  202.   Res := (Renderer as TOGLRenderer).Direct3DDevice.CreateIndexBuffer(Size, BufferUsage[Static], D3DFMT_INDEX16, BufferPool[(Renderer as TOGLRenderer).MixedVPMode], D3DBuf);
  203.   if Failed(Res) then begin
  204.     Log.Log('TOGLBuffers.CreateIndexBuffer: Error creating index buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  205.     Exit;
  206.   end;
  207.   SetLength(IndexBuffers, Length(IndexBuffers)+1);
  208.   Result := High(IndexBuffers);
  209.   IndexBuffers[Result].BufferSize := Size;
  210.   IndexBuffers[Result].Buffer     := D3DBuf;
  211.   IndexBuffers[Result].Static     := Static;
  212. end;
  213. function TOGLBuffers.ResizeVertexBuffer(Index, NewSize: Integer): Boolean;
  214. var Res: HResult; D3DBuf: IDirect3DVertexBuffer8;
  215. begin
  216.   Assert((Index >= 0) and (Index <= High(VertexBuffers)), 'TOGLBuffers.ResizeVertexBuffer: Invalid bufer index');
  217.   Result := False;
  218.   Res := (Renderer as TOGLRenderer).Direct3DDevice.CreateVertexBuffer(NewSize, BufferUsage[VertexBuffers[Index].Static], 0, BufferPool[(Renderer as TOGLRenderer).MixedVPMode], D3DBuf);
  219.   if Failed(Res) then begin
  220.     Log.Log('TOGLBuffers.ResizeVertexBuffer: Error resizing vertex buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  221.     Exit;
  222.   end;
  223.   VertexBuffers[Index].Buffer     := nil;
  224.   VertexBuffers[Index].Buffer     := D3DBuf;
  225.   VertexBuffers[Index].BufferSize := NewSize;
  226.   Result := True;
  227. end;
  228. function TOGLBuffers.ResizeIndexBuffer(Index, NewSize: Integer): Boolean;
  229. var Res: HResult; D3DBuf: IDirect3DIndexBuffer8;
  230. begin
  231.   Assert((Index >= 0) and (Index <= High(IndexBuffers)), 'TOGLBuffers.ResizeIndexBuffer: Invalid bufer index');
  232.   Result := False;
  233.   Res := (Renderer as TOGLRenderer).Direct3DDevice.CreateIndexBuffer(NewSize, BufferUsage[IndexBuffers[Index].Static], D3DFMT_INDEX16, BufferPool[(Renderer as TOGLRenderer).MixedVPMode], D3DBuf);
  234.   if Failed(Res) then begin
  235.     Log.Log('TOGLBuffers.ResizeIndexBuffer: Error resizing Index buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  236.     Exit;
  237.   end;
  238.   IndexBuffers[Index].Buffer     := nil;
  239.   IndexBuffers[Index].Buffer     := D3DBuf;
  240.   IndexBuffers[Index].BufferSize := NewSize;
  241.   Result := True;
  242. end;
  243. function TOGLBuffers.LockVertexBuffer(Index, Offset, Size: Integer; DiscardExisting: Boolean): Pointer;
  244. var Res: HResult; Data: PByte;
  245. begin
  246.   Assert((Index >= 0) and (Index <= High(VertexBuffers)), 'TOGLBuffers.LockVertexBuffer: Invalid bufer index');
  247.   Result := nil;
  248.   Res := VertexBuffers[Index].Buffer.Lock(Offset, Size, Data, BufferLockFlags[VertexBuffers[Index].Static, DiscardExisting]);
  249.   if Failed(Res) then begin
  250.     Log.Log('TOGLBuffers.LockVertexBuffer: Error locking vertex buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  251.     Exit;
  252.   end;
  253.   Result := Data;
  254. end;
  255. function TOGLBuffers.LockIndexBuffer(Index, Offset, Size: Integer; DiscardExisting: Boolean): Pointer;
  256. var Res: HResult; Data: PByte;
  257. begin
  258.   Assert((Index >= 0) and (Index <= High(IndexBuffers)), 'TOGLBuffers.LockIndexBuffer: Invalid bufer index');
  259.   Result := nil;
  260.   Res := IndexBuffers[Index].Buffer.Lock(Offset, Size, Data, BufferLockFlags[IndexBuffers[Index].Static, DiscardExisting]);
  261.   if Failed(Res) then begin
  262.     Log.Log('TOGLBuffers.LockIndexBuffer: Error locking index buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  263.     Exit;
  264.   end;
  265.   Result := Data;
  266. end;
  267. procedure TOGLBuffers.UnlockVertexBuffer(Index: Integer);
  268. begin
  269.   Assert((Index >= 0) and (Index <= High(VertexBuffers)), 'TOGLBuffers.UnlockVertexBuffer: Invalid bufer index');
  270.   VertexBuffers[Index].Buffer.UnLock;
  271. end;
  272. procedure TOGLBuffers.UnlockIndexBuffer(Index: Integer);
  273. begin
  274.   Assert((Index >= 0) and (Index <= High(IndexBuffers)), 'TOGLBuffers.UnlockIndexBuffer: Invalid bufer index');
  275.   IndexBuffers[Index].Buffer.UnLock;
  276. end;
  277. function TOGLBuffers.AttachVertexBuffer(Index, StreamIndex, VertexSize: Integer): Boolean;
  278. var Res: HResult;
  279. begin
  280.   Result := True;
  281.   Assert((Index >= 0) and (Index <= High(VertexBuffers)), 'TOGLBuffers.AttachVertexBuffer: Invalid bufer index');
  282.   Res := TOGLRenderer(Renderer).Direct3DDevice.SetStreamSource(StreamIndex, VertexBuffers[Index].Buffer, VertexSize);
  283.   if Failed(Res) then begin
  284.     Log.Log('TOGLBuffers.AttachVertexBuffer: Error attaching vertex buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  285.     Exit;
  286.   end;
  287.   Result := False;
  288. end;
  289. function TOGLBuffers.AttachIndexBuffer(Index, StartingVertex: Integer): Boolean;
  290. var Res: HResult;
  291. begin
  292.   Result := False;
  293.   Assert((Index >= 0) and (Index <= High(IndexBuffers)), 'TOGLBuffers.AttachIndexBuffer: Invalid bufer index');
  294.   Res := TOGLRenderer(Renderer).Direct3DDevice.SetIndices(IndexBuffers[Index].Buffer, StartingVertex);
  295.   if Failed(Res) then begin
  296.     Log.Log('TOGLBuffers.AttachIndexBuffer: Error attaching vertex buffer. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  297.     Exit;
  298.   end;
  299.   Result := True;
  300. end;
  301. procedure TOGLBuffers.Clear;
  302. var i: Integer;
  303. begin
  304.   for i := 0 to High(VertexBuffers) do VertexBuffers[i].Buffer := nil;
  305.   for i := 0 to High(IndexBuffers)  do IndexBuffers[i].Buffer  := nil;
  306.   VertexBuffers := nil;
  307.   IndexBuffers  := nil;
  308. end;
  309. { TOGLStateWrapper }
  310. function TOGLStateWrapper.APICreateRenderTarget(Index, Width, Height: Integer; AColorFormat, ADepthFormat: Cardinal): Boolean;
  311. var Res: HResult;
  312. begin
  313.   Result := False;
  314.   // Free texture and its surface
  315.   if Assigned(FRenderTargets[Index].ColorBuffer)  then IDirect3DSurface8(FRenderTargets[Index].ColorBuffer)  := nil;
  316.   if Assigned(FRenderTargets[Index].ColorTexture) then IDirect3DTexture8(FRenderTargets[Index].ColorTexture) := nil;
  317.   // Create texture
  318.   Res := Direct3DDevice.CreateTexture(Width, Height, 1, D3DUSAGE_RENDERTARGET, TD3DFormat(PFormats[AColorFormat]), D3DPOOL_DEFAULT, IDirect3DTexture8(FRenderTargets[Index].ColorTexture));
  319.   if Failed(Res) then begin
  320.     {$IFDEF Logging}
  321.     Log.Log(ClassName + '.APICreateRenderTarget: Error creating render target texture: Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  322.     {$ENDIF}
  323.     Exit;
  324.   end;
  325.   // Obtain surface
  326.   Res := IDirect3DTexture8(FRenderTargets[Index].ColorTexture).GetSurfaceLevel(0, IDirect3DSurface8(FRenderTargets[Index].ColorBuffer));
  327.   if Failed(Res) then begin
  328.     {$IFDEF LOGGING}
  329.     Log.Log(Format('Error obtaining surface of a render target texture of camera "%S". Error code: %D "%S"', [Camera.Name, Res, HResultToStr(Res)]), lkError);
  330.     {$ENDIF}
  331.     Exit;
  332.   end;
  333.   if ADepthFormat = pfUndefined then
  334.     FRenderTargets[Index].DepthBuffer := nil else begin
  335.       // Free depth texture and its surface
  336.       if Assigned(FRenderTargets[Index].DepthBuffer)  then IDirect3DSurface8(FRenderTargets[Index].DepthBuffer)  := nil;
  337.       if Assigned(FRenderTargets[Index].DepthTexture) then IDirect3DTexture8(FRenderTargets[Index].DepthTexture) := nil;
  338.       Res := Direct3DDevice.CreateTexture(Width, Height, 1, D3DUSAGE_DEPTHSTENCIL, TD3DFormat(PFormats[ADepthFormat]), D3DPOOL_DEFAULT, IDirect3DTexture8(FRenderTargets[Index].DepthTexture));
  339.       if Failed(Res) then begin
  340.         Res:= Direct3DDevice.CreateDepthStencilSurface(Width, Height, TD3DFormat(PFormats[ADepthFormat]), D3DMULTISAMPLE_NONE, IDirect3DSurface8(FRenderTargets[Index].DepthBuffer));
  341.         if Failed(Res) then begin
  342.           {$IFDEF Logging}
  343.           Log.Log(Format('%S.APICreateRenderTarget: Error creating depth surface for render target of camera "%S". Error code: %D "%S"', [ClassName, Camera.Name, Res, HResultToStr(Res)]), lkError);
  344.           {$ENDIF}
  345.           Exit;
  346.         end;
  347.       end else begin
  348.         Res := IDirect3DTexture8(FRenderTargets[Index].DepthTexture).GetSurfaceLevel(0, IDirect3DSurface8(FRenderTargets[Index].DepthBuffer));
  349.         if Failed(Res) then begin
  350.           {$IFDEF LOGGING}
  351.           Log.Log(Format('Error obtaining surface of a depth surface for render target of camera "%S". Error code: %D "%S"', [Camera.Name, Res, HResultToStr(Res)]), lkError);
  352.           {$ENDIF}
  353.           Exit;
  354.         end;
  355.       end;
  356.     end;
  357.   Result := True;
  358. end;
  359. procedure TOGLStateWrapper.DestroyRenderTarget(Index: Integer);
  360. begin
  361.   if Assigned(FRenderTargets[Index].ColorBuffer)  then IDirect3DSurface8(FRenderTargets[Index].ColorBuffer)._Release;
  362.   if Assigned(FRenderTargets[Index].DepthBuffer)  then IDirect3DSurface8(FRenderTargets[Index].DepthBuffer)._Release;
  363.   if Assigned(FRenderTargets[Index].ColorTexture) then IDirect3DTexture8(FRenderTargets[Index].ColorTexture)._Release;
  364.   if Assigned(FRenderTargets[Index].DepthTexture) then IDirect3DTexture8(FRenderTargets[Index].DepthTexture)._Release;
  365.   FRenderTargets[Index].ColorBuffer  := nil;
  366.   FRenderTargets[Index].DepthBuffer  := nil;
  367.   FRenderTargets[Index].ColorTexture := nil;
  368.   FRenderTargets[Index].DepthTexture := nil;
  369.   FRenderTargets[Index].LastUpdateFrame := -1;
  370.   FRenderTargets[Index].IsDepthTexture:= False;
  371. end;
  372. function TOGLStateWrapper.SetRenderTarget(const Camera: TCamera; TextureTarget: Boolean): Boolean;
  373. var Res: HResult;
  374. begin
  375.   Result := False;
  376.   if TextureTarget then begin                                         // Render to texture
  377.     if Camera.RenderTargetIndex <> -1 then begin
  378.       FRenderTargets[Camera.RenderTargetIndex].LastUpdateFrame := Renderer.FramesRendered;
  379.       CurrentRenderTarget := IDirect3DSurface8(FRenderTargets[Camera.RenderTargetIndex].ColorBuffer);
  380.       CurrentDepthStencil := IDirect3DSurface8(FRenderTargets[Camera.RenderTargetIndex].DepthBuffer);
  381.       Res := Direct3DDevice.SetRenderTarget(CurrentRenderTarget, CurrentDepthStencil);
  382.       if Failed(Res) then begin
  383.         {$IFDEF LOGGING}
  384.         Log.Log(Format('Error setting render target to texture of camera "%S". Error code: %D "%S"', [Camera.Name, Res, HResultToStr(Res)]), lkError);
  385.         {$ENDIF}
  386.         CurrentDepthStencil := nil;
  387.         Exit;
  388.       end;
  389.       
  390.     end;
  391.   end else begin
  392.     Res := Direct3DDevice.SetRenderTarget(MainRenderTarget, MainDepthStencil);
  393.     CurrentRenderTarget := MainRenderTarget;
  394.     CurrentDepthStencil := MainDepthStencil;
  395.     if Failed(Res) then begin
  396.       {$IFDEF LOGGING}
  397.       Log.Log('Error restoring render target. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  398.       {$ENDIF}
  399.       Exit;
  400.     end;
  401.   end;
  402.   Inc(FPerfProfile.RenderTargetChanges);
  403.   Result := True;
  404. end;
  405. function TOGLStateWrapper.CreateVertexShader(Item: TShaderResource; Declaration: TVertexDeclaration): Integer;
  406. var
  407.   Res: HResult;
  408.   {$IFNDEF DISABLED3OGL}
  409.   Data, Constants: ID3DXBuffer;
  410.   {$ENDIF}
  411.   VDecl: POGLVertexDeclaration; ConstsSize: Integer;
  412. begin
  413.   Result := inherited CreateVertexShader(Item, Declaration);
  414.   {$IFNDEF DISABLED3OGL}
  415.   if not Assigned(Item.Data) and (Item.Source <> '') then begin
  416.     Data := nil;
  417.     Constants := nil;
  418.     Res := D3DXAssembleShader(Item.Source[1], Length(Item.Source), D3DXASM_SKIPVALIDATION*0, @Constants, @Data, nil);
  419.     if Failed(Res) then begin
  420.       Log.Log('Error assembling vertex shader from resource "' + Item.Name + '". Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  421.       Result := -1;
  422.       LastError := reVertexShaderAssembleFail;
  423.       Exit;
  424.     end;
  425.     Assert(Assigned(Data));
  426.     // Fill resource with compiled code and constants data
  427.     Item.Allocate(Data.GetBufferSize + Constants.GetBufferSize);
  428.     Move(Data.GetBufferPointer^, Item.Data^, Data.GetBufferSize);
  429.     Move(Constants.GetBufferPointer^, PtrOffs(Item.Data, Data.GetBufferSize)^, Constants.GetBufferSize);
  430.     Item.SetCodeSize(Data.GetBufferSize);
  431.   end;
  432.   {$ENDIF}
  433.   ConstsSize := (Item.DataSize - Item.CodeSize) * Ord(Assigned(Item.Data) and (Item.CodeSize <> 0));
  434.   GetMem(VDecl, (Length(Declaration)+2) * SizeOf(Cardinal) + ConstsSize);
  435.   DeclarationToAPI(Declaration, Pointer(Integer(Item.Data) + Item.CodeSize), ConstsSize, VDecl);
  436.   Res := Direct3DDevice.CreateVertexShader(Pointer(VDecl), Item.Data, Cardinal(FVertexShaders[Result].Shader), D3DUSAGE_SOFTWAREPROCESSING * Ord(TOGLRenderer(Renderer).MixedVPMode));
  437.   FreeMem(VDecl);
  438.   if Failed(Res) then begin
  439.     {$IFDEF LOGGING}
  440.     Log.Log('Error creating vertex shader from resource "' + Item.Name + '". Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  441.     {$ENDIF}
  442.     Result := -1;
  443.     LastError := reVertexShaderCreateFail;
  444.     Exit;
  445.   end;
  446. end;
  447. function TOGLStateWrapper.CreatePixelShader(Item: TShaderResource): Integer;
  448. var Res: HResult; {$IFNDEF DISABLED3OGL} Data: ID3DXBuffer; {$ENDIF}
  449. begin
  450.   Result := inherited CreatePixelShader(Item);
  451.   {$IFNDEF DISABLED3OGL}
  452.   if not Assigned(Item.Data) and (Item.Source <> '') then begin
  453.     Data := nil;
  454.     Res := D3DXAssembleShader(Item.Source[1], Length(Item.Source), D3DXASM_SKIPVALIDATION*0, nil, @Data, nil);
  455. //    Res := D3DXAssembleShaderFromFileA(PChar(Item.Source), D3DXASM_SKIPVALIDATION , nil, @Data, nil);
  456.     if Failed(Res) then begin
  457.       Log.Log('Error assembling pixel shader from resource "' + Item.Name + '". Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  458.       Result := -1;
  459.       LastError := rePixelShaderAssembleFail;
  460.       Exit;
  461.     end;
  462.     Assert(Assigned(Data));
  463.     Item.Allocate(Data.GetBufferSize);
  464.     Move(Data.GetBufferPointer^, Item.Data^, Item.DataSize);
  465.   end;
  466.   {$ENDIF}
  467.   Res := Direct3DDevice.CreatePixelShader(Item.Data, Cardinal(FPixelShaders[Result].Shader));
  468.   if Failed(Res) then begin
  469.     {$IFDEF LOGGING}
  470.     Log.Log('Error creating pixel shader from resource "' + Item.Name + '". Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  471.     {$ENDIF}
  472.     Result := -1;
  473.     LastError := rePixelShaderCreateFail;
  474.     Exit;
  475.   end;
  476. end;
  477. procedure TOGLStateWrapper.SetFog(Kind: Cardinal; Color: BaseTypes.TColor; AFogStart, AFogEnd, ADensity: Single);
  478. begin
  479.   if Kind <> fkNone then begin
  480.     Direct3DDevice.SetRenderState(D3DRS_FOGENABLE, Ord(True));
  481.     Direct3DDevice.SetRenderState(D3DRS_FOGCOLOR,  Color.C);
  482.     case Kind of
  483.       fkVertex: begin
  484.         Direct3DDevice.SetRenderState(D3DRS_FOGVERTEXMODE,   D3DFOG_LINEAR);
  485.         Direct3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE , 0);
  486.         Direct3DDevice.SetRenderState(D3DRS_FOGTABLEMODE,    D3DFOG_NONE);
  487.       end;
  488.       fkVertexRanged: begin
  489.         Direct3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE , 1);
  490.         Direct3DDevice.SetRenderState(D3DRS_FOGVERTEXMODE,   D3DFOG_LINEAR);
  491.         Direct3DDevice.SetRenderState(D3DRS_FOGTABLEMODE,    D3DFOG_NONE);
  492.       end;
  493.       fkTableLinear: begin
  494.         Direct3DDevice.SetRenderState(D3DRS_FOGTABLEMODE,    D3DFOG_LINEAR);
  495.         Direct3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE , 0);
  496.         Direct3DDevice.SetRenderState(D3DRS_FOGVERTEXMODE,   D3DFOG_NONE);
  497.       end;
  498.       fkTABLEEXP: begin
  499.         Direct3DDevice.SetRenderState(D3DRS_FOGTABLEMODE,    D3DFOG_EXP);
  500.         Direct3DDevice.SetRenderState(D3DRS_FOGDENSITY,      Cardinal((@ADensity)^));
  501.         Direct3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE , 0);
  502.         Direct3DDevice.SetRenderState(D3DRS_FOGVERTEXMODE,   D3DFOG_NONE);
  503.       end;
  504.       fkTABLEEXP2: begin
  505.         Direct3DDevice.SetRenderState(D3DRS_FOGTABLEMODE,    D3DFOG_EXP2);
  506.         Direct3DDevice.SetRenderState(D3DRS_FOGDENSITY,      Cardinal((@ADensity)^));
  507.         Direct3DDevice.SetRenderState(D3DRS_RANGEFOGENABLE , 0);
  508.         Direct3DDevice.SetRenderState(D3DRS_FOGVERTEXMODE,   D3DFOG_NONE);
  509.       end;
  510.     end;
  511.     Direct3DDevice.SetRenderState(D3DRS_FOGSTART, Cardinal((@AFogStart)^));
  512.     Direct3DDevice.SetRenderState(D3DRS_FOGEND,   Cardinal((@AFogEnd)^));
  513.   end else Direct3DDevice.SetRenderState(D3DRS_FOGENABLE, Ord(False));
  514. end;
  515. procedure TOGLStateWrapper.SetBlending(Enabled: Boolean; SrcBlend, DestBlend, AlphaRef, ATestFunc, Operation: Integer);
  516. begin
  517.   if Enabled then begin
  518.     Direct3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
  519.     Direct3DDevice.SetRenderState(D3DRS_SRCBLEND,         BlendModes[SrcBlend]);
  520.     Direct3DDevice.SetRenderState(D3DRS_DESTBLEND,        BlendModes[DestBlend]);
  521.     Direct3DDevice.SetRenderState(D3DRS_BLENDOP,          BlendOps[Operation]);
  522.   end else Direct3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
  523.   Direct3DDevice.SetRenderState(D3DRS_ALPHATESTENABLE, Ord(ATestFunc <> tfAlways));
  524.   Direct3DDevice.SetRenderState(D3DRS_ALPHAFUNC,       TestFuncs[ATestFunc]);
  525.   Direct3DDevice.SetRenderState(D3DRS_ALPHAREF,        AlphaRef);
  526. end;
  527. procedure TOGLStateWrapper.SetZBuffer(ZTestFunc, ZBias: Integer; ZWrite: Boolean);
  528. begin
  529. //  Direct3DDevice.SetRenderState(D3DRS_ZE-NABLE, );
  530.   Direct3DDevice.SetRenderState(D3DRS_ZFUNC,        TestFuncs[ZTestFunc]);
  531.   Direct3DDevice.SetRenderState(D3DRS_ZBIAS,        ZBias);
  532.   Direct3DDevice.SetRenderState(D3DRS_ZWRITEENABLE, Ord(ZWrite));
  533. end;
  534. procedure TOGLStateWrapper.SetCullAndFillMode(FillMode, ShadeMode, CullMode: Integer; ColorMask: Cardinal);
  535. begin
  536.   if FillMode <> fmDEFAULT then
  537.     Direct3DDevice.SetRenderState(D3DRS_FILLMODE, FillModes[FillMode]) else if Camera <> nil then
  538.       Direct3DDevice.SetRenderState(D3DRS_FILLMODE, FillModes[Camera.DefaultFillMode]);
  539.   Direct3DDevice.SetRenderState(D3DRS_SHADEMODE, ShadeModes[ShadeMode]);
  540.   case CullMode of
  541.     cmCAMERADEFAULT: if Camera <> nil then Direct3DDevice.SetRenderState(D3DRS_CULLMODE, CullModes[Camera.DefaultCullMode]);
  542.     cmCAMERAINVERSE: if Camera <> nil then begin
  543.       if Camera.DefaultCullMode = cmCCW then
  544.        Direct3DDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW) else
  545.         if Camera.DefaultCullMode = cmCW then Direct3DDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW) else
  546.          Direct3DDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  547.     end;
  548.     else Direct3DDevice.SetRenderState(D3DRS_CULLMODE, CullModes[CullMode]);
  549.   end;
  550.   ColorMask := Ord(ColorMask and $FF > 0) or Ord(ColorMask and $FF00 > 0) shl 1 or Ord(ColorMask and $FF0000 > 0) shl 2 or Ord(ColorMask and $FF000000 > 0)  shl 3;
  551.   Direct3DDevice.SetRenderState(D3DRS_COLORWRITEENABLE, ColorMask);
  552. end;
  553. procedure TOGLStateWrapper.SetStencilState(SFailOp, ZFailOp, PassOp, STestFunc: Integer);
  554. begin
  555. // Disable stencil if Func = Always and ZFail = PassOP = Keep
  556.   if (ZFailOp = soKeep) and (PassOp = soKeep) and (STestFunc <> tfAlways) then
  557.    Direct3DDevice.SetRenderState(D3DRS_STENCILENABLE, 0) else begin
  558.      Direct3DDevice.SetRenderState(D3DRS_STENCILENABLE, 1);
  559.      Direct3DDevice.SetRenderState(D3DRS_STENCILFUNC,   TestFuncs[STestFunc]);
  560.      Direct3DDevice.SetRenderState(D3DRS_STENCILFAIL,   StencilOps[SFailOp]);
  561.      Direct3DDevice.SetRenderState(D3DRS_STENCILZFAIL,  StencilOps[ZFailOp]);
  562.      Direct3DDevice.SetRenderState(D3DRS_STENCILPASS,   StencilOps[PassOp]);
  563.    end;
  564. end;
  565. procedure TOGLStateWrapper.SetStencilValues(SRef, SMask, SWriteMask: Integer);
  566. begin
  567.   Direct3DDevice.SetRenderState(D3DRS_STENCILREF,       Cardinal(SRef));
  568.   Direct3DDevice.SetRenderState(D3DRS_STENCILMASK,      Cardinal(SMask));
  569.   Direct3DDevice.SetRenderState(D3DRS_STENCILWRITEMASK, Cardinal(SWriteMask));
  570. end;
  571. procedure TOGLStateWrapper.SetTextureWrap(const CoordSet: TTWrapCoordSet);
  572. const D3DRS_WRAP: array[0..7] of TD3DRenderStateType = (D3DRS_WRAP0, D3DRS_WRAP1, D3DRS_WRAP2, D3DRS_WRAP3, D3DRS_WRAP4, D3DRS_WRAP5, D3DRS_WRAP6, D3DRS_WRAP7);
  573. var i: Integer;
  574. begin
  575.   for i := 0 to 7 do
  576.     Direct3DDevice.SetRenderState(D3DRS_WRAP[i], D3DWRAPCOORD_0 * Ord(CoordSet[i] and twUCoord  > 0) or
  577.                                                  D3DWRAPCOORD_1 * Ord(CoordSet[i] and twVCoord  > 0) or
  578.                                                  D3DWRAPCOORD_2 * Ord(CoordSet[i] and twWCoord  > 0) or
  579.                                                  D3DWRAPCOORD_3 * Ord(CoordSet[i] and twW2Coord > 0));
  580. end;
  581. procedure TOGLStateWrapper.SetLighting(Enable: Boolean; AAmbient: BaseTypes.TColor; SpecularMode: Integer; NormalizeNormals: Boolean);
  582. begin
  583.   Direct3dDevice.SetRenderState(D3DRS_SPECULARENABLE,   Ord(SpecularMode <> slNone));
  584.   Direct3dDevice.SetRenderState(D3DRS_LOCALVIEWER,      Ord(SpecularMode = slAccurate));
  585.   Direct3DDevice.SetRenderState(D3DRS_NORMALIZENORMALS, Ord(NormalizeNormals));
  586.   Direct3DDevice.SetRenderState(D3DRS_LIGHTING,         Ord(Enable));
  587.   Direct3DDevice.SetRenderState(D3DRS_AMBIENT,          AAmbient.C);
  588. end;
  589. procedure TOGLStateWrapper.SetEdgePoint(PointSprite, PointScale, EdgeAntialias: Boolean);
  590. begin
  591.   Direct3dDevice.SetRenderState(D3DRS_POINTSPRITEENABLE, Ord(PointSprite));
  592.   Direct3DDevice.SetRenderState(D3DRS_POINTSCALEENABLE,  Ord(PointScale));
  593.   Direct3DDevice.SetRenderState(D3DRS_EDGEANTIALIAS,     Ord(EdgeAntialias));
  594. end;
  595. procedure TOGLStateWrapper.SetTextureFactor(ATextureFactor: BaseTypes.TColor);
  596. begin
  597.   Direct3DDevice.SetRenderState(D3DRS_TEXTUREFACTOR, ATextureFactor.C);
  598. end;
  599. procedure TOGLStateWrapper.SetMaterial(const AAmbient, ADiffuse, ASpecular, AEmissive: BaseTypes.TColor4S; APower: Single);
  600. var Mat: TD3DMATERIAL8; Res: HResult;
  601. begin
  602.   Mat.Ambient  := TD3DColorValue(AAmbient);
  603.   Mat.Diffuse  := TD3DColorValue(ADiffuse);
  604.   Mat.Specular := TD3DColorValue(ASpecular);
  605.   Mat.Emissive := TD3DColorValue(AEmissive);
  606.   Mat.Power    := APower;
  607.   Res := Direct3DDevice.SetMaterial(Mat);
  608.   if Failed(Res) then Log.Log('***Error', lkError);
  609. end;
  610. procedure TOGLStateWrapper.SetPointValues(APointSize, AMinPointSize, AMaxPointSize, APointScaleA, APointScaleB, APointScaleC: Single);
  611. begin
  612. //  AMaxPointSize := MinS(AMaxPointSize, Renderer.MaxPointSize);
  613.   AMinPointSize := MinS(AMinPointSize, AMaxPointSize);
  614.   APointSize := MinS(MaxS(APointSIze, AMinPointSize), AMaxPointSize);
  615.   Direct3DDevice.SetRenderState(D3DRS_POINTSIZE,     Cardinal((@APointSize)^));
  616.   Direct3DDevice.SetRenderState(D3DRS_POINTSIZE_MIN, Cardinal((@AMinPointSize)^));
  617.   Direct3DDevice.SetRenderState(D3DRS_POINTSIZE_MAX, Cardinal((@AMaxPointSize)^));
  618.   Direct3DDevice.SetRenderState(D3DRS_POINTSCALE_A,  Cardinal((@APointScaleA)^));
  619.   Direct3DDevice.SetRenderState(D3DRS_POINTSCALE_B,  Cardinal((@APointScaleB)^));
  620.   Direct3DDevice.SetRenderState(D3DRS_POINTSCALE_C,  Cardinal((@APointScaleC)^));
  621. end;
  622. procedure TOGLStateWrapper.SetLinePattern(ALinePattern: Longword);
  623. begin
  624.   Direct3DDevice.SetRenderState(D3DRS_LINEPATTERN, $00010001+0*ALinePattern);
  625. end;
  626. procedure TOGLStateWrapper.SetClipPlane(Index: Cardinal; Plane: PPlane);
  627. var Res: HResult;
  628. begin
  629.   ClipPlanesState := ClipPlanesState and not (1 shl Index) or Cardinal(Ord(Assigned(Plane)) shl Index);
  630.   Direct3DDevice.SetRenderState(D3DRS_CLIPPLANEENABLE, ClipPlanesState);
  631.   if Assigned(Plane) then begin
  632.     Res := Direct3DDevice.SetClipPlane(Index, PSingle(Plane));
  633.     {$IFDEF DEBUGMODE}
  634.     if Failed(Res) then
  635.       Log.Log('Error setting clip plane. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  636.     {$ENDIF} 
  637.   end;
  638. end;
  639. procedure TOGLStateWrapper.ApplyPass(const Pass: TRenderPass);
  640. var i, TexCount: Integer; Stage: ^TStage; Res: HResult;
  641. begin
  642.   Assert(Assigned(Pass), ClassName + '.ApplyPass: Invalid pass');
  643.   if (Pass.VertexShaderIndex <> sivNull) then begin                                // Try to resolve vertex shader
  644.     if Pass.VertexShaderIndex = sivUnresolved then ResolveVertexShader(Pass);
  645.     VertexShaderFlag := Pass.VertexShaderIndex <> sivUnresolved;
  646.   end else VertexShaderFlag := False;
  647.   if TOGLRenderer(Renderer).MixedVPMode then TOGLRenderer(Renderer).Direct3dDevice.SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, Ord(VertexShaderFlag));
  648.   SetFog(Pass.FogKind, Pass.FogColor, Pass.FogStart, Pass.FogEnd, Pass.FogDensity);
  649. //  SetPointValues(Pass.PointSize, Pass.MinPointSize, Pass.MaxPointSize, Pass.PointScaleA, Pass.PointScaleB, Pass.PointScaleC);
  650. //  SetLinePattern(Pass.LinePattern);
  651.   SetBlending(Pass.BlendingState.Enabled, Pass.BlendingState.SrcBlend, Pass.BlendingState.DestBlend, Pass.BlendingState.AlphaRef, Pass.BlendingState.ATestFunc, Pass.BlendingState.Operation);
  652.   SetZBuffer(Pass.ZBufferState.ZTestFunc, Pass.ZBufferState.ZBias, Pass.ZBufferState.ZWrite);
  653.   SetCullAndFillMode(Pass.FillShadeMode.FillMode, Pass.FillShadeMode.ShadeMode, Pass.FillShadeMode.CullMode, Pass.FillShadeMode.ColorMask);
  654.   SetStencilState(Pass.StencilState.SFailOp, Pass.StencilState.ZFailOp, Pass.StencilState.PassOp, Pass.StencilState.STestFunc);
  655.   SetStencilValues(Pass.StencilRef, Pass.StencilMask, Pass.StencilWriteMask);
  656.   SetTextureWrap(Pass.TextureWrap.CoordSet);
  657.   SetLighting(Pass.LightingState.Enabled, Pass.LightingState.GlobalAmbient, Pass.LightingState.SpecularMode, Pass.LightingState.NormalizeNormals);
  658.   SetEdgePoint(Pass.PointEdgeState.PointSprite, Pass.PointEdgeState.PointScale, Pass.PointEdgeState.EdgeAntialias);
  659.   SetTextureFactor(Pass.TextureFactor);
  660.   ApplyTextureMatrices(Pass);
  661.   SetMaterial(Pass.Ambient, Pass.Diffuse, Pass.Specular, Pass.Emissive, Pass.Power);
  662.   if VertexShaderFlag then begin
  663.     Res := Direct3DDevice.SetVertexShader(Cardinal(FVertexShaders[Pass.VertexShaderIndex].Shader));
  664.     {$IFDEF DEBUGMODE} if Res <> D3D_OK then begin Log.Log('TOGLStateWrapper.ApplyPass: Error setting vertex shader: ' +  HResultToStr(Res), lkError); end; {$ENDIF}
  665.   end;  
  666.   if (Pass.PixelShaderIndex <> sivNull) then begin                                 // Try to resolve pixel shader
  667.     if Pass.PixelShaderIndex = sivUnresolved then ResolvePixelShader(Pass);
  668.     PixelShaderFlag := Pass.PixelShaderIndex <> sivUnresolved;
  669.   end else PixelShaderFlag := False;
  670.   if PixelShaderFlag then
  671.     Res := Direct3DDevice.SetPixelShader(Cardinal(FPixelShaders[Pass.PixelShaderIndex].Shader)) else
  672.       Res := Direct3DDevice.SetPixelShader(0);
  673.   {$IFDEF DEBUGMODE} if Res <> D3D_OK then begin Log.Log('TOGLStateWrapper.ApplyPass: Error setting pixel shader: ' +  HResultToStr(Res), lkError); end; {$ENDIF}
  674.   if (LastError = reNone) and (Pass.TotalStages > Renderer.MaxTextureStages) then LastError := reTooManyStages;
  675.   TexCount := 0;
  676.   for i := 0 to MinI(Pass.TotalStages-1, Renderer.MaxTextureStages-1) do begin
  677.     Stage := @Pass.Stages[i];
  678. //    Assert(Stage.TextureIndex <> -1, ClassName + '.ApplyPass: ');
  679.     if (Stage.TextureIndex <> tivNull) and
  680. //      ((Stage.TextureIndex <> tivRenderTarget) or (Stage.Camera.RenderTargetIndex <> -1)) and
  681.       ((Stage.TextureIndex <> tivUnresolved) or Renderer.Textures.Resolve(Pass, i)) then begin
  682.       if (Stage.TextureIndex <> tivRenderTarget) then begin
  683.         {$IFDEF DEBUGMODE} Res := D3D_OK; {$ENDIF}
  684.         Renderer.Textures.Apply(i, Stage.TextureIndex);
  685.         Inc(TexCount);
  686.       end else begin
  687.         if Stage.Camera.IsDepthTexture and not Renderer.DepthTextures then begin
  688.           LastError := reNoDepthTextures;
  689.           Log.Log('******** !!!!!!!!!');
  690.         end else if Stage.Camera.RenderTargetIndex <> -1 then begin
  691.           if Stage.Camera.IsDepthTexture then
  692.             Res := Direct3DDevice.SetTexture(i, IDirect3DTexture8(FRenderTargets[Stage.Camera.RenderTargetIndex].DepthTexture))
  693.           else
  694.             Res := Direct3DDevice.SetTexture(i, IDirect3DTexture8(FRenderTargets[Stage.Camera.RenderTargetIndex].ColorTexture));
  695.         end else
  696.           Res := Direct3DDevice.SetTexture(i, nil);
  697.       end;
  698.       
  699.       {$IFDEF DEBUGMODE} if Res <> D3D_OK then begin Log.Log('TOGLStateWrapper.ApplyPass: Error setting texture: ' +  HResultToStr(Res), lkError); end; {$ENDIF}
  700.       Direct3DDevice.SetTextureStageState(i, D3DTSS_ADDRESSU, TexAddressing[Stage.TAddressing and $00F]);
  701.       Direct3DDevice.SetTextureStageState(i, D3DTSS_ADDRESSV, TexAddressing[(Stage.TAddressing shr 4) and $00F]);
  702.       Direct3DDevice.SetTextureStageState(i, D3DTSS_ADDRESSW, TexAddressing[(Stage.TAddressing shr 8) and $00F]);
  703.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MINFILTER, TexFilters[Stage.Filtering and $00F]);
  704.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MAGFILTER, TexFilters[(Stage.Filtering shr 4) and $00F]);
  705.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MIPFILTER, TexFilters[(Stage.Filtering shr 8) and $00F]);
  706.       Direct3DDevice.SetTextureStageState(i, D3DTSS_BORDERCOLOR, Stage.TextureBorder.C);
  707.       if VertexShaderFlag then
  708.         Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i) else
  709.           Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, Stage.UVSource and $0F or TexCoordSources[Stage.UVSource shr 4]);
  710.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, Stage.MaxMipLevel);
  711.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MAXMIPLEVEL,   Stage.MaxMipLevel);
  712.       Direct3DDevice.SetTextureStageState(i, D3DTSS_MAXANISOTROPY, Stage.MaxAnisotropy);
  713.     end else Direct3DDevice.SetTexture(i, nil);
  714.     if Pass.PixelShaderIndex < 0 then begin
  715.       Direct3DDevice.SetTextureStageState(i, D3DTSS_COLOROP,   TexOperation[Stage.ColorOp]);
  716.       Direct3DDevice.SetTextureStageState(i, D3DTSS_COLORARG1, TexArgument[Stage.ColorArg1] or Cardinal(D3DTA_COMPLEMENT * Ord(Stage.InvertColorArg1)));
  717.       Direct3DDevice.SetTextureStageState(i, D3DTSS_COLORARG2, TexArgument[Stage.ColorArg2] or Cardinal(D3DTA_COMPLEMENT * Ord(Stage.InvertColorArg2)));
  718.       Direct3DDevice.SetTextureStageState(i, D3DTSS_ALPHAOP,   TexOperation[Stage.AlphaOp]);
  719.       Direct3DDevice.SetTextureStageState(i, D3DTSS_AlphaARG1, TexArgument[Stage.AlphaArg1] or Cardinal(D3DTA_COMPLEMENT * Ord(Stage.InvertAlphaArg1)));
  720.       Direct3DDevice.SetTextureStageState(i, D3DTSS_AlphaARG2, TexArgument[Stage.AlphaArg2] or Cardinal(D3DTA_COMPLEMENT * Ord(Stage.InvertAlphaArg2)));
  721.       if Stage.StoreToTemp then
  722.         Direct3DDevice.SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_TEMP) else
  723.           Direct3DDevice.SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
  724.     end;
  725.   end;
  726.   if (LastError = reNone) and (TexCount > Renderer.MaxTexturesPerPass) then LastError := reTooManyTextures;
  727.   if (Pass.TotalStages < Integer(Renderer.MaxTextureStages)) then begin
  728.     if (Pass.PixelShaderIndex < 0) then begin
  729.       Direct3DDevice.SetTexture(Pass.TotalStages, nil);
  730.       Direct3DDevice.SetTextureStageState(Pass.TotalStages, D3DTSS_COLOROP, TexOperation[toDisable]);
  731.       Direct3DDevice.SetTextureStageState(Pass.TotalStages, D3DTSS_ALPHAOP, TexOperation[toDisable]);
  732.     end;
  733.     Direct3DDevice.SetTextureStageState(Pass.TotalStages, D3DTSS_TEXCOORDINDEX, Pass.TotalStages);
  734.     Direct3DDevice.SetTextureStageState(Pass.TotalStages, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  735.   end;
  736.   ApplyClipPlanes;
  737. end;
  738. const D3DTS_TEXTURE: array[0..7] of TD3DTransformStateType =
  739.       (D3DTS_TEXTURE0, D3DTS_TEXTURE1, D3DTS_TEXTURE2, D3DTS_TEXTURE3,
  740.        D3DTS_TEXTURE4, D3DTS_TEXTURE5, D3DTS_TEXTURE6, D3DTS_TEXTURE7);
  741. procedure TOGLStateWrapper.ApplyTextureMatrices(const Pass: TRenderPass);
  742. var i: Integer; Mat: TMatrix4s;
  743. begin
  744.   for i := 0 to MinI(Pass.TotalStages-1, Renderer.MaxTextureStages-1) do begin
  745.         case Pass.Stages[i].TextureMatrixType of
  746.           tmNone: if VertexShaderFlag then begin
  747.               if StageMatrixSet[i] then begin
  748.                 Direct3DDevice.SetTransform(D3DTS_TEXTURE[i], TD3DMatrix(IdentityMatrix4s));
  749.                 StageMatrixSet[i] := False;
  750.               end;
  751.             end else begin
  752.               if StageMatrixSet[i] then begin
  753.                 Direct3DDevice.SetTransform(D3DTS_TEXTURE[i], TD3DMatrix(IdentityMatrix4s));
  754.                 StageMatrixSet[i] := False;
  755.               end;
  756.               Mat := IdentityMatrix4s;
  757.             end;
  758.           tmCameraInverse: if Assigned(Renderer.LastAppliedCamera) then begin
  759.               MulMatrix4s(Mat, InvertAffineMatrix4s(Renderer.LastAppliedCamera.ViewMatrix),
  760.                                ScaleMatrix4s(Pass.Stages[i].TextureMatrixBias, Pass.Stages[i].TextureMatrixBias, Pass.Stages[i].TextureMatrixBias));
  761.               StageMatrixSet[i] := True;
  762.             end;
  763.           tmMirror: begin
  764.             Mat := IdentityMatrix4s;
  765.             if Assigned(Renderer.LastAppliedCamera) then
  766.               Mat := MulMatrix4s(Mat, InvertAffineMatrix4s(Renderer.LastAppliedCamera.ViewMatrix));
  767.             if Assigned(Pass.Stages[i].Camera) then begin
  768.               Mat := MulMatrix4s(Mat, Pass.Stages[i].Camera.TotalMatrix);
  769.             end;
  770.             Renderer.BiasMat._41 := 0.5;
  771.             Renderer.BiasMat._42 := 0.5 + Pass.Stages[i].TextureMatrixBias;
  772.             Renderer.BiasMat._43 := 0;
  773.             Mat := MulMatrix4s(Mat, Renderer.BiasMat);
  774.             StageMatrixSet[i] := True;
  775.           end;
  776.           tmShadowMap: if Assigned(Pass.Stages[i].Camera) then begin
  777. //            mat := IdentityMatrix4s;
  778.             Mat := InvertAffineMatrix4s(Camera.ViewMatrix);
  779.             Mat := MulMatrix4s(Mat, Pass.Stages[i].Camera.ViewMatrix);
  780.             Mat := MulMatrix4s(Mat, Pass.Stages[i].Camera.ProjMatrix);
  781.             Renderer.BiasMat._41 := 0.5 + (0.5 / Pass.Stages[i].Camera.RenderTargetWidth);
  782.             Renderer.BiasMat._42 := 0.5 + (0.5 / Pass.Stages[i].Camera.RenderTargetHeight);
  783.             Renderer.BiasMat._43 := Pass.Stages[i].TextureMatrixBias;
  784.             Mat := MulMatrix4s(Mat, Renderer.BiasMat);
  785.             StageMatrixSet[i] := True;
  786.           end;
  787.           tmScale: begin
  788.             Mat := ScaleMatrix4s(Pass.Stages[i].TextureMatrixBias, Pass.Stages[i].TextureMatrixBias, Pass.Stages[i].TextureMatrixBias);
  789.             StageMatrixSet[i] := True;
  790.           end;
  791.           tmCustom: ;
  792.           else Assert(False);
  793.         end;
  794.     if VertexShaderFlag then begin
  795. //      Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
  796.       Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, Cardinal(D3DTTFF_PROJECTED * Ord(Pass.Stages[i].TTransform and $80 > 0)));
  797.       TransposeMatrix4s(Mat);
  798.       APISetShaderConstant(skVertex, 32, Mat.Rows[0]);
  799.       APISetShaderConstant(skVertex, 33, Mat.Rows[1]);
  800.       APISetShaderConstant(skVertex, 34, Mat.Rows[2]);
  801.       APISetShaderConstant(skVertex, 35, Mat.Rows[3]);
  802.     end else begin
  803.       Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, TexTransformFlags[Pass.Stages[i].TTransform and $0F] or Cardinal(D3DTTFF_PROJECTED * Ord(Pass.Stages[i].TTransform and $80 > 0)));
  804.       Direct3DDevice.SetTransform(D3DTS_TEXTURE[i], TD3DMatrix(Mat));
  805.     end;
  806.   end;
  807. end;
  808. procedure TOGLStateWrapper.ApplyCustomTextureMatrices(const Pass: TRenderPass; Item: TVisible);
  809. var i: Integer; Mat: TMatrix4s;
  810. begin
  811.   for i := 0 to MinI(Pass.TotalStages-1, Renderer.MaxTextureStages-1) do
  812.     if Pass.Stages[i].TextureMatrixType = tmCustom then begin
  813.       Direct3DDevice.SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, TexTransformFlags[Pass.Stages[i].TTransform and $0F] or Cardinal(D3DTTFF_PROJECTED * Ord(Pass.Stages[i].TTransform and $80 > 0)));
  814.       if Assigned(Item.RetrieveTextureMatrix) then Item.RetrieveTextureMatrix(i, Mat) else Mat := IdentityMatrix4s;
  815.       Direct3DDevice.SetTransform(D3DTS_TEXTURE[i], TD3DMatrix(Mat));
  816.       StageMatrixSet[i] := True;
  817.     end;
  818. end;
  819. procedure TOGLStateWrapper.ObtainRenderTargetSurfaces;
  820. begin
  821.   Direct3DDevice.GetRenderTarget(MainRenderTarget);
  822.   Direct3DDevice.GetDepthStencilSurface(MainDepthStencil);
  823.   CurrentRenderTarget := MainRenderTarget;
  824.   CurrentDepthStencil := MainDepthStencil;
  825. end;
  826. procedure TOGLStateWrapper.CleanUpNonManaged;
  827. var i: Integer;
  828. begin
  829.   for i := 0 to High(FRenderTargets) do DestroyRenderTarget(i);
  830.   MainRenderTarget := nil;
  831.   MainDepthStencil := nil;
  832.   CurrentRenderTarget := nil;
  833.   CurrentDepthStencil := nil;
  834. end;
  835. procedure TOGLStateWrapper.RestoreNonManaged;
  836. var i: Integer;
  837. begin
  838.   for i := 0 to High(FRenderTargets) do CreateRenderTarget(i, FRenderTargets[i].Width, FRenderTargets[i].Height, FRenderTargets[i].ActualColorFormat, FRenderTargets[i].ActualDepthFormat, FRenderTargets[i].IsDepthTexture);
  839.   ObtainRenderTargetSurfaces;
  840. end;
  841. procedure TOGLStateWrapper.FVFToDeclaration(VertexFormat: Cardinal; var Result: POGLVertexDeclaration);
  842. const Floats: array[1..4] of Longword = (D3DVSDT_FLOAT1, D3DVSDT_FLOAT2, D3DVSDT_FLOAT3, D3DVSDT_FLOAT4);
  843. var Ind, i: Integer; ErrorStr: string;
  844. begin
  845.   ErrorStr := Format('%S.%S: FVF containing transformed verticed can not be conveted to vertex declaration', [ClassName, 'FVFToDeclaration']);
  846.   Assert(not VertexContains(VertexFormat, vfTRANSFORMED), ErrorStr);
  847.   if VertexContains(VertexFormat, vfTRANSFORMED) then begin
  848.     {$IFDEF LOGGING} Log.Log(ErrorStr, lkError); {$ENDIF}
  849.     Exit;
  850.   end;
  851. {  Size := 3;
  852.   if GetVertexWeightsCount(VertexFormat) > 0   then Inc(Size);
  853.   if VertexContains(VertexFormat, vfNORMALS)   then Inc(Size);
  854.   if VertexContains(VertexFormat, vfPOINTSIZE) then Inc(Size);
  855.   if VertexContains(VertexFormat, vfDIFFUSE)   then Inc(Size);
  856.   if VertexContains(VertexFormat, vfSPECULAR)  then Inc(Size);
  857.   Inc(Size, GetVertexTextureSetsCount(VertexFormat));
  858. }
  859.   Ind := 0;
  860.   Result^[Ind] := D3DVSD_STREAM(0);
  861.   Inc(Ind);
  862.   Result^[Ind] := D3DVSD_REG(0, D3DVSDT_FLOAT3);                                        // Position
  863.   Inc(Ind);
  864.   if GetVertexWeightsCount(VertexFormat) > 0 then begin
  865.     Result^[Ind] := D3DVSD_REG(1, Floats[GetVertexWeightsCount(VertexFormat) +          // Blending weights
  866.                                          Ord(GetVertexIndexedBlending(VertexFormat))]);
  867.     Inc(Ind);
  868.   end;
  869.   if VertexContains(VertexFormat, vfNORMALS) then begin
  870.     Result^[Ind] := D3DVSD_REG(2, D3DVSDT_FLOAT3);                                      // Normals
  871.     Inc(Ind);
  872.   end;
  873.   if VertexContains(VertexFormat, vfPOINTSIZE) then begin
  874.     Result^[Ind] := D3DVSD_REG(3, D3DVSDT_FLOAT1);                                      // Point size
  875.     Inc(Ind);
  876.   end;
  877.   if VertexContains(VertexFormat, vfDIFFUSE) then begin
  878.     Result^[Ind] := D3DVSD_REG(4, D3DVSDT_D3DCOLOR);                                    // Diffuse color
  879.     Inc(Ind);
  880.   end;
  881.   if VertexContains(VertexFormat, vfSPECULAR) then begin
  882.     Result^[Ind] := D3DVSD_REG(5, D3DVSDT_D3DCOLOR);                                    // Specular color
  883.     Inc(Ind);
  884.   end;
  885.   for i := 0 to GetVertexTextureSetsCount(VertexFormat)-1 do begin
  886.     Result^[Ind] := D3DVSD_REG(6+i, Floats[GetVertexTextureCoordsCount(VertexFormat, i)]);       // Texture coordinates set i
  887.     Inc(Ind);
  888.   end;
  889.   Result^[Ind] := D3DVSD_END;
  890. end;
  891. procedure TOGLStateWrapper.DeclarationToAPI(Declaration: TVertexDeclaration; ConstantsData: Pointer; ConstantsSize: Integer; var Result: POGLVertexDeclaration);
  892. const ErrorStr = '.DeclarationToAPI: Invalid vertex declaration';
  893. var i, ConstantTokens: Integer;
  894. begin
  895.   if ConstantsSize <> 0 then begin
  896.     ConstantTokens := ConstantsSize div SizeOf(Result^[0]);
  897.     Assert(ConstantsSize mod SizeOf(Result^[0]) = 0);
  898.     Move(ConstantsData^, Result^, ConstantsSize);
  899.   end else ConstantTokens := 0;
  900.   Result^[ConstantTokens] := D3DVSD_STREAM(0);
  901.   for i := 0 to High(Declaration) do case Declaration[i] of
  902.     vdtFloat1:  Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_FLOAT1);
  903.     vdtFloat2:  Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_FLOAT2);
  904.     vdtFloat3:  Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_FLOAT3);
  905.     vdtFloat4:  Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_FLOAT4);
  906.     vdtColor:   Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_D3DCOLOR);
  907.     vdtByte4:   Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_UBYTE4);
  908.     vdtInt16_2: Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_SHORT2);
  909.     vdtInt16_4: Result^[i+1+ConstantTokens] := D3DVSD_REG(i, D3DVSDT_SHORT4);
  910.     vdtNothing: Result^[i+1+ConstantTokens] := D3DVSD_NOP;
  911.     else begin
  912.       Assert(False, ClassName + ErrorStr);
  913.       {$IFDEF LOGGING} Log.Log(ClassName + ErrorStr, lkError); {$ENDIF}
  914.     end;
  915.   end;
  916.   Result[High(Declaration)+ConstantTokens+2] := D3DVSD_END;
  917. end;
  918. procedure TOGLStateWrapper.APISetShaderConstant(ShaderKind: TShaderKind; ShaderRegister: Integer; const Vector: TShaderRegisterType);
  919. begin
  920.   case ShaderKind of
  921.     skVertex: Direct3DDevice.SetVertexShaderConstant(ShaderRegister, Vector, 1);
  922.     skPixel:  Direct3DDevice.SetPixelShaderConstant(ShaderRegister, Vector, 1);
  923.   end;
  924. end;
  925. procedure TOGLStateWrapper.APISetShaderConstant(const Constant: TShaderConstant);
  926. begin
  927.   with Constant do case ShaderKind of
  928.     skVertex: Direct3DDevice.SetVertexShaderConstant(ShaderRegister, Value, 1);
  929.     skPixel:  Direct3DDevice.SetPixelShaderConstant(ShaderRegister, Value, 1);
  930.   end;
  931. end;
  932. function TOGLStateWrapper.APIValidatePass(const Pass: TRenderPass; out ResultStr: string): Boolean;
  933. var Res: HResult; NumPasses: Cardinal;
  934. begin
  935.   Res := Direct3DDevice.ValidateDevice(NumPasses);
  936.   case Res of
  937.     D3D_OK, D3DERR_CONFLICTINGTEXTUREFILTER, D3DERR_UNSUPPORTEDTEXTUREFILTER: Result := True;
  938.     else Result := False;
  939.   end;
  940.   if Res <> D3D_OK then ResultStr := ' (' + HResultToStr(Res) + ')' else ResultStr := '';
  941. end;
  942. { TOGLRenderer }
  943. constructor TOGLRenderer.Create(Manager: TItemsManager);
  944. var i: Integer; AID: TD3DAdapter_Identifier8;
  945. begin
  946.   {$Include C2OGLInit.inc}
  947.   inherited;
  948.   Log.Log('Starting OGLRenderer...', lkNotice);
  949.   if not LoadDirect3D8 then begin
  950.     Log.Log('DirectX 8 or greater not installed', lkFatalError);
  951.     Exit;
  952.   end;
  953.   Direct3DDevice := nil;
  954.   FillChar(AID, SizeOf(AID), 0);
  955.   Direct3D := Direct3DCreate8(D3D_SDK_VERSION);
  956. //  if Direct3D <> nil then i := Direct3D._Release;
  957.   if Direct3D = nil then begin
  958.     Log.Log(ClassName + '.Create: Error creating Direct3D object', lkFatalError);
  959.   end else begin
  960.     Log.Log(ClassName + '.Create: Direct3D object succesfully Create');
  961.     FTotalAdapters := Direct3D.GetAdapterCount;
  962.     SetLength(FAdapterNames, TotalAdapters);
  963.     for i := 0 to TotalAdapters - 1 do begin
  964.       // Fill in adapter info
  965.       Direct3D.GetAdapterIdentifier(i, D3DENUM_NO_WHQL_LEVEL, AID);
  966.       FAdapterNames[i] := AID.Description;
  967.       {$IFDEF LOGGING}
  968.       Log.Log('Found video adapter "'+AID.Description+'"');
  969.       Log.Log('  Driver: ' + AID.Driver);
  970.       Log.Log('  Driver version: Product ' + IntToStr((AID.DriverVersion shr 48) and $FFFF) + ', version ' + IntToStr((AID.DriverVersion shr 32) and $FFFF) +
  971.               ', subversion ' + IntToStr((AID.DriverVersion shr 16) and $FFFF) + ', build ' + IntToStr(AID.DriverVersion and $FFFF));
  972.       Log.Log('  Vendor ID: ' + IntToStr(AID.VendorId) + ', device ID: ' + IntToStr(AID.DeviceId)+', subsystem ID: ' + IntToStr(AID.SubSysId) + ', revision: ' + IntToStr(AID.Revision));
  973. //      if AID.WHQLLevel = 0 then Log.Log('Driver is not WHQL certified') else Log.Log('Driver is WHQL certified');
  974.       {$ENDIF}
  975.     end;
  976.   end;
  977.   FCurrentAdapter := D3DADAPTER_DEFAULT;
  978.   SetDeviceType(dtHAL);
  979.   Textures   := TOGLTextures.Create;
  980.   APIState   := TOGLStateWrapper.Create;
  981.   APIBuffers := TOGLBuffers.Create(Self);
  982.   InternalInit;
  983. end;
  984. function TOGLRenderer.APICheckFormat(const Format, Usage, RTFormat: Cardinal): Boolean;
  985. var Res: HResult; D3DUsage, AdapterFormat: Cardinal; D3DResType: TD3DResourceType;
  986. begin
  987.   Result := False;
  988. //  if Format = pfa8r8g8b8 then Exit;
  989.   Assert((Format < TotalPixelFormats));
  990.   if (Format <= 0) or (Format >= TotalPixelFormats) or (PFormats[Format] = Cardinal(D3DFMT_UNKNOWN)) then Exit;
  991.   case Usage of
  992.     fuRenderTarget: begin D3DUsage := D3DUSAGE_RENDERTARGET; D3DResType := D3DRTYPE_TEXTURE; end;
  993.     fuDepthStencil, fuDEPTHTEXTURE: begin
  994.       if not IsDepthFormat(Format) then Exit;
  995.       D3DUsage := D3DUSAGE_DEPTHSTENCIL;
  996.       if Usage = fuDepthStencil then
  997.         D3DResType := D3DRTYPE_SURFACE else
  998.           D3DResType := D3DRTYPE_TEXTURE;
  999.     end;
  1000.     fuVolumeTexture:  begin D3DUsage := 0; D3DResType := D3DRTYPE_VOLUMETEXTURE; end;
  1001.     fuCubeTexture:    begin D3DUsage := 0; D3DResType := D3DRTYPE_CUBETEXTURE;  end;
  1002.     else {fuTexture:} begin D3DUsage := 0; D3DResType := D3DRTYPE_TEXTURE; end;
  1003.   end;
  1004.   if FFullScreen then
  1005.     AdapterFormat := PFormats[VideoMode[CurrentVideoMode].Format] else
  1006.       AdapterFormat := PFormats[DesktopVideoMode.Format];
  1007.   Res := Direct3D.CheckDeviceFormat(FCurrentAdapter, CurrentDeviceType, TD3DFormat(AdapterFormat), D3DUsage, D3DResType, TD3DFormat(PFormats[Format]));
  1008.   case Res of
  1009.     D3D_OK: Result := True;
  1010.     D3DERR_INVALIDCALL: {$IFDEF DEBUGMODE} {$IFDEF LOGGING} Log.Log(ClassName + 'CheckTextureFormat: Invalid call', lkWarning)  {$ENDIF} {$ENDIF} ;
  1011.     D3DERR_NOTAVAILABLE: ;
  1012.     else {$IFDEF LOGGING} Log.Log(ClassName + 'CheckTextureFormat: Unknown error', lkWarning) {$ENDIF} ;
  1013.   end;
  1014.   // Check if depth-stencil is compatible with a render target format
  1015.   if Result and ((Usage = fuDepthStencil) or (Usage = fuDEPTHTEXTURE)) and (RTFormat <> pfUndefined) then begin
  1016.     Result := False;
  1017.     Res := Direct3D.CheckDepthStencilMatch(FCurrentAdapter, CurrentDeviceType, TD3DFormat(AdapterFormat), TD3DFormat(PFormats[RTFormat]), TD3DFormat(PFormats[Format]));
  1018.     case Res of
  1019.       D3D_OK: Result := True;
  1020.       D3DERR_INVALIDCALL: {$IFDEF LOGGING} Log.Log(ClassName + 'CheckDepthStencilMatch: Invalid call', lkWarning) {$ENDIF} ;
  1021.       D3DERR_NOTAVAILABLE: ;
  1022.       else {$IFDEF LOGGING} Log.Log(ClassName + 'CheckDepthStencilMatch: Unknown error', lkWarning) {$ENDIF} ;
  1023.     end;
  1024.   end;
  1025. end;
  1026. procedure TOGLRenderer.APIPrepareFVFStates(Item: TVisible);
  1027. //const D3DTS_AdditionalWorld: array[0..2] of TD3DTransformStateType = (D3DTS_World1, D3DTS_World2, D3DTS_World3);
  1028. var i: Integer;
  1029. begin
  1030.   Direct3DDevice.SetVertexShader(APIBuffers.GetFVF(Item.CurrentTesselator.VertexFormat));
  1031.   // Item matrices setting
  1032.   Direct3DDevice.SetTransform(D3DTS_World, TD3DMatrix(Item.Transform));
  1033.   for i := 0 to Length(Item.BlendMatrices)-1 do
  1034.     Direct3DDevice.SetTransform(D3DTS_WORLDMATRIX(i), TD3DMatrix(Item.BlendMatrices[i]));
  1035.   //           * Move to material settings *
  1036.   Direct3DDevice.SetRenderState(D3DRS_VERTEXBLEND, (Item.CurrentTesselator.VertexFormat shr 28) and $7);        // Turn on vertex blending if weights present
  1037.   Direct3DDevice.SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, Ord((Item.CurrentTesselator.VertexFormat shr 28) and vwIndexedBlending = vwIndexedBlending));
  1038.   Direct3DDevice.SetRenderState(D3DRS_COLORVERTEX, Ord(Item.CurrentTesselator.VertexFormat and vfDiffuse > 0));   // Turn on vertex coloring if diffuse present
  1039.   if Item.CurrentTesselator.VertexFormat and vfDiffuse > 0 then
  1040.     Direct3DDevice.SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1) else
  1041.       Direct3DDevice.SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
  1042.   if Item.CurrentTesselator.VertexFormat and vfSpecular > 0 then
  1043.     Direct3DDevice.SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2) else
  1044.       Direct3DDevice.SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
  1045. end;
  1046. procedure TOGLRenderer.InternalDeInit;
  1047. begin
  1048.   CleanUpNonManaged;
  1049.   FreeAndNil(APIBuffers);
  1050.   FAdapterNames := nil;
  1051.   FVideoModes   := nil;
  1052. //  i := Direct3DDevice._Release;
  1053.   Direct3DDevice := nil;
  1054.   if Assigned(Direct3D) then begin
  1055. //    i := Direct3D._Release;
  1056.     Direct3D := nil;
  1057.   end;
  1058.   inherited;
  1059. end;
  1060. procedure TOGLRenderer.SetDeviceType(DevType: Cardinal);
  1061. const DXDeviceTypes: array[0..2] of TD3DDEVTYPE = (D3DDEVTYPE_HAL, D3DDEVTYPE_REF, D3DDEVTYPE_SW);
  1062. begin
  1063.   if DevType > 2 then Exit;
  1064.   CurrentDeviceType := DXDeviceTypes[DevType];
  1065.   SetVideoAdapter(FCurrentAdapter);  
  1066. end;
  1067. function TOGLRenderer.FindDepthStencilFormat(iAdapter: Word; DeviceType: TD3DDEVTYPE; TargetFormat: TD3DFORMAT; var DepthStencilFormat: TD3DFORMAT) : Boolean;
  1068. const
  1069.   TotalDepthFormats = 6;
  1070.   DepthFormats: array[False..True, 0..TotalDepthFormats-1] of TD3DFORMAT = (
  1071.   (D3DFMT_D32,   D3DFMT_D24X8,   D3DFMT_D24S8, D3DFMT_D24X4S4, D3DFMT_D16,   D3DFMT_D15S1),
  1072.   (D3DFMT_D24S8, D3DFMT_D24X4S4, D3DFMT_D15S1, D3DFMT_D32,     D3DFMT_D24X8, D3DFMT_D16));
  1073. var i: Integer;
  1074. begin
  1075.   Result := True;
  1076.   for i := 0 to TotalDepthFormats-1 do
  1077.     if not Failed(Direct3D.CheckDeviceFormat(iAdapter, DeviceType, TargetFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, DepthFormats[arUseStencil in AppRequirements.Flags, i])) then
  1078.       if not Failed(Direct3D.CheckDepthStencilMatch(iAdapter, DeviceType, TargetFormat, TargetFormat, DepthFormats[arUseStencil in AppRequirements.Flags, i])) then begin
  1079.         DepthStencilFormat := DepthFormats[arUseStencil in AppRequirements.Flags, i];
  1080.         Exit;
  1081.       end;
  1082.   Result := False;
  1083. end;
  1084. procedure TOGLRenderer.BuildModeList;
  1085. var
  1086.   iMode: Integer;
  1087.   dwNumModes: Longword;
  1088.   DisplayMode : TD3DDISPLAYMODE;
  1089.   m : Longword;
  1090.   procedure SortModes(N: Integer; Values: TVideoModes);
  1091.   type _QSDataType = TVideoMode;
  1092.     function _QSCompare(const V1, V2: _QSDataType): Integer;
  1093.     begin
  1094.       Result := Integer(GetBytesPerPixel(V1.Format)) - Integer(GetBytesPerPixel(V2.Format));
  1095.       if Result = 0 then
  1096.         Result := (V1.Width shl 16 + V1.Height) -
  1097.                   (V2.Width shl 16 + V2.Height);
  1098.       if Result = 0 then Result := V1.RefreshRate - V2.RefreshRate;
  1099.     end;
  1100.   {$I basics_quicksort.inc}              // Include the quick sort algorithm
  1101.   {$IFNDEF ForCodeNavigationWork} begin end; {$ENDIF}
  1102. begin
  1103.   // Enumerate all display modes on this adapter
  1104.   FTotalVideoModes := Direct3D.GetAdapterModeCount(FCurrentAdapter);
  1105.   SetLength(FVideoModes, FTotalVideoModes);
  1106.   dwNumModes := 0;
  1107.   for iMode := 0 to FTotalVideoModes - 1 do begin
  1108.     // Get the display mode attributes
  1109.     Direct3D.EnumAdapterModes(FCurrentAdapter, iMode, DisplayMode);
  1110.     // Filter out low-resolution modes
  1111.     if DisplayMode.Height < AppRequirements.MinYResolution then Continue;
  1112.     // Filter out unsupported with chosen device type modes
  1113.     if Failed(Direct3D.CheckDeviceType(FCurrentAdapter, CurrentDeviceType, DisplayMode.Format, DisplayMode.Format, False)) and
  1114.        Failed(Direct3D.CheckDeviceType(FCurrentAdapter, CurrentDeviceType, DisplayMode.Format, DisplayMode.Format, True)) then
  1115.       Continue;
  1116.     // Check if the mode already exists (to filter out refresh rates)
  1117.     m := 0;
  1118.     while m < dwNumModes do begin
  1119.       if not (arModesUseRefresh in AppRequirements.Flags) and
  1120.          (FVideoModes[m].Width  = Integer(DisplayMode.Width) ) and
  1121.          (FVideoModes[m].Height = Integer(DisplayMode.Height)) and
  1122.          (PFormats[FVideoModes[m].Format] = Cardinal(DisplayMode.Format)) then Break;
  1123.       Inc(m);
  1124.     end;
  1125.     // If we found a new mode, add it to the list of modes
  1126.     if m = dwNumModes then begin
  1127.       FVideoModes[dwNumModes].Width       := DisplayMode.Width;
  1128.       FVideoModes[dwNumModes].Height      := DisplayMode.Height;
  1129.       FVideoModes[dwNumModes].Format      := APIToPixelFormat(Cardinal(DisplayMode.Format));
  1130.       FVideoModes[dwNumModes].RefreshRate := DisplayMode.RefreshRate;
  1131.       Inc(dwNumModes);
  1132.     end;
  1133.   end;
  1134.   FTotalVideoModes := dwNumModes;
  1135.   SetLength(FVideoModes, FTotalVideoModes);
  1136.   // Sort the list of display modes (by format, then width, then height, then refresh)
  1137.   SortModes(FTotalVideoModes, FVideoModes);
  1138.   {$IFDEF LOGGING} {$IFDEF EXTLOGGING}
  1139. //  for i := 0 to FTotalVideoModes-1 do begin
  1140. //    Log.Log(Format('Video mode: [%Dx%Dx%D, %DHz', [FVideoModes[i].Width, FVideoModes[i].Height, GetBitDepth(FVideoModes[i].Format), FVideoModes[i].RefreshRate]));
  1141. //  end;
  1142.   {$ENDIF} {$ENDIF}
  1143. end;
  1144. procedure TOGLRenderer.SetGamma(Gamma, Contrast, Brightness: Single);
  1145. begin
  1146.   inherited;
  1147.   if IsReady then
  1148.     Direct3DDevice.SetGammaRamp(D3DSGR_NO_CALIBRATION, TD3DGammaRamp(GammaRamp));
  1149. end;
  1150. procedure TOGLRenderer.CheckCaps;
  1151. {$IFDEF EXTLOGGING}
  1152. const CanStr: array[False..True] of string[3] = ('[ ]', '[X]');
  1153. {$ENDIF}
  1154. var Caps: TD3DCaps8;
  1155. begin
  1156.   if Direct3DDevice = nil then begin
  1157.     Log.Log('CheckCaps: Direct3D device was not initialized', lkError);
  1158.     Exit;
  1159.   end;
  1160.   Direct3DDevice.GetDeviceCaps(Caps);
  1161.   {$IFDEF EXTLOGGING}
  1162.   Log.Log('Checking 3D device capabilites...', lkNotice);
  1163.   Log.Log('----------', lkInfo);
  1164.   Log.Log(' Driver caps', lkInfo);
  1165.   Log.Log(CanStr[Caps.Caps and D3DCAPS_READ_SCANLINE > 0]+' Display hardware is capable of returning the current scan line', lkInfo);
  1166.   Log.Log(CanStr[Caps.Caps2 and D3DCAPS2_CANRENDERWINDOWED > 0]+' The driver is capable of rendering in windowed mode', lkInfo);
  1167.   Log.Log(CanStr[Caps.Caps2 and D3DDEVCAPS_HWTRANSFORMANDLIGHT > 0]+' The driver supports dynamic gamma ramp adjustment in full-screen mode', lkInfo);
  1168.   Log.Log(' Device caps', lkInfo);
  1169.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_DRAWPRIMTLVERTEX > 0]+' Device exports a DrawPrimitive-aware hardware abstraction layer (HAL)', lkInfo);
  1170.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_HWRASTERIZATION > 0]+' Device has hardware acceleration for scene rasterization', lkInfo);
  1171.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_HWTRANSFORMANDLIGHT > 0]+' Device can support transformation and lighting in hardware', lkInfo);
  1172.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_PUREDEVICE > 0]+' Device can support rasterization, transform, lighting, and shading in hardware', lkInfo);
  1173.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_TEXTUREVIDEOMEMORY > 0]+' Device can retrieve textures from device memory', lkInfo);
  1174.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_TLVERTEXSYSTEMMEMORY > 0]+' Device can use buffers from system memory for transformed and lit vertices', lkInfo);
  1175.   Log.Log(CanStr[Caps.DevCaps and D3DDEVCAPS_TLVERTEXVIDEOMEMORY > 0]+' Device can use buffers from video memory for transformed and lit vertices', lkInfo);
  1176.   Log.Log(' Raster caps', lkInfo);
  1177.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_FOGRANGE > 0]+' Device supports range-based fog', lkInfo);
  1178.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_FOGTABLE > 0]+' Device supports table fog', lkInfo);
  1179.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_FOGVERTEX > 0]+' Device calculates the fog value during the lighting operation, and interpolates the fog value during rasterization', lkInfo);
  1180.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_MIPMAPLODBIAS > 0]+' Device supports level-of-detail (LOD) bias adjustments', lkInfo);
  1181.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE > 0]+' Device provides limited multisample support through a stretch-blt implementation', lkInfo);
  1182.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_WBUFFER > 0]+' Device supports depth buffering using w', lkInfo);
  1183.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_WFOG > 0]+' Device supports w-based fog', lkInfo);
  1184.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_ZBUFFERLESSHSR > 0]+' Device can perform hidden-surface removal (HSR)', lkInfo);
  1185.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_ZFOG > 0]+' Device supports z-based fog', lkInfo);
  1186.   Log.Log(CanStr[Caps.RasterCaps and D3DPRASTERCAPS_PAT > 0]+' Device supports patterned drawing', lkInfo);
  1187.   Log.Log(CanStr[Caps.ShadeCaps and D3DPSHADECAPS_SPECULARGOURAUDRGB > 0]+' Device can support specular highlights in Gouraud shading in the RGB color model', lkInfo);
  1188.   Log.Log(' Vertex processing caps', lkInfo);
  1189.   Log.Log('Max clip planes: ' + IntToStr(Caps.MaxUserClipPlanes), lkInfo);
  1190.   Log.Log(CanStr[Caps.VertexProcessingCaps and D3DVTXPCAPS_TEXGEN > 0]+' Device can generate texture coordinates', lkInfo);
  1191.   Log.Log(CanStr[Caps.VertexProcessingCaps and D3DVTXPCAPS_TWEENING > 0]+' Device supports vertex tweening', lkInfo);
  1192.   Log.Log(CanStr[Caps.VertexProcessingCaps and D3DVTXPCAPS_MATERIALSOURCE7 > 0]+' Device supports selectable vertex color sources', lkInfo);
  1193.   Log.Log('Max vertex w: '+FloatToStrF(Caps.MaxVertexW, ffFixed, 10, 1), lkInfo);
  1194.   Log.Log(CanStr[Caps.PrimitiveMiscCaps and D3DPMISCCAPS_CLIPTLVERTS > 0]+' Device clips post-transformed vertex primitives', lkInfo);
  1195.   Log.Log('Max number of primitives: '+IntToStr(Caps.MaxPrimitiveCount), lkInfo);
  1196.   Log.Log('Max vertex index: '+IntToStr(Caps.MaxVertexIndex), lkInfo);
  1197.   Log.Log(' Blending operations caps', lkInfo);
  1198.   Log.Log(CanStr[Caps.PrimitiveMiscCaps and D3DPMISCCAPS_BLENDOP  > 0]+' Device supports all the alpha-blending operations (ADD, SUB, REVSUB, MIN, MAX)', lkInfo);
  1199.   Log.Log(' Source blending caps', lkInfo);
  1200.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_DESTALPHA > 0]+' Blend factor is (Ad, Ad, Ad, Ad)', lkInfo);
  1201.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_DESTCOLOR > 0]+' Blend factor is (Rd, Gd, Bd, Ad)', lkInfo);
  1202.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_INVDESTALPHA > 0]+' Blend factor is (1朅d, 1朅d, 1朅d, 1朅d)', lkInfo);
  1203.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_INVDESTCOLOR  > 0]+' Blend factor is (1朢d, 1朑d, 1朆d, 1朅d)', lkInfo);
  1204.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_INVSRCALPHA > 0]+' Blend factor is (1朅s, 1朅s, 1朅s, 1朅s)', lkInfo);
  1205.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_INVSRCCOLOR > 0]+' Blend factor is (1朢d, 1朑d, 1朆d, 1朅d)', lkInfo);
  1206.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_ONE > 0]+' Blend factor is (1, 1, 1, 1)', lkInfo);
  1207.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_SRCALPHA > 0]+' Blend factor is (As, As, As, As)', lkInfo);
  1208.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_SRCALPHASAT > 0]+' Blend factor is (f, f, f, 1); f = min(As, 1-Ad)', lkInfo);
  1209.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_SRCCOLOR > 0]+' Blend factor is (Rs, Gs, Bs, As)', lkInfo);
  1210.   Log.Log(CanStr[Caps.SrcBlendCaps and D3DPBLENDCAPS_ZERO > 0]+' Blend factor is (0, 0, 0, 0)', lkInfo);
  1211.   Log.Log(' Destination blending caps', lkInfo);
  1212.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_DESTALPHA > 0]+' Blend factor is (Ad, Ad, Ad, Ad)', lkInfo);
  1213.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_DESTCOLOR > 0]+' Blend factor is (Rd, Gd, Bd, Ad)', lkInfo);
  1214.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_INVDESTALPHA > 0]+' Blend factor is (1朅d, 1朅d, 1朅d, 1朅d)', lkInfo);
  1215.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_INVDESTCOLOR  > 0]+' Blend factor is (1朢d, 1朑d, 1朆d, 1朅d)', lkInfo);
  1216.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_INVSRCALPHA > 0]+' Blend factor is (1朅s, 1朅s, 1朅s, 1朅s)', lkInfo);
  1217.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_INVSRCCOLOR > 0]+' Blend factor is (1朢d, 1朑d, 1朆d, 1朅d)', lkInfo);
  1218.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_ONE > 0]+' Blend factor is (1, 1, 1, 1)', lkInfo);
  1219.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_SRCALPHA > 0]+' Blend factor is (As, As, As, As)', lkInfo);
  1220.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_SRCALPHASAT > 0]+' Blend factor is (f, f, f, 1); f = min(As, 1-Ad)', lkInfo);
  1221.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_SRCCOLOR > 0]+' Blend factor is (Rs, Gs, Bs, As)', lkInfo);
  1222.   Log.Log(CanStr[Caps.DestBlendCaps and D3DPBLENDCAPS_ZERO > 0]+' Blend factor is (0, 0, 0, 0)', lkInfo);
  1223.   Log.Log(' Texture caps', lkInfo);
  1224.   Log.Log('Max texture width: '+IntToStr(Caps.MaxTextureWidth), lkInfo);
  1225.   Log.Log('Max texture height: '+IntToStr(Caps.MaxTextureHeight), lkInfo);
  1226.   Log.Log('Max texture repeat times: '+IntToStr(Caps.MaxTextureRepeat), lkInfo);
  1227.   Log.Log('Max texture aspect ratio: '+IntToStr(Caps.MaxTextureAspectRatio), lkInfo);
  1228.   Log.Log('Max texture blend stages: '+IntToStr(Caps.MaxTextureBlendStages), lkInfo);
  1229.   Log.Log('Max simultaneous textures: '+IntToStr(Caps.MaxSimultaneousTextures), lkInfo);
  1230.   Log.Log(CanStr[Caps.PrimitiveMiscCaps and D3DPMISCCAPS_TSSARGTEMP > 0]+' Texture stage destination can be temporal register', lkInfo);
  1231.   Log.Log(CanStr[Caps.TextureCaps and D3DPTEXTURECAPS_ALPHA > 0]+' Alpha in texture pixels is supported', lkInfo);
  1232.   Log.Log(CanStr[Caps.TextureCaps and D3DPTEXTURECAPS_ALPHAPALETTE > 0]+' Device can draw alpha from texture palettes', lkInfo);
  1233.   Log.Log(CanStr[Caps.TextureCaps and D3DPTEXTURECAPS_PROJECTED > 0]+' Supports the D3DTTFF_PROJECTED texture transformation flag', lkInfo);
  1234.   Log.Log(CanStr[not (Caps.TextureCaps and D3DPTEXTURECAPS_SQUAREONLY > 0)]+' Textures can be nonsquare', lkInfo);
  1235.   {$ENDIF}
  1236.   CheckTextureFormats;
  1237.   {$IFDEF EXTLOGGING}
  1238.   Log.Log(CanStr[DepthTextures]+' Depth textures support', lkInfo);
  1239.   Log.Log(' Texture operation caps', lkInfo);
  1240.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_ADD > 0]+' The D3DTOP_ADD texture-blending operation is supported', lkInfo);
  1241.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_ADDSIGNED > 0]+' The D3DTOP_ADDSIGNED texture-blending operation is supported', lkInfo);
  1242.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_ADDSIGNED2X > 0]+' The D3DTOP_ADDSIGNED2X texture-blending operation is supported', lkInfo);
  1243.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_ADDSMOOTH > 0]+' The D3DTOP_ADDSMOOTH texture-blending operation is supported', lkInfo);
  1244.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BLENDCURRENTALPHA > 0]+' The D3DTOP_BLENDCURRENTALPHA texture-blending operation is supported', lkInfo);
  1245.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BLENDDIFFUSEALPHA > 0]+' The D3DTOP_BLENDDIFFUSEALPHA texture-blending operation is supported', lkInfo);
  1246.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BLENDFACTORALPHA > 0]+' The D3DTOP_BLENDFACTORALPHA texture-blending operation is supported', lkInfo);
  1247.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BLENDTEXTUREALPHA > 0]+' The D3DTOP_BLENDTEXTUREALPHA texture-blending operation is supported', lkInfo);
  1248.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BLENDTEXTUREALPHAPM > 0]+' The D3DTOP_BLENDTEXTUREALPHAPM texture-blending operation is supported', lkInfo);
  1249.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BUMPENVMAP > 0]+' The D3DTOP_BUMPENVMAP texture-blending operation is supported', lkInfo);
  1250.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_BUMPENVMAPLUMINANCE > 0]+' The D3DTOP_BUMPENVMAPLUMINANCE texture-blending operation is supported', lkInfo);
  1251.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_DISABLE > 0]+' The D3DTOP_DISABLE texture-blending operation is supported', lkInfo);
  1252.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_DOTPRODUCT3 > 0]+' The D3DTOP_DOTPRODUCT3 texture-blending operation is supported', lkInfo);
  1253.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_LERP > 0]+' The D3DTOP_LERP texture-blending operation is supported', lkInfo);
  1254.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATE > 0]+' The D3DTOP_MODULATE texture-blending operation is supported', lkInfo);
  1255.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATE2X > 0]+' The D3DTOP_MODULATE2X texture-blending operation is supported', lkInfo);
  1256.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATE4X > 0]+' The D3DTOP_MODULATE4X texture-blending operation is supported', lkInfo);
  1257.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR > 0]+' The D3DTOP_MODULATEALPHA_ADDCOLOR texture-blending operation is supported', lkInfo);
  1258.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA > 0]+' The D3DTOP_MODULATECOLOR_ADDALPHA texture-blending operation is supported', lkInfo);
  1259.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR > 0]+' The D3DTOP_MODULATEINVALPHA_ADDCOLOR texture-blending operation is supported', lkInfo);
  1260.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA > 0]+' The D3DTOP_MODULATEINVCOLOR_ADDALPHA texture-blending operation is supported', lkInfo);
  1261.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_MULTIPLYADD > 0]+' The D3DTOP_MULTIPLYADD texture-blending operation is supported', lkInfo);
  1262.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_PREMODULATE > 0]+' The D3DTOP_PREMODULATE texture-blending operation is supported', lkInfo);
  1263.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_SELECTARG1 > 0]+' The D3DTOP_SELECTARG1 texture-blending operation is supported', lkInfo);
  1264.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_SELECTARG2 > 0]+' The D3DTOP_SELECTARG2 texture-blending operation is supported', lkInfo);
  1265.   Log.Log(CanStr[Caps.TextureOpCaps and D3DTEXOPCAPS_SUBTRACT > 0]+' The D3DTOP_SUBTRACT texture-blending operation is supported', lkInfo);
  1266.   Log.Log(' Stencil buffer caps', lkInfo);
  1267.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_DECR > 0]+' The D3DSTENCILOP_DECR operation is supported', lkInfo);
  1268.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_DECRSAT > 0]+' The D3DSTENCILOP_DECRSAT operation is supported', lkInfo);
  1269.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_INCR > 0]+' The D3DSTENCILOP_INCR operation is supported', lkInfo);
  1270.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_INCRSAT > 0]+' The D3DSTENCILOP_INCRSAT operation is supported', lkInfo);
  1271.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_INVERT > 0]+' The D3DSTENCILOP_INVERT operation is supported', lkInfo);
  1272.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_KEEP > 0]+' The D3DSTENCILOP_KEEP operation is supported', lkInfo);
  1273.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_REPLACE > 0]+' The D3DSTENCILOP_REPLACE operation is supported', lkInfo);
  1274.   Log.Log(CanStr[Caps.StencilCaps and D3DSTENCILCAPS_ZERO > 0]+' The D3DSTENCILOP_ZERO operation is supported', lkInfo);
  1275.   Log.Log(' Shaders', lkInfo);
  1276.   Log.Log('Vertex shader version: ' + IntToStr((Caps.VertexShaderVersion shr 8) and $FF)+'.'+ IntToStr(Caps.VertexShaderVersion and $FF), lkInfo);
  1277.   Log.Log('Vertex shader constant registers: '+IntToStr(Caps.MaxVertexShaderConst), lkInfo);
  1278.   Log.Log('Pixel shader version: ' + IntToStr((Caps.PixelShaderVersion shr 8) and $FF)+'.' + IntToStr(Caps.PixelShaderVersion and $FF), lkInfo);
  1279.   Log.Log('Max pixel shader value: ' + FloatToStrF(Caps.MaxPixelShaderValue, ffFixed, 10, 1), lkInfo);
  1280.   Log.Log('----------', lkInfo);
  1281.   {$ENDIF}
  1282.   HardwareClipping   := Caps.PrimitiveMiscCaps and D3DPMISCCAPS_CLIPTLVERTS > 0;  // ToDo: wrong cap!
  1283.   WBuffering         := Caps.RasterCaps and D3DPRASTERCAPS_WBUFFER > 0;
  1284.   SquareTextures     := Caps.TextureCaps and D3DPTEXTURECAPS_SQUAREONLY > 0;
  1285.   Power2Textures     := Caps.TextureCaps and D3DPTEXTURECAPS_POW2 > 0;
  1286.   MaxClipPlanes      := Caps.MaxUserClipPlanes;
  1287.   MaxTextureWidth    := Caps.MaxTextureWidth;
  1288.   MaxTextureHeight   := Caps.MaxTextureHeight;
  1289.   MaxTexturesPerPass := Caps.MaxSimultaneousTextures;
  1290.   MaxTextureStages   := Caps.MaxTextureBlendStages;
  1291.   MaxPointSize       := Caps.MaxPointSize;
  1292.   if Caps.DevCaps and D3DDEVCAPS_HWTRANSFORMANDLIGHT > 0 then MaxHardwareLights := Caps.MaxActiveLights else MaxHardwareLights := 0;
  1293.   MaxAPILights       := 8;
  1294.   MaxPrimitiveCount  := Caps.MaxPrimitiveCount;
  1295.   MaxVertexIndex     := Caps.MaxVertexIndex;
  1296.   VertexShaderVersionMajor := (Caps.VertexShaderVersion shr 8) and $FF;
  1297.   VertexShaderVersionMinor := Caps.VertexShaderVersion and $FF;
  1298.   PixelShaderVersionMajor  := (Caps.PixelShaderVersion shr 8) and $FF;
  1299.   PixelShaderVersionMinor  := Caps.PixelShaderVersion and $FF;
  1300.   MaxVertexShaderConsts    := Caps.MaxVertexShaderConst;
  1301.   MixedVPMode := MixedVPMode and (VertexShaderVersionMajor = 0) and (VertexShaderVersionMinor = 0);
  1302.   if MixedVPMode then Log.Log('Hardware transform and lighting with software vertex shader emulation used', lkWarning); 
  1303. end;
  1304. procedure TOGLRenderer.CheckTextureFormats;
  1305. var i: Integer;
  1306. {$IFDEF EXTLOGGING}
  1307. const SupportStr: array[False..True] of string[14] = ('     [ ]      ', '     [X]      ');
  1308. {$ENDIF}
  1309. begin
  1310.   {$IFDEF EXTLOGGING}
  1311.   Log.Log(' Texture formats supported', lkInfo);
  1312.   Log.Log(' Format     Texture    RenderTarget   DepthStencil   Vol texture   Cube texture  Depth texture');
  1313. //  Log.Log('    Video format: '+IntToStr(CPFormats[RenderPars.VideoFormat]));
  1314.   for i := 0 to High(PFormats) do if PFormats[i] <> Cardinal(D3DFMT_UNKNOWN) then begin
  1315.     Log.Log(Format('%-8.8s', [PixelFormatToStr(i)]) + SupportStr[APICheckFormat(i, fuTexture,       pfUndefined)] +
  1316.                                                       SupportStr[APICheckFormat(i, fuRenderTarget,  pfUndefined)] +
  1317.                                                       SupportStr[APICheckFormat(i, fuDepthStencil,  pfUndefined)] +
  1318.                                                       SupportStr[APICheckFormat(i, fuVolumeTexture, pfUndefined)] +
  1319.                                                       SupportStr[APICheckFormat(i, fuCubeTexture,   pfUndefined)] +
  1320.                                                       SupportStr[APICheckFormat(i, fuDEPTHTEXTURE,  pfUndefined)]
  1321.                                                       );
  1322.   end;
  1323.   {$ENDIF}
  1324.   i := High(PFormats);
  1325.   while (i >= 0) and
  1326.         not ((PFormats[i] <> Cardinal(D3DFMT_UNKNOWN)) and APICheckFormat(i, fuDEPTHTEXTURE,  pfUndefined)) do
  1327.     Dec(i);
  1328.   DepthTextures := (i >= 0);
  1329. end;
  1330. function TOGLRenderer.FillPresentPars(var D3DPP: TD3DPresent_Parameters): Boolean;
  1331. var D3DDM: TD3DDisplayMode; Res: HResult;
  1332. begin
  1333.   Result := False;
  1334.   if not LastFullScreen then begin
  1335.     Res := Direct3D.GetAdapterDisplayMode(FCurrentAdapter, D3DDM);
  1336.     if Failed(Res) then begin
  1337.       {$IFDEF LOGGING} Log.Log(ClassName + 'FillPresentPars: Error obtaining display mode. Result: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError); {$ENDIF}
  1338.       Exit;
  1339.     end;
  1340.     DesktopVideoMode.Width       := D3DDM.Width;
  1341.     DesktopVideoMode.Height      := D3DDM.Height;
  1342.     DesktopVideoMode.RefreshRate := D3DDM.RefreshRate;
  1343.     DesktopVideoMode.Format      := APIToPixelFormat(Cardinal(D3DDM.Format));
  1344.   end;
  1345.   FillChar(D3DPP, SizeOf(D3DPP), 0);
  1346.   if not FFullScreen then begin
  1347.     if LastFullScreen then SetWindowLong(RenderWindowHandle, GWL_STYLE, FNormalWindowStyle);
  1348.     if not PrepareWindow then begin
  1349.       {$IFDEF LOGGING} Log.Log(ClassName + 'FillPresentPars: Error creating windowed viewport', lkError); {$ENDIF}
  1350.       Exit;
  1351.     end;
  1352.     if LastFullScreen then SetWindowLong(RenderWindowHandle, GWL_STYLE, FNormalWindowStyle);
  1353.     {$IFDEF LOGGING} Log.Log(Format('  Viewport: Windowed %Dx%Dx%D', [RenderWidth, RenderHeight, GetBitsPerPixel(DesktopVideoMode.Format)])); {$ENDIF}
  1354.     D3DPP.BackBufferFormat := TD3DFormat(PFormats[DesktopVideoMode.Format]);
  1355.   end else begin
  1356.     if Direct3dDevice = nil then begin
  1357.       GetWindowRect(RenderWindowHandle, FWindowedRect);
  1358.     end;
  1359.     RenderWidth  := VideoMode[CurrentVideoMode].Width;
  1360.     RenderHeight := VideoMode[CurrentVideoMode].Height;
  1361.     D3DPP.BackBufferFormat := TD3DFormat(PFormats[VideoMode[CurrentVideoMode].Format]);
  1362.     D3DPP.FullScreen_RefreshRateInHz := D3DPRESENT_RATE_DEFAULT;
  1363.     if arForceNoVSync in AppRequirements.Flags then D3DPP.FullScreen_PresentationInterval := D3DPRESENT_INTERVAL_IMMEDIATE else
  1364.       if arForceVSync in AppRequirements.Flags then D3DPP.FullScreen_PresentationInterval := D3DPRESENT_INTERVAL_ONE else
  1365.         D3DPP.FullScreen_PresentationInterval := D3DPRESENT_INTERVAL_DEFAULT;
  1366.     SetWindowLong(RenderWindowHandle, GWL_STYLE, Integer(FullScreenWindowStyle));
  1367.     SetWindowLong(RenderWindowHandle, GWL_EXSTYLE, WS_EX_TOPMOST);
  1368.     {$IFDEF LOGGING} Log.Log(Format('  Viewport: Fullscreen %Dx%Dx%D', [RenderWidth, RenderHeight, GetBitsPerPixel(VideoMode[CurrentVideoMode].Format)])); {$ENDIF}
  1369.   end;
  1370.   D3DPP.BackBufferWidth  := RenderWidth;
  1371.   D3DPP.BackBufferHeight := RenderHeight;
  1372.   D3DPP.BackBufferCount := AppRequirements.TotalBackBuffers;
  1373.   D3DPP.MultiSampleType := D3DMULTISAMPLE_NONE;
  1374.   if arPreserveBackBuffer in AppRequirements.Flags then D3DPP.SwapEffect := D3DSWAPEFFECT_FLIP else D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;
  1375.   D3DPP.hDeviceWindow := RenderWindowHandle;
  1376.   D3DPP.Windowed      := not FFullScreen;
  1377.   D3DPP.EnableAutoDepthStencil := (arUseZBuffer in AppRequirements.Flags) or (arUseStencil in AppRequirements.Flags);
  1378. //  D3DPP.AutoDepthStencilFormat := ge
  1379.   D3DPP.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER * Ord(arLockableBackBuffer in AppRequirements.Flags);
  1380.   if D3DPP.EnableAutoDepthStencil and not FindDepthStencilFormat(FCurrentAdapter, CurrentDeviceType, D3DPP.BackBufferFormat, D3DPP.AutoDepthStencilFormat) then begin
  1381.     {$IFDEF LOGGING}
  1382.     Log.Log(ClassName + 'Viewport: Suitable depth buffer format not found. Depth testing disabled', lkError);
  1383.     {$ENDIF}
  1384.     D3DPP.EnableAutoDepthStencil := False;
  1385.   end;
  1386.   LastFullScreen := FFullScreen;
  1387.   Result := True;
  1388. end;
  1389. procedure TOGLRenderer.CleanUpNonManaged;
  1390. begin
  1391.   Buffers.Reset;
  1392.   (APIState as TOGLStateWrapper).CleanUpNonManaged;
  1393. end;
  1394. procedure TOGLRenderer.RestoreNonManaged;
  1395. begin
  1396.   Assert(Assigned(Direct3DDevice));
  1397.   (APIState as TOGLStateWrapper).RestoreNonManaged;
  1398. end;
  1399. procedure TOGLRenderer.GetAPIDeclaration(Declaration: TVertexDeclaration; Result: POGLVertexDeclaration);
  1400. var i: Integer;
  1401. begin
  1402.   Result^[0] := D3DVSD_STREAM(0);
  1403.   for i := 0 to High(Declaration) do
  1404.     Result^[i+1] := D3DVSD_REG(i, VertexDataTypeToD3DVSDT[Declaration[i]]);
  1405.   Result^[High(Declaration) + 2] := D3DVSD_END;
  1406. end;
  1407. function TOGLRenderer.APICreateDevice(WindowHandle, AVideoMode: Cardinal; AFullScreen: Boolean): Boolean;
  1408.   procedure SetLight;
  1409.   var HLight: TD3DLIGHT8;
  1410.   begin
  1411.     with HLight do begin
  1412.       _Type := D3DLIGHT_DIRECTIONAL;
  1413.       Diffuse.r  := 0.5; Diffuse.g  := 0.5; Diffuse.b  := 0.5; Diffuse.a  := 0.5;
  1414.       Specular.r := 0.0; Specular.g := 0.0; Specular.b := 0.0; Specular.a := 0.0;
  1415.       Ambient.r  := 0.5; Ambient.g  := 0.5; Ambient.b  := 0.5; Ambient.a  := 0.5;
  1416.       Direction.X := 0; Direction.Y := -1; Direction.Z := 0;
  1417.     end;
  1418.     Direct3dDevice.SetLight(0, HLight);
  1419.     Direct3dDevice.LightEnable(0, True);
  1420.   end;
  1421. var
  1422.   D3DPP:   TD3DPresent_Parameters;
  1423.   D3DCaps: TD3DCaps8;
  1424.   DCFlags: Cardinal;
  1425.   Res: HResult;
  1426.   function TryHardwareVP(Flag: Cardinal): Boolean;
  1427.   begin
  1428.     Result := (D3DCaps.DevCaps and D3DDEVCAPS_HWTRANSFORMANDLIGHT) = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
  1429.     if Result then DCFlags := Flag else begin
  1430.       {$IFDEF LOGGING} Log.Log(ClassName + '.APICreateDevice: Hardware vertex processing not supported. Switching to software vertex processing', lkWarning); {$ENDIF}
  1431.     end;
  1432.   end;
  1433. //  var i, j, k: Integer; m, mi: tmatrix4s; dm, dmi: td3dmatrix; Det: Single; quat: TQuaternion;
  1434. begin
  1435.   Result := False;
  1436.   
  1437.   if Direct3D = nil then begin
  1438.     {$IFDEF Logging} Log.Log(ClassName + '.APICreateDevice: Direct3D object was not initialized', lkFatalError); {$ENDIF}
  1439.     Exit;
  1440.   end;
  1441.   FState := rsNotReady;
  1442.   Res := Direct3D.GetDeviceCaps(FCurrentAdapter, CurrentDeviceType, D3DCaps);
  1443.   if Failed(Res) then begin
  1444.     {$IFDEF LOGGING} Log.Log(ClassName + '.APICreateDevice: Error obtaining device capabilities. Result: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError); {$ENDIF}
  1445.     Exit;
  1446.   end;
  1447.   FCurrentVideoMode := AVideoMode;
  1448.   FFullScreen := AFullScreen;           // Use windowed mode if current video mode is invalid
  1449.   if FFullScreen then if (D3DCaps.Caps2 and D3DCAPS2_CANRENDERWINDOWED = 0) then begin     // Device does not support windowed mode
  1450.     FCurrentVideoMode := 0;
  1451.     FFullScreen := False;
  1452.     {$IFDEF LOGGING} Log.Log(ClassName + 'APICreateDevice: Windowed rendering is not supported', lkError); {$ENDIF}
  1453.   end;
  1454.   RenderWindowHandle := WindowHandle;
  1455.   FNormalWindowStyle := GetWindowLong(RenderWindowHandle, GWL_STYLE);
  1456.   if FNormalWindowStyle = 0 then
  1457.     FNormalWindowStyle := WS_OVERLAPPED or WS_CAPTION or WS_THICKFRAME or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SIZEBOX or WS_SYSMENU;
  1458.   if not FillPresentPars(D3DPP) then Exit;
  1459. // Set device creation flags
  1460.   DCFlags := D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  1461.   case AppRequirements.HWAccelerationLevel of
  1462.     haMixedVP:    TryHardwareVP(D3DCREATE_MIXED_VERTEXPROCESSING);
  1463.     haHardwareVP: TryHardwareVP(D3DCREATE_HARDWARE_VERTEXPROCESSING);
  1464.     haPureDevice: if TryHardwareVP(D3DCREATE_HARDWARE_VERTEXPROCESSING) then
  1465.       if (D3DCaps.DevCaps and D3DDEVCAPS_PUREDEVICE) = D3DDEVCAPS_PUREDEVICE then begin
  1466.         DCFlags := DCFlags or D3DCREATE_PUREDEVICE;
  1467.         Log.Log('  ' + ClassName + '.APICreateDevice: Pure device');
  1468.       end else begin
  1469.         Log.Log(ClassName + '.APICreateDevice: Pure device is not supported', lkWarning);
  1470.       end;
  1471.   end;
  1472.   MixedVPMode := DCFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
  1473.   if arPreserveFPU in AppRequirements.Flags then DCFlags := DCFlags or D3DCREATE_FPU_PRESERVE;
  1474.   if arMultithreadedRender in AppRequirements.Flags then DCFlags := DCFlags or D3DCREATE_MULTITHREADED;
  1475.   if Direct3dDevice <> nil then Direct3dDevice := nil;
  1476.   repeat
  1477.     Res := Direct3D.CreateDevice(D3DADAPTER_DEFAULT, CurrentDeviceType, WindowHandle, DCFlags, D3DPP, Direct3DDevice);
  1478.   until not Failed(Res) or (D3DPP.BackBufferCount = AppRequirements.TotalBackBuffers);
  1479.   if Failed(Res) then begin
  1480.     Log.Log(ClassName + 'APICreateDevice: Error creating Direct3D device. Result: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkFatalError);
  1481.     Exit;
  1482.   end;
  1483. //  if not AFullScreen then ShowWindow(RenderWindowHandle, SW_SHOW);
  1484.   (APIState as TOGLStateWrapper).Direct3dDevice := Direct3dDevice;
  1485.   (Textures as TOGLTextures).Direct3dDevice     := Direct3dDevice;
  1486.   Direct3dDevice.SetRenderState(D3DRS_DITHERENABLE, 1);
  1487.   Direct3DDevice.SetRenderState(D3DRS_CLIPPING, 1);
  1488.   Direct3DDevice.SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  1489.   SetLight;
  1490.   TOGLStateWrapper(APIState).ObtainRenderTargetSurfaces;
  1491.   FState := rsOK;
  1492.   Active := True;
  1493.   Result := True;
  1494. end;
  1495. function TOGLRenderer.RestoreDevice(AVideoMode: Cardinal; AFullScreen: Boolean): Boolean;
  1496. var D3DPP: TD3DPresent_Parameters; Res: HResult; ChangeWindowed: Boolean;
  1497. begin
  1498.   {$IFDEF LOGGING}
  1499.   Log.Log('Restoring viewport', lkNotice);
  1500.   {$ENDIF}
  1501.   Result := False;
  1502.   FState := rsLost;
  1503.   ChangeWindowed := FFullScreen <> AFullScreen;
  1504.   if ChangeWindowed then begin
  1505.     if AFullScreen then begin                                           // We're going fullscreen
  1506.       ShowWindow(RenderWindowHandle, SW_RESTORE);
  1507.       GetWindowRect(RenderWindowHandle, FWindowedRect);
  1508.       SetWindowLong(RenderWindowHandle, GWL_EXSTYLE, WS_EX_TOPMOST);
  1509.     end else                                                            // We're going windowed
  1510.       if not SetWindowPos(RenderWindowHandle, HWND_NOTOPMOST, WindowedRect.Left, WindowedRect.Top,
  1511.                           WindowedRect.Right - WindowedRect.Left, WindowedRect.Bottom - WindowedRect.Top,
  1512.                           SWP_DRAWFRAME or SWP_NOCOPYBITS or SWP_SHOWWINDOW) then begin
  1513.         {$IFDEF LOGGING} Log.Log(ClassName + '.RestoreDevice: Can''t set window position (1)', lkError); {$ENDIF}
  1514.       end;
  1515.   end;
  1516.   FCurrentVideoMode := AVideoMode;
  1517.   FFullScreen       := AFullScreen;
  1518.   if not FillPresentPars(D3DPP) then Exit;
  1519.   CleanUpNonManaged;
  1520.   Res := Direct3DDevice.Reset(D3DPP);
  1521.   if Failed(Res) then begin
  1522.     {$IFDEF LOGGING}
  1523.     Log.Log('Error resetting viewport. Result: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  1524.     {$ENDIF}
  1525.     FState := rsLost;
  1526.     Exit;
  1527.   end;
  1528.   if ChangeWindowed then
  1529.     if not AFullScreen then begin                      // We're become windowed
  1530.       if not SetWindowPos(RenderWindowHandle, HWND_NOTOPMOST, WindowedRect.Left, WindowedRect.Top,
  1531.                           WindowedRect.Right - WindowedRect.Left, WindowedRect.Bottom - WindowedRect.Top,
  1532.                           SWP_DRAWFRAME or SWP_NOCOPYBITS or SWP_SHOWWINDOW or SWP_NOMOVE or SWP_NOSIZE) then begin
  1533.         {$IFDEF LOGGING} Log.Log(ClassName + '.RestoreDevice: Can''t set window position (2)', lkError); {$ENDIF}
  1534.       end;
  1535.     end else begin
  1536. //      ShowWindow(RenderWindowHandle, SW_MAXIMIZE);
  1537.       PostMessage(RenderWindowHandle, WM_SIZE, 0, RenderHeight * 65536 + RenderWidth);    // To notify the application about render window resizing
  1538.     end;
  1539.   RestoreNonManaged;
  1540. {  if WBuffering then
  1541.    Direct3dDevice.SetRenderState(D3DRS_ZENABLE, D3DZB_USEW) else
  1542.     Direct3dDevice.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);}
  1543.   Direct3dDevice.SetRenderState(D3DRS_DITHERENABLE, 1);
  1544.   Direct3DDevice.SetRenderState(D3DRS_CLIPPING, 1);
  1545.   Direct3DDevice.SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  1546. //  f := 2.0;
  1547. //  Direct3DDevice.SetRenderState(D3DRS_PATCHSEGMENTS, Cardinal((@f)^));
  1548. //  Direct3DDevice.SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_CONTINUOUS);
  1549.   inherited RestoreDevice(AVideoMode, AFullScreen);
  1550.   FState := rsOK;
  1551.   Result := True;
  1552. end;
  1553. procedure TOGLRenderer.StartFrame;
  1554. var Res: HResult;
  1555. begin
  1556.   inherited;
  1557.   if not IsReady then Exit;
  1558.   if Active then Res := Direct3DDevice.Present(nil, nil, 0, nil) else Res := Direct3DDevice.TestCooperativeLevel;
  1559.   if Res = D3DERR_DEVICELOST then begin
  1560.     FState := rsLost;
  1561. //    LostTime := Globals.CurrentTime;
  1562.     {$IFDEF LOGGING}
  1563.     Log.Log('Render: Device lost. Need to restore', lkWarning);
  1564.     {$ENDIF}
  1565.     Sleep(0);
  1566.     Exit;
  1567.   end;
  1568.   Direct3DDevice.BeginScene;
  1569. end;
  1570. procedure TOGLRenderer.FinishFrame;
  1571. begin
  1572. (*  if (State = rsLost) and (Timer.Time - LostTime > MaxLostTime) and Active then begin
  1573.     FState := rsTryToRestore;
  1574.     {$IFDEF LOGGING}
  1575.     Log.Log('No device restoration attempts in last ' + IntToStr(MaxLostTime) + ' milliseconds. Forcing restoration', lkWarning);
  1576.     {$ENDIF}
  1577.   end;*)
  1578.   if (State = rsLost) then begin
  1579.     if not RestoreDevice(FCurrentVideoMode, FFullScreen) then Sleep(0);
  1580.     Exit;
  1581.   end;
  1582.   if not IsReady then begin Sleep(0); Exit; end;
  1583.   Direct3DDevice.EndScene;
  1584.   if not Active then begin FState := rsLost; Sleep(0); Exit; end;
  1585.   FState := rsOK;
  1586.   Inc(FFramesRendered);
  1587. end;
  1588. procedure TOGLRenderer.ApplyLight(Index: Integer; const ALight: TLight);
  1589. var HLight: TD3DLIGHT8;
  1590. begin
  1591.   if not IsReady then Exit;
  1592.   inherited;
  1593.   if ALight = nil then Direct3dDevice.LightEnable(Index, False) else begin
  1594.     with HLight do begin
  1595.       case ALight.Kind of
  1596.         ltDirectional:  _Type := D3DLIGHT_DIRECTIONAL;
  1597.         ltPoint:        _Type := D3DLIGHT_POINT;
  1598.         ltSpot:         _Type := D3DLIGHT_SPOT;
  1599.       end;
  1600.       Diffuse  := TD3DColorValue(ALight.Diffuse);
  1601.       Specular := TD3DColorValue(ALight.Specular);
  1602.       Ambient  := TD3DColorValue(ALight.Ambient);
  1603.       TVector3s(Direction) := ALight.ForwardVector;
  1604.       TVector3s(Position)  := ALight.GetAbsLocation;
  1605.       Range := ALight.Range;
  1606.       Falloff := ALight.Falloff;
  1607.       Attenuation0 := ALight.Attenuation0;
  1608.       Attenuation1 := ALight.Attenuation1;
  1609.       Attenuation2 := ALight.Attenuation2;
  1610.       Theta := ALight.Theta;
  1611.       Phi   := ALight.Phi;
  1612.     end;
  1613.     Direct3dDevice.SetLight(Index, HLight);
  1614.     Direct3dDevice.LightEnable(Index, True);
  1615.   end;
  1616. end;
  1617. procedure TOGLRenderer.ApplyCamera(Camera: TCamera);
  1618. begin
  1619.   inherited;
  1620.   if not IsReady or (Camera = nil) or (Direct3DDevice = nil) then Exit;
  1621.   Direct3DDevice.SetTransform(D3DTS_VIEW, TD3DMatrix(Camera.ViewMatrix));
  1622.   Direct3DDevice.SetTransform(D3DTS_PROJECTION, TD3DMatrix(Camera.ProjMatrix));
  1623. end;
  1624. procedure TOGLRenderer.SetViewPort(const X, Y, Width, Height: Integer; const MinZ, MaxZ: Single);
  1625. begin
  1626.   inherited;
  1627.   if not IsReady then Exit;
  1628.   Direct3DDevice.SetViewport(TD3DViewport8(ViewPort));
  1629. end;
  1630. procedure TOGLRenderer.APIRenderIndexedStrip(Tesselator: TTesselator; StripIndex: Integer);
  1631. var Res: HResult;
  1632. begin
  1633.   APIBuffers.AttachIndexBuffer(InternalGetIndexBufferIndex(Tesselator.TesselationStatus[tbIndex].TesselatorType = ttStatic,
  1634.                                                            Tesselator.TesselationStatus[tbIndex].BufferIndex),
  1635.                                (Tesselator.TesselationStatus[tbVertex].Offset + StripIndex * Tesselator.StripOffset));
  1636.   Res := Direct3DDevice.DrawIndexedPrimitive(TD3DPrimitiveType(CPTypes[Tesselator.PrimitiveType]), 0,
  1637.                                              Tesselator.IndexingVertices, Tesselator.TesselationStatus[tbIndex].Offset, Tesselator.TotalPrimitives);
  1638.   {$IFDEF DEBUGMODE}
  1639.   if Res <> D3D_OK then Log.Log(ClassName + '.RenderTesselator: DrawIndexedPrimitive returned "Invalid call" error ', lkError);
  1640.   {$ENDIF}
  1641.   Inc(FPerfProfile.DrawCalls);
  1642.   Inc(FPerfProfile.PrimitivesRendered, Tesselator.TotalPrimitives);
  1643. end;
  1644. procedure TOGLRenderer.APIRenderStrip(Tesselator: TTesselator; StripIndex: Integer);
  1645. var Res: HResult;
  1646. begin
  1647.   Res := Direct3DDevice.DrawPrimitive(TD3DPrimitiveType(CPTypes[Tesselator.PrimitiveType]), Tesselator.TesselationStatus[tbVertex].Offset, Tesselator.TotalPrimitives);
  1648.   {$IFDEF DEBUGMODE}
  1649.   if Res <> D3D_OK then Log.Log(ClassName + '.RenderTesselator: DrawPrimitive returned "Invalid call" error ', lkError);
  1650.   {$ENDIF}
  1651.   Inc(FPerfProfile.DrawCalls);
  1652.   Inc(FPerfProfile.PrimitivesRendered, Tesselator.TotalPrimitives);
  1653. end;
  1654. procedure TOGLRenderer.RenderItemBox(Item: TProcessing; Color: BaseTypes.TColor);
  1655. var Tess: TTesselator; Mat: TMatrix4s; Temp: TVector3s; DPass: TRenderPass;
  1656. begin
  1657.   if not IsReady then Exit;
  1658. //                * Move to material settings *
  1659.   Direct3DDevice.SetRenderState(D3DRS_VERTEXBLEND, 0);
  1660.   Direct3DDevice.SetRenderState(D3DRS_COLORVERTEX, 0);
  1661.   Direct3DDevice.SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
  1662.   Direct3DDevice.SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
  1663.   Mat  := Item.Transform;
  1664.   Temp := Transform3Vector3s(CutMatrix3s(Mat), AddVector3s(Item.BoundingBox.P2, Item.BoundingBox.P1));
  1665.   Mat._41 := Mat._41 + Temp.X*0.5;
  1666.   Mat._42 := Mat._42 + Temp.Y*0.5;
  1667.   Mat._43 := Mat._43 + Temp.Z*0.5;
  1668.   Temp := SubVector3s(Item.BoundingBox.P2, Item.BoundingBox.P1);
  1669.   Mat  := MulMatrix4s(ScaleMatrix4s(Temp.X*0.5, Temp.Y*0.5, Temp.Z*0.5), Mat);
  1670.   Direct3DDevice.SetTransform(D3DTS_World, TD3DMatrix(Mat));
  1671.   Tess := DebugTesselators[Ord(bvkOOBB)];
  1672.   if not Buffers.Put(Tess) then Exit;
  1673.   Direct3DDevice.SetVertexShader(APIBuffers.GetFVF(Tess.VertexFormat));
  1674.   if Assigned(DebugMaterial) and (DebugMaterial.TotalTechniques > 0) then begin
  1675.     DPass := DebugMaterial[0].Passes[0];
  1676.     DPass.Ambient  := ColorTo4S(Color);
  1677.     DPass.Diffuse  := ColorTo4S(Color);
  1678.     DPass.Specular := ColorTo4S(Color);
  1679.     APIState.ApplyPass(DPass);
  1680.     RenderTesselator(Tess);
  1681.   end;
  1682. end;
  1683. procedure TOGLRenderer.RenderItemDebug(Item: TProcessing);
  1684. var CurPass, i: Integer; Tess: TTesselator; Mat: TMatrix4s; Offset: TVector3s;
  1685. begin
  1686.   if not IsReady then Exit;
  1687. //                * Move to material settings *
  1688.   Direct3DDevice.SetRenderState(D3DRS_VERTEXBLEND, 0);
  1689.   Direct3DDevice.SetRenderState(D3DRS_COLORVERTEX, 0);
  1690.   Direct3DDevice.SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,  D3DMCS_MATERIAL);
  1691.   Direct3DDevice.SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,  D3DMCS_MATERIAL);
  1692.   Direct3DDevice.SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
  1693.   DebugMaterial[0].Passes[0].Ambient  := GetColor4S(0, 1, 0, 1);// ColorTo4S(Globals.DebugColor);
  1694.   DebugMaterial[0].Passes[0].Diffuse  := GetColor4S(0, 1, 0, 1);// ColorTo4S(Globals.DebugColor);
  1695.   DebugMaterial[0].Passes[0].Specular := GetColor4S(0, 1, 0, 1);// ColorTo4S(Globals.DebugColor);
  1696.   for i := 0 to Length(Item.Colliding.Volumes)-1 do begin
  1697.     Mat := Item.Transform;
  1698.     Transform3Vector3s(Offset, CutMatrix3s(Mat), Item.Colliding.Volumes[i].Offset);
  1699.     Mat._41 := Mat._41 + Offset.X;
  1700.     Mat._42 := Mat._42 + Offset.Y;
  1701.     Mat._43 := Mat._43 + Offset.Z;
  1702.     Mat := MulMatrix4s(ScaleMatrix4s(Item.Colliding.Volumes[i].Dimensions.X, Item.Colliding.Volumes[i].Dimensions.Y, Item.Colliding.Volumes[i].Dimensions.Z), Mat);
  1703.     Direct3DDevice.SetTransform(D3DTS_World, TD3DMatrix(Mat));
  1704.     Tess := DebugTesselators[Ord(Item.Colliding.Volumes[i].VolumeKind)];
  1705.     if not Buffers.Put(Tess) then Exit;
  1706.     Direct3DDevice.SetVertexShader(APIBuffers.GetFVF(Tess.VertexFormat));
  1707.     if Assigned(DebugMaterial) and (DebugMaterial.TotalTechniques > 0) then
  1708.       if Assigned(DebugMaterial.Technique[0]) then
  1709.         for CurPass := 0 to DebugMaterial[0].TotalPasses-1 do if DebugMaterial[0].Passes[CurPass] <> nil then begin
  1710.           APIState.ApplyPass(DebugMaterial[0].Passes[CurPass]);
  1711.           RenderTesselator(Tess);
  1712.         end;
  1713.   end;
  1714. end;
  1715. procedure TOGLRenderer.Clear(Flags: TClearFlagsSet; Color: BaseTypes.TColor; Z: Single; Stencil: Cardinal);
  1716. begin
  1717.   if (Flags = []) or not IsReady then Exit;
  1718. //  if State = rsTryToRestore then begin RestoreDevice; Exit; end;
  1719.   Direct3DDevice.Clear(0, nil, D3DCLEAR_TARGET  * Ord((ClearFrameBuffer in Flags) and Assigned(TOGLStateWrapper(APIState).CurrentRenderTarget)) or
  1720.                               (D3DCLEAR_ZBUFFER * Ord(ClearZBuffer in Flags) or
  1721.                                D3DCLEAR_STENCIL * Ord(ClearStencilBuffer in Flags)) * Ord(Assigned(TOGLStateWrapper(APIState).CurrentDepthStencil)),
  1722.                                Color.C, Z, Stencil);
  1723. end;
  1724. { TOGLTextures }
  1725. function TOGLTextures.APICreateTexture(Index: Integer): Boolean;
  1726. var
  1727.   LevelsGenerated: Integer;
  1728.   Res: HResult;
  1729. begin
  1730.   Result := False;
  1731.   if not Renderer.IsReady then Exit;
  1732.   Res := Direct3DDevice.CreateTexture(FTextures[Index].Width, FTextures[Index].Height, FTextures[Index].Levels, 0, TD3DFormat(PFormats[FTextures[Index].Format]), D3DPOOL_MANAGED, IDirect3DTexture8(FTextures[Index].Texture));
  1733.   if Failed(Res) then begin
  1734.     Log.Log(ClassName + '.CreateOGLTexture: Error creating texture object: Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  1735.     Log.Log(Format('  Call parameters: Dimensions: %Dx%D, Levels: %D, Format: %S', [FTextures[Index].Width, FTextures[Index].Height, FTextures[Index].Levels, PixelFormatToStr(FTextures[Index].Format)]), lkError);
  1736.     Exit;
  1737.   end;
  1738.   LevelsGenerated := IDirect3DTexture8(FTextures[Index].Texture).GetLevelCount;
  1739.   if LevelsGenerated <> FTextures[Index].Levels then begin
  1740.     Log.Log(Format('%S.CreateOGLTexture: Unexpected number of mipmap levels generated: %D instead of %D', [ClassName, LevelsGenerated, FTextures[Index].Levels]), lkWarning);
  1741.     FTextures[Index].Levels := MinI(LevelsGenerated, FTextures[Index].Levels);
  1742.   end;
  1743.   Result := True;
  1744. end;
  1745. procedure TOGLTextures.UnLoad(Index: Integer);
  1746. begin
  1747. //  inherited;
  1748. end;
  1749. function TOGLTextures.Update(Index: Integer; Src: Pointer; Rect: BaseTypes.PRect3D): Boolean;
  1750. var
  1751.   w, h, i, j, k, DataSize, DataOfs: Integer;
  1752.   Tex: IDirect3DTexture8;
  1753.   LDesc: TD3DSurface_Desc;
  1754.   LockedRect: TLockedRectData;
  1755. begin
  1756.   Result := False;
  1757.   if (Index > High(FTextures)) or IsEmpty(FTextures[Index]) then begin
  1758.     Log.Log(ClassName + '.Update: Invalid texture index', lkError);
  1759.     Exit;
  1760.   end;
  1761.   if (Src = nil) then Exit;
  1762.   if (FTextures[Index].Texture = nil) then if not APICreateTexture(Index) then Exit;
  1763.   Tex := IDirect3DTexture8(FTextures[Index].Texture);
  1764.   Tex.GetLevelDesc(0, LDesc);
  1765.   w := LDesc.Width; h:= LDesc.Height;
  1766.   DataOfs := 0;
  1767.   for k := 0 to FTextures[Index].Levels-1 do begin
  1768.     if not Lock(Index, k, nil, LockedRect, []) then Exit;
  1769. //    for i := 0 to w-1 do for j := 0 to h-1 do TDWordBuffer(LockedRect.pBits^)[j*w+i] := TDWordBuffer(Src^)[(j*LDesc.Height div h) * LDesc.Width + (i*LDesc.Width div w)];
  1770.     if Rect <> nil then begin                   //    ToDo -cBugfix: only 32bit case
  1771.       for i := Rect.Left to Rect.Right do for j := Rect.Top to Rect.Bottom do
  1772.         TDWordBuffer(LockedRect.Data^)[j*w+i] :=
  1773.           TDWordBuffer(Src^)[(j*Integer(LDesc.Height) div h) * Integer(LDesc.Width) + (i*Integer(LDesc.Width) div w)];
  1774.       Rect.Left := Rect.Left div 2;
  1775.       Rect.Right := Rect.Right div 2;
  1776.       Rect.Top := Rect.Top div 2;
  1777.       Rect.Bottom := Rect.Bottom div 2;
  1778.     end else begin
  1779.       DataSize := w * h * GetBytesPerPixel(FTextures[Index].Format);
  1780.       Move(PtrOffs(Src, DataOfs)^, LockedRect.Data^, DataSize);
  1781.       Inc(DataOfs, DataSize);
  1782.     end;
  1783.     Unlock(Index, k);
  1784.     w := w shr 1; if w = 0 then w := 1;
  1785.     h := h shr 1; if h = 0 then h := 1;
  1786.   end;
  1787. //  Textures[TextureID].Resource := -1;
  1788.   Result := True;
  1789. end;
  1790. function TOGLTextures.Read(Index: Integer; Dest: Pointer; Rect: BaseTypes.PRect3D): Boolean;
  1791. begin
  1792.   Result := False;
  1793. end;
  1794. procedure TOGLTextures.Delete(Index: Integer);
  1795. begin
  1796.   if Assigned(FTextures[Index].Texture) then IDirect3DTexture8(FTextures[Index].Texture)._Release;
  1797.   inherited;
  1798. end;
  1799. procedure TOGLTextures.Apply(Stage, Index: Integer);
  1800. var Res: HResult;
  1801. begin
  1802.   if Assigned(FTextures[Index].Texture) or Load(Index) then begin
  1803.     Res := Direct3DDevice.SetTexture(Stage, IDirect3DTexture8(FTextures[Index].Texture));
  1804.     {$IFDEF DEBUGMODE} if Res <> D3D_OK then Log.Log(Format('TOGLTextures.ApplyTexture: Error setting stage''s %D texture with resource "%S". Error "%S"', [Stage, FTextures[Index].Resource.GetFullName, HResultToStr(Res)]), lkError); {$ENDIF}
  1805.   end;  
  1806. end;
  1807. function TOGLTextures.Lock(AIndex, AMipLevel: Integer; const ARect: BaseTypes.PRect; out LockRectData: TLockedRectData; LockFlags: TLockFlags): Boolean;
  1808. var
  1809.   LockedRect: TD3DLocked_Rect;
  1810.   Res: HResult;
  1811.   Tex: IDirect3DTexture8;
  1812.   Flags: DWord;
  1813. begin
  1814.   Result := False;
  1815.   if (AIndex > High(FTextures)) or IsEmpty(FTextures[AIndex]) then begin
  1816.     Log.Log(ClassName + '.Lock: Invalid texture index (' + IntToStr(AIndex) + ')', lkError);
  1817.     Exit;
  1818.   end;
  1819.   Tex := IDirect3DTexture8(FTextures[AIndex].Texture);
  1820.   Flags := 0;
  1821.   if lfDiscard     in LockFlags then Flags := Flags or D3DLOCK_DISCARD;
  1822.   if lfReadOnly    in LockFlags then Flags := Flags or D3DLOCK_READONLY;
  1823.   if lfNoOverwrite in LockFlags then Flags := Flags or D3DLOCK_NOOVERWRITE;
  1824.   Res := Tex.LockRect(AMipLevel, LockedRect, @ARect^, Flags);
  1825.   if Succeeded(Res) then begin
  1826.     LockRectData.Data  := LockedRect.pBits;
  1827.     LockRectData.Pitch := LockedRect.Pitch;
  1828.     Result := True;
  1829.   end else begin
  1830.     LockRectData.Data  := nil;
  1831.     Log.Log('Error locking texture level # ' + IntToStr(AIndex) + '. Error code: ' + IntToStr(Res) + ' "' + HResultToStr(Res) + '"', lkError);
  1832.   end;
  1833. end;
  1834. procedure TOGLTextures.UnLock(AIndex, AMipLevel: Integer);
  1835. var Tex: IDirect3DTexture8;
  1836. begin
  1837.   if (AIndex > High(FTextures)) or IsEmpty(FTextures[AIndex]) then begin
  1838.     Log.Log(ClassName + '.Lock: Invalid texture index (' + IntToStr(AIndex) + ')', lkError);
  1839.     Exit;
  1840.   end;
  1841.   Tex := IDirect3DTexture8(FTextures[AIndex].Texture);
  1842.   Tex.UnlockRect(AMipLevel);
  1843. end;
  1844. end.