@@ -41,7 +41,9 @@ class FramebufferData | |||||
{ | { | ||||
friend class Framebuffer; | friend class Framebuffer; | ||||
ibox2 m_saved_viewport; | |||||
ivec2 m_size; | ivec2 m_size; | ||||
bool m_bound; | |||||
#if defined USE_D3D9 | #if defined USE_D3D9 | ||||
IDirect3DTexture9 *m_texture; | IDirect3DTexture9 *m_texture; | ||||
@@ -288,6 +290,7 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format) | |||||
: m_data(new FramebufferData) | : m_data(new FramebufferData) | ||||
{ | { | ||||
m_data->m_size = size; | m_data->m_size = size; | ||||
m_data->m_bound = false; | |||||
#if defined USE_D3D9 | #if defined USE_D3D9 | ||||
if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, | if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, | ||||
D3DUSAGE_RENDERTARGET, | D3DUSAGE_RENDERTARGET, | ||||
@@ -370,7 +373,11 @@ Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format) | |||||
"invalid framebuffer status 0x%x", status); | "invalid framebuffer status 0x%x", status); | ||||
# endif | # endif | ||||
Unbind(); | |||||
# if GL_VERSION_1_1 || GL_ES_VERSION_2_0 | |||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); | |||||
# else | |||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | |||||
# endif | |||||
#endif | #endif | ||||
} | } | ||||
@@ -412,6 +419,8 @@ ivec2 Framebuffer::GetSize() const | |||||
void Framebuffer::Bind() | void Framebuffer::Bind() | ||||
{ | { | ||||
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(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface))) | ||||
Abort(); | Abort(); | ||||
@@ -423,34 +432,40 @@ void Framebuffer::Bind() | |||||
# else | # else | ||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo); | glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo); | ||||
# endif | # endif | ||||
//change viewport draw size | |||||
Video::SetCustomSize(m_data->m_size); | |||||
#endif | #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() | 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, | if (FAILED(g_d3ddevice->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 | |||||
if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) | if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) | ||||
Abort(); | Abort(); | ||||
m_data->m_back_surface->Release(); | m_data->m_back_surface->Release(); | ||||
#else | #else | ||||
//Restore viewport draw size | |||||
Video::RestoreSize(); | |||||
# if GL_VERSION_1_1 || GL_ES_VERSION_2_0 | # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 | ||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); | glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
# else | # else | ||||
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); | ||||
# endif | # endif | ||||
#endif | #endif | ||||
g_renderer->SetViewport(m_data->m_saved_viewport); | |||||
m_data->m_bound = false; | |||||
} | } | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -54,17 +54,13 @@ class RenderContextData | |||||
private: | private: | ||||
Scene *m_scene; | Scene *m_scene; | ||||
TrackedState<ibox2> m_viewport; | |||||
TrackedState<vec4> m_clear_color; | TrackedState<vec4> m_clear_color; | ||||
TrackedState<float> m_clear_depth; | TrackedState<float> m_clear_depth; | ||||
TrackedState<AlphaFunc> m_alpha_func; | TrackedState<AlphaFunc> m_alpha_func; | ||||
TrackedState<float> m_alpha_value; | TrackedState<float> m_alpha_value; | ||||
TrackedState<BlendFunc> m_blend_src, m_blend_dst; | TrackedState<BlendFunc> m_blend_src, m_blend_dst; | ||||
TrackedState<DepthFunc> m_depth_func; | TrackedState<DepthFunc> m_depth_func; | ||||
TrackedState<CullMode> m_face_culling; | TrackedState<CullMode> m_face_culling; | ||||
}; | }; | ||||
@@ -80,6 +76,9 @@ RenderContext::RenderContext() | |||||
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()) | if (m_data->m_clear_color.HasChanged()) | ||||
g_renderer->SetClearColor(m_data->m_clear_color.GetValue()); | g_renderer->SetClearColor(m_data->m_clear_color.GetValue()); | ||||
@@ -103,6 +102,14 @@ RenderContext::~RenderContext() | |||||
delete m_data; | 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) | void RenderContext::SetClearColor(vec4 color) | ||||
{ | { | ||||
if (!m_data->m_clear_color.HasChanged()) | if (!m_data->m_clear_color.HasChanged()) | ||||
@@ -53,6 +53,7 @@ class RendererData | |||||
friend class Renderer; | friend class Renderer; | ||||
private: | private: | ||||
ibox2 m_viewport; | |||||
vec4 m_clear_color; | vec4 m_clear_color; | ||||
float m_clear_depth; | float m_clear_depth; | ||||
AlphaFunc m_alpha_func; | AlphaFunc m_alpha_func; | ||||
@@ -72,7 +73,7 @@ private: | |||||
* Public Renderer class | * Public Renderer class | ||||
*/ | */ | ||||
Renderer::Renderer() | |||||
Renderer::Renderer(ivec2 size) | |||||
: m_data(new RendererData()) | : m_data(new RendererData()) | ||||
{ | { | ||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
@@ -91,6 +92,9 @@ Renderer::Renderer() | |||||
#endif | #endif | ||||
/* Initialise rendering states */ | /* 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); | m_data->m_clear_color = vec4(-1.f); | ||||
SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f)); | SetClearColor(vec4(0.1f, 0.2f, 0.3f, 1.0f)); | ||||
@@ -126,12 +130,41 @@ Renderer::~Renderer() | |||||
delete m_data; | 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 | * Clear color | ||||
*/ | */ | ||||
void Renderer::SetClearColor(vec4 color) | void Renderer::SetClearColor(vec4 color) | ||||
{ | { | ||||
if (m_data->m_clear_color == color) | |||||
return; | |||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
/* Nothing to do */ | /* Nothing to do */ | ||||
#else | #else | ||||
@@ -152,6 +185,9 @@ vec4 Renderer::GetClearColor() const | |||||
void Renderer::SetClearDepth(float depth) | void Renderer::SetClearDepth(float depth) | ||||
{ | { | ||||
if (m_data->m_clear_depth == depth) | |||||
return; | |||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
/* Nothing to do */ | /* Nothing to do */ | ||||
#elif defined HAVE_GLES_2X | #elif defined HAVE_GLES_2X | ||||
@@ -27,6 +27,7 @@ public: | |||||
RenderContext(); | RenderContext(); | ||||
~RenderContext(); | ~RenderContext(); | ||||
void SetViewport(ibox2 viewport); | |||||
void SetClearColor(vec4 color); | void SetClearColor(vec4 color); | ||||
void SetClearDepth(float depth); | void SetClearDepth(float depth); | ||||
void SetAlphaFunc(AlphaFunc func, float alpha); | void SetAlphaFunc(AlphaFunc func, float alpha); | ||||
@@ -115,10 +115,13 @@ private: | |||||
/* Only the Video class can create a renderer for now. */ | /* Only the Video class can create a renderer for now. */ | ||||
friend class Video; | friend class Video; | ||||
Renderer(); | |||||
Renderer(ivec2 size); | |||||
~Renderer(); | ~Renderer(); | ||||
public: | public: | ||||
void SetViewport(ibox2 viewport); | |||||
ibox2 GetViewport() const; | |||||
void SetClearColor(vec4 color); | void SetClearColor(vec4 color); | ||||
vec4 GetClearColor() const; | vec4 GetClearColor() const; | ||||
@@ -48,7 +48,6 @@ class VideoData | |||||
friend class Video; | friend class Video; | ||||
private: | private: | ||||
static ivec2 saved_viewport; | |||||
static DebugRenderMode render_mode; | static DebugRenderMode render_mode; | ||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
# if defined USE_D3D9 | # if defined USE_D3D9 | ||||
@@ -61,7 +60,6 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
ivec2 VideoData::saved_viewport(0, 0); | |||||
DebugRenderMode VideoData::render_mode = DebugRenderMode::Default; | DebugRenderMode VideoData::render_mode = DebugRenderMode::Default; | ||||
#if defined USE_D3D9 || defined _XBOX | #if defined USE_D3D9 || defined _XBOX | ||||
@@ -95,8 +93,6 @@ void Video::Setup(ivec2 size) | |||||
size = lol::min(size, ivec2(VideoMode.dwDisplayWidth, | size = lol::min(size, ivec2(VideoMode.dwDisplayWidth, | ||||
VideoMode.dwDisplayHeight); | VideoMode.dwDisplayHeight); | ||||
# endif | # endif | ||||
VideoData::saved_viewport = size; | |||||
D3DPRESENT_PARAMETERS d3dpp; | D3DPRESENT_PARAMETERS d3dpp; | ||||
memset(&d3dpp, 0, sizeof(d3dpp)); | memset(&d3dpp, 0, sizeof(d3dpp)); | ||||
d3dpp.BackBufferWidth = size.x; | d3dpp.BackBufferWidth = size.x; | ||||
@@ -123,51 +119,16 @@ void Video::Setup(ivec2 size) | |||||
g_d3ddevice = VideoData::d3d_dev; | g_d3ddevice = VideoData::d3d_dev; | ||||
g_renderer = new Renderer(); | |||||
g_renderer = new Renderer(size); | |||||
#else | #else | ||||
/* Initialise OpenGL */ | /* Initialise OpenGL */ | ||||
g_renderer = new Renderer(); | |||||
glViewport(0, 0, size.x, size.y); | |||||
VideoData::saved_viewport = size; | |||||
g_renderer = new Renderer(size); | |||||
#endif | #endif | ||||
/* Initialise reasonable scene default properties */ | /* Initialise reasonable scene default properties */ | ||||
SetDebugRenderMode(DebugRenderMode::Default); | 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) | void Video::SetDebugRenderMode(DebugRenderMode d) | ||||
{ | { | ||||
switch(d) | switch(d) | ||||
@@ -243,10 +204,6 @@ void Video::Clear(ClearMask m) | |||||
g_renderer->GetClearDepth(), 0))) | g_renderer->GetClearDepth(), 0))) | ||||
Abort(); | Abort(); | ||||
#else | #else | ||||
/* FIXME: is this necessary here? */ | |||||
ivec2 size = GetSize(); | |||||
glViewport(0, 0, size.x, size.y); | |||||
GLbitfield mask = 0; | GLbitfield mask = 0; | ||||
if (m & ClearMask::Color) | if (m & ClearMask::Color) | ||||
mask |= GL_COLOR_BUFFER_BIT; | mask |= GL_COLOR_BUFFER_BIT; | ||||
@@ -302,19 +259,9 @@ void Video::Capture(uint32_t *buffer) | |||||
ivec2 Video::GetSize() | 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 */ | } /* namespace lol */ | ||||
@@ -68,8 +68,6 @@ public: | |||||
static void Setup(ivec2 size); | static void Setup(ivec2 size); | ||||
static void Destroy(); | static void Destroy(); | ||||
static void SetCustomSize(ivec2 size); | |||||
static void RestoreSize(); | |||||
static void SetDebugRenderMode(DebugRenderMode d); | static void SetDebugRenderMode(DebugRenderMode d); | ||||
static DebugRenderMode GetDebugRenderMode(); | static DebugRenderMode GetDebugRenderMode(); | ||||
static void Clear(ClearMask m); | static void Clear(ClearMask m); | ||||