Browse Source

gpu: get rid of the global D3D device pointer and move D3D initialisation

code from the Video to the Renderer class.
legacy
Sam Hocevar sam 11 years ago
parent
commit
532f679f8a
11 changed files with 198 additions and 201 deletions
  1. +13
    -13
      src/gpu/framebuffer.cpp
  2. +11
    -9
      src/gpu/indexbuffer.cpp
  3. +54
    -4
      src/gpu/renderer.cpp
  4. +36
    -34
      src/gpu/shader.cpp
  5. +12
    -10
      src/gpu/texture.cpp
  6. +58
    -44
      src/gpu/vertexbuffer.cpp
  7. +2
    -0
      src/lol/gpu/renderer.h
  8. +2
    -1
      src/lol/gpu/vertexbuffer.h
  9. +8
    -8
      src/platform/sdl/sdlapp.cpp
  10. +2
    -5
      src/platform/xbox/xboxapp.cpp
  11. +0
    -73
      src/video.cpp

+ 13
- 13
src/gpu/framebuffer.cpp View File

@@ -23,12 +23,6 @@


using namespace std; using namespace std;


#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -46,9 +40,11 @@ class FramebufferData
bool m_bound; bool m_bound;


#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DTexture9 *m_texture; IDirect3DTexture9 *m_texture;
IDirect3DSurface9 *m_surface, *m_back_surface; IDirect3DSurface9 *m_surface, *m_back_surface;
#elif defined _XBOX #elif defined _XBOX
D3DDevice9 *m_dev;
D3DTexture *m_texture; D3DTexture *m_texture;
D3DSurface *m_surface, *m_back_surface; D3DSurface *m_surface, *m_back_surface;
#else #else
@@ -292,7 +288,9 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format)
m_data->m_size = size; m_data->m_size = size;
m_data->m_bound = false; m_data->m_bound = false;
#if defined USE_D3D9 #if defined USE_D3D9
if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1,
m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();

if (FAILED(m_data->m_dev->CreateTexture(size.x, size.y, 1,
D3DUSAGE_RENDERTARGET, D3DUSAGE_RENDERTARGET,
(D3DFORMAT)fbo_format.GetFormat(), D3DPOOL_DEFAULT, (D3DFORMAT)fbo_format.GetFormat(), D3DPOOL_DEFAULT,
&m_data->m_texture, nullptr))) &m_data->m_texture, nullptr)))
@@ -300,11 +298,13 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format)
if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface))) if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface)))
Abort(); Abort();
#elif defined _XBOX #elif defined _XBOX
if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, 0,
m_data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();

if (FAILED(m_data->m_dev->CreateTexture(size.x, size.y, 1, 0,
fbo_format.GetFormat(), D3DPOOL_DEFAULT, fbo_format.GetFormat(), D3DPOOL_DEFAULT,
&m_data->m_texture, nullptr))) &m_data->m_texture, nullptr)))
Abort(); Abort();
if (FAILED(g_d3ddevice->CreateRenderTarget(size.x, size.y,
if (FAILED(m_data->m_dev->CreateRenderTarget(size.x, size.y,
fbo_format.GetFormat(), fbo_format.GetFormat(),
D3DMULTISAMPLE_NONE, 0, 0, D3DMULTISAMPLE_NONE, 0, 0,
&m_data->m_surface, nullptr))) &m_data->m_surface, nullptr)))
@@ -422,9 +422,9 @@ void Framebuffer::Bind()
ASSERT(!m_data->m_bound, "trying to bind an already bound framebuffer"); ASSERT(!m_data->m_bound, "trying to bind an already bound framebuffer");


#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface)))
if (FAILED(m_data->m_dev->GetRenderTarget(0, &m_data->m_back_surface)))
Abort(); Abort();
if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_surface)))
if (FAILED(m_data->m_dev->SetRenderTarget(0, m_data->m_surface)))
Abort(); Abort();
#else #else
# if GL_VERSION_1_1 || GL_ES_VERSION_2_0 # if GL_VERSION_1_1 || GL_ES_VERSION_2_0
@@ -448,12 +448,12 @@ void Framebuffer::Unbind()


#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
# if defined _XBOX # if defined _XBOX
if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr,
if (FAILED(m_data->m_dev->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr,
m_data->m_texture, nullptr, 0, 0, nullptr, m_data->m_texture, nullptr, 0, 0, nullptr,
0, 0, nullptr))) 0, 0, nullptr)))
Abort(); Abort();
# endif # endif
if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
if (FAILED(m_data->m_dev->SetRenderTarget(0, m_data->m_back_surface)))
Abort(); Abort();
m_data->m_back_surface->Release(); m_data->m_back_surface->Release();
#else #else


