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

游戏引擎

开发平台:

Delphi

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