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.
5 #include "cc/output/program_binding.h"
7 #include "base/debug/trace_event.h"
8 #include "cc/output/geometry_binding.h"
9 #include "cc/output/gl_renderer.h" // For the GLC() macro.
10 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
11 #include "third_party/khronos/GLES2/gl2.h"
13 using WebKit::WebGraphicsContext3D
;
17 ProgramBindingBase::ProgramBindingBase()
20 fragment_shader_id_(0),
21 initialized_(false) {}
23 ProgramBindingBase::~ProgramBindingBase() {
24 // If you hit these asserts, you initialized but forgot to call Cleanup().
26 DCHECK(!vertex_shader_id_
);
27 DCHECK(!fragment_shader_id_
);
28 DCHECK(!initialized_
);
31 void ProgramBindingBase::Init(WebGraphicsContext3D
* context
,
32 const std::string
& vertex_shader
,
33 const std::string
& fragment_shader
) {
34 TRACE_EVENT0("cc", "ProgramBindingBase::init");
35 vertex_shader_id_
= LoadShader(context
, GL_VERTEX_SHADER
, vertex_shader
);
36 if (!vertex_shader_id_
) {
37 if (!IsContextLost(context
))
38 LOG(ERROR
) << "Failed to create vertex shader";
43 LoadShader(context
, GL_FRAGMENT_SHADER
, fragment_shader
);
44 if (!fragment_shader_id_
) {
45 GLC(context
, context
->deleteShader(vertex_shader_id_
));
46 vertex_shader_id_
= 0;
47 if (!IsContextLost(context
))
48 LOG(ERROR
) << "Failed to create fragment shader";
53 CreateShaderProgram(context
, vertex_shader_id_
, fragment_shader_id_
);
54 DCHECK(program_
|| IsContextLost(context
));
57 void ProgramBindingBase::Link(WebGraphicsContext3D
* context
) {
58 GLC(context
, context
->linkProgram(program_
));
59 CleanupShaders(context
);
64 GLC(context
, context
->getProgramiv(program_
, GL_LINK_STATUS
, &linked
));
66 if (!IsContextLost(context
))
67 LOG(ERROR
) << "Failed to link shader program";
68 GLC(context
, context
->deleteProgram(program_
));
73 void ProgramBindingBase::Cleanup(WebGraphicsContext3D
* context
) {
79 GLC(context
, context
->deleteProgram(program_
));
82 CleanupShaders(context
);
85 unsigned ProgramBindingBase::LoadShader(WebGraphicsContext3D
* context
,
87 const std::string
& shader_source
) {
88 unsigned shader
= context
->createShader(type
);
91 GLC(context
, context
->shaderSource(shader
, shader_source
.data()));
92 GLC(context
, context
->compileShader(shader
));
95 GLC(context
, context
->getShaderiv(shader
, GL_COMPILE_STATUS
, &compiled
));
97 GLC(context
, context
->deleteShader(shader
));
104 unsigned ProgramBindingBase::CreateShaderProgram(WebGraphicsContext3D
* context
,
105 unsigned vertex_shader
,
106 unsigned fragment_shader
) {
107 unsigned program_object
= context
->createProgram();
108 if (!program_object
) {
109 if (!IsContextLost(context
))
110 LOG(ERROR
) << "Failed to create shader program";
114 GLC(context
, context
->attachShader(program_object
, vertex_shader
));
115 GLC(context
, context
->attachShader(program_object
, fragment_shader
));
117 // Bind the common attrib locations.
119 context
->bindAttribLocation(program_object
,
120 GeometryBinding::PositionAttribLocation(),
123 context
->bindAttribLocation(program_object
,
124 GeometryBinding::TexCoordAttribLocation(),
127 context
->bindAttribLocation(
129 GeometryBinding::TriangleIndexAttribLocation(),
132 return program_object
;
135 void ProgramBindingBase::CleanupShaders(WebGraphicsContext3D
* context
) {
136 if (vertex_shader_id_
) {
137 GLC(context
, context
->deleteShader(vertex_shader_id_
));
138 vertex_shader_id_
= 0;
140 if (fragment_shader_id_
) {
141 GLC(context
, context
->deleteShader(fragment_shader_id_
));
142 fragment_shader_id_
= 0;
146 bool ProgramBindingBase::IsContextLost(WebGraphicsContext3D
* context
) {
147 return (context
->getGraphicsResetStatusARB() != GL_NO_ERROR
);