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