mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
189 lines
5.3 KiB
C++
189 lines
5.3 KiB
C++
// 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) {
|
|
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 gpu
|