| // Copyright 2011 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 "cc/output/program_binding.h" |
| |
| #include "base/trace_event/trace_event.h" |
| #include "cc/output/geometry_binding.h" |
| #include "gpu/GLES2/gl2extchromium.h" |
| #include "gpu/command_buffer/client/gles2_interface.h" |
| |
| using gpu::gles2::GLES2Interface; |
| |
| namespace cc { |
| |
| ProgramKey::ProgramKey() = default; |
| ProgramKey::ProgramKey(const ProgramKey& other) = default; |
| ProgramKey::~ProgramKey() = default; |
| |
| bool ProgramKey::operator==(const ProgramKey& other) const { |
| return type_ == other.type_ && precision_ == other.precision_ && |
| sampler_ == other.sampler_ && blend_mode_ == other.blend_mode_ && |
| aa_mode_ == other.aa_mode_ && swizzle_mode_ == other.swizzle_mode_ && |
| is_opaque_ == other.is_opaque_ && |
| premultiplied_alpha_ == other.premultiplied_alpha_ && |
| has_background_color_ == other.has_background_color_ && |
| mask_mode_ == other.mask_mode_ && |
| mask_for_background_ == other.mask_for_background_ && |
| has_color_matrix_ == other.has_color_matrix_ && |
| yuv_alpha_texture_mode_ == other.yuv_alpha_texture_mode_ && |
| uv_texture_mode_ == other.uv_texture_mode_ && |
| color_conversion_mode_ == other.color_conversion_mode_; |
| } |
| |
| // static |
| ProgramKey ProgramKey::DebugBorder() { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_DEBUG_BORDER; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::SolidColor(AAMode aa_mode) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_SOLID_COLOR; |
| result.aa_mode_ = aa_mode; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::Tile(TexCoordPrecision precision, |
| SamplerType sampler, |
| AAMode aa_mode, |
| SwizzleMode swizzle_mode, |
| bool is_opaque) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_TILE; |
| result.precision_ = precision; |
| result.sampler_ = sampler; |
| result.aa_mode_ = aa_mode; |
| result.swizzle_mode_ = swizzle_mode; |
| result.is_opaque_ = is_opaque; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::Texture(TexCoordPrecision precision, |
| SamplerType sampler, |
| PremultipliedAlphaMode premultiplied_alpha, |
| bool has_background_color) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_TEXTURE; |
| result.precision_ = precision; |
| result.sampler_ = sampler; |
| result.premultiplied_alpha_ = premultiplied_alpha; |
| result.has_background_color_ = has_background_color; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::RenderPass(TexCoordPrecision precision, |
| SamplerType sampler, |
| BlendMode blend_mode, |
| AAMode aa_mode, |
| MaskMode mask_mode, |
| bool mask_for_background, |
| bool has_color_matrix) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_RENDER_PASS; |
| result.precision_ = precision; |
| result.sampler_ = sampler; |
| result.blend_mode_ = blend_mode; |
| result.aa_mode_ = aa_mode; |
| result.mask_mode_ = mask_mode; |
| result.mask_for_background_ = mask_for_background; |
| result.has_color_matrix_ = has_color_matrix; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::VideoStream(TexCoordPrecision precision) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_VIDEO_STREAM; |
| result.precision_ = precision; |
| result.sampler_ = SAMPLER_TYPE_EXTERNAL_OES; |
| return result; |
| } |
| |
| // static |
| ProgramKey ProgramKey::YUVVideo(TexCoordPrecision precision, |
| SamplerType sampler, |
| YUVAlphaTextureMode yuv_alpha_texture_mode, |
| UVTextureMode uv_texture_mode, |
| ColorConversionMode color_conversion_mode) { |
| ProgramKey result; |
| result.type_ = PROGRAM_TYPE_YUV_VIDEO; |
| result.precision_ = precision; |
| result.sampler_ = sampler; |
| result.yuv_alpha_texture_mode_ = yuv_alpha_texture_mode; |
| DCHECK(yuv_alpha_texture_mode == YUV_NO_ALPHA_TEXTURE || |
| yuv_alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE); |
| result.uv_texture_mode_ = uv_texture_mode; |
| DCHECK(uv_texture_mode == UV_TEXTURE_MODE_UV || |
| uv_texture_mode == UV_TEXTURE_MODE_U_V); |
| result.color_conversion_mode_ = color_conversion_mode; |
| return result; |
| } |
| |
| ProgramBindingBase::ProgramBindingBase() |
| : program_(0), |
| vertex_shader_id_(0), |
| fragment_shader_id_(0), |
| initialized_(false) {} |
| |
| ProgramBindingBase::~ProgramBindingBase() { |
| // If you hit these asserts, you initialized but forgot to call Cleanup(). |
| DCHECK(!program_); |
| DCHECK(!vertex_shader_id_); |
| DCHECK(!fragment_shader_id_); |
| DCHECK(!initialized_); |
| } |
| |
| bool ProgramBindingBase::Init(GLES2Interface* context, |
| const std::string& vertex_shader, |
| const std::string& fragment_shader) { |
| TRACE_EVENT0("cc", "ProgramBindingBase::init"); |
| vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader); |
| if (!vertex_shader_id_) |
| return false; |
| |
| fragment_shader_id_ = |
| LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader); |
| if (!fragment_shader_id_) { |
| context->DeleteShader(vertex_shader_id_); |
| vertex_shader_id_ = 0; |
| return false; |
| } |
| |
| program_ = |
| CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_); |
| return !!program_; |
| } |
| |
| bool ProgramBindingBase::Link(GLES2Interface* context) { |
| context->LinkProgram(program_); |
| CleanupShaders(context); |
| if (!program_) |
| return false; |
| #ifndef NDEBUG |
| int linked = 0; |
| context->GetProgramiv(program_, GL_LINK_STATUS, &linked); |
| if (!linked) { |
| char buffer[1024] = ""; |
| context->GetProgramInfoLog(program_, sizeof(buffer), nullptr, buffer); |
| DLOG(ERROR) << "Error compiling shader: " << buffer; |
| return false; |
| } |
| #endif |
| return true; |
| } |
| |
| void ProgramBindingBase::Cleanup(GLES2Interface* context) { |
| initialized_ = false; |
| if (!program_) |
| return; |
| |
| DCHECK(context); |
| context->DeleteProgram(program_); |
| program_ = 0; |
| |
| CleanupShaders(context); |
| } |
| |
| unsigned ProgramBindingBase::LoadShader(GLES2Interface* context, |
| unsigned type, |
| const std::string& shader_source) { |
| unsigned shader = context->CreateShader(type); |
| if (!shader) |
| return 0u; |
| |
| const char* shader_source_str[] = { shader_source.data() }; |
| int shader_length[] = { static_cast<int>(shader_source.length()) }; |
| context->ShaderSource( |
| shader, 1, |
| shader_source_str, |
| shader_length); |
| context->CompileShader(shader); |
| #if DCHECK_IS_ON() |
| int compiled = 0; |
| context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled); |
| if (!compiled) { |
| char buffer[1024] = ""; |
| context->GetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); |
| DLOG(ERROR) << "Error compiling shader: " << buffer |
| << "\n shader program: " << shader_source; |
| return 0u; |
| } |
| #endif |
| return shader; |
| } |
| |
| unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context, |
| unsigned vertex_shader, |
| unsigned fragment_shader) { |
| unsigned program_object = context->CreateProgram(); |
| if (!program_object) |
| return 0; |
| |
| context->AttachShader(program_object, vertex_shader); |
| context->AttachShader(program_object, fragment_shader); |
| |
| // Bind the common attrib locations. |
| context->BindAttribLocation( |
| program_object, GeometryBinding::PositionAttribLocation(), "a_position"); |
| context->BindAttribLocation( |
| program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord"); |
| context->BindAttribLocation(program_object, |
| GeometryBinding::TriangleIndexAttribLocation(), |
| "a_index"); |
| |
| return program_object; |
| } |
| |
| void ProgramBindingBase::CleanupShaders(GLES2Interface* context) { |
| if (vertex_shader_id_) { |
| context->DeleteShader(vertex_shader_id_); |
| vertex_shader_id_ = 0; |
| } |
| if (fragment_shader_id_) { |
| context->DeleteShader(fragment_shader_id_); |
| fragment_shader_id_ = 0; |
| } |
| } |
| |
| bool ProgramBindingBase::IsContextLost(GLES2Interface* context) { |
| return context->GetGraphicsResetStatusKHR() != GL_NO_ERROR; |
| } |
| |
| } // namespace cc |