+ 11
- 9
src/gpu/indexbuffer.cpp View File

@@ -23,12 +23,6 @@


using namespace std; using namespace std;


#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -44,8 +38,10 @@ class IndexBufferData
size_t m_size; size_t m_size;


#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DIndexBuffer9 *m_ibo; IDirect3DIndexBuffer9 *m_ibo;
#elif defined _XBOX #elif defined _XBOX
D3DDevice9 *m_dev;
D3DIndexBuffer *m_ibo; D3DIndexBuffer *m_ibo;
#else #else
GLuint m_ibo; GLuint m_ibo;
@@ -65,7 +61,13 @@ IndexBuffer::IndexBuffer(size_t size)
if (!size) if (!size)
return; return;
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (FAILED(g_d3ddevice->CreateIndexBuffer(size, D3DUSAGE_WRITEONLY,
# if defined USE_D3D9
m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
# elif defined _XBOX
m_data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();
# endif

if (FAILED(m_data->m_dev->CreateIndexBuffer(size, D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_MANAGED, D3DFMT_INDEX16, D3DPOOL_MANAGED,
&m_data->m_ibo, nullptr))) &m_data->m_ibo, nullptr)))
Abort(); Abort();
@@ -126,7 +128,7 @@ void IndexBuffer::Bind()
return; return;


#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (FAILED(g_d3ddevice->SetIndices(m_data->m_ibo)))
if (FAILED(m_data->m_dev->SetIndices(m_data->m_ibo)))
Abort(); Abort();
#else #else
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_data->m_ibo);
@@ -142,7 +144,7 @@ void IndexBuffer::Unbind()
return; return;


#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (FAILED(g_d3ddevice->SetIndices(nullptr)))
if (FAILED(m_data->m_dev->SetIndices(nullptr)))
Abort(); Abort();
#else #else
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


+ 54
- 4
src/gpu/renderer.cpp View File

@@ -31,10 +31,11 @@
#include "core.h" #include "core.h"
#include "lolgl.h" #include "lolgl.h"


/* FIXME: find a way to pass g_hwnd from the windowing system */
#if defined USE_D3D9 #if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
extern HWND g_hwnd;
#elif defined _XBOX #elif defined _XBOX
extern D3DDevice *g_d3ddevice;
HWND g_hwnd = 0;
#endif #endif


namespace lol namespace lol
@@ -62,9 +63,12 @@ private:
DepthFunc m_depth_func; DepthFunc m_depth_func;
CullMode m_face_culling; CullMode m_face_culling;


private:
#if defined USE_D3D9 #if defined USE_D3D9
IDirect3D9 *m_d3d_ctx;
IDirect3DDevice9 *m_d3d_dev; IDirect3DDevice9 *m_d3d_dev;
#elif defined _XBOX #elif defined _XBOX
Direct3D *m_d3d_ctx;
D3DDevice *m_d3d_dev; D3DDevice *m_d3d_dev;
#endif #endif
}; };
@@ -77,8 +81,45 @@ Renderer::Renderer(ivec2 size)
: m_data(new RendererData()) : m_data(new RendererData())
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
/* FIXME: we should be in charge of creating this */
m_data->m_d3d_dev = g_d3ddevice;
/* Create Direct3D context */
m_data->m_d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
if (!m_data->m_d3d_ctx)
{
Log::Error("cannot initialise D3D\n");
exit(EXIT_FAILURE);
}

/* Create Direct3D device */
# if defined _XBOX
XVIDEO_MODE VideoMode;
XGetVideoMode(&VideoMode);
size = lol::min(size, ivec2(VideoMode.dwDisplayWidth,
VideoMode.dwDisplayHeight);
# endif
D3DPRESENT_PARAMETERS d3dpp;
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.BackBufferWidth = size.x;
d3dpp.BackBufferHeight = size.y;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.hDeviceWindow = g_hwnd;
# if defined USE_SDL
d3dpp.Windowed = TRUE;
# endif
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

HRESULT hr = VideoData::d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, g_hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &m_data->m_d3d_dev);
if (FAILED(hr))
{
Log::Error("cannot create D3D device\n");
exit(EXIT_FAILURE);
}

