1 // Copyright (c) 2012 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 "gpu/command_buffer/service/shader_manager.h"
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
15 Shader::Shader(GLuint service_id
, GLenum shader_type
)
17 service_id_(service_id
),
18 shader_type_(shader_type
),
25 void Shader::DoCompile(ShaderTranslatorInterface
* translator
,
26 TranslatedShaderSourceType type
) {
27 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
28 // glShaderSource and then glCompileShader.
29 const char* source_for_driver
= source_
.c_str();
31 valid_
= translator
->Translate(source_
,
41 signature_source_
= source_
;
42 source_for_driver
= translated_source_
.c_str();
45 glShaderSource(service_id_
, 1, &source_for_driver
, NULL
);
46 glCompileShader(service_id_
);
49 glGetShaderiv(service_id_
,
50 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
,
52 scoped_ptr
<char[]> buffer(new char[max_len
]);
54 glGetTranslatedShaderSourceANGLE(
55 service_id_
, max_len
, &len
, buffer
.get());
56 DCHECK(max_len
== 0 || len
< max_len
);
57 DCHECK(len
== 0 || buffer
[len
] == '\0');
58 translated_source_
= std::string(buffer
.get(), len
);
61 GLint status
= GL_FALSE
;
62 glGetShaderiv(service_id_
, GL_COMPILE_STATUS
, &status
);
63 if (status
!= GL_TRUE
) {
64 // We cannot reach here if we are using the shader translator.
65 // All invalid shaders must be rejected by the translator.
66 // All translated shaders must compile.
68 glGetShaderiv(service_id_
, GL_INFO_LOG_LENGTH
, &max_len
);
69 scoped_ptr
<char[]> buffer(new char[max_len
]);
71 glGetShaderInfoLog(service_id_
, max_len
, &len
, buffer
.get());
72 DCHECK(max_len
== 0 || len
< max_len
);
73 DCHECK(len
== 0 || buffer
[len
] == '\0');
75 log_info_
= std::string(buffer
.get(), len
);
76 LOG_IF(ERROR
, translator
)
77 << "Shader translator allowed/produced an invalid shader "
78 << "unless the driver is buggy:"
79 << "\n--original-shader--\n" << source_
80 << "\n--translated-shader--\n" << source_for_driver
81 << "\n--info-log--\n" << log_info_
;
85 void Shader::IncUseCount() {
89 void Shader::DecUseCount() {
91 DCHECK_GE(use_count_
, 0);
94 void Shader::MarkAsDeleted() {
95 DCHECK_NE(service_id_
, 0u);
99 const Shader::VariableInfo
* Shader::GetAttribInfo(
100 const std::string
& name
) const {
101 VariableMap::const_iterator it
= attrib_map_
.find(name
);
102 return it
!= attrib_map_
.end() ? &it
->second
: NULL
;
105 const std::string
* Shader::GetAttribMappedName(
106 const std::string
& original_name
) const {
107 for (VariableMap::const_iterator it
= attrib_map_
.begin();
108 it
!= attrib_map_
.end(); ++it
) {
109 if (it
->second
.name
== original_name
)
115 const std::string
* Shader::GetOriginalNameFromHashedName(
116 const std::string
& hashed_name
) const {
117 NameMap::const_iterator it
= name_map_
.find(hashed_name
);
118 if (it
!= name_map_
.end())
119 return &(it
->second
);
123 const Shader::VariableInfo
* Shader::GetUniformInfo(
124 const std::string
& name
) const {
125 VariableMap::const_iterator it
= uniform_map_
.find(name
);
126 return it
!= uniform_map_
.end() ? &it
->second
: NULL
;
129 const Shader::VariableInfo
* Shader::GetVaryingInfo(
130 const std::string
& name
) const {
131 VariableMap::const_iterator it
= varying_map_
.find(name
);
132 return it
!= varying_map_
.end() ? &it
->second
: NULL
;
135 ShaderManager::ShaderManager() {}
137 ShaderManager::~ShaderManager() {
138 DCHECK(shaders_
.empty());
141 void ShaderManager::Destroy(bool have_context
) {
142 while (!shaders_
.empty()) {
144 Shader
* shader
= shaders_
.begin()->second
.get();
145 if (!shader
->IsDeleted()) {
146 glDeleteShader(shader
->service_id());
147 shader
->MarkAsDeleted();
150 shaders_
.erase(shaders_
.begin());
154 Shader
* ShaderManager::CreateShader(
157 GLenum shader_type
) {
158 std::pair
<ShaderMap::iterator
, bool> result
=
159 shaders_
.insert(std::make_pair(
160 client_id
, scoped_refptr
<Shader
>(
161 new Shader(service_id
, shader_type
))));
162 DCHECK(result
.second
);
163 return result
.first
->second
.get();
166 Shader
* ShaderManager::GetShader(GLuint client_id
) {
167 ShaderMap::iterator it
= shaders_
.find(client_id
);
168 return it
!= shaders_
.end() ? it
->second
.get() : NULL
;
171 bool ShaderManager::GetClientId(GLuint service_id
, GLuint
* client_id
) const {
172 // This doesn't need to be fast. It's only used during slow queries.
173 for (ShaderMap::const_iterator it
= shaders_
.begin();
174 it
!= shaders_
.end(); ++it
) {
175 if (it
->second
->service_id() == service_id
) {
176 *client_id
= it
->first
;
183 bool ShaderManager::IsOwned(Shader
* shader
) {
184 for (ShaderMap::iterator it
= shaders_
.begin();
185 it
!= shaders_
.end(); ++it
) {
186 if (it
->second
.get() == shader
) {
193 void ShaderManager::RemoveShader(Shader
* shader
) {
195 DCHECK(IsOwned(shader
));
196 if (shader
->IsDeleted() && !shader
->InUse()) {
197 for (ShaderMap::iterator it
= shaders_
.begin();
198 it
!= shaders_
.end(); ++it
) {
199 if (it
->second
.get() == shader
) {
208 void ShaderManager::MarkAsDeleted(Shader
* shader
) {
210 DCHECK(IsOwned(shader
));
211 shader
->MarkAsDeleted();
212 RemoveShader(shader
);
215 void ShaderManager::UseShader(Shader
* shader
) {
217 DCHECK(IsOwned(shader
));
218 shader
->IncUseCount();
221 void ShaderManager::UnuseShader(Shader
* shader
) {
223 DCHECK(IsOwned(shader
));
224 shader
->DecUseCount();
225 RemoveShader(shader
);