|  | // 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 "gpu/command_buffer/service/gl_utils.h" | 
|  | #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 
|  | #include "ui/gfx/geometry/size.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 { | 
|  | namespace gles2 { | 
|  |  | 
|  | 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) { | 
|  | static_assert( | 
|  | kVertexPositionAttrib == 0u, | 
|  | "kVertexPositionAttrib 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 gles2 | 
|  | }  // namespace gpu |