#else #else
# if defined USE_GLEW && !defined __APPLE__ # if defined USE_GLEW && !defined __APPLE__
/* Initialise GLEW if necessary */ /* Initialise GLEW if necessary */
@@ -130,6 +171,15 @@ Renderer::~Renderer()
delete m_data; delete m_data;
} }


void *Renderer::GetDevice()
{
#if defined USE_D3D9 || defined _XBOX
return m_data->m_d3d_dev;
#else
return nullptr;
#endif
}

/* /*
* Buffer clearing * Buffer clearing
*/ */


+ 36
- 34
src/gpu/shader.cpp View File

@@ -32,12 +32,6 @@


using namespace std; using namespace std;


#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -51,10 +45,12 @@ class ShaderData


private: private:
#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DVertexShader9 *vert_shader; IDirect3DVertexShader9 *vert_shader;
IDirect3DPixelShader9 *frag_shader; IDirect3DPixelShader9 *frag_shader;
ID3DXConstantTable *vert_table, *frag_table; ID3DXConstantTable *vert_table, *frag_table;
#elif defined _XBOX #elif defined _XBOX
D3DDevice9 *m_dev;
D3DVertexShader *vert_shader; D3DVertexShader *vert_shader;
D3DPixelShader *frag_shader; D3DPixelShader *frag_shader;
ID3DXConstantTable *vert_table, *frag_table; ID3DXConstantTable *vert_table, *frag_table;
@@ -193,6 +189,12 @@ Shader::Shader(char const *vert, char const *frag)
/* Compile vertex shader */ /* Compile vertex shader */
data->vert_crc = ShaderData::hash(vert); data->vert_crc = ShaderData::hash(vert);
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
# if defined USE_D3D9
data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
# elif defined _XBOX
data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();
# endif

hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, nullptr, "main", hr = D3DXCompileShader(vert, (UINT)strlen(vert), macros, nullptr, "main",
"vs_3_0", 0, &shader_code, &error_msg, "vs_3_0", 0, &shader_code, &error_msg,
&data->vert_table); &data->vert_table);
@@ -202,7 +204,7 @@ Shader::Shader(char const *vert, char const *frag)
error_msg ? error_msg->GetBufferPointer() : "error"); error_msg ? error_msg->GetBufferPointer() : "error");
Log::Error("shader source:\n%s\n", vert); Log::Error("shader source:\n%s\n", vert);
} }
g_d3ddevice->CreateVertexShader((DWORD *)shader_code->GetBufferPointer(),
data->m_dev->CreateVertexShader((DWORD *)shader_code->GetBufferPointer(),
&data->vert_shader); &data->vert_shader);
shader_code->Release(); shader_code->Release();
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
@@ -246,7 +248,7 @@ Shader::Shader(char const *vert, char const *frag)
error_msg ? error_msg->GetBufferPointer() : "error"); error_msg ? error_msg->GetBufferPointer() : "error");
Log::Error("shader source:\n%s\n", frag); Log::Error("shader source:\n%s\n", frag);
} }
g_d3ddevice->CreatePixelShader((DWORD *)shader_code->GetBufferPointer(),
data->m_dev->CreatePixelShader((DWORD *)shader_code->GetBufferPointer(),
&data->frag_shader); &data->frag_shader);
shader_code->Release(); shader_code->Release();
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
@@ -419,9 +421,9 @@ void Shader::SetUniform(ShaderUniform const &uni, ivec4 const &v)
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
data->m_dev->SetPixelShaderConstantI((UINT)uni.frag, &v[0], 1);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
data->m_dev->SetVertexShaderConstantI((UINT)uni.vert, &v[0], 1);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform4i(uni.frag, v.x, v.y, v.z, v.w); glUniform4i(uni.frag, v.x, v.y, v.z, v.w);
#else #else
@@ -475,9 +477,9 @@ void Shader::SetUniform(ShaderUniform const &uni, vec4 const &v)
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &v[0], 1);
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &v[0], 1);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1);
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &v[0], 1);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform4fv(uni.frag, 1, &v[0]); glUniform4fv(uni.frag, 1, &v[0]);
#else #else
@@ -493,9 +495,9 @@ void Shader::SetUniform(ShaderUniform const &uni, mat2 const &m)
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
/* FIXME: do we need padding here like for the mat3 version? */ /* FIXME: do we need padding here like for the mat3 version? */
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 1);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 1);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]); glUniformMatrix2fv(uni.frag, 1, GL_FALSE, &m[0][0]);
#else #else
@@ -514,9 +516,9 @@ void Shader::SetUniform(ShaderUniform const &uni, mat3 const &m)
* a new data structure; a 4×4 matrix will do. */ * a new data structure; a 4×4 matrix will do. */
mat4 tmp(m, 1.0f); mat4 tmp(m, 1.0f);
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &tmp[0][0], 3);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &tmp[0][0], 3);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]); glUniformMatrix3fv(uni.frag, 1, GL_FALSE, &m[0][0]);
#else #else
@@ -533,9 +535,9 @@ void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag, &m[0][0], 4);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert, &m[0][0], 4);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]); glUniformMatrix4fv(uni.frag, 1, GL_FALSE, &m[0][0]);
#else #else
@@ -549,10 +551,10 @@ void Shader::SetUniform(ShaderUniform const &uni, mat4 const &m)
void Shader::SetUniform(ShaderUniform const &uni, ShaderTexture tex, int index) void Shader::SetUniform(ShaderUniform const &uni, ShaderTexture tex, int index)
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
g_d3ddevice->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
g_d3ddevice->SetSamplerState(index, D3DSAMP_MAGFILTER, tex.m_attrib & 0xff);
g_d3ddevice->SetSamplerState(index, D3DSAMP_MINFILTER, (tex.m_attrib >> 8) & 0xff);
g_d3ddevice->SetSamplerState(index, D3DSAMP_MIPFILTER, (tex.m_attrib >> 16) & 0xff);
data->m_dev->SetTexture(index, (LPDIRECT3DTEXTURE9)tex.m_flags);
data->m_dev->SetSamplerState(index, D3DSAMP_MAGFILTER, tex.m_attrib & 0xff);
data->m_dev->SetSamplerState(index, D3DSAMP_MINFILTER, (tex.m_attrib >> 8) & 0xff);
data->m_dev->SetSamplerState(index, D3DSAMP_MIPFILTER, (tex.m_attrib >> 16) & 0xff);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glActiveTexture(GL_TEXTURE0 + index); glActiveTexture(GL_TEXTURE0 + index);
//glEnable(GL_TEXTURE_2D); //glEnable(GL_TEXTURE_2D);
@@ -573,10 +575,10 @@ void Shader::SetUniform(ShaderUniform const &uni, Array<float> const &v)
/* FIXME: this will not work properly because we don't know how tell DX9 /* FIXME: this will not work properly because we don't know how tell DX9
* it's a bunch of floats instead of vec4. */ * it's a bunch of floats instead of vec4. */
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
&v[0], v.Count() / 4); &v[0], v.Count() / 4);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
&v[0], v.Count() / 4); &v[0], v.Count() / 4);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform1fv(uni.frag, v.Count(), &v[0]); glUniform1fv(uni.frag, v.Count(), &v[0]);
@@ -596,10 +598,10 @@ void Shader::SetUniform(ShaderUniform const &uni, Array<vec2> const &v)
/* FIXME: this will not work properly because we don't know how tell DX9 /* FIXME: this will not work properly because we don't know how tell DX9
* it's a bunch of vec2 instead of vec4. */ * it's a bunch of vec2 instead of vec4. */
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
&v[0][0], v.Count() / 2); &v[0][0], v.Count() / 2);
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
&v[0][0], v.Count() / 2); &v[0][0], v.Count() / 2);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform2fv(uni.frag, v.Count(), &v[0][0]); glUniform2fv(uni.frag, v.Count(), &v[0][0]);
@@ -619,10 +621,10 @@ void Shader::SetUniform(ShaderUniform const &uni, Array<vec3> const &v)
/* FIXME: this will not work properly because we don't know how tell DX9 /* FIXME: this will not work properly because we don't know how tell DX9
* it's a bunch of vec3 instead of vec4. */ * it's a bunch of vec3 instead of vec4. */
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
&v[0][0], v.Count()); &v[0][0], v.Count());
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
&v[0][0], v.Count()); &v[0][0], v.Count());
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform3fv(uni.frag, v.Count(), &v[0][0]); glUniform3fv(uni.frag, v.Count(), &v[0][0]);
@@ -640,10 +642,10 @@ void Shader::SetUniform(ShaderUniform const &uni, Array<vec4> const &v)
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (uni.flags & 1) if (uni.flags & 1)
g_d3ddevice->SetPixelShaderConstantF((UINT)uni.frag,
data->m_dev->SetPixelShaderConstantF((UINT)uni.frag,
&v[0][0], v.Count()); &v[0][0], v.Count());
if (uni.flags & 2) if (uni.flags & 2)
g_d3ddevice->SetVertexShaderConstantF((UINT)uni.vert,
data->m_dev->SetVertexShaderConstantF((UINT)uni.vert,
&v[0][0], v.Count()); &v[0][0], v.Count());
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUniform4fv(uni.frag, v.Count(), &v[0][0]); glUniform4fv(uni.frag, v.Count(), &v[0][0]);
@@ -661,8 +663,8 @@ void Shader::Bind() const
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
HRESULT hr; HRESULT hr;
hr = g_d3ddevice->SetVertexShader(data->vert_shader);
hr = g_d3ddevice->SetPixelShader(data->frag_shader);
hr = data->m_dev->SetVertexShader(data->vert_shader);
hr = data->m_dev->SetPixelShader(data->frag_shader);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
glUseProgram(data->prog_id); glUseProgram(data->prog_id);
#else #else
@@ -677,8 +679,8 @@ void Shader::Unbind() const
{ {
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
HRESULT hr; HRESULT hr;
hr = g_d3ddevice->SetVertexShader(nullptr);
hr = g_d3ddevice->SetPixelShader(nullptr);
hr = data->m_dev->SetVertexShader(nullptr);
hr = data->m_dev->SetPixelShader(nullptr);
#elif !defined __CELLOS_LV2__ #elif !defined __CELLOS_LV2__
/* FIXME: untested */ /* FIXME: untested */
glUseProgram(0); glUseProgram(0);


+ 12
- 10
src/gpu/texture.cpp View File

@@ -23,12 +23,6 @@


using namespace std; using namespace std;


#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -45,11 +39,13 @@ class TextureData
PixelFormat m_format; PixelFormat m_format;


#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DTexture9 *m_texture; IDirect3DTexture9 *m_texture;
D3DTEXTUREFILTERTYPE m_mag_filter; D3DTEXTUREFILTERTYPE m_mag_filter;
D3DTEXTUREFILTERTYPE m_min_filter;
D3DTEXTUREFILTERTYPE m_mip_filter;
D3DTEXTUREFILTERTYPE m_min_filter;
D3DTEXTUREFILTERTYPE m_mip_filter;
#elif defined _XBOX #elif defined _XBOX
D3DDevice9 *m_dev;
D3DTexture *m_texture; D3DTexture *m_texture;
#else #else
GLuint m_texture; GLuint m_texture;
@@ -75,6 +71,12 @@ Texture::Texture(ivec2 size, PixelFormat format)
m_data->m_format = format; m_data->m_format = format;


#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
# if defined USE_D3D9
m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
# elif defined _XBOX
m_data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();
# endif

static struct static struct
{ {
D3DFORMAT format; D3DFORMAT format;
@@ -109,7 +111,7 @@ Texture::Texture(ivec2 size, PixelFormat format)
int d3d_usage = D3DUSAGE_WRITEONLY; int d3d_usage = D3DUSAGE_WRITEONLY;
# endif # endif


g_d3ddevice->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
m_data->m_dev->CreateTexture(m_data->m_size.x, m_data->m_size.y, 1,
d3d_usage, d3d_format, d3d_usage, d3d_format,
D3DPOOL_DEFAULT, &m_data->m_texture, nullptr); D3DPOOL_DEFAULT, &m_data->m_texture, nullptr);
m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes; m_data->m_bytes_per_elem = GET_CLAMPED(d3d_formats, format).bytes;
@@ -185,7 +187,7 @@ ShaderTexture Texture::GetTexture() const
void Texture::Bind() void Texture::Bind()
{ {
#if defined _XBOX || defined USE_D3D9 #if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetTexture(0, m_data->m_texture);
m_data->m_dev->SetTexture(0, m_data->m_texture);
#else #else
# if !defined HAVE_GLES_2X # if !defined HAVE_GLES_2X
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);


+ 58
- 44
src/gpu/vertexbuffer.cpp View File

@@ -23,12 +23,6 @@


using namespace std; using namespace std;


#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -45,8 +39,10 @@ class VertexBufferData
size_t m_size; size_t m_size;


#if defined USE_D3D9 #if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DVertexBuffer9 *m_vbo; IDirect3DVertexBuffer9 *m_vbo;
#elif defined _XBOX #elif defined _XBOX
D3DDevice9 *m_dev;
D3DVertexBuffer *m_vbo; D3DVertexBuffer *m_vbo;
#else #else
GLuint m_vbo; GLuint m_vbo;
@@ -54,6 +50,26 @@ class VertexBufferData
#endif #endif
}; };


//
// The VertexDeclarationData class
// -------------------------------
//

class VertexDeclarationData
{
friend class VertexBuffer;
friend class VertexDeclaration;

#if defined USE_D3D9
IDirect3DDevice9 *m_dev;
IDirect3DVertexDeclaration9 *m_vdecl;
#elif defined _XBOX
D3DDevice9 *m_dev;
D3DVertexDeclaration *m_vdecl;
#else
#endif
};

// //
// The VertexDeclaration class // The VertexDeclaration class
// --------------------------- // ---------------------------
@@ -72,7 +88,9 @@ VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
VertexStreamBase const &s9, VertexStreamBase const &s9,
VertexStreamBase const &s10, VertexStreamBase const &s10,
VertexStreamBase const &s11, VertexStreamBase const &s11,
VertexStreamBase const &s12) : m_count(0)
VertexStreamBase const &s12)
: m_count(0),
m_data(new VertexDeclarationData())
{ {
if (&s1 != &VertexStreamBase::Empty) AddStream(s1); if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
if (&s2 != &VertexStreamBase::Empty) AddStream(s2); if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
@@ -92,29 +110,19 @@ VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
VertexDeclaration::~VertexDeclaration() VertexDeclaration::~VertexDeclaration()
{ {
#if defined _XBOX || defined USE_D3D9 #if defined _XBOX || defined USE_D3D9
# if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
# elif defined _XBOX
D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
# endif

if (FAILED(vdecl->Release()))
if (FAILED(m_data->m_vdecl->Release()))
Abort(); Abort();
#else #else


#endif #endif

delete m_data;
} }


void VertexDeclaration::Bind() void VertexDeclaration::Bind()
{ {
#if defined _XBOX || defined USE_D3D9 #if defined _XBOX || defined USE_D3D9
# if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
# elif defined _XBOX
D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
# endif

if (FAILED(g_d3ddevice->SetVertexDeclaration(vdecl)))
if (FAILED(m_data->m_dev->SetVertexDeclaration(m_data->m_vdecl)))
Abort(); Abort();
#else #else
/* FIXME: Nothing to do? */ /* FIXME: Nothing to do? */
@@ -130,28 +138,28 @@ void VertexDeclaration::DrawElements(MeshPrimitive type, int skip, int count)
switch (type) switch (type)
{ {
case MeshPrimitive::Triangles: case MeshPrimitive::Triangles:
if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_TRIANGLELIST,
skip, count)))
if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLELIST,
skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::TriangleStrips: case MeshPrimitive::TriangleStrips:
if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
skip, count)))
if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLESTRIP,
skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::TriangleFans: case MeshPrimitive::TriangleFans:
if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
skip, count)))
if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_TRIANGLEFAN,
skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::Points: case MeshPrimitive::Points:
if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_POINTLIST,
skip, count)))
if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_POINTLIST,
skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::Lines: case MeshPrimitive::Lines:
if (FAILED(g_d3ddevice->DrawPrimitive(D3DPT_LINELIST,
skip, count)))
if (FAILED(m_data->m_dev->DrawPrimitive(D3DPT_LINELIST,
skip, count)))
Abort(); Abort();
break; break;
} }
@@ -190,29 +198,29 @@ void VertexDeclaration::DrawIndexedElements(MeshPrimitive type, int vbase,
{ {
case MeshPrimitive::Triangles: case MeshPrimitive::Triangles:
count = count / 3; count = count / 3;
if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
vbase, vskip, vcount, skip, count))) vbase, vskip, vcount, skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::TriangleStrips: case MeshPrimitive::TriangleStrips:
count = count - 2; count = count - 2;
if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,
if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLESTRIP,
vbase, vskip, vcount, skip, count))) vbase, vskip, vcount, skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::TriangleFans: case MeshPrimitive::TriangleFans:
count = count - 2; count = count - 2;
if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN,
if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_TRIANGLEFAN,
vbase, vskip, vcount, skip, count))) vbase, vskip, vcount, skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::Points: case MeshPrimitive::Points:
if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_POINTLIST,
if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_POINTLIST,
vbase, vskip, vcount, skip, count))) vbase, vskip, vcount, skip, count)))
Abort(); Abort();
break; break;
case MeshPrimitive::Lines: case MeshPrimitive::Lines:
if (FAILED(g_d3ddevice->DrawIndexedPrimitive(D3DPT_LINELIST,
if (FAILED(m_data->m_dev->DrawIndexedPrimitive(D3DPT_LINELIST,
vbase, vskip, vcount, skip, count))) vbase, vskip, vcount, skip, count)))
Abort(); Abort();
break; break;
@@ -258,7 +266,7 @@ void VertexDeclaration::Unbind()
if (m_streams[i].index != stream) if (m_streams[i].index != stream)
{ {
stream = m_streams[i].index; stream = m_streams[i].index;
if (FAILED(g_d3ddevice->SetStreamSource(stream, 0, 0, 0)))
if (FAILED(m_data->m_dev->SetStreamSource(stream, 0, 0, 0)))
Abort(); Abort();
} }
/* "NULL is an invalid input to SetVertexDeclaration" (DX9 guide), so /* "NULL is an invalid input to SetVertexDeclaration" (DX9 guide), so
@@ -329,7 +337,8 @@ void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
/* FIXME: precompute most of the crap above! */ /* FIXME: precompute most of the crap above! */
if (stream >= 0) if (stream >= 0)
{ {
if (FAILED(g_d3ddevice->SetStreamSource(stream, vb->m_data->m_vbo, 0, stride)))
if (FAILED(m_data->m_dev->SetStreamSource(stream, vb->m_data->m_vbo,
0, stride)))
Abort(); Abort();
} }
#else #else
@@ -553,15 +562,14 @@ void VertexDeclaration::Initialize()
elements[m_count] = end_element[0]; elements[m_count] = end_element[0];


