blob: 8e92e9815b05be7a308a8ab3b8d4a26b544cc352 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// 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
[email protected]a8461d82012-10-16 21:11:145#include "cc/program_binding.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]6331a1172012-10-18 11:35:137#include "base/debug/trace_event.h"
[email protected]a8461d82012-10-16 21:11:148#include "cc/geometry_binding.h"
[email protected]c4040a522012-10-21 15:01:409#include "cc/gl_renderer.h" // For the GLC() macro.
[email protected]920caa52012-12-18 22:39:5010#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
[email protected]d9c28522012-10-18 23:35:4311#include "third_party/khronos/GLES2/gl2.h"
[email protected]94f206c12012-08-25 00:09:1412
13using WebKit::WebGraphicsContext3D;
14
[email protected]9c88e562012-09-14 22:21:3015namespace cc {
[email protected]94f206c12012-08-25 00:09:1416
17ProgramBindingBase::ProgramBindingBase()
18 : m_program(0)
19 , m_vertexShaderId(0)
20 , m_fragmentShaderId(0)
21 , m_initialized(false)
22{
23}
24
25ProgramBindingBase::~ProgramBindingBase()
26{
27 // If you hit these asserts, you initialized but forgot to call cleanup().
[email protected]1d993172012-10-18 18:15:0428 DCHECK(!m_program);
29 DCHECK(!m_vertexShaderId);
30 DCHECK(!m_fragmentShaderId);
31 DCHECK(!m_initialized);
[email protected]94f206c12012-08-25 00:09:1432}
33
[email protected]515e8d232012-09-10 19:15:2734void ProgramBindingBase::init(WebGraphicsContext3D* context, const std::string& vertexShader, const std::string& fragmentShader)
[email protected]94f206c12012-08-25 00:09:1435{
36 TRACE_EVENT0("cc", "ProgramBindingBase::init");
[email protected]d9c28522012-10-18 23:35:4337 m_vertexShaderId = loadShader(context, GL_VERTEX_SHADER, vertexShader);
[email protected]94f206c12012-08-25 00:09:1438 if (!m_vertexShaderId) {
[email protected]d01f0d432012-11-17 22:24:4739 if (!IsContextLost(context))
[email protected]1d993172012-10-18 18:15:0440 LOG(ERROR) << "Failed to create vertex shader";
[email protected]94f206c12012-08-25 00:09:1441 return;
42 }
43
[email protected]d9c28522012-10-18 23:35:4344 m_fragmentShaderId = loadShader(context, GL_FRAGMENT_SHADER, fragmentShader);
[email protected]94f206c12012-08-25 00:09:1445 if (!m_fragmentShaderId) {
46 GLC(context, context->deleteShader(m_vertexShaderId));
47 m_vertexShaderId = 0;
[email protected]d01f0d432012-11-17 22:24:4748 if (!IsContextLost(context))
[email protected]1d993172012-10-18 18:15:0449 LOG(ERROR) << "Failed to create fragment shader";
[email protected]94f206c12012-08-25 00:09:1450 return;
51 }
52
53 m_program = createShaderProgram(context, m_vertexShaderId, m_fragmentShaderId);
[email protected]d01f0d432012-11-17 22:24:4754 DCHECK(m_program || IsContextLost(context));
[email protected]94f206c12012-08-25 00:09:1455}
56
57void ProgramBindingBase::link(WebGraphicsContext3D* context)
58{
59 GLC(context, context->linkProgram(m_program));
60 cleanupShaders(context);
[email protected]e7f87cfb2012-10-17 01:25:1861#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:1462 int linked = 0;
[email protected]d9c28522012-10-18 23:35:4363 GLC(context, context->getProgramiv(m_program, GL_LINK_STATUS, &linked));
[email protected]94f206c12012-08-25 00:09:1464 if (!linked) {
[email protected]d01f0d432012-11-17 22:24:4765 if (!IsContextLost(context))
[email protected]1d993172012-10-18 18:15:0466 LOG(ERROR) << "Failed to link shader program";
[email protected]94f206c12012-08-25 00:09:1467 GLC(context, context->deleteProgram(m_program));
[email protected]94f206c12012-08-25 00:09:1468 }
69#endif
70}
71
72void ProgramBindingBase::cleanup(WebGraphicsContext3D* context)
73{
74 m_initialized = false;
75 if (!m_program)
76 return;
77
[email protected]1d993172012-10-18 18:15:0478 DCHECK(context);
[email protected]94f206c12012-08-25 00:09:1479 GLC(context, context->deleteProgram(m_program));
80 m_program = 0;
81
82 cleanupShaders(context);
83}
84
[email protected]515e8d232012-09-10 19:15:2785unsigned ProgramBindingBase::loadShader(WebGraphicsContext3D* context, unsigned type, const std::string& shaderSource)
[email protected]94f206c12012-08-25 00:09:1486{
87 unsigned shader = context->createShader(type);
88 if (!shader)
89 return 0;
[email protected]515e8d232012-09-10 19:15:2790 GLC(context, context->shaderSource(shader, shaderSource.data()));
[email protected]94f206c12012-08-25 00:09:1491 GLC(context, context->compileShader(shader));
[email protected]e7f87cfb2012-10-17 01:25:1892#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:1493 int compiled = 0;
[email protected]d9c28522012-10-18 23:35:4394 GLC(context, context->getShaderiv(shader, GL_COMPILE_STATUS, &compiled));
[email protected]94f206c12012-08-25 00:09:1495 if (!compiled) {
96 GLC(context, context->deleteShader(shader));
97 return 0;
98 }
99#endif
100 return shader;
101}
102
103unsigned ProgramBindingBase::createShaderProgram(WebGraphicsContext3D* context, unsigned vertexShader, unsigned fragmentShader)
104{
105 unsigned programObject = context->createProgram();
106 if (!programObject) {
[email protected]d01f0d432012-11-17 22:24:47107 if (!IsContextLost(context))
[email protected]1d993172012-10-18 18:15:04108 LOG(ERROR) << "Failed to create shader program";
[email protected]94f206c12012-08-25 00:09:14109 return 0;
110 }
111
112 GLC(context, context->attachShader(programObject, vertexShader));
113 GLC(context, context->attachShader(programObject, fragmentShader));
114
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"));
118
119 return programObject;
120}
121
122void ProgramBindingBase::cleanupShaders(WebGraphicsContext3D* context)
123{
124 if (m_vertexShaderId) {
125 GLC(context, context->deleteShader(m_vertexShaderId));
126 m_vertexShaderId = 0;
127 }
128 if (m_fragmentShaderId) {
129 GLC(context, context->deleteShader(m_fragmentShaderId));
130 m_fragmentShaderId = 0;
131 }
132}
133
[email protected]d01f0d432012-11-17 22:24:47134bool ProgramBindingBase::IsContextLost(WebGraphicsContext3D* context) {
135 return (context->getGraphicsResetStatusARB() != GL_NO_ERROR);
136}
137
[email protected]bc5e77c2012-11-05 20:00:49138} // namespace cc