1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/viz/service/display/program_binding.h"
6
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event.h"
9 #include "components/viz/service/display/geometry_binding.h"
10 #include "gpu/GLES2/gl2extchromium.h"
11 #include "gpu/command_buffer/client/gles2_interface.h"
12 #include "ui/gfx/color_transform.h"
13
14 using gpu::gles2::GLES2Interface;
15
16 namespace viz {
17
18 ProgramKey::ProgramKey() = default;
19
20 ProgramKey::ProgramKey(const ProgramKey& other) = default;
21
22 ProgramKey::~ProgramKey() = default;
23
operator ==(const ProgramKey & other) const24 bool ProgramKey::operator==(const ProgramKey& other) const {
25 return type_ == other.type_ && precision_ == other.precision_ &&
26 sampler_ == other.sampler_ && blend_mode_ == other.blend_mode_ &&
27 aa_mode_ == other.aa_mode_ && is_opaque_ == other.is_opaque_ &&
28 premultiplied_alpha_ == other.premultiplied_alpha_ &&
29 has_background_color_ == other.has_background_color_ &&
30 has_tex_clamp_rect_ == other.has_tex_clamp_rect_ &&
31 mask_mode_ == other.mask_mode_ &&
32 mask_for_background_ == other.mask_for_background_ &&
33 has_color_matrix_ == other.has_color_matrix_ &&
34 yuv_alpha_texture_mode_ == other.yuv_alpha_texture_mode_ &&
35 uv_texture_mode_ == other.uv_texture_mode_ &&
36 color_conversion_mode_ == other.color_conversion_mode_ &&
37 color_transform_ == other.color_transform_ &&
38 has_output_color_matrix_ == other.has_output_color_matrix_ &&
39 has_rounded_corner_ == other.has_rounded_corner_;
40 }
41
operator !=(const ProgramKey & other) const42 bool ProgramKey::operator!=(const ProgramKey& other) const {
43 return !(*this == other);
44 }
45
46 // static
DebugBorder()47 ProgramKey ProgramKey::DebugBorder() {
48 ProgramKey result;
49 result.type_ = PROGRAM_TYPE_DEBUG_BORDER;
50 return result;
51 }
52
53 // static
SolidColor(AAMode aa_mode,bool tint_color,bool rounded_corner)54 ProgramKey ProgramKey::SolidColor(AAMode aa_mode,
55 bool tint_color,
56 bool rounded_corner) {
57 ProgramKey result;
58 result.type_ = PROGRAM_TYPE_SOLID_COLOR;
59 result.aa_mode_ = aa_mode;
60 result.has_tint_color_matrix_ = tint_color;
61 result.has_rounded_corner_ = rounded_corner;
62 return result;
63 }
64
65 // static
Tile(TexCoordPrecision precision,SamplerType sampler,AAMode aa_mode,PremultipliedAlphaMode premultiplied_alpha,bool is_opaque,bool has_tex_clamp_rect,bool tint_color,bool rounded_corner)66 ProgramKey ProgramKey::Tile(TexCoordPrecision precision,
67 SamplerType sampler,
68 AAMode aa_mode,
69 PremultipliedAlphaMode premultiplied_alpha,
70 bool is_opaque,
71 bool has_tex_clamp_rect,
72 bool tint_color,
73 bool rounded_corner) {
74 ProgramKey result;
75 result.type_ = PROGRAM_TYPE_TILE;
76 result.precision_ = precision;
77 result.sampler_ = sampler;
78 result.aa_mode_ = aa_mode;
79 result.is_opaque_ = is_opaque;
80 result.has_tex_clamp_rect_ = has_tex_clamp_rect;
81 result.has_tint_color_matrix_ = tint_color;
82 result.premultiplied_alpha_ = premultiplied_alpha;
83 result.has_rounded_corner_ = rounded_corner;
84 return result;
85 }
86
87 // static
Texture(TexCoordPrecision precision,SamplerType sampler,PremultipliedAlphaMode premultiplied_alpha,bool has_background_color,bool has_tex_clamp_rect,bool tint_color,bool rounded_corner)88 ProgramKey ProgramKey::Texture(TexCoordPrecision precision,
89 SamplerType sampler,
90 PremultipliedAlphaMode premultiplied_alpha,
91 bool has_background_color,
92 bool has_tex_clamp_rect,
93 bool tint_color,
94 bool rounded_corner) {
95 ProgramKey result;
96 result.type_ = PROGRAM_TYPE_TEXTURE;
97 result.precision_ = precision;
98 result.sampler_ = sampler;
99 result.premultiplied_alpha_ = premultiplied_alpha;
100 result.has_background_color_ = has_background_color;
101 result.has_tex_clamp_rect_ = has_tex_clamp_rect;
102 result.has_tint_color_matrix_ = tint_color;
103 result.has_rounded_corner_ = rounded_corner;
104 return result;
105 }
106
107 // static
RenderPass(TexCoordPrecision precision,SamplerType sampler,BlendMode blend_mode,AAMode aa_mode,MaskMode mask_mode,bool mask_for_background,bool has_color_matrix,bool tint_color,bool rounded_corner)108 ProgramKey ProgramKey::RenderPass(TexCoordPrecision precision,
109 SamplerType sampler,
110 BlendMode blend_mode,
111 AAMode aa_mode,
112 MaskMode mask_mode,
113 bool mask_for_background,
114 bool has_color_matrix,
115 bool tint_color,
116 bool rounded_corner) {
117 ProgramKey result;
118 result.type_ = PROGRAM_TYPE_RENDER_PASS;
119 result.precision_ = precision;
120 result.sampler_ = sampler;
121 result.blend_mode_ = blend_mode;
122 result.aa_mode_ = aa_mode;
123 result.mask_mode_ = mask_mode;
124 result.mask_for_background_ = mask_for_background;
125 result.has_color_matrix_ = has_color_matrix;
126 result.has_tint_color_matrix_ = tint_color;
127 result.has_rounded_corner_ = rounded_corner;
128 return result;
129 }
130
131 // static
VideoStream(TexCoordPrecision precision,bool rounded_corner)132 ProgramKey ProgramKey::VideoStream(TexCoordPrecision precision,
133 bool rounded_corner) {
134 ProgramKey result;
135 result.type_ = PROGRAM_TYPE_VIDEO_STREAM;
136 result.precision_ = precision;
137 result.sampler_ = SAMPLER_TYPE_EXTERNAL_OES;
138 result.has_rounded_corner_ = rounded_corner;
139 return result;
140 }
141
142 // static
YUVVideo(TexCoordPrecision precision,SamplerType sampler,YUVAlphaTextureMode yuv_alpha_texture_mode,UVTextureMode uv_texture_mode,bool tint_color,bool rounded_corner)143 ProgramKey ProgramKey::YUVVideo(TexCoordPrecision precision,
144 SamplerType sampler,
145 YUVAlphaTextureMode yuv_alpha_texture_mode,
146 UVTextureMode uv_texture_mode,
147 bool tint_color,
148 bool rounded_corner) {
149 ProgramKey result;
150 result.type_ = PROGRAM_TYPE_YUV_VIDEO;
151 result.precision_ = precision;
152 result.sampler_ = sampler;
153 result.yuv_alpha_texture_mode_ = yuv_alpha_texture_mode;
154 DCHECK(yuv_alpha_texture_mode == YUV_NO_ALPHA_TEXTURE ||
155 yuv_alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE);
156 result.uv_texture_mode_ = uv_texture_mode;
157 DCHECK(uv_texture_mode == UV_TEXTURE_MODE_UV ||
158 uv_texture_mode == UV_TEXTURE_MODE_U_V);
159 result.has_tint_color_matrix_ = tint_color;
160 result.has_rounded_corner_ = rounded_corner;
161 return result;
162 }
163
SetColorTransform(const gfx::ColorTransform * transform)164 void ProgramKey::SetColorTransform(const gfx::ColorTransform* transform) {
165 color_transform_ = nullptr;
166 if (transform->IsIdentity()) {
167 color_conversion_mode_ = COLOR_CONVERSION_MODE_NONE;
168 } else {
169 color_conversion_mode_ = COLOR_CONVERSION_MODE_SHADER;
170 color_transform_ = transform;
171 }
172 }
173
ProgramBindingBase()174 ProgramBindingBase::ProgramBindingBase()
175 : program_(0),
176 vertex_shader_id_(0),
177 fragment_shader_id_(0),
178 initialized_(false) {}
179
~ProgramBindingBase()180 ProgramBindingBase::~ProgramBindingBase() {
181 // If you hit these asserts, you initialized but forgot to call Cleanup().
182 DCHECK(!program_);
183 DCHECK(!vertex_shader_id_);
184 DCHECK(!fragment_shader_id_);
185 DCHECK(!initialized_);
186 }
187
Init(GLES2Interface * context,const std::string & vertex_shader,const std::string & fragment_shader)188 bool ProgramBindingBase::Init(GLES2Interface* context,
189 const std::string& vertex_shader,
190 const std::string& fragment_shader) {
191 TRACE_EVENT0("viz", "ProgramBindingBase::init");
192 vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader);
193 if (!vertex_shader_id_)
194 return false;
195
196 fragment_shader_id_ =
197 LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader);
198 if (!fragment_shader_id_) {
199 context->DeleteShader(vertex_shader_id_);
200 vertex_shader_id_ = 0;
201 return false;
202 }
203
204 program_ =
205 CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_);
206 return !!program_;
207 }
208
Link(GLES2Interface * context)209 bool ProgramBindingBase::Link(GLES2Interface* context) {
210 context->LinkProgram(program_);
211 CleanupShaders(context);
212 if (!program_)
213 return false;
214 #ifndef NDEBUG
215 int linked = 0;
216 context->GetProgramiv(program_, GL_LINK_STATUS, &linked);
217 if (!linked) {
218 char buffer[1024] = "";
219 context->GetProgramInfoLog(program_, sizeof(buffer), nullptr, buffer);
220 DLOG(ERROR) << "Error compiling shader: " << buffer;
221 return false;
222 }
223 #endif
224 return true;
225 }
226
Cleanup(GLES2Interface * context)227 void ProgramBindingBase::Cleanup(GLES2Interface* context) {
228 initialized_ = false;
229 if (!program_)
230 return;
231
232 DCHECK(context);
233 context->DeleteProgram(program_);
234 program_ = 0;
235
236 CleanupShaders(context);
237 }
238
LoadShader(GLES2Interface * context,unsigned type,const std::string & shader_source)239 unsigned ProgramBindingBase::LoadShader(GLES2Interface* context,
240 unsigned type,
241 const std::string& shader_source) {
242 unsigned shader = context->CreateShader(type);
243 if (!shader)
244 return 0u;
245
246 const char* shader_source_str[] = {shader_source.data()};
247 int shader_length[] = {static_cast<int>(shader_source.length())};
248 context->ShaderSource(shader, 1, shader_source_str, shader_length);
249 context->CompileShader(shader);
250 #if DCHECK_IS_ON()
251 int compiled = 0;
252 context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
253 if (!compiled) {
254 char buffer[1024] = "";
255 context->GetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer);
256 DLOG(ERROR) << "Error compiling shader: " << buffer
257 << "\n shader program: " << shader_source;
258 return 0u;
259 }
260 #endif
261 return shader;
262 }
263
CreateShaderProgram(GLES2Interface * context,unsigned vertex_shader,unsigned fragment_shader)264 unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context,
265 unsigned vertex_shader,
266 unsigned fragment_shader) {
267 unsigned program_object = context->CreateProgram();
268 if (!program_object)
269 return 0;
270
271 context->AttachShader(program_object, vertex_shader);
272 context->AttachShader(program_object, fragment_shader);
273
274 // Bind the common attrib locations.
275 context->BindAttribLocation(
276 program_object, GeometryBinding::PositionAttribLocation(), "a_position");
277 context->BindAttribLocation(
278 program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord");
279 context->BindAttribLocation(program_object,
280 GeometryBinding::TriangleIndexAttribLocation(),
281 "a_index");
282
283 return program_object;
284 }
285
CleanupShaders(GLES2Interface * context)286 void ProgramBindingBase::CleanupShaders(GLES2Interface* context) {
287 if (vertex_shader_id_) {
288 context->DeleteShader(vertex_shader_id_);
289 vertex_shader_id_ = 0;
290 }
291 if (fragment_shader_id_) {
292 context->DeleteShader(fragment_shader_id_);
293 fragment_shader_id_ = 0;
294 }
295 }
296
IsContextLost(GLES2Interface * context)297 bool ProgramBindingBase::IsContextLost(GLES2Interface* context) {
298 return context->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
299 }
300
301 } // namespace viz
302