| @@ -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); | ||||