# if defined USE_D3D9 # if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl;
m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
# elif defined _XBOX # elif defined _XBOX
D3DVertexDeclaration *vdecl;
m_data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();
# endif # endif


if (FAILED(g_d3ddevice->CreateVertexDeclaration(elements, &vdecl)))
if (FAILED(m_data->m_dev->CreateVertexDeclaration(elements,
&m_data->m_vdecl)))
Abort(); Abort();

m_data = vdecl;
#else #else


#endif #endif
@@ -636,7 +644,13 @@ VertexBuffer::VertexBuffer(size_t size)
if (!size) if (!size)
return; return;
#if defined USE_D3D9 || defined _XBOX #if defined USE_D3D9 || defined _XBOX
if (FAILED(g_d3ddevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, nullptr,
# if defined USE_D3D9
m_data->m_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
# elif defined _XBOX
m_data->m_dev = (D3DDevice9 *)g_renderer->GetDevice();
# endif

if (FAILED(m_data->m_dev->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, nullptr,
D3DPOOL_MANAGED, &m_data->m_vbo, nullptr))) D3DPOOL_MANAGED, &m_data->m_vbo, nullptr)))
Abort(); Abort();
#else #else


+ 2
- 0
src/lol/gpu/renderer.h View File

@@ -138,6 +138,8 @@ private:
Renderer(ivec2 size); Renderer(ivec2 size);
~Renderer(); ~Renderer();


