//DJXShaders v1.2
unit DJXShaders;

interface

uses
  Classes,
  Windows,
  SysUtils,
  DJXClasses,
  DJXUtils,
  Direct3D9,
  D3DX9;

type
  TDJXShaderList = class;
  TDJXShader = class;
  TDJXVertexShader = class;
  TDJXPixelShader = class;

  PDJXCompiledShader = ^TDJXCompiledShader;
  TDJXCompiledShader = array of byte;

  TDJXShader = class
  private
    m_DanJetX: Pointer;
    m_Name: string;
    m_Errors: string;
    m_CompiledShader: PDJXCompiledShader;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    property DanJetX: pointer read m_DanJetX write m_DanJetX;
    property Name: string read m_Name write m_Name;
    property Errors: string read m_Errors write m_Errors;
    procedure SetToDevice; virtual;
    procedure LoadFromFile(f: string); virtual;
    procedure LoadFromFileCompiled(f: string); virtual;
    procedure LoadFromMemory(Ptr: Pointer; Size: DWORD); virtual;
    procedure Release; virtual;
    procedure OnLostDevice; virtual;
    procedure OnResetDevice; virtual;
  end;

  TDJXVertexShader = class (TDJXShader)
  private
    m_Shader: IDirect3DVertexShader9;
  public
    property Shader: IDirect3DVertexShader9 read m_Shader write m_Shader;
  published
    constructor Create; override;
    destructor Destroy; override;
    procedure SetToDevice; override;
    procedure LoadFromFile(f: string); override;
    procedure LoadFromFileCompiled(f: string); override;
    procedure LoadFromMemory(Ptr: Pointer; Size: DWORD); override;
    procedure Release; override;
    procedure OnLostDevice; override;
    procedure OnResetDevice; override;
  end;

  TDJXPixelShader = class (TDJXShader)
  private
    m_Shader: IDirect3DPixelShader9;
  public
    property Shader: IDirect3DPixelShader9 read m_Shader write m_Shader;
  published
    constructor Create; override;
    destructor Destroy; override;
    procedure SetToDevice; override;
    procedure LoadFromFile(f: string); override;
    procedure LoadFromFileCompiled(f: string); override;
    procedure LoadFromMemory(Ptr: Pointer; Size: DWORD); override;
    procedure Release; override;
    procedure OnLostDevice; override;
    procedure OnResetDevice; override;
  end;

  TDJXShaderList = class(TDJXComponent)
  protected
    m_Shaders: Tlist;
    function getItem(Index: integer): TDJXShader;
    procedure setItem(Index: integer; Value: TDJXShader);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property DanJetX: Pointer read m_DanJetX write m_DanJetX;
    property Shader[Index: integer]: TDJXShader read getItem write setItem;
    function Find(name: string): TDJXShader;
    function Add(Shader: TDJXShader): TDJXShader;
    procedure FreeShaders;
    function LoadVertexShaderFromFile(f: string; NameInList: string): TDJXVertexShader;
    function LoadVertexShaderFromFileCompiled(f: string; NameInList: string): TDJXVertexShader;
    function LoadVertexShaderFromMemory(Ptr: Pointer; Size: DWORD; NameInList: string): TDJXVertexShader;
    function LoadPixelShaderFromFile(f: string; NameInList: string): TDJXPixelShader;
    function LoadPixelShaderFromFileCompiled(f: string; NameInList: string): TDJXPixelShader;
    function LoadPixelShaderFromMemory(Ptr: Pointer; Size: DWORD; NameInList: string): TDJXPixelShader;
    procedure Init(DanJetX: Pointer); override;
    procedure OnLostDevice; override;
    procedure OnResetDevice; override;
    procedure ClearVertexShader;
    procedure ClearPixelShader;
  published
  end;



implementation

uses
  DJX;

//TDJXVertexShader BEGIN
constructor TDJXVertexShader.Create;
begin
  inherited Create;
end;
destructor TDJXVertexShader.Destroy;
begin
  safe_release(m_Shader);
  inherited Destroy;
end;

procedure TDJXVertexShader.SetToDevice;
begin
  TDanJetX(m_DanJetX).Device.SetVertexShader(m_Shader);
end;
procedure TDJXVertexShader.LoadFromFile(f: string);
begin
  safe_release(m_Shader);
  inherited LoadFromFile(f);
  TDanJetX(m_DanJetX).Device.CreateVertexShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXVertexShader.LoadFromFileCompiled(f: string);
