diff options
author | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 10:30:44 +0000 |
---|---|---|
committer | piman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-30 10:30:44 +0000 |
commit | 09e1727e620979f016f6b78748f7085e5a00838a (patch) | |
tree | 813b47043aaca2c75630bf24a279e86f0b9b5f22 /gpu | |
parent | 316248b10045aaecfcff81c509a3448d57518118 (diff) | |
download | chromium_src-09e1727e620979f016f6b78748f7085e5a00838a.zip chromium_src-09e1727e620979f016f6b78748f7085e5a00838a.tar.gz chromium_src-09e1727e620979f016f6b78748f7085e5a00838a.tar.bz2 |
gpu: Defer reads from default framebuffer when needed.
On some platforms, we want to unschedule after a swap until the ack, but the
DeferDraws mechanism allows us to delay the unschedule until we actually need to
access the back buffer. Up to now, only commands that *write* to the framebuffer
were considered, however we also need to consider *reads*. This fixes that.
BUG=None
Review URL: https://chromiumcodereview.appspot.com/11412262
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@170435 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
6 files changed, 71 insertions, 19 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index ecd62a8..da321b2 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1184,6 +1184,8 @@ _FUNCTION_INFO = { 'unit_test': False, 'extension': True, 'pepper_interface': 'FramebufferBlit', + 'defer_reads': True, + 'defer_draws': True, }, 'BufferData': { 'type': 'Manual', @@ -1203,8 +1205,8 @@ _FUNCTION_INFO = { 'result': ['GLenum'], }, 'Clear': { - 'type': 'Manual', - 'cmd_args': 'GLbitfield mask' + 'decoder_func': 'DoClear', + 'defer_draws': True, }, 'ClearColor': { 'type': 'StateSet', @@ -1263,9 +1265,11 @@ _FUNCTION_INFO = { 'CopyTexImage2D': { 'decoder_func': 'DoCopyTexImage2D', 'unit_test': False, + 'defer_reads': True, }, 'CopyTexSubImage2D': { 'decoder_func': 'DoCopyTexSubImage2D', + 'defer_reads': True, }, 'CreateProgram': { 'type': 'Create', @@ -1396,12 +1400,14 @@ _FUNCTION_INFO = { 'DrawArrays': { 'type': 'Manual', 'cmd_args': 'GLenumDrawMode mode, GLint first, GLsizei count', + 'defer_draws': True, }, 'DrawElements': { 'type': 'Manual', 'cmd_args': 'GLenumDrawMode mode, GLsizei count, ' 'GLenumIndexType type, GLuint index_offset', - 'client_test': False + 'client_test': False, + 'defer_draws': True, }, 'Enable': { 'decoder_func': 'DoEnable', @@ -1794,6 +1800,7 @@ _FUNCTION_INFO = { 'uint32 pixels_shm_id, uint32 pixels_shm_offset, ' 'uint32 result_shm_id, uint32 result_shm_offset', 'result': ['uint32'], + 'defer_reads': True, }, 'RegisterSharedIdsCHROMIUM': { 'type': 'Custom', @@ -2097,6 +2104,7 @@ _FUNCTION_INFO = { 'extension': True, 'unit_test': False, 'pepper_interface': 'InstancedArrays', + 'defer_draws': True, }, 'DrawElementsInstancedANGLE': { 'type': 'Manual', @@ -2106,6 +2114,7 @@ _FUNCTION_INFO = { 'unit_test': False, 'client_test': False, 'pepper_interface': 'InstancedArrays', + 'defer_draws': True, }, 'VertexAttribDivisorANGLE': { 'type': 'Manual', @@ -2567,6 +2576,7 @@ COMPILE_ASSERT(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, "error::Error GLES2DecoderImpl::Handle%s(\n" % func.name) file.Write( " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) + self.WriteHandlerDeferReadWrite(func, file); if len(func.GetOriginalArgs()) > 0: last_arg = func.GetLastOriginalArg() all_but_last_arg = func.GetOriginalArgs()[:-1] @@ -2586,6 +2596,7 @@ COMPILE_ASSERT(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, "error::Error GLES2DecoderImpl::Handle%s(\n" % func.name) file.Write( " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) + self.WriteHandlerDeferReadWrite(func, file); last_arg = func.GetLastOriginalArg() all_but_last_arg = func.GetOriginalArgs()[:-1] for arg in all_but_last_arg: @@ -2604,6 +2615,7 @@ COMPILE_ASSERT(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, "error::Error GLES2DecoderImpl::Handle%s(\n" % func.name) file.Write( " uint32 immediate_data_size, const gles2::%s& c) {\n" % func.name) + self.WriteHandlerDeferReadWrite(func, file); last_arg = func.GetLastOriginalArg() all_but_last_arg = func.GetOriginalArgs()[:-1] for arg in all_but_last_arg: @@ -2616,6 +2628,20 @@ COMPILE_ASSERT(offsetof(%(cmd_name)s::Result, %(field_name)s) == %(offset)d, file.Write("}\n") file.Write("\n") + def WriteHandlerDeferReadWrite(self, func, file): + """Writes the code to handle deferring reads or writes.""" + defer_reads = func.GetInfo('defer_reads') + defer_draws = func.GetInfo('defer_draws') + conditions = [] + if defer_draws: + conditions.append('ShouldDeferDraws()'); + if defer_reads: + conditions.append('ShouldDeferReads()'); + if not conditions: + return + file.Write(" if (%s)\n" % ' || '.join(conditions)) + file.Write(" return error::kDeferCommandUntilLater;\n") + def WriteValidUnitTest(self, func, file, test, extra = {}): """Writes a valid unit test.""" if func.GetInfo('expectation') == False: diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 30389fa..bf24aa8 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -662,12 +662,6 @@ void GLES2Implementation::RestoreArrayBuffer(bool restore) { } } -void GLES2Implementation::Clear(GLbitfield mask) { - GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClear(" << mask << ")"); - helper_->Clear(mask); -} - void GLES2Implementation::DrawElements( GLenum mode, GLsizei count, GLenum type, const void* indices) { GPU_CLIENT_SINGLE_THREAD_CHECK(); diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 1e8b056..8e452c2 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h @@ -117,6 +117,12 @@ GLenum GLES2Implementation::CheckFramebufferStatus(GLenum target) { return *result; } +void GLES2Implementation::Clear(GLbitfield mask) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glClear(" << mask << ")"); + helper_->Clear(mask); +} + void GLES2Implementation::ClearColor( GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { GPU_CLIENT_SINGLE_THREAD_CHECK(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 6e1f7bf..8914a84 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1409,6 +1409,12 @@ class GLES2DecoderImpl : public GLES2Decoder { surface_->DeferDraws(); } + bool ShouldDeferReads() { + return !offscreen_target_frame_buffer_.get() && + state_.bound_read_framebuffer == NULL && + surface_->DeferDraws(); + } + void ForceCompileShaderIfPending(ShaderManager::ShaderInfo* info); // Generate a member function prototype for each command in an automated and @@ -3125,7 +3131,7 @@ bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) { error::Error GLES2DecoderImpl::HandleResizeCHROMIUM( uint32 immediate_data_size, const gles2::ResizeCHROMIUM& c) { - if (ShouldDeferDraws()) + if (!offscreen_target_frame_buffer_.get() && surface_->DeferDraws()) return error::kDeferCommandUntilLater; GLuint width = static_cast<GLuint>(c.width); @@ -4238,8 +4244,7 @@ error::Error GLES2DecoderImpl::HandleRegisterSharedIdsCHROMIUM( } error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) { - if (ShouldDeferDraws()) - return error::kDeferCommandUntilLater; + DCHECK(!ShouldDeferDraws()); if (CheckBoundFramebuffersValid("glClear")) { UNSHIPPED_TRACE_EVENT_INSTANT2( "test_gpu", "DoClear", @@ -4251,12 +4256,6 @@ error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) { return error::kNoError; } -error::Error GLES2DecoderImpl::HandleClear( - uint32 immediate_data_size, const gles2::Clear& c) { - GLbitfield mask = static_cast<GLbitfield>(c.mask); - return DoClear(mask); -} - void GLES2DecoderImpl::DoFramebufferRenderbuffer( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint client_renderbuffer_id) { @@ -4505,6 +4504,7 @@ void GLES2DecoderImpl::DoBlitFramebufferEXT( GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + DCHECK(!ShouldDeferReads() && !ShouldDeferDraws()); if (!features().chromium_framebuffer_multisample) { SetGLError(GL_INVALID_OPERATION, "glBlitFramebufferEXT", "function not available"); @@ -6238,6 +6238,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE( error::Error GLES2DecoderImpl::HandleReadPixels( uint32 immediate_data_size, const gles2::ReadPixels& c) { + if (ShouldDeferReads()) + return error::kDeferCommandUntilLater; GLint x = c.x; GLint y = c.y; GLsizei width = c.width; @@ -7424,6 +7426,7 @@ void GLES2DecoderImpl::DoCopyTexImage2D( GLsizei width, GLsizei height, GLint border) { + DCHECK(!ShouldDeferReads()); TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); if (!info) { SetGLError(GL_INVALID_OPERATION, @@ -7526,6 +7529,7 @@ void GLES2DecoderImpl::DoCopyTexSubImage2D( GLint y, GLsizei width, GLsizei height) { + DCHECK(!ShouldDeferReads()); TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); if (!info) { SetGLError(GL_INVALID_OPERATION, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 4a41a9f..722ee76 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -252,6 +252,15 @@ error::Error GLES2DecoderImpl::HandleCheckFramebufferStatus( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleClear( + uint32 immediate_data_size, const gles2::Clear& c) { + if (ShouldDeferDraws()) + return error::kDeferCommandUntilLater; + GLbitfield mask = static_cast<GLbitfield>(c.mask); + DoClear(mask); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleClearColor( uint32 immediate_data_size, const gles2::ClearColor& c) { GLclampf red = static_cast<GLclampf>(c.red); @@ -402,6 +411,8 @@ error::Error GLES2DecoderImpl::HandleCompressedTexSubImage2DImmediate( error::Error GLES2DecoderImpl::HandleCopyTexImage2D( uint32 immediate_data_size, const gles2::CopyTexImage2D& c) { + if (ShouldDeferReads()) + return error::kDeferCommandUntilLater; GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); GLenum internalformat = static_cast<GLenum>(c.internalformat); @@ -438,6 +449,8 @@ error::Error GLES2DecoderImpl::HandleCopyTexImage2D( error::Error GLES2DecoderImpl::HandleCopyTexSubImage2D( uint32 immediate_data_size, const gles2::CopyTexSubImage2D& c) { + if (ShouldDeferReads()) + return error::kDeferCommandUntilLater; GLenum target = static_cast<GLenum>(c.target); GLint level = static_cast<GLint>(c.level); GLint xoffset = static_cast<GLint>(c.xoffset); @@ -2635,6 +2648,8 @@ error::Error GLES2DecoderImpl::HandleViewport( error::Error GLES2DecoderImpl::HandleBlitFramebufferEXT( uint32 immediate_data_size, const gles2::BlitFramebufferEXT& c) { + if (ShouldDeferDraws() || ShouldDeferReads()) + return error::kDeferCommandUntilLater; GLint srcX0 = static_cast<GLint>(c.srcX0); GLint srcY0 = static_cast<GLint>(c.srcY0); GLint srcX1 = static_cast<GLint>(c.srcX1); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 7e817667..914ced8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -308,8 +308,15 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgsBadSharedMemoryId) { cmd.Init(GL_FRAMEBUFFER, shared_memory_id_, kInvalidSharedMemoryOffset); EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); } -// TODO(gman): Clear +TEST_F(GLES2DecoderTest1, ClearValidArgs) { + EXPECT_CALL(*gl_, Clear(1)); + SpecializedSetup<Clear, 0>(true); + Clear cmd; + cmd.Init(1); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} TEST_F(GLES2DecoderTest1, ClearColorValidArgs) { EXPECT_CALL(*gl_, ClearColor(1, 2, 3, 4)); |