void *GetDevice();

public: public:
void Clear(ClearMask mask); void Clear(ClearMask mask);




+ 2
- 1
src/lol/gpu/vertexbuffer.h View File

@@ -311,7 +311,8 @@ private:
struct { uint8_t stream_type, index, usage, size; int reg; } m_streams[12 + 1]; struct { uint8_t stream_type, index, usage, size; int reg; } m_streams[12 + 1];
int m_count; int m_count;


void *m_data;
private:
class VertexDeclarationData *m_data;
}; };


} /* namespace lol */ } /* namespace lol */


+ 8
- 8
src/platform/sdl/sdlapp.cpp View File

@@ -34,7 +34,6 @@


#if defined USE_SDL && defined USE_D3D9 #if defined USE_SDL && defined USE_D3D9
HWND g_hwnd = nullptr; HWND g_hwnd = nullptr;
extern IDirect3DDevice9 *g_d3ddevice;
#endif #endif


namespace lol namespace lol
@@ -115,24 +114,25 @@ void SdlApp::ShowPointer(bool show)
void SdlApp::Tick() void SdlApp::Tick()
{ {
#if defined USE_SDL && defined USE_D3D9 #if defined USE_SDL && defined USE_D3D9
IDirect3DDevice9 *d3d_dev = (IDirect3DDevice9 *)g_renderer->GetDevice();
HRESULT hr; HRESULT hr;
hr = g_d3ddevice->BeginScene();
hr = d3d_dev->BeginScene();
if (FAILED(hr)) if (FAILED(hr))
Abort(); Abort();
#endif #endif

/* Tick the renderer, show the frame and clamp to desired framerate. */ /* Tick the renderer, show the frame and clamp to desired framerate. */
Ticker::TickDraw(); Ticker::TickDraw();
#if defined USE_SDL
# if defined USE_D3D9
hr = g_d3ddevice->EndScene();
#if defined USE_SDL && defined USE_D3D9
hr = d3d_dev->EndScene();
if (FAILED(hr)) if (FAILED(hr))
Abort(); Abort();
hr = g_d3ddevice->Present(nullptr, nullptr, nullptr, nullptr);
hr = d3d_dev->Present(nullptr, nullptr, nullptr, nullptr);
if (FAILED(hr)) if (FAILED(hr))
Abort(); Abort();
# else
#elif defined USE_SDL
SDL_GL_SwapBuffers(); SDL_GL_SwapBuffers();
# endif
#endif #endif
} }