begin
  safe_release(m_Shader);
  inherited LoadFromFileCompiled(f);
  TDanJetX(m_DanJetX).Device.CreateVertexShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXVertexShader.LoadFromMemory(Ptr: Pointer; Size: DWORD);
begin
  safe_release(m_Shader);
  inherited LoadFromMemory(Ptr, Size);
  TDanJetX(m_DanJetX).Device.CreateVertexShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXVertexShader.Release;
begin
  inherited Release;
  safe_release(m_Shader);
end;
procedure TDJXVertexShader.OnLostDevice;
begin
  safe_release(m_Shader);
end;
procedure TDJXVertexShader.OnResetDevice;
begin
  if m_CompiledShader <> nil then
  TDanJetX(m_DanJetX).Device.CreateVertexShader(
    @(m_CompiledShader^[0]),
    m_Shader
  );
end;
//TDJXVertexShader END

//TDJXPixelShader BEGIN
constructor TDJXPixelShader.Create;
begin
  inherited Create;
end;
destructor TDJXPixelShader.Destroy;
begin
  safe_release(m_Shader);
  inherited Destroy;
end;

procedure TDJXPixelShader.SetToDevice;
begin
  TDanJetX(m_DanJetX).Device.SetPixelShader(m_Shader);
end;
procedure TDJXPixelShader.LoadFromFile(f: string);
begin
  safe_release(m_Shader);
  inherited LoadFromFile(f);
  TDanJetX(m_DanJetX).Device.CreatePixelShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXPixelShader.LoadFromFileCompiled(f: string);
begin
  safe_release(m_Shader);
  inherited LoadFromFileCompiled(f);
  TDanJetX(m_DanJetX).Device.CreatePixelShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXPixelShader.LoadFromMemory(Ptr: Pointer; Size: DWORD);
begin
  safe_release(m_Shader);
  inherited LoadFromMemory(Ptr, Size);
  TDanJetX(m_DanJetX).Device.CreatePixelShader(@(m_CompiledShader^[0]), m_Shader);
end;
procedure TDJXPixelShader.Release;
begin
  inherited Release;
  safe_release(m_Shader);
end;
procedure TDJXPixelShader.OnLostDevice;
begin
  safe_release(m_Shader);
end;
procedure TDJXPixelShader.OnResetDevice;
begin
  if m_CompiledShader <> nil then
  TDanJetX(m_DanJetX).Device.CreatePixelShader(
    @(m_CompiledShader^[0]),
    m_Shader
  );
end;
//TDJXPixelShader END

//TDJXShader BEGIN
constructor TDJXShader.Create;
begin
  inherited Create;
end;
destructor TDJXShader.Destroy;
begin
  Release;
  inherited Destroy;
end;

procedure TDJXShader.SetToDevice;
begin
  //Reserved
end;
procedure TDJXShader.LoadFromFile(f: string);
var
  ShaderBuffer: ID3DXBuffer;
  ErrorBuffer: ID3DXBuffer;
begin
  Release;
  m_Errors := '';
  if FAILED(D3DXAssembleShaderFromFile(PChar(f), nil, nil, 0, @ShaderBuffer, @ErrorBuffer)) then
  begin
    setlength(m_Errors, ErrorBuffer.GetBufferSize);
    move(Pchar(ErrorBuffer.GetBufferPointer)^, m_Errors[1], ErrorBuffer.GetBufferSize);
    safe_release(ErrorBuffer);
    exit;
  end;
  if m_CompiledShader = nil then New(m_CompiledShader);
  SetLength(m_CompiledShader^, ShaderBuffer.GetBufferSize);
  move(PByte(ShaderBuffer.GetBufferPointer)^, m_CompiledShader^[0], ShaderBuffer.GetBufferSize);
  safe_release(ShaderBuffer);
end;
procedure TDJXShader.LoadFromFileCompiled(f: string);
var
  FStream: TFileStream;
begin
  Release;
  m_Errors := '';
  New(m_CompiledShader);
  FStream := TFileStream.Create(f, fmOpenRead);
  setlength(m_CompiledShader^, FStream.Size);
  FStream.Position := 0;
  FStream.ReadBuffer(m_CompiledShader^[0], FStream.Size);
  FStream.Free;
end;
procedure TDJXShader.LoadFromMemory(Ptr: Pointer; Size: DWORD);
begin
  Release;
  m_Errors := '';
  New(m_CompiledShader);
  setlength(m_CompiledShader^, Size);
  move(PByte(Ptr)^, m_CompiledShader^[0], Size);
