summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-12 22:54:53 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-12 22:54:53 +0000
commitd8a872846fdcff1329c0e7a7d9c6950bd6fc5128 (patch)
tree8e1147835157ada26f72ca195b8a9a912f3f1367 /gpu
parent7ffd7c77996c40ef3ddbe49a2908496238aca484 (diff)
downloadchromium_src-d8a872846fdcff1329c0e7a7d9c6950bd6fc5128.zip
chromium_src-d8a872846fdcff1329c0e7a7d9c6950bd6fc5128.tar.gz
chromium_src-d8a872846fdcff1329c0e7a7d9c6950bd6fc5128.tar.bz2
Cache more GL state client side
Honestly I'm mixed on this. Caching takes time. This CL punishes optimized programs (those that don't query GL) to help those don't follow OpenGL best practices (ie, not calling query functions except during initialization. TEST=unit tests BUG=127810 Review URL: https://chromiumcodereview.appspot.com/10389105 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136780 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py3
-rw-r--r--gpu/command_buffer/client/gles2_implementation.cc149
-rw-r--r--gpu/command_buffer/client/gles2_implementation.h89
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h28
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc83
5 files changed, 254 insertions, 98 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index eae991f..ccdbc4e 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -948,6 +948,7 @@ _FUNCTION_INFO = {
'DetachShader': {'decoder_func': 'DoDetachShader'},
'Disable': {
'decoder_func': 'DoDisable',
+ 'impl_func': False,
},
'DisableVertexAttribArray': {
'decoder_func': 'DoDisableVertexAttribArray',
@@ -965,6 +966,7 @@ _FUNCTION_INFO = {
},
'Enable': {
'decoder_func': 'DoEnable',
+ 'impl_func': False,
},
'EnableVertexAttribArray': {
'decoder_func': 'DoEnableVertexAttribArray',
@@ -1246,6 +1248,7 @@ _FUNCTION_INFO = {
'IsEnabled': {
'type': 'Is',
'decoder_func': 'DoIsEnabled',
+ 'impl_func': False,
},
'IsFramebuffer': {
'type': 'Is',
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 466e854..e5e03ad 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -454,17 +454,18 @@ bool GLES2Implementation::Initialize(
GL_NUM_SHADER_BINARY_FORMATS,
};
+ GetMultipleIntegervCHROMIUM(
+ pnames, arraysize(pnames),
+ &gl_state_.int_state.max_combined_texture_image_units,
+ sizeof(gl_state_.int_state));
+
util_.set_num_compressed_texture_formats(
- gl_state_.num_compressed_texture_formats);
+ gl_state_.int_state.num_compressed_texture_formats);
util_.set_num_shader_binary_formats(
- gl_state_.num_shader_binary_formats);
-
- GetMultipleIntegervCHROMIUM(
- pnames, arraysize(pnames), &gl_state_.max_combined_texture_image_units,
- sizeof(gl_state_));
+ gl_state_.int_state.num_shader_binary_formats);
texture_units_.reset(
- new TextureUnit[gl_state_.max_combined_texture_image_units]);
+ new TextureUnit[gl_state_.int_state.max_combined_texture_image_units]);
query_tracker_.reset(new QueryTracker(mapped_memory_.get()));
@@ -473,7 +474,7 @@ bool GLES2Implementation::Initialize(
this, kClientSideArrayId, arraysize(reserved_ids_), &reserved_ids_[0]);
client_side_buffer_helper_.reset(new ClientSideBufferHelper(
- gl_state_.max_vertex_attribs,
+ gl_state_.int_state.max_vertex_attribs,
reserved_ids_[0],
reserved_ids_[1]));
#endif
@@ -734,43 +735,143 @@ void GLES2Implementation::SetBucketAsString(
SetBucketContents(bucket_id, str.c_str(), str.size() + 1);
}
+bool GLES2Implementation::SetCapabilityState(GLenum cap, bool enabled) {
+ switch (cap) {
+ case GL_DITHER:
+ gl_state_.enable_state.dither = enabled;
+ return true;
+ case GL_BLEND:
+ gl_state_.enable_state.blend = enabled;
+ return true;
+ case GL_CULL_FACE:
+ gl_state_.enable_state.cull_face = enabled;
+ return true;
+ case GL_DEPTH_TEST:
+ gl_state_.enable_state.depth_test = enabled;
+ return true;
+ case GL_POLYGON_OFFSET_FILL:
+ gl_state_.enable_state.polygon_offset_fill = enabled;
+ return true;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ gl_state_.enable_state.sample_alpha_to_coverage = enabled;
+ return true;
+ case GL_SAMPLE_COVERAGE:
+ gl_state_.enable_state.sample_coverage = enabled;
+ return true;
+ case GL_SCISSOR_TEST:
+ gl_state_.enable_state.scissor_test = enabled;
+ return true;
+ case GL_STENCIL_TEST:
+ gl_state_.enable_state.stencil_test = enabled;
+ return true;
+ default:
+ return false;
+ }
+}
+
+void GLES2Implementation::Disable(GLenum cap) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << this << "] glDisable("
+ << GLES2Util::GetStringCapability(cap) << ")");
+ SetCapabilityState(cap, false);
+ helper_->Disable(cap);
+}
+
+void GLES2Implementation::Enable(GLenum cap) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << this << "] glEnable("
+ << GLES2Util::GetStringCapability(cap) << ")");
+ SetCapabilityState(cap, true);
+ helper_->Enable(cap);
+}
+
+GLboolean GLES2Implementation::IsEnabled(GLenum cap) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << this << "] glIsEnabled("
+ << GLES2Util::GetStringCapability(cap) << ")");
+ bool state = false;
+ switch (cap) {
+ case GL_DITHER:
+ state = gl_state_.enable_state.dither;
+ break;
+ case GL_BLEND:
+ state = gl_state_.enable_state.blend;
+ break;
+ case GL_CULL_FACE:
+ state = gl_state_.enable_state.cull_face;
+ break;
+ case GL_DEPTH_TEST:
+ state = gl_state_.enable_state.depth_test;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ state = gl_state_.enable_state.polygon_offset_fill;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ state = gl_state_.enable_state.sample_alpha_to_coverage;
+ break;
+ case GL_SAMPLE_COVERAGE:
+ state = gl_state_.enable_state.sample_coverage;
+ break;
+ case GL_SCISSOR_TEST:
+ state = gl_state_.enable_state.scissor_test;
+ break;
+ case GL_STENCIL_TEST:
+ state = gl_state_.enable_state.stencil_test;
+ break;
+ default: {
+ typedef IsEnabled::Result Result;
+ Result* result = GetResultAs<Result*>();
+ if (!result) {
+ return GL_FALSE;
+ }
+ *result = 0;
+ helper_->IsEnabled(cap, GetResultShmId(), GetResultShmOffset());
+ WaitForCmd();
+ state = (*result) != 0;
+ break;
+ }
+ }
+ GPU_CLIENT_LOG("returned " << state);
+ return state;
+}
+
bool GLES2Implementation::GetHelper(GLenum pname, GLint* params) {
switch (pname) {
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
- *params = gl_state_.max_combined_texture_image_units;
+ *params = gl_state_.int_state.max_combined_texture_image_units;
return true;
case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
- *params = gl_state_.max_cube_map_texture_size;
+ *params = gl_state_.int_state.max_cube_map_texture_size;
return true;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
- *params = gl_state_.max_fragment_uniform_vectors;
+ *params = gl_state_.int_state.max_fragment_uniform_vectors;
return true;
case GL_MAX_RENDERBUFFER_SIZE:
- *params = gl_state_.max_renderbuffer_size;
+ *params = gl_state_.int_state.max_renderbuffer_size;
return true;
case GL_MAX_TEXTURE_IMAGE_UNITS:
- *params = gl_state_.max_texture_image_units;
+ *params = gl_state_.int_state.max_texture_image_units;
return true;
case GL_MAX_TEXTURE_SIZE:
- *params = gl_state_.max_texture_size;
+ *params = gl_state_.int_state.max_texture_size;
return true;
case GL_MAX_VARYING_VECTORS:
- *params = gl_state_.max_varying_vectors;
+ *params = gl_state_.int_state.max_varying_vectors;
return true;
case GL_MAX_VERTEX_ATTRIBS:
- *params = gl_state_.max_vertex_attribs;
+ *params = gl_state_.int_state.max_vertex_attribs;
return true;
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
- *params = gl_state_.max_vertex_texture_image_units;
+ *params = gl_state_.int_state.max_vertex_texture_image_units;
return true;
case GL_MAX_VERTEX_UNIFORM_VECTORS:
- *params = gl_state_.max_vertex_uniform_vectors;
+ *params = gl_state_.int_state.max_vertex_uniform_vectors;
return true;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
- *params = gl_state_.num_compressed_texture_formats;
+ *params = gl_state_.int_state.num_compressed_texture_formats;
return true;
case GL_NUM_SHADER_BINARY_FORMATS:
- *params = gl_state_.num_shader_binary_formats;
+ *params = gl_state_.int_state.num_shader_binary_formats;
return true;
case GL_ARRAY_BUFFER_BINDING:
if (share_group_->bind_generates_resource()) {
@@ -2164,8 +2265,8 @@ void GLES2Implementation::ActiveTexture(GLenum texture) {
GPU_CLIENT_LOG("[" << this << "] glActiveTexture("
<< GLES2Util::GetStringEnum(texture) << ")");
GLuint texture_index = texture - GL_TEXTURE0;
- if (texture_index >=
- static_cast<GLuint>(gl_state_.max_combined_texture_image_units)) {
+ if (texture_index >= static_cast<GLuint>(
+ gl_state_.int_state.max_combined_texture_image_units)) {
SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
return;
}
@@ -2339,7 +2440,9 @@ void GLES2Implementation::DeleteTexturesHelper(
return;
}
for (GLsizei ii = 0; ii < n; ++ii) {
- for (GLint tt = 0; tt < gl_state_.max_combined_texture_image_units; ++tt) {
+ for (GLint tt = 0;
+ tt < gl_state_.int_state.max_combined_texture_image_units;
+ ++tt) {
TextureUnit& unit = texture_units_[tt];
if (textures[ii] == unit.bound_texture_2d) {
unit.bound_texture_2d = 0;
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 60fd9c7..67d0c15 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -100,34 +100,62 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
};
// Stores client side cached GL state.
- struct GLState {
- GLState()
- : max_combined_texture_image_units(0),
- max_cube_map_texture_size(0),
- max_fragment_uniform_vectors(0),
- max_renderbuffer_size(0),
- max_texture_image_units(0),
- max_texture_size(0),
- max_varying_vectors(0),
- max_vertex_attribs(0),
- max_vertex_texture_image_units(0),
- max_vertex_uniform_vectors(0),
- num_compressed_texture_formats(0),
- num_shader_binary_formats(0) {
- }
-
- GLint max_combined_texture_image_units;
- GLint max_cube_map_texture_size;
- GLint max_fragment_uniform_vectors;
- GLint max_renderbuffer_size;
- GLint max_texture_image_units;
- GLint max_texture_size;
- GLint max_varying_vectors;
- GLint max_vertex_attribs;
- GLint max_vertex_texture_image_units;
- GLint max_vertex_uniform_vectors;
- GLint num_compressed_texture_formats;
- GLint num_shader_binary_formats;
+ struct GLCachedState {
+ struct IntState {
+ IntState()
+ : max_combined_texture_image_units(0),
+ max_cube_map_texture_size(0),
+ max_fragment_uniform_vectors(0),
+ max_renderbuffer_size(0),
+ max_texture_image_units(0),
+ max_texture_size(0),
+ max_varying_vectors(0),
+ max_vertex_attribs(0),
+ max_vertex_texture_image_units(0),
+ max_vertex_uniform_vectors(0),
+ num_compressed_texture_formats(0),
+ num_shader_binary_formats(0) {
+ }
+
+ GLint max_combined_texture_image_units;
+ GLint max_cube_map_texture_size;
+ GLint max_fragment_uniform_vectors;
+ GLint max_renderbuffer_size;
+ GLint max_texture_image_units;
+ GLint max_texture_size;
+ GLint max_varying_vectors;
+ GLint max_vertex_attribs;
+ GLint max_vertex_texture_image_units;
+ GLint max_vertex_uniform_vectors;
+ GLint num_compressed_texture_formats;
+ GLint num_shader_binary_formats;
+ };
+ struct EnableState {
+ EnableState()
+ : blend(false),
+ cull_face(false),
+ depth_test(false),
+ dither(false),
+ polygon_offset_fill(false),
+ sample_alpha_to_coverage(false),
+ sample_coverage(false),
+ scissor_test(false),
+ stencil_test(false) {
+ }
+
+ bool blend;
+ bool cull_face;
+ bool depth_test;
+ bool dither;
+ bool polygon_offset_fill;
+ bool sample_alpha_to_coverage;
+ bool sample_coverage;
+ bool scissor_test;
+ bool stencil_test;
+ };
+
+ IntState int_state;
+ EnableState enable_state;
};
// The maxiumum result size from simple GL get commands.
@@ -439,6 +467,9 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
bool IsExtensionAvailable(const char* ext);
+ // Caches certain capabilties state. Return true if cached.
+ bool SetCapabilityState(GLenum cap, bool enabled);
+
IdHandlerInterface* GetIdHandler(int id_namespace) const;
GLES2Util util_;
@@ -451,7 +482,7 @@ class GLES2_IMPL_EXPORT GLES2Implementation {
ExtensionStatus angle_pack_reverse_row_order_status;
- GLState gl_state_;
+ GLCachedState gl_state_;
// pack alignment as last set by glPixelStorei
GLint pack_alignment_;
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index b578d7d..5fd8087 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -350,23 +350,14 @@ void DetachShader(GLuint program, GLuint shader) {
helper_->DetachShader(program, shader);
}
-void Disable(GLenum cap) {
- GPU_CLIENT_SINGLE_THREAD_CHECK();
- GPU_CLIENT_LOG("[" << this << "] glDisable(" << GLES2Util::GetStringCapability(cap) << ")"); // NOLINT
- helper_->Disable(cap);
-}
+void Disable(GLenum cap);
void DrawArrays(GLenum mode, GLint first, GLsizei count);
void DrawElements(
GLenum mode, GLsizei count, GLenum type, const void* indices);
-void Enable(GLenum cap) {
- GPU_CLIENT_SINGLE_THREAD_CHECK();
- GPU_CLIENT_LOG("[" << this << "] glEnable(" << GLES2Util::GetStringCapability(
- cap) << ")");
- helper_->Enable(cap);
-}
+void Enable(GLenum cap);
void Finish();
@@ -828,20 +819,7 @@ GLboolean IsBuffer(GLuint buffer) {
return *result;
}
-GLboolean IsEnabled(GLenum cap) {
- GPU_CLIENT_SINGLE_THREAD_CHECK();
- GPU_CLIENT_LOG("[" << this << "] glIsEnabled(" << GLES2Util::GetStringCapability(cap) << ")"); // NOLINT
- typedef IsEnabled::Result Result;
- Result* result = GetResultAs<Result*>();
- if (!result) {
- return GL_FALSE;
- }
- *result = 0;
- helper_->IsEnabled(cap, GetResultShmId(), GetResultShmOffset());
- WaitForCmd();
- GPU_CLIENT_LOG("returned " << *result);
- return *result;
-}
+GLboolean IsEnabled(GLenum cap);
GLboolean IsFramebuffer(GLuint framebuffer) {
GPU_CLIENT_SINGLE_THREAD_CHECK();
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index a999f01..f406c46 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -333,8 +333,15 @@ class GLES2ImplementationTest : public testing::Test {
virtual void TearDown() OVERRIDE;
bool NoCommandsWritten() {
- return static_cast<const uint8*>(static_cast<const void*>(commands_))[0] ==
- kInitialValue;
+ Buffer ring_buffer = helper_->get_ring_buffer();
+ const uint8* cmds = reinterpret_cast<const uint8*>(ring_buffer.ptr);
+ const uint8* end = cmds + ring_buffer.size;
+ for (; cmds < end; ++cmds) {
+ if (*cmds != kInitialValue) {
+ return false;
+ }
+ }
+ return true;
}
QueryTracker::Query* GetQuery(GLuint id) {
@@ -354,30 +361,31 @@ class GLES2ImplementationTest : public testing::Test {
helper_.reset(new GLES2CmdHelper(command_buffer()));
helper_->Initialize(kCommandBufferSizeBytes);
- GLES2Implementation::GLState state;
- state.max_combined_texture_image_units = kMaxCombinedTextureImageUnits;
- state.max_cube_map_texture_size = kMaxCubeMapTextureSize;
- state.max_fragment_uniform_vectors = kMaxFragmentUniformVectors;
- state.max_renderbuffer_size = kMaxRenderbufferSize;
- state.max_texture_image_units = kMaxTextureImageUnits;
- state.max_texture_size = kMaxTextureSize;
- state.max_varying_vectors = kMaxVaryingVectors;
- state.max_vertex_attribs = kMaxVertexAttribs;
- state.max_vertex_texture_image_units = kMaxVertexTextureImageUnits;
- state.max_vertex_uniform_vectors = kMaxVertexUniformVectors;
- state.num_compressed_texture_formats = kNumCompressedTextureFormats;
- state.num_shader_binary_formats = kNumShaderBinaryFormats;
-
- // This just happens to work for now because GLState has 1 GLint per
- // state. If GLState gets more complicated this code will need to get
- // more complicated.
- ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(state) * 2);
+ GLES2Implementation::GLCachedState state;
+ GLES2Implementation::GLCachedState::IntState& int_state = state.int_state;
+ int_state.max_combined_texture_image_units = kMaxCombinedTextureImageUnits;
+ int_state.max_cube_map_texture_size = kMaxCubeMapTextureSize;
+ int_state.max_fragment_uniform_vectors = kMaxFragmentUniformVectors;
+ int_state.max_renderbuffer_size = kMaxRenderbufferSize;
+ int_state.max_texture_image_units = kMaxTextureImageUnits;
+ int_state.max_texture_size = kMaxTextureSize;
+ int_state.max_varying_vectors = kMaxVaryingVectors;
+ int_state.max_vertex_attribs = kMaxVertexAttribs;
+ int_state.max_vertex_texture_image_units = kMaxVertexTextureImageUnits;
+ int_state.max_vertex_uniform_vectors = kMaxVertexUniformVectors;
+ int_state.num_compressed_texture_formats = kNumCompressedTextureFormats;
+ int_state.num_shader_binary_formats = kNumShaderBinaryFormats;
+
+ // This just happens to work for now because IntState has 1 GLint per state.
+ // If IntState gets more complicated this code will need to get more
+ // complicated.
+ ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(int_state) * 2);
{
InSequence sequence;
EXPECT_CALL(*command_buffer(), OnFlush())
- .WillOnce(SetMemory(mem1.ptr + sizeof(state), state))
+ .WillOnce(SetMemory(mem1.ptr + sizeof(int_state), int_state))
.RetiresOnSaturation();
GetNextToken(); // eat the token that starting up will use.
@@ -2393,6 +2401,39 @@ TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) {
EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
}
+TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) {
+ static const GLenum kStates[] = {
+ GL_DITHER,
+ GL_BLEND,
+ GL_CULL_FACE,
+ GL_DEPTH_TEST,
+ GL_POLYGON_OFFSET_FILL,
+ GL_SAMPLE_ALPHA_TO_COVERAGE,
+ GL_SAMPLE_COVERAGE,
+ GL_SCISSOR_TEST,
+ GL_STENCIL_TEST,
+ };
+ struct Cmds {
+ Enable enable_cmd;
+ };
+ Cmds expected;
+
+ for (size_t ii = 0; ii < arraysize(kStates); ++ii) {
+ GLenum state = kStates[ii];
+ expected.enable_cmd.Init(state);
+ GLboolean result = gl_->IsEnabled(state);
+ EXPECT_FALSE(result);
+ EXPECT_TRUE(NoCommandsWritten());
+ const void* commands = GetPut();
+ gl_->Enable(state);
+ EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
+ ClearCommands();
+ result = gl_->IsEnabled(state);
+ EXPECT_TRUE(result);
+ EXPECT_TRUE(NoCommandsWritten());
+ }
+}
+
TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) {
// Test GetQueryivEXT returns 0 if no current query.
GLint param = -1;