+ 2
- 5
src/platform/xbox/xboxapp.cpp View File

@@ -20,10 +20,6 @@
#include "xboxapp.h" #include "xboxapp.h"
#include "xboxinput.h" #include "xboxinput.h"


#if defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol namespace lol
{ {


@@ -67,7 +63,8 @@ void XboxApp::Tick()
Ticker::TickDraw(); Ticker::TickDraw();


#if defined _XBOX #if defined _XBOX
g_d3ddevice->Present(nullptr, nullptr, nullptr, nullptr);
D3DDevice9 *d3d_dev = (D3DDevice9 *)g_renderer->GetDevice();
d3d_dev->Present(nullptr, nullptr, nullptr, nullptr);
#endif #endif
} }




+ 0
- 73
src/video.cpp View File

@@ -31,15 +31,6 @@


using namespace std; using namespace std;


/* FIXME: g_d3ddevice should never be exported */
#if defined USE_D3D9
IDirect3DDevice9 *g_d3ddevice;
extern HWND g_hwnd;
#elif defined _XBOX
D3DDevice *g_d3ddevice;
HWND g_hwnd = 0;
#endif

namespace lol namespace lol
{ {


@@ -49,81 +40,17 @@ class VideoData


private: private:
static DebugRenderMode render_mode; static DebugRenderMode render_mode;
#if defined USE_D3D9 || defined _XBOX
# if defined USE_D3D9
static IDirect3D9 *d3d_ctx;
static IDirect3DDevice9 *d3d_dev;
# elif defined _XBOX
static Direct3D *d3d_ctx;
static D3DDevice *d3d_dev;
# endif
#endif
}; };


