374 lines
12 KiB
MQL5
374 lines
12 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| DXDispatcher.mqh |
|
||
|
//| Copyright 2000-2025, MetaQuotes Ltd. |
|
||
|
//| https://www.mql5.com |
|
||
|
//+------------------------------------------------------------------+
|
||
|
#property copyright "Copyright 2000-2025, MetaQuotes Ltd."
|
||
|
#property link "https://www.mql5.com"
|
||
|
//---
|
||
|
#include "DXObjectBase.mqh"
|
||
|
#include "DXData.mqh"
|
||
|
#include "DXBuffers.mqh"
|
||
|
#include "DXInput.mqh"
|
||
|
#include "DXTexture.mqh"
|
||
|
#include "DXShader.mqh"
|
||
|
//--- default shaders
|
||
|
#resource "Shaders/DefaultShaderVertex.hlsl" as string ExtDefaultShaderVertex;
|
||
|
#resource "Shaders/DefaultShaderPixel.hlsl" as string ExtDefaultShaderPixel;
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| DX dispatcher which holds all resources |
|
||
|
//+------------------------------------------------------------------+
|
||
|
class CDXDispatcher : public CDXObjectBase
|
||
|
{
|
||
|
protected:
|
||
|
CDXObjectBase m_dx_resources; // DX resources list (Textures, Shaders, etc.)
|
||
|
//--- default shaders
|
||
|
CDXShader* m_default_vs;
|
||
|
CDXShader* m_default_ps;
|
||
|
|
||
|
public:
|
||
|
CDXDispatcher(void);
|
||
|
~CDXDispatcher(void);
|
||
|
//--- create/destroy
|
||
|
bool Create(int context);
|
||
|
void Destroy(void);
|
||
|
//--- check resources
|
||
|
void Check(void);
|
||
|
//--- get DX Context Handle
|
||
|
int DXContext(void) const { return(m_context); }
|
||
|
//--- create shaders
|
||
|
CDXShader* ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type);
|
||
|
CDXShader* ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point);
|
||
|
CDXShader* ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point);
|
||
|
//--- create buffers
|
||
|
template<typename TVertex>
|
||
|
CDXVertexBuffer* VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY);
|
||
|
CDXIndexBuffer* IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY);
|
||
|
//--- create shader inputs
|
||
|
template<typename TInput>
|
||
|
CDXInput* InputCreate(void);
|
||
|
CDXTexture* TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);
|
||
|
CDXTexture* TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0);
|
||
|
|
||
|
private:
|
||
|
//--- add resource to list
|
||
|
bool ResourceAdd(CDXObjectBase *resource);
|
||
|
//--- check resources
|
||
|
void ResourcesCheck(void);
|
||
|
};
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Constructor |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXDispatcher::CDXDispatcher(void)
|
||
|
{
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Destructor |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXDispatcher::~CDXDispatcher(void)
|
||
|
{
|
||
|
Destroy();
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create |
|
||
|
//+------------------------------------------------------------------+
|
||
|
bool CDXDispatcher::Create(int context)
|
||
|
{
|
||
|
//--- check if context already exist
|
||
|
if(m_context!=INVALID_HANDLE)
|
||
|
return(false);
|
||
|
//--- save context
|
||
|
m_context=context;
|
||
|
//---
|
||
|
return(true);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Destroy |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDXDispatcher::Destroy(void)
|
||
|
{
|
||
|
//--- release default shaders
|
||
|
if(m_default_ps)
|
||
|
{
|
||
|
m_default_ps.Release();
|
||
|
m_default_ps=NULL;
|
||
|
}
|
||
|
if(m_default_vs)
|
||
|
{
|
||
|
m_default_vs.Release();
|
||
|
m_default_vs=NULL;
|
||
|
}
|
||
|
//--- release and delete all DX resources
|
||
|
while(m_dx_resources.Next())
|
||
|
{
|
||
|
CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next();
|
||
|
resource.Release();
|
||
|
}
|
||
|
//--- forget context
|
||
|
m_context=INVALID_HANDLE;
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Check resources |
|
||
|
//+------------------------------------------------------------------+
|
||
|
void CDXDispatcher::Check(void)
|
||
|
{
|
||
|
//---
|
||
|
CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next();
|
||
|
//--- release and delete all DX resources
|
||
|
while(CheckPointer(resource)!=POINTER_INVALID)
|
||
|
{
|
||
|
CDXHandleShared* next=(CDXHandleShared*)resource.Next();
|
||
|
//--- if references count 1 or less, then only we hold the resource
|
||
|
if(resource.References()<=1)
|
||
|
resource.Release();
|
||
|
//---
|
||
|
resource=next;
|
||
|
}
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create default shader of specified type |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXShader* CDXDispatcher::ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type)
|
||
|
{
|
||
|
switch(shader_type)
|
||
|
{
|
||
|
//--- default pixel shader
|
||
|
case DX_SHADER_PIXEL:
|
||
|
{
|
||
|
if(m_default_ps==NULL)
|
||
|
m_default_ps=ShaderCreateFromSource(DX_SHADER_PIXEL,ExtDefaultShaderPixel,"PSMain");
|
||
|
return(m_default_ps);
|
||
|
}
|
||
|
//--- default vertex shader
|
||
|
case DX_SHADER_VERTEX:
|
||
|
{
|
||
|
if(m_default_vs==NULL)
|
||
|
{
|
||
|
m_default_vs=ShaderCreateFromSource(DX_SHADER_VERTEX,ExtDefaultShaderVertex,"VSMain");
|
||
|
if(m_default_vs && !m_default_vs.LayoutSet<DXVertex>())
|
||
|
{
|
||
|
m_default_vs.Release();
|
||
|
m_default_vs=NULL;
|
||
|
}
|
||
|
}
|
||
|
return(m_default_vs);
|
||
|
}
|
||
|
}
|
||
|
//--- return result
|
||
|
return(NULL);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create new shader of specified type from file |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXShader* CDXDispatcher::ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point)
|
||
|
{
|
||
|
//--- open source file
|
||
|
int file=FileOpen(path,FILE_READ);
|
||
|
if(file==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- check file size
|
||
|
uint size=(uint)FileSize(file);
|
||
|
FileClose(file);
|
||
|
if(size>16*1024*1024)
|
||
|
return(NULL);
|
||
|
//--- prepare buffer
|
||
|
char buffer[];
|
||
|
ArrayResize(buffer,size);
|
||
|
//--- read file into buffer
|
||
|
int read=(int)FileLoad(path,buffer);
|
||
|
if(read<=0)
|
||
|
return(NULL);
|
||
|
//--- convert vuffer to string
|
||
|
string source=CharArrayToString(buffer,0,WHOLE_ARRAY,CP_UTF8);
|
||
|
//--- add shader by source
|
||
|
return(ShaderCreateFromSource(shader_type,source,entry_point));
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create new shader of specified type from source code |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXShader* CDXDispatcher::ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new shader
|
||
|
CDXShader* shader=new CDXShader();
|
||
|
if(shader==NULL)
|
||
|
return(NULL);
|
||
|
//--- create shader
|
||
|
if(!shader.Create(m_context,shader_type,source,entry_point))
|
||
|
{
|
||
|
shader.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add shader to resources list
|
||
|
if(!ResourceAdd(shader))
|
||
|
{
|
||
|
shader.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return shader
|
||
|
return(shader);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create vertex buffer |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template<typename TVertex>
|
||
|
CDXVertexBuffer* CDXDispatcher::VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new buffer
|
||
|
CDXVertexBuffer* buffer=new CDXVertexBuffer();
|
||
|
if(buffer==NULL)
|
||
|
return(NULL);
|
||
|
//--- create buffer
|
||
|
if(!buffer.Create(m_context,vertices,start,count))
|
||
|
{
|
||
|
buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add buffer to resources list
|
||
|
if(!ResourceAdd(buffer))
|
||
|
{
|
||
|
buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return buffer
|
||
|
return(buffer);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create vertex buffer |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXIndexBuffer* CDXDispatcher::IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new buffer
|
||
|
CDXIndexBuffer* buffer=new CDXIndexBuffer();
|
||
|
if(buffer==NULL)
|
||
|
return(NULL);
|
||
|
//--- create buffer
|
||
|
if(!buffer.Create(m_context,indicies,start,count))
|
||
|
{
|
||
|
buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add buffer to resources list
|
||
|
if(!ResourceAdd(buffer))
|
||
|
{
|
||
|
buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return input buffer
|
||
|
return(buffer);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create shader input buffer |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template<typename TInput>
|
||
|
CDXInput* CDXDispatcher::InputCreate(void)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new input buffer
|
||
|
CDXInput* input_buffer=new CDXInput();
|
||
|
if(input_buffer==NULL)
|
||
|
return(NULL);
|
||
|
//--- create buffer
|
||
|
if(!input_buffer.Create<TInput>(m_context))
|
||
|
{
|
||
|
input_buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add buffer to resources list
|
||
|
if(!ResourceAdd(input_buffer))
|
||
|
{
|
||
|
input_buffer.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return shader
|
||
|
return(input_buffer);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create texture from bitmap file |
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXTexture* CDXDispatcher::TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new texture
|
||
|
CDXTexture* texture=new CDXTexture();
|
||
|
if(texture==NULL)
|
||
|
return(NULL);
|
||
|
//--- create texture
|
||
|
if(!texture.Create(m_context,path,data_x,data_y,data_width,data_height))
|
||
|
{
|
||
|
texture.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add texture to resources list
|
||
|
if(!ResourceAdd(texture))
|
||
|
{
|
||
|
texture.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return shader
|
||
|
return(texture);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Create texture from raw data, only 32-bit pixel formats supported|
|
||
|
//+------------------------------------------------------------------+
|
||
|
CDXTexture* CDXDispatcher::TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0)
|
||
|
{
|
||
|
//--- check context
|
||
|
if(m_context==INVALID_HANDLE)
|
||
|
return(NULL);
|
||
|
//--- allocate new texture
|
||
|
CDXTexture* texture=new CDXTexture();
|
||
|
if(texture==NULL)
|
||
|
return(NULL);
|
||
|
//--- create texture
|
||
|
if(!texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height))
|
||
|
{
|
||
|
texture.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- add texture to resources list
|
||
|
if(!ResourceAdd(texture))
|
||
|
{
|
||
|
texture.Release();
|
||
|
return(NULL);
|
||
|
}
|
||
|
//--- return shader
|
||
|
return(texture);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Add DX resource |
|
||
|
//+------------------------------------------------------------------+
|
||
|
bool CDXDispatcher::ResourceAdd(CDXObjectBase *resource)
|
||
|
{
|
||
|
//--- add resource
|
||
|
if(!CheckPointer(resource))
|
||
|
return(false);
|
||
|
//---
|
||
|
CDXObjectBase *last=&m_dx_resources;
|
||
|
while(CheckPointer(last.Next())!=POINTER_INVALID)
|
||
|
{
|
||
|
if(last==resource)
|
||
|
return(false);
|
||
|
//---
|
||
|
last=last.Next();
|
||
|
}
|
||
|
//---
|
||
|
resource.Next(NULL);
|
||
|
resource.Prev(last);
|
||
|
last.Next(resource);
|
||
|
return(true);
|
||
|
}
|
||
|
//+------------------------------------------------------------------+
|