diff options
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r-- | gpu/command_buffer/service/BUILD.gn | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info_unittest.cc | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc | 188 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h | 54 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 26 |
5 files changed, 271 insertions, 0 deletions
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn index 4013c3a..1c43029 100644 --- a/gpu/command_buffer/service/BUILD.gn +++ b/gpu/command_buffer/service/BUILD.gn @@ -44,6 +44,8 @@ source_set("service") { "feature_info.cc", "framebuffer_manager.h", "framebuffer_manager.cc", + "gles2_cmd_clear_framebuffer.cc", + "gles2_cmd_clear_framebuffer.h", "gles2_cmd_copy_texture_chromium.cc", "gles2_cmd_copy_texture_chromium.h", "gles2_cmd_decoder.h", diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index 88a0a37..53dbf6c 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -134,6 +134,7 @@ TEST_F(FeatureInfoTest, Basic) { #undef GPU_OP EXPECT_EQ(0, info_->workarounds().max_texture_size); EXPECT_EQ(0, info_->workarounds().max_cube_map_texture_size); + EXPECT_FALSE(info_->workarounds().gl_clear_broken); // Test good types. { diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc new file mode 100644 index 0000000..765dcb9 --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.cc @@ -0,0 +1,188 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h" + +#include "base/basictypes.h" +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder.h" + +namespace { + +#define SHADER(src) \ + "#ifdef GL_ES\n" \ + "precision mediump float;\n" \ + "#endif\n" #src + +const char* g_vertex_shader_source = { + SHADER( + uniform float u_clear_depth; + attribute vec4 a_position; + void main(void) { + gl_Position = vec4(a_position.x, a_position.y, u_clear_depth, 1.0); + } + ), +}; + +const char* g_fragment_shader_source = { + SHADER( + uniform vec4 u_clear_color; + void main(void) { + gl_FragColor = u_clear_color; + } + ), +}; + +void CompileShader(GLuint shader, const char* shader_source) { + glShaderSource(shader, 1, &shader_source, 0); + glCompileShader(shader); +#if DCHECK_IS_ON + GLint compile_status = GL_FALSE; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status); + if (GL_TRUE != compile_status) { + char buffer[1024]; + GLsizei length = 0; + glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); + std::string log(buffer, length); + DLOG(ERROR) << "Error compiling shader: " << log; + DLOG(ERROR) << "Shader compilation failure."; + } +#endif +} + +} // namespace + +namespace gpu { + +ClearFramebufferResourceManager::ClearFramebufferResourceManager( + const gles2::GLES2Decoder* decoder) + : initialized_(false), program_(0u), buffer_id_(0u) { + Initialize(decoder); +} + +ClearFramebufferResourceManager::~ClearFramebufferResourceManager() { + Destroy(); + DCHECK(!buffer_id_); +} + +void ClearFramebufferResourceManager::Initialize( + const gles2::GLES2Decoder* decoder) { + COMPILE_ASSERT( + kVertexPositionAttrib == 0u, + Position_attribs_must_be_0); + DCHECK(!buffer_id_); + + glGenBuffersARB(1, &buffer_id_); + glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); + const GLfloat kQuadVertices[] = {-1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f}; + glBufferData( + GL_ARRAY_BUFFER, sizeof(kQuadVertices), kQuadVertices, GL_STATIC_DRAW); + decoder->RestoreBufferBindings(); + initialized_ = true; +} + +void ClearFramebufferResourceManager::Destroy() { + if (!initialized_) + return; + + glDeleteProgram(program_); + glDeleteBuffersARB(1, &buffer_id_); + buffer_id_ = 0; +} + +void ClearFramebufferResourceManager::ClearFramebuffer( + const gles2::GLES2Decoder* decoder, + const gfx::Size& framebuffer_size, + GLbitfield mask, + GLfloat clear_color_red, + GLfloat clear_color_green, + GLfloat clear_color_blue, + GLfloat clear_color_alpha, + GLfloat clear_depth_value, + GLint clear_stencil_value) { + if (!initialized_) { + DLOG(ERROR) << "Uninitialized manager."; + return; + } + + if (!program_) { + program_ = glCreateProgram(); + GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); + CompileShader(vertex_shader, g_vertex_shader_source); + glAttachShader(program_, vertex_shader); + GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + CompileShader(fragment_shader, g_fragment_shader_source); + glAttachShader(program_, fragment_shader); + glBindAttribLocation(program_, kVertexPositionAttrib, "a_position"); + glLinkProgram(program_); +#if DCHECK_IS_ON + GLint linked = GL_FALSE; + glGetProgramiv(program_, GL_LINK_STATUS, &linked); + if (GL_TRUE != linked) + DLOG(ERROR) << "Program link failure."; +#endif + depth_handle_ = glGetUniformLocation(program_, "u_clear_depth"); + color_handle_ = glGetUniformLocation(program_, "u_clear_color"); + glDeleteShader(fragment_shader); + glDeleteShader(vertex_shader); + } + glUseProgram(program_); + +#if DCHECK_IS_ON + glValidateProgram(program_); + GLint validation_status = GL_FALSE; + glGetProgramiv(program_, GL_VALIDATE_STATUS, &validation_status); + if (GL_TRUE != validation_status) + DLOG(ERROR) << "Invalid shader."; +#endif + + decoder->ClearAllAttributes(); + glEnableVertexAttribArray(kVertexPositionAttrib); + + glBindBuffer(GL_ARRAY_BUFFER, buffer_id_); + glVertexAttribPointer(kVertexPositionAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glUniform1f(depth_handle_, clear_depth_value); + glUniform4f(color_handle_, clear_color_red, clear_color_green, + clear_color_blue, clear_color_alpha); + + if (!(mask & GL_COLOR_BUFFER_BIT)) { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + + if (mask & GL_DEPTH_BUFFER_BIT) { + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + } else { + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + } + + if (mask & GL_STENCIL_BUFFER_BIT) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, clear_stencil_value, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + } else { + glDisable(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilMask(0); + } + + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDisable(GL_POLYGON_OFFSET_FILL); + + glViewport(0, 0, framebuffer_size.width(), framebuffer_size.height()); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + decoder->RestoreAllAttributes(); + decoder->RestoreProgramBindings(); + decoder->RestoreBufferBindings(); + decoder->RestoreGlobalState(); +} + +} // namespace gpu diff --git a/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h new file mode 100644 index 0000000..6b533f5 --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h @@ -0,0 +1,54 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_CLEAR_FRAMEBUFFER_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_CLEAR_FRAMEBUFFER_H_ + +#include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/gpu_export.h" + +namespace gfx { +class Size; +} + +namespace gpu { +namespace gles2 { +class GLES2Decoder; +} + +class GPU_EXPORT ClearFramebufferResourceManager { + public: + ClearFramebufferResourceManager(const gles2::GLES2Decoder* decoder); + ~ClearFramebufferResourceManager(); + + + void ClearFramebuffer(const gles2::GLES2Decoder* decoder, + const gfx::Size& framebuffer_size, + GLbitfield mask, + GLfloat clear_color_red, + GLfloat clear_color_green, + GLfloat clear_color_blue, + GLfloat clear_color_alpha, + GLfloat clear_depth_value, + GLint clear_stencil_value); + + private: + void Initialize(const gles2::GLES2Decoder* decoder); + void Destroy(); + + // The attributes used during invocation of the extension. + static const GLuint kVertexPositionAttrib = 0; + + bool initialized_; + GLuint program_; + GLuint depth_handle_; + GLuint color_handle_; + GLuint buffer_id_; + + DISALLOW_COPY_AND_ASSIGN(ClearFramebufferResourceManager); +}; + +} // namespace gpu. + +#endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_CLEAR_FRAMEBUFFER_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 5dd9f64..dec594b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -41,6 +41,7 @@ #include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/framebuffer_manager.h" #include "gpu/command_buffer/service/gl_utils.h" +#include "gpu/command_buffer/service/gles2_cmd_clear_framebuffer.h" #include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" #include "gpu/command_buffer/service/gles2_cmd_validation.h" #include "gpu/command_buffer/service/gpu_state_tracer.h" @@ -1840,6 +1841,7 @@ class GLES2DecoderImpl : public GLES2Decoder, #endif scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; + scoped_ptr<ClearFramebufferResourceManager> clear_framebuffer_blit_; // Cached values of the currently assigned viewport dimensions. GLsizei viewport_max_width_; @@ -2764,6 +2766,14 @@ bool GLES2DecoderImpl::Initialize( AsyncPixelTransferManager::Create(context.get())); async_pixel_transfer_manager_->Initialize(texture_manager()); + if (workarounds().gl_clear_broken) { + DCHECK(!clear_framebuffer_blit_.get()); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glClearWorkaroundInit"); + clear_framebuffer_blit_.reset(new ClearFramebufferResourceManager(this)); + if (LOCAL_PEEK_GL_ERROR("glClearWorkaroundInit") != GL_NO_ERROR) + return false; + } + framebuffer_manager()->AddObserver(this); return true; @@ -3549,6 +3559,8 @@ void GLES2DecoderImpl::Destroy(bool have_context) { copy_texture_CHROMIUM_.reset(); } + clear_framebuffer_blit_.reset(); + if (state_.current_program.get()) { program_manager()->UnuseProgram(shader_manager(), state_.current_program.get()); @@ -3614,6 +3626,7 @@ void GLES2DecoderImpl::Destroy(bool have_context) { state_.current_program = NULL; copy_texture_CHROMIUM_.reset(); + clear_framebuffer_blit_.reset(); if (query_manager_.get()) { query_manager_->Destroy(have_context); @@ -5106,6 +5119,19 @@ error::Error GLES2DecoderImpl::DoClear(GLbitfield mask) { if (CheckBoundFramebuffersValid("glClear")) { ApplyDirtyState(); ScopedRenderTo do_render(framebuffer_state_.bound_draw_framebuffer.get()); + if (workarounds().gl_clear_broken) { + ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::ClearWorkaround", + GetErrorState()); + if (!BoundFramebufferHasDepthAttachment()) + mask &= ~GL_DEPTH_BUFFER_BIT; + if (!BoundFramebufferHasStencilAttachment()) + mask &= ~GL_STENCIL_BUFFER_BIT; + clear_framebuffer_blit_->ClearFramebuffer( + this, GetBoundReadFrameBufferSize(), mask, state_.color_clear_red, + state_.color_clear_green, state_.color_clear_blue, + state_.color_clear_alpha, state_.depth_clear, state_.stencil_clear); + return error::kNoError; + } glClear(mask); } return error::kNoError; |