DebugRenderMode VideoData::render_mode = DebugRenderMode::Default; DebugRenderMode VideoData::render_mode = DebugRenderMode::Default;


#if defined USE_D3D9 || defined _XBOX
# if defined USE_D3D9
IDirect3D9 *VideoData::d3d_ctx;
IDirect3DDevice9 *VideoData::d3d_dev;
# elif defined _XBOX
Direct3D *VideoData::d3d_ctx;
D3DDevice *VideoData::d3d_dev;
# endif
#endif

/* /*
* Public Video class * Public Video class
*/ */


void Video::Setup(ivec2 size) void Video::Setup(ivec2 size)
{ {
#if defined USE_D3D9 || defined _XBOX
VideoData::d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
if (!VideoData::d3d_ctx)
{
Log::Error("cannot initialise D3D\n");
exit(EXIT_FAILURE);
}

/* Choose best viewport size */
# if defined _XBOX
XVIDEO_MODE VideoMode;
XGetVideoMode(&VideoMode);
size = lol::min(size, ivec2(VideoMode.dwDisplayWidth,
VideoMode.dwDisplayHeight);
# endif
D3DPRESENT_PARAMETERS d3dpp;
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.BackBufferWidth = size.x;
d3dpp.BackBufferHeight = size.y;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.hDeviceWindow = g_hwnd;
# if defined USE_SDL
d3dpp.Windowed = TRUE;
# endif
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;

HRESULT hr = VideoData::d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, g_hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &VideoData::d3d_dev);
if (FAILED(hr))
{
Log::Error("cannot create D3D device\n");
exit(EXIT_FAILURE);
}

g_d3ddevice = VideoData::d3d_dev;

g_renderer = new Renderer(size); g_renderer = new Renderer(size);
#else
/* Initialise OpenGL */
g_renderer = new Renderer(size);
#endif


/* Initialise reasonable scene default properties */ /* Initialise reasonable scene default properties */
SetDebugRenderMode(DebugRenderMode::Default); SetDebugRenderMode(DebugRenderMode::Default);


Loading…
Cancel
Save