summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-30 10:30:44 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-30 10:30:44 +0000
commit09e1727e620979f016f6b78748f7085e5a00838a (patch)
tree813b47043aaca2c75630bf24a279e86f0b9b5f22 /gpu
parent316248b10045aaecfcff81c509a3448d57518118 (diff)
downloadchromium_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')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py32
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc6
-rw-r--r--gpu/command_buffer/client/gles2_implementation_impl_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc22
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h15
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h9
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));