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/program_binding.h"
7 #include "base/debug/trace_event.h"
8 #include "cc/geometry_binding.h"
9 #include "cc/gl_renderer.h" // For the GLC() macro.
10 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
11 #include "third_party/khronos/GLES2/gl2.h"
13 using WebKit::WebGraphicsContext3D
;
17 ProgramBindingBase::ProgramBindingBase()
20 , m_fragmentShaderId(0)
21 , m_initialized(false)
25 ProgramBindingBase::~ProgramBindingBase()
27 // If you hit these asserts, you initialized but forgot to call cleanup().
29 DCHECK(!m_vertexShaderId
);
30 DCHECK(!m_fragmentShaderId
);
31 DCHECK(!m_initialized
);
34 void ProgramBindingBase::init(WebGraphicsContext3D
* context
, const std::string
& vertexShader
, const std::string
& fragmentShader
)
36 TRACE_EVENT0("cc", "ProgramBindingBase::init");
37 m_vertexShaderId
= loadShader(context
, GL_VERTEX_SHADER
, vertexShader
);
38 if (!m_vertexShaderId
) {
39 if (!IsContextLost(context
))
40 LOG(ERROR
) << "Failed to create vertex shader";
44 m_fragmentShaderId
= loadShader(context
, GL_FRAGMENT_SHADER
, fragmentShader
);
45 if (!m_fragmentShaderId
) {
46 GLC(context
, context
->deleteShader(m_vertexShaderId
));
48 if (!IsContextLost(context
))
49 LOG(ERROR
) << "Failed to create fragment shader";
53 m_program
= createShaderProgram(context
, m_vertexShaderId
, m_fragmentShaderId
);
54 DCHECK(m_program
|| IsContextLost(context
));
57 void ProgramBindingBase::link(WebGraphicsContext3D
* context
)
59 GLC(context
, context
->linkProgram(m_program
));
60 cleanupShaders(context
);
63 GLC(context
, context
->getProgramiv(m_program
, GL_LINK_STATUS
, &linked
));
65 if (!IsContextLost(context
))
66 LOG(ERROR
) << "Failed to link shader program";
67 GLC(context
, context
->deleteProgram(m_program
));
72 void ProgramBindingBase::cleanup(WebGraphicsContext3D
* context
)
74 m_initialized
= false;
79 GLC(context
, context
->deleteProgram(m_program
));
82 cleanupShaders(context
);
85 unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D
* context
, unsigned type
, const std::string
& shaderSource
)
87 unsigned shader
= context
->createShader(type
);
90 GLC(context
, context
->shaderSource(shader
, shaderSource
.data()));
91 GLC(context
, context
->compileShader(shader
));
94 GLC(context
, context
->getShaderiv(shader
, GL_COMPILE_STATUS
, &compiled
));
96 GLC(context
, context
->deleteShader(shader
));
103 unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D
* context
, unsigned vertexShader
, unsigned fragmentShader
)
105 unsigned programObject
= context
->createProgram();
106 if (!programObject
) {
107 if (!IsContextLost(context
))
108 LOG(ERROR
) << "Failed to create shader program";
112 GLC(context
, context
->attachShader(programObject
, vertexShader
));
113 GLC(context
, context
->attachShader(programObject
, fragmentShader
));
115 // Bind the common attrib locations.
116 GLC(context
, context
->bindAttribLocation(programObject
, GeometryBinding::positionAttribLocation(), "a_position"));
117 GLC(context
, context
->bindAttribLocation(programObject
, GeometryBinding::texCoordAttribLocation(), "a_texCoord"));
119 return programObject
;
122 void ProgramBindingBase::cleanupShaders(WebGraphicsContext3D
* context
)
124 if (m_vertexShaderId
) {
125 GLC(context
, context
->deleteShader(m_vertexShaderId
));
126 m_vertexShaderId
= 0;
128 if (m_fragmentShaderId
) {
129 GLC(context
, context
->deleteShader(m_fragmentShaderId
));
130 m_fragmentShaderId
= 0;
134 bool ProgramBindingBase::IsContextLost(WebGraphicsContext3D
* context
) {
135 return (context
->getGraphicsResetStatusARB() != GL_NO_ERROR
);