@@ -41,7 +41,9 @@ class FramebufferData | |||
{ | |||
friend class Framebuffer; | |||
ibox2 m_saved_viewport; | |||
ivec2 m_size; | |||
bool m_bound; | |||
#if defined USE_D3D9 | |||
IDirect3DTexture9 *m_texture; | |||
@@ -288,6 +290,7 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format) | |||
: m_data(new FramebufferData) | |||
{ | |||
m_data->m_size = size; | |||
m_data->m_bound = false; | |||
#if defined USE_D3D9 | |||
if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, | |||
D3DUSAGE_RENDERTARGET, | |||
@@ -370,7 +373,11 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format) | |||
"invalid framebuffer status 0x%x", status); | |||
# endif | |||
Unbind(); | |||
# if GL_VERSION_1_1 || GL_ES_VERSION_2_0 | |||
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |||
# else | |||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | |||
# endif | |||
#endif | |||
} | |||
@@ -412,6 +419,8 @@ ivec2 Framebuffer::GetSize() const | |||
void Framebuffer::Bind() | |||
{ | |||
ASSERT(!m_data->m_bound, "trying to bind an already bound framebuffer"); | |||
#if defined USE_D3D9 || defined _XBOX | |||
if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface))) | |||
Abort(); | |||
@@ -423,34 +432,40 @@ void Framebuffer::Bind() | |||
# else | |||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo); | |||
# endif | |||
//change viewport draw size | |||
Video::SetCustomSize(m_data->m_size); | |||
#endif | |||
/* FIXME: this should be done in the RenderContext object | |||
* instead, maybe by getting rid of Framebuffer::Bind() and | |||
* creating RenderContext::SetFramebuffer() instead. */ | |||
m_data->m_saved_viewport = g_renderer->GetViewport(); | |||
g_renderer->SetViewport(ibox2(ivec2(0), m_data->m_size)); | |||
m_data->m_bound = true; | |||
} | |||
void Framebuffer::Unbind() | |||
{ | |||
#if defined USE_D3D9 | |||
if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) | |||
Abort(); | |||
m_data->m_back_surface->Release(); | |||
#elif defined _XBOX | |||
ASSERT(m_data->m_bound, "trying to unbind an unbound framebuffer"); | |||
#if defined USE_D3D9 || defined _XBOX | |||
# if defined _XBOX | |||
if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr, | |||
m_data->m_texture, nullptr, 0, 0, nullptr, | |||
0, 0, nullptr))) | |||
Abort(); | |||
# endif | |||
if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) | |||
Abort(); | |||
m_data->m_back_surface->Release(); | |||
#else | |||
//Restore viewport draw size | |||
Video::RestoreSize(); | |||
# if GL_VERSION_1_1 || GL_ES_VERSION_2_0 | |||
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |||
# else | |||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | |||
# endif | |||
#endif | |||
g_renderer->SetViewport(m_data->m_saved_viewport); | |||
m_data->m_bound = false; | |||
} | |||
} /* namespace lol */ | |||
@@ -54,17 +54,13 @@ class RenderContextData | |||
private: | |||
Scene *m_scene; | |||
TrackedState<ibox2> m_viewport; | |||
TrackedState<vec4> m_clear_color; | |||
TrackedState<float> m_clear_depth; | |||
TrackedState<AlphaFunc> m_alpha_func; | |||
TrackedState<float> m_alpha_value; | |||
TrackedState<BlendFunc> m_blend_src, m_blend_dst; | |||
TrackedState<DepthFunc> m_depth_func; | |||
TrackedState<CullMode> m_face_culling; | |||
}; | |||
@@ -80,6 +76,9 @@ RenderContext::RenderContext() | |||
RenderContext::~RenderContext() | |||
{ | |||
if (m_data->m_viewport.HasChanged()) | |||
g_renderer->SetViewport(m_data->m_viewport.GetValue()); | |||
if (m_data->m_clear_color.HasChanged()) | |||
g_renderer->SetClearColor(m_data->m_clear_color.GetValue()); | |||
@@ -103,6 +102,14 @@ RenderContext::~RenderContext() | |||
delete m_data; | |||
} | |||
void RenderContext::SetViewport(ibox2 viewport) | |||
{ | |||
if (!m_data->m_viewport.HasChanged()) | |||
m_data->m_viewport.TrackValue(g_renderer->GetViewport()); | |||
g_renderer->SetViewport(viewport); | |||
} | |||
void RenderContext::SetClearColor(vec4 color) | |||
{ | |||
if (!m_data->m_clear_color.HasChanged()) | |||
@@ -53,6 +53,7 @@ class RendererData | |||
friend class Renderer; | |||
private: | |||
ibox2 m_viewport; | |||
vec4 m_clear_color; | |||
float m_clear_depth; | |||
AlphaFunc m_alpha_func; | |||
@@ -72,7 +73,7 @@ private: | |||
* Public Renderer class | |||
*/ | |||
Renderer::Renderer() | |||
Renderer::Renderer(ivec2 size) | |||
: m_data(new RendererData()) | |||
{ | |||
#if defined USE_D3D9 || defined _XBOX | |||
@@ -91,6 +92,9 @@ Renderer::Renderer() | |||
#endif | |||
/* Initialise rendering states */ | |||
m_data->m_viewport = ibox2(0, 0, 0, 0); | |||
SetViewport(ibox2(vec2(0), size)); | |||
m_data->m_clear_color = vec4(-1.f); | |||
SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f)); | |||
@@ -126,12 +130,41 @@ Renderer::~Renderer() | |||
delete m_data; | |||
} | |||
/* | |||
* Viewport dimensions | |||
*/ | |||
void Renderer::SetViewport(ibox2 viewport) | |||
{ | |||
if (m_data->m_viewport == viewport) | |||
return; | |||
#if defined USE_D3D9 || defined _XBOX | |||
D3DVIEWPORT9 vp = { viewport.A.x, viewport.A.y, | |||
viewport.B.x, viewport.B.y, | |||
0.0f, 1.0f }; | |||
m_data->m_d3d_dev->SetViewport(&vp); | |||
#else | |||
glViewport(viewport.A.x, viewport.A.y, viewport.B.x, viewport.B.y); | |||
#endif | |||
m_data->m_viewport = viewport; | |||
} | |||
ibox2 Renderer::GetViewport() const | |||
{ | |||
return m_data->m_viewport; | |||
} | |||
/* | |||
* Clear color | |||
*/ | |||
void Renderer::SetClearColor(vec4 color) | |||
{ | |||
if (m_data->m_clear_color == color) | |||
return; | |||
#if defined USE_D3D9 || defined _XBOX | |||
/* Nothing to do */ | |||
#else | |||
@@ -152,6 +185,9 @@ vec4 Renderer::GetClearColor() const | |||
void Renderer::SetClearDepth(float depth) | |||
{ | |||
if (m_data->m_clear_depth == depth) | |||
return; | |||
#if defined USE_D3D9 || defined _XBOX | |||
/* Nothing to do */ | |||
#elif defined HAVE_GLES_2X | |||
@@ -27,6 +27,7 @@ public: | |||
RenderContext(); | |||
~RenderContext(); | |||
void SetViewport(ibox2 viewport); | |||
void SetClearColor(vec4 color); | |||
void SetClearDepth(float depth); | |||
void SetAlphaFunc(AlphaFunc func, float alpha); | |||
@@ -115,10 +115,13 @@ private: | |||
/* Only the Video class can create a renderer for now. */ | |||
friend class Video; | |||
Renderer(); | |||
Renderer(ivec2 size); | |||
~Renderer(); | |||
public: | |||
void SetViewport(ibox2 viewport); | |||
ibox2 GetViewport() const; | |||
void SetClearColor(vec4 color); | |||
vec4 GetClearColor() const; | |||
@@ -48,7 +48,6 @@ class VideoData | |||
friend class Video; | |||
private: | |||
static ivec2 saved_viewport; | |||
static DebugRenderMode render_mode; | |||
#if defined USE_D3D9 || defined _XBOX | |||
# if defined USE_D3D9 | |||
@@ -61,7 +60,6 @@ private: | |||
#endif | |||
}; | |||
ivec2 VideoData::saved_viewport(0, 0); | |||
DebugRenderMode VideoData::render_mode = DebugRenderMode::Default; | |||
#if defined USE_D3D9 || defined _XBOX | |||
@@ -95,8 +93,6 @@ void Video::Setup(ivec2 size) | |||
size = lol::min(size, ivec2(VideoMode.dwDisplayWidth, | |||
VideoMode.dwDisplayHeight); | |||
# endif | |||
VideoData::saved_viewport = size; | |||
D3DPRESENT_PARAMETERS d3dpp; | |||
memset(&d3dpp, 0, sizeof(d3dpp)); | |||
d3dpp.BackBufferWidth = size.x; | |||
@@ -123,51 +119,16 @@ void Video::Setup(ivec2 size) | |||
g_d3ddevice = VideoData::d3d_dev; | |||
g_renderer = new Renderer(); | |||
g_renderer = new Renderer(size); | |||
#else | |||
/* Initialise OpenGL */ | |||
g_renderer = new Renderer(); | |||
glViewport(0, 0, size.x, size.y); | |||
VideoData::saved_viewport = size; | |||
g_renderer = new Renderer(size); | |||
#endif | |||
/* Initialise reasonable scene default properties */ | |||
SetDebugRenderMode(DebugRenderMode::Default); | |||
} | |||
void Video::SetCustomSize(ivec2 size) | |||
{ | |||
ivec4 current_size(0); | |||
#if defined USE_D3D9 || defined _XBOX | |||
# define STR0(x) #x | |||
# define STR(x) STR0(x) | |||
# pragma message(__FILE__ "(" STR(__LINE__) "): warning: Video::SetSize() not implemented") | |||
#elif defined __CELLOS_LV2__ | |||
// FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions | |||
#else | |||
glGetIntegerv(GL_VIEWPORT, (GLint*)¤t_size); | |||
if (current_size.zw != size) | |||
glViewport(0, 0, size.x, size.y); | |||
#endif | |||
} | |||
void Video::RestoreSize() | |||
{ | |||
ivec4 current_size(0); | |||
#if defined USE_D3D9 || defined _XBOX | |||
# define STR0(x) #x | |||
# define STR(x) STR0(x) | |||
# pragma message(__FILE__ "(" STR(__LINE__) "): warning: Video::SetSize() not implemented") | |||
#elif defined __CELLOS_LV2__ | |||
// FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions | |||
#else | |||
glGetIntegerv(GL_VIEWPORT, (GLint*)¤t_size); | |||
if (current_size.zw != VideoData::saved_viewport) | |||
glViewport(0, 0, VideoData::saved_viewport.x, VideoData::saved_viewport.y); | |||
#endif | |||
} | |||
void Video::SetDebugRenderMode(DebugRenderMode d) | |||
{ | |||
switch(d) | |||
@@ -243,10 +204,6 @@ void Video::Clear(ClearMask m) | |||
g_renderer->GetClearDepth(), 0))) | |||
Abort(); | |||
#else | |||
/* FIXME: is this necessary here? */ | |||
ivec2 size = GetSize(); | |||
glViewport(0, 0, size.x, size.y); | |||
GLbitfield mask = 0; | |||
if (m & ClearMask::Color) | |||
mask |= GL_COLOR_BUFFER_BIT; | |||
@@ -302,19 +259,9 @@ void Video::Capture(uint32_t *buffer) | |||
ivec2 Video::GetSize() | |||
{ | |||
#if defined USE_D3D9 || defined _XBOX | |||
return VideoData::saved_viewport; | |||
#elif 1 | |||
/* GetSize() is called too often on the game thread; we cannot rely on | |||
* the GL context at this point */ | |||
return VideoData::saved_viewport; | |||
#elif defined __CELLOS_LV2__ | |||
// FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions | |||
#else | |||
GLint v[4]; | |||
glGetIntegerv(GL_VIEWPORT, v); | |||
return ivec2(v[2], v[3]); | |||
#endif | |||
ibox2 viewport = g_renderer->GetViewport(); | |||
return viewport.B - viewport.A; | |||
} | |||
} /* namespace lol */ | |||
@@ -68,8 +68,6 @@ public: | |||
static void Setup(ivec2 size); | |||
static void Destroy(); | |||
static void SetCustomSize(ivec2 size); | |||
static void RestoreSize(); | |||
static void SetDebugRenderMode(DebugRenderMode d); | |||
static DebugRenderMode GetDebugRenderMode(); | |||
static void Clear(ClearMask m); | |||