diff options
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/client.cc | 9 | ||||
-rw-r--r-- | o3d/core/cross/command_buffer/states_cb.cc | 22 | ||||
-rw-r--r-- | o3d/core/cross/gl/render_surface_gl.cc | 13 | ||||
-rw-r--r-- | o3d/core/cross/gl/renderer_gl.cc | 1 | ||||
-rw-r--r-- | o3d/core/cross/render_surface_set.cc | 9 | ||||
-rw-r--r-- | o3d/core/cross/render_surface_set.h | 1 | ||||
-rw-r--r-- | o3d/core/cross/render_surface_test.cc | 84 | ||||
-rw-r--r-- | o3d/core/cross/renderer.cc | 74 | ||||
-rw-r--r-- | o3d/core/cross/renderer.h | 49 | ||||
-rw-r--r-- | o3d/core/win/d3d9/renderer_d3d9.cc | 12 |
10 files changed, 186 insertions, 88 deletions
diff --git a/o3d/core/cross/client.cc b/o3d/core/cross/client.cc index 2e0224d..a7f5924 100644 --- a/o3d/core/cross/client.cc +++ b/o3d/core/cross/client.cc @@ -452,13 +452,16 @@ String Client::GetScreenshotAsDataURL() { const RenderSurface* old_render_surface_; const RenderDepthStencilSurface* old_depth_surface_; + bool is_back_buffer; - renderer_->GetRenderSurfaces(&old_render_surface_, &old_depth_surface_); - renderer_->SetRenderSurfaces(surface, depth); + renderer_->GetRenderSurfaces(&old_render_surface_, &old_depth_surface_, + &is_back_buffer); + renderer_->SetRenderSurfaces(surface, depth, true); RenderClientInner(false, true); - renderer_->SetRenderSurfaces(old_render_surface_, old_depth_surface_); + renderer_->SetRenderSurfaces(old_render_surface_, old_depth_surface_, + is_back_buffer); Bitmap::Ref bitmap(surface->GetBitmap()); if (bitmap.IsNull()) { diff --git a/o3d/core/cross/command_buffer/states_cb.cc b/o3d/core/cross/command_buffer/states_cb.cc index bf29c19..9126069 100644 --- a/o3d/core/cross/command_buffer/states_cb.cc +++ b/o3d/core/cross/command_buffer/states_cb.cc @@ -255,6 +255,26 @@ class BitFieldStateHandler : public TypedStateHandler<ParamInteger> { bool *dirty_; }; +// A handler for the color write state. +class ColorWriteStateHandler : public TypedStateHandler<ParamInteger> { + public: + ColorWriteStateHandler(uint32 *value, bool *dirty) + : value_(value), + dirty_(dirty) { + } + + virtual void SetStateFromTypedParam(RendererCB* renderer, + ParamInteger* param) const { + int mask = param->value(); + o3d::command_buffer::set_color_write::AllColorsMask::Set(value_, mask); + renderer->SetWriteMask(mask); + *dirty_ = true; + } + private: + uint32 *value_; + bool *dirty_; +}; + // A template that generates a handler for full-size values (uint32, int32, // float). // Template Parameters: @@ -618,7 +638,7 @@ void RendererCB::StateManager::AddStateHandlers(RendererCB *renderer) { new EnableStateHandler<DitherEnable>(arg, dirty)); renderer->AddStateHandler( State::kColorWriteEnableParamName, - new BitFieldStateHandler<AllColorsMask>(arg, dirty)); + new ColorWriteStateHandler(arg, dirty)); } } diff --git a/o3d/core/cross/gl/render_surface_gl.cc b/o3d/core/cross/gl/render_surface_gl.cc index 52f7cc9..6570baa 100644 --- a/o3d/core/cross/gl/render_surface_gl.cc +++ b/o3d/core/cross/gl/render_surface_gl.cc @@ -62,16 +62,19 @@ Bitmap::Ref RenderSurfaceGL::PlatformSpecificGetBitmap() const { bitmap->Allocate( Texture::ARGB8, clip_width(), clip_height(), 1, Bitmap::IMAGE); - const RenderSurface* old_render_surface_; - const RenderDepthStencilSurface* old_depth_surface_; + const RenderSurface* old_render_surface; + const RenderDepthStencilSurface* old_depth_surface; + bool old_is_back_buffer; - renderer->GetRenderSurfaces(&old_render_surface_, &old_depth_surface_); - renderer->SetRenderSurfaces(this, NULL); + renderer->GetRenderSurfaces(&old_render_surface, &old_depth_surface, + &old_is_back_buffer); + renderer->SetRenderSurfaces(this, NULL, false); ::glReadPixels(0, 0, clip_width(), clip_height(), GL_BGRA, GL_UNSIGNED_BYTE, bitmap->image_data()); - renderer->SetRenderSurfaces(old_render_surface_, old_depth_surface_); + renderer->SetRenderSurfaces(old_render_surface, old_depth_surface, + old_is_back_buffer); return bitmap; } diff --git a/o3d/core/cross/gl/renderer_gl.cc b/o3d/core/cross/gl/renderer_gl.cc index 90fa3881..b52e324 100644 --- a/o3d/core/cross/gl/renderer_gl.cc +++ b/o3d/core/cross/gl/renderer_gl.cc @@ -492,6 +492,7 @@ class ColorWriteEnableHandler : public TypedStateHandler<ParamInteger> { (mask & 0x2) != 0, (mask & 0x4) != 0, (mask & 0x8) != 0); + renderer->SetWriteMask(mask); } }; diff --git a/o3d/core/cross/render_surface_set.cc b/o3d/core/cross/render_surface_set.cc index 7774b11..7ea058a 100644 --- a/o3d/core/cross/render_surface_set.cc +++ b/o3d/core/cross/render_surface_set.cc @@ -92,10 +92,12 @@ void RenderSurfaceSet::Render(RenderContext* render_context) { } render_context->renderer()->GetRenderSurfaces( &old_render_surface_, - &old_depth_stencil_surface_); + &old_depth_stencil_surface_, + &old_is_back_buffer_); render_context->renderer()->SetRenderSurfaces( render_surface(), - render_depth_stencil_surface()); + render_depth_stencil_surface(), + false); } void RenderSurfaceSet::PostRender(RenderContext* render_context) { @@ -103,7 +105,8 @@ void RenderSurfaceSet::PostRender(RenderContext* render_context) { return; } render_context->renderer()->SetRenderSurfaces(old_render_surface_, - old_depth_stencil_surface_); + old_depth_stencil_surface_, + old_is_back_buffer_); } } // namespace o3d diff --git a/o3d/core/cross/render_surface_set.h b/o3d/core/cross/render_surface_set.h index f46e1ab..d843df0 100644 --- a/o3d/core/cross/render_surface_set.h +++ b/o3d/core/cross/render_surface_set.h @@ -100,6 +100,7 @@ class RenderSurfaceSet : public RenderNode { const RenderSurface* old_render_surface_; const RenderDepthStencilSurface* old_depth_stencil_surface_; + bool old_is_back_buffer_; ParamRenderSurface::Ref render_surface_param_; ParamRenderDepthStencilSurface::Ref render_depth_stencil_surface_param_; diff --git a/o3d/core/cross/render_surface_test.cc b/o3d/core/cross/render_surface_test.cc index fd45a90..c70b3e0 100644 --- a/o3d/core/cross/render_surface_test.cc +++ b/o3d/core/cross/render_surface_test.cc @@ -47,30 +47,6 @@ extern o3d::DisplayWindow* g_display_window; namespace o3d {
-class MockRenderer {
- public:
- explicit MockRenderer(Renderer* renderer)
- : renderer_(renderer) {}
- virtual ~MockRenderer() {}
-
- void StartRendering() {
- renderer_->set_rendering(true);
- }
- void FinishRendering() {
- renderer_->set_rendering(false);
- }
- void SetRenderSurfaces(const RenderSurface* surface, - const RenderDepthStencilSurface* depth_surface) {
- renderer_->SetRenderSurfaces(surface, depth_surface);
- }
- void GetRenderSurfaces(const RenderSurface** surface, - const RenderDepthStencilSurface** depth_surface) {
- renderer_->GetRenderSurfaces(surface, depth_surface);
- }
- private:
- Renderer* renderer_;
-};
-
class RenderSurfaceTest : public testing::Test {
public:
RenderSurfaceTest()
@@ -80,8 +56,8 @@ class RenderSurfaceTest : public testing::Test { return service_locator_;
}
- MockRenderer* renderer() {
- return renderer_;
+ Renderer* renderer() {
+ return g_renderer;
}
protected:
@@ -89,16 +65,14 @@ class RenderSurfaceTest : public testing::Test { service_locator_ = new ServiceLocator;
features_ = new Features(service_locator_);
pack_ = object_manager_->CreatePack();
- renderer_ = new MockRenderer(g_renderer);
- renderer_->StartRendering();
+ g_renderer->StartRendering();
}
virtual void TearDown() {
- renderer_->FinishRendering();
+ g_renderer->FinishRendering();
pack_->Destroy();
delete features_;
delete service_locator_;
- delete renderer_;
}
Pack* pack() { return pack_; }
@@ -107,7 +81,6 @@ class RenderSurfaceTest : public testing::Test { ServiceLocator* service_locator_;
Features* features_;
Pack* pack_;
- MockRenderer* renderer_;
};
// Test that non PoT textures can't make render surfaces
@@ -151,41 +124,15 @@ TEST_F(RenderSurfaceTest, SwapRenderSurfaces) { pack()->CreateDepthStencilSurface(16, 32);
// Now swap surfaces.
- renderer()->SetRenderSurfaces(render_surface, depth_surface);
+ renderer()->SetRenderSurfaces(render_surface, depth_surface, false);
const RenderSurface* test_render_surface = NULL;
const RenderDepthStencilSurface* test_depth_surface = NULL;
- renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ bool test_is_back_buffer;
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface,
+ &test_is_back_buffer);
ASSERT_TRUE(test_render_surface == render_surface);
ASSERT_TRUE(test_depth_surface == depth_surface);
-}
-
-TEST_F(RenderSurfaceTest, SetBackSurfaces) {
- Texture2D* texture = pack()->CreateTexture2D(16, 32, Texture::ARGB8, 2, true);
- ASSERT_TRUE(NULL != texture);
-
- RenderSurface::Ref render_surface = texture->GetRenderSurface(0);
- ASSERT_TRUE(NULL != render_surface);
- ASSERT_TRUE(texture == render_surface->texture());
-
- RenderDepthStencilSurface* depth_surface =
- pack()->CreateDepthStencilSurface(16, 32);
-
- // Save the original surfaces for comparison.
- const RenderSurface* original_render_surface = NULL;
- const RenderDepthStencilSurface* original_depth_surface = NULL;
- renderer()->GetRenderSurfaces(&original_render_surface,
- &original_depth_surface);
- // Now swap surfaces.
- renderer()->SetRenderSurfaces(render_surface, depth_surface);
- // Return the back buffers
- renderer()->SetRenderSurfaces(NULL, NULL);
- // Get the original surfaces again for comparison.
- const RenderSurface* restored_render_surface = NULL;
- const RenderDepthStencilSurface* restored_depth_surface = NULL;
- renderer()->GetRenderSurfaces(&original_render_surface,
- &original_depth_surface);
- ASSERT_TRUE(original_render_surface == restored_render_surface);
- ASSERT_TRUE(original_depth_surface == restored_depth_surface);
+ ASSERT_FALSE(test_is_back_buffer);
}
TEST_F(RenderSurfaceTest, RenderSurfaceSetTest) {
@@ -208,19 +155,26 @@ TEST_F(RenderSurfaceTest, RenderSurfaceSetTest) { const RenderSurface* old_render_surface = NULL;
const RenderDepthStencilSurface* old_depth_surface = NULL;
- renderer()->GetRenderSurfaces(&old_render_surface, &old_depth_surface);
+ bool old_is_back_buffer = false;
+ renderer()->GetRenderSurfaces(&old_render_surface, &old_depth_surface,
+ &old_is_back_buffer);
render_surface_set->Render(&render_context);
const RenderSurface* test_render_surface = NULL;
const RenderDepthStencilSurface* test_depth_surface = NULL;
- renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ bool test_is_back_buffer = false;
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface,
+ &test_is_back_buffer);
ASSERT_TRUE(test_render_surface == render_surface);
ASSERT_TRUE(test_depth_surface == depth_surface);
+ ASSERT_FALSE(test_is_back_buffer);
render_surface_set->PostRender(&render_context);
- renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface,
+ &test_is_back_buffer);
ASSERT_TRUE(test_render_surface == old_render_surface);
ASSERT_TRUE(test_depth_surface == old_depth_surface);
+ ASSERT_TRUE(test_is_back_buffer == old_is_back_buffer);
}
} // namespace o3d
diff --git a/o3d/core/cross/renderer.cc b/o3d/core/cross/renderer.cc index 9bc9cf5..846c59c 100644 --- a/o3d/core/cross/renderer.cc +++ b/o3d/core/cross/renderer.cc @@ -101,11 +101,13 @@ bool Renderer::IsForceSoftwareRenderer() { Renderer::Renderer(ServiceLocator* service_locator) : current_render_surface_(NULL), current_depth_surface_(NULL), + current_render_surface_is_back_buffer_(true), service_locator_(service_locator), service_(service_locator, this), features_(service_locator), viewport_(0.0f, 0.0f, 1.0f, 1.0f), depth_range_(0.0f, 1.0f), + write_mask_(0xf), render_frame_count_(0), transforms_processed_(0), transforms_culled_(0), @@ -124,7 +126,8 @@ Renderer::Renderer(ServiceLocator* service_locator) display_height_(0), dest_x_offset_(0), dest_y_offset_(0), - supports_npot_(false) { + supports_npot_(false), + back_buffer_cleared_(false) { } Renderer::~Renderer() { @@ -259,6 +262,8 @@ bool Renderer::StartRendering() { draw_elements_processed_ = 0; draw_elements_rendered_ = 0; primitives_rendered_ = 0; + back_buffer_cleared_ = 0; + current_render_surface_is_back_buffer_ = true; result = PlatformSpecificStartRendering(); if (result) { @@ -317,9 +322,57 @@ void Renderer::Clear(const Float4 &color, bool depth_flag, int stencil, bool stencil_flag) { + // If we are currently rendering to the backbuffer and it has not been cleared + // AND if we are not about to clear it entirely then clear it. + bool covers_everything = false; + if (!back_buffer_cleared_ && current_render_surface_is_back_buffer_) { + covers_everything = + !(viewport_[0] != 0.0f || viewport_[1] != 0.0f || + viewport_[2] != 1.0f || viewport_[3] != 1.0f || + depth_range_[0] != 0.0f || depth_range_[1] != 1.0f) && + color_flag && depth_flag && stencil_flag && write_mask_ == 0xF; + if (!covers_everything) { + ClearBackBuffer(); + } + } + ApplyDirtyStates(); PlatformSpecificClear( color, color_flag, depth, depth_flag, stencil, stencil_flag); + + // If we are currently rendering to the backbuffer and it has not been cleared + // and we just cleared everything then mark it as cleared. + if (!back_buffer_cleared_ && current_render_surface_is_back_buffer_ && + covers_everything) { + back_buffer_cleared_ = true; + } +} + +void Renderer::ClearBackBuffer() { + DCHECK(rendering_); + DCHECK(!back_buffer_cleared_); + DCHECK(current_render_surface_is_back_buffer_); + + // Save all states that would effect clear the back buffer. + Float4 old_viewport; + Float2 old_depth_range; + GetViewport(&old_viewport, &old_depth_range); + + // Set the states needed to clear the entire backbuffer. + SetViewport(Float4(0.0f, 0.0f, 1.0f, 1.0f), Float2(0.0f, 1.0f)); + PushRenderStates(clear_back_buffer_state_); + ApplyDirtyStates(); + + // Clear the backbuffer. + PlatformSpecificClear( + Float4(0.5f, 0.5f, 0.5f, 1.0f), true, + 0.0f, true, + 0, true); + back_buffer_cleared_ = true; + + // restore the states. + SetViewport(old_viewport, old_depth_range); + PopRenderStates(); } void Renderer::GetViewport(Float4* viewport, Float2* depth_range) { @@ -475,8 +528,12 @@ void CreateStateParam(State *state, } void Renderer::AddDefaultStates() { + // TODO(gman): It's possible for the user to get these out of the client + // and then change them which could lead to inconsistent results. default_state_ = State::Ref(new State(service_locator_, this)); default_state_->set_name(O3D_STRING_CONSTANT("defaultState")); + clear_back_buffer_state_ = State::Ref(new State(service_locator_, this)); + clear_back_buffer_state_->set_name(O3D_STRING_CONSTANT("clearState")); CreateStateParam<ParamBoolean>(default_state_, State::kAlphaTestEnableParamName, @@ -605,6 +662,10 @@ void Renderer::AddDefaultStates() { DCHECK(param_stack.empty()); param_stack.push_back(param); } + + CreateStateParam<ParamInteger>(clear_back_buffer_state_, + State::kColorWriteEnableParamName, + 0xf); } void Renderer::RemoveDefaultStates() { @@ -647,6 +708,7 @@ void Renderer::RenderElement(Element* element, Material* material, ParamObject* override, ParamCache* param_cache) { + ClearBackBufferIfNotCleared(); IncrementDrawElementsRendered(); State *current_state = material ? material->state() : NULL; PushRenderStates(current_state); @@ -707,8 +769,10 @@ void Renderer::PopRenderStates() { void Renderer::SetRenderSurfaces( const RenderSurface* surface, - const RenderDepthStencilSurface* depth_surface) { + const RenderDepthStencilSurface* depth_surface, + bool is_back_buffer) { DCHECK(rendering_); + current_render_surface_is_back_buffer_ = is_back_buffer; if (surface != NULL || depth_surface != NULL) { SetRenderSurfacesPlatformSpecific(surface, depth_surface); current_render_surface_ = surface; @@ -733,11 +797,15 @@ void Renderer::SetRenderSurfaces( void Renderer::GetRenderSurfaces( const RenderSurface** surface, - const RenderDepthStencilSurface** depth_surface) { + const RenderDepthStencilSurface** depth_surface, + bool* is_back_buffer) { + DCHECK(rendering_); DCHECK(surface); DCHECK(depth_surface); + DCHECK(is_back_buffer); *surface = current_render_surface_; *depth_surface = current_depth_surface_; + *is_back_buffer = current_render_surface_is_back_buffer_; } bool Renderer::SafeToBindTexture(Texture* texture) const { diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h index 3328e4d..20c6086 100644 --- a/o3d/core/cross/renderer.h +++ b/o3d/core/cross/renderer.h @@ -296,8 +296,11 @@ class Renderer { // surface: RenderSurface to bind to the color buffer. // depth_surface: RenderDepthStencilSurface to bind to the depth/stencil // buffer. + // is_back_buffer: True if the render surface being set should be considered + // the backbuffer. void SetRenderSurfaces(const RenderSurface* surface, - const RenderDepthStencilSurface* depth_surface); + const RenderDepthStencilSurface* depth_surface, + bool is_back_buffer); // Gets the current render surfaces. // Parameters: @@ -305,8 +308,11 @@ class Renderer { // buffer. // depth_surface: pointer to variable to hold RenderDepthStencilSurface to // bind to the depth/stencil buffer. + // is_back_buffer: pointer to variable to hold whether or not the surface + // returned is the back buffer. void GetRenderSurfaces(const RenderSurface** surface, - const RenderDepthStencilSurface** depth_surface); + const RenderDepthStencilSurface** depth_surface, + bool* is_back_buffer); // Creates a StreamBank, returning a platform specific implementation class. virtual StreamBank::Ref CreateStreamBank() = 0; @@ -518,6 +524,14 @@ class Renderer { rendering_ = rendering; } + // Used only by the ColorWriteEnable state handlers. Should not be used + // elsewhere. + // Sets the write mask. This must be called by platform specific renderers + // when the color write mask is changed. + void SetWriteMask(int mask) { + write_mask_ = mask & 0xF; + } + protected: typedef vector_map<String, StateHandler*> StateHandlerMap; typedef std::vector<ParamVector> ParamVectorArray; @@ -618,6 +632,7 @@ class Renderer { // The current render surfaces. NULL = no surface. const RenderSurface* current_render_surface_; const RenderDepthStencilSurface* current_depth_surface_; + bool current_render_surface_is_back_buffer_; Sampler::Ref error_sampler_; // sampler used when one is missing. Texture::Ref error_texture_; // texture used when one is missing. @@ -638,6 +653,10 @@ class Renderer { // State object holding the default state settings. State::Ref default_state_; + // A State object holding the settings required to be able to clear the + // back buffer. + State::Ref clear_back_buffer_state_; + // Lost Resources Callbacks. LostResourcesCallbackManager lost_resources_callback_manager_; @@ -654,6 +673,22 @@ class Renderer { } private: + // Adds the default states to their respective stacks. + void AddDefaultStates(); + + // Removes the default states from their respective stacks. + void RemoveDefaultStates(); + + // Clears the backbuffer. + void ClearBackBuffer(); + + // Clears the backbuffer if it has not been cleared. + void ClearBackBufferIfNotCleared() { + if (!back_buffer_cleared_ && current_render_surface_is_back_buffer_) { + ClearBackBuffer(); + } + } + ServiceLocator* service_locator_; ServiceImplementation<Renderer> service_; ServiceDependency<Features> features_; @@ -664,6 +699,9 @@ class Renderer { // Current depth range. Float2 depth_range_; + // Current write mask. + int write_mask_; + int render_frame_count_; // count of times we've rendered frame. int transforms_processed_; // count of transforms processed this frame. int transforms_culled_; // count of transforms culled this frame. @@ -702,11 +740,8 @@ class Renderer { // Whether or not the underlying API supports non-power-of-two textures. bool supports_npot_; - // Adds the default states to their respective stacks. - void AddDefaultStates(); - - // Removes the default states from their respective stacks. - void RemoveDefaultStates(); + // Whether the backbuffer has been cleared this frame. + bool back_buffer_cleared_; DISALLOW_COPY_AND_ASSIGN(Renderer); }; diff --git a/o3d/core/win/d3d9/renderer_d3d9.cc b/o3d/core/win/d3d9/renderer_d3d9.cc index 1089723..6a92bb9 100644 --- a/o3d/core/win/d3d9/renderer_d3d9.cc +++ b/o3d/core/win/d3d9/renderer_d3d9.cc @@ -735,6 +735,16 @@ class IntegerStateHandler : public TypedStateHandler<ParamInteger> { } }; +class ColorWriteStateHandler : public TypedStateHandler<ParamInteger> { + public: + virtual void SetStateFromTypedParam(RendererD3D9* renderer, + ParamInteger* param) const { + int mask = param->value(); + HR(renderer->d3d_device()->SetRenderState(D3DRS_COLORWRITEENABLE, mask)); + renderer->SetWriteMask(mask); + } +}; + class AlphaReferenceHandler : public TypedStateHandler<ParamFloat> { public: virtual void SetStateFromTypedParam(RendererD3D9* renderer, @@ -888,7 +898,7 @@ RendererD3D9::RendererD3D9(ServiceLocator* service_locator) AddStateHandler(State::kStencilWriteMaskParamName, new IntegerStateHandler<D3DRS_STENCILWRITEMASK>); AddStateHandler(State::kColorWriteEnableParamName, - new IntegerStateHandler<D3DRS_COLORWRITEENABLE>); + new ColorWriteStateHandler); AddStateHandler(State::kBlendEquationParamName, new BlendEquationHandler<D3DRS_BLENDOP>); AddStateHandler(State::kTwoSidedStencilEnableParamName, |