end;
procedure TDJXShader.Release;
begin
  if m_CompiledShader <> nil then
  begin
    SetLength(m_CompiledShader^, 0);
    Dispose(m_CompiledShader);
    m_CompiledShader := nil;
  end;
end;
procedure TDJXShader.OnLostDevice;
begin
  //Reserved
end;
procedure TDJXShader.OnResetDevice;
begin
  //Reserved
end;
//TDJXShader END

//TDJXShaderList BEGIN
constructor TDJXShaderList.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  m_Shaders := Tlist.Create;
end;
destructor TDJXShaderList.Destroy;
begin
  FreeShaders;
  m_Shaders.Free;
  inherited Destroy;
end;

function TDJXShaderList.getItem(Index: integer): TDJXShader;
begin
  result := TDJXShader(m_Shaders.items[Index]);
end;
procedure TDJXShaderList.setItem(Index: integer; Value: TDJXShader);
begin
  m_Shaders.items[Index] := Value;
end;

function TDJXShaderList.Find(name: string): TDJXShader;
var
  i: integer;
begin
  for i := 0 to m_Shaders.Count - 1 do
  if TDJXShader(m_Shaders.Items[i]).Name = name then
  begin
    result := TDJXShader(m_Shaders.Items[i]);
    exit;
  end;
  result := nil;
end;
function TDJXShaderList.Add(Shader: TDJXShader): TDJXShader;
begin
  m_Shaders.Add(Shader);
  result := Shader;
end;
procedure TDJXShaderList.FreeShaders;
begin
  if m_Shaders <> nil then
  begin
    while m_Shaders.Count > 0 do
    begin
      TDJXShader(m_Shaders.Items[0]).Free;
      m_Shaders.Delete(0);
    end;
  end;
end;
function TDJXShaderList.LoadVertexShaderFromFile(f: string; NameInList: string): TDJXVertexShader;
var
  shader: TDJXVertexShader;
begin
  shader := TDJXVertexShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromFile(f);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXVertexShader(Add(shader));
end;
function TDJXShaderList.LoadVertexShaderFromFileCompiled(f: string; NameInList: string): TDJXVertexShader;
var
  shader: TDJXVertexShader;
begin
  shader := TDJXVertexShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromFileCompiled(f);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXVertexShader(Add(shader));
end;
function TDJXShaderList.LoadVertexShaderFromMemory(Ptr: Pointer; Size: DWORD; NameInList: string): TDJXVertexShader;
var
  shader: TDJXVertexShader;
begin
  shader := TDJXVertexShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromMemory(Ptr, Size);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXVertexShader(Add(shader));
end;
function TDJXShaderList.LoadPixelShaderFromFile(f: string; NameInList: string): TDJXPixelShader;
var
  shader: TDJXPixelShader;
begin
  shader := TDJXPixelShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromFile(f);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXPixelShader(Add(shader));
end;
function TDJXShaderList.LoadPixelShaderFromFileCompiled(f: string; NameInList: string): TDJXPixelShader;
var
  shader: TDJXPixelShader;
begin
  shader := TDJXPixelShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromFileCompiled(f);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXPixelShader(Add(shader));
end;
function TDJXShaderList.LoadPixelShaderFromMemory(Ptr: Pointer; Size: DWORD; NameInList: string): TDJXPixelShader;
var
  shader: TDJXPixelShader;
begin
  shader := TDJXPixelShader.Create;
  shader.m_DanJetX := m_DanJetX;
  shader.LoadFromMemory(Ptr, Size);
  if length(shader.Errors) > 0 then
  begin
    shader.Free;
    exit;
  end;
  shader.Name := NameInList;
  result := TDJXPixelShader(Add(shader));
end;
procedure TDJXShaderList.Init(DanJetX: Pointer);
begin
  inherited Init(DanJetX);
end;
procedure TDJXShaderList.OnLostDevice;
var
  i: integer;
begin
  for i := 0 to m_Shaders.Count - 1 do
  begin
    TDJXShader(m_Shaders.Items[i]).OnLostDevice;
  end;
end;
procedure TDJXShaderList.OnResetDevice;
var
  i: integer;
begin
  for i := 0 to m_Shaders.Count - 1 do
  begin
    TDJXShader(m_Shaders.Items[i]).OnResetDevice;
  end;
end;
procedure TDJXShaderList.ClearVertexShader;
begin
  TDanJetX(m_DanJetX).Device.SetVertexShader(nil);
end;
procedure TDJXShaderList.ClearPixelShader;
begin
  TDanJetX(m_DanJetX).Device.SetPixelShader(nil);
end;
//TDJXShaderList END


end.
