summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gles2_cmd_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc475
1 files changed, 285 insertions, 190 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 05e5968..fc9032a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -729,7 +729,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
GLenum GetGLError();
// Sets our wrapper for the GLError.
- void SetGLError(GLenum error);
+ void SetGLError(GLenum error, const char* msg);
// Copies the real GL errors to the wrapper. This is so we can
// make sure there are no native GL errors before calling some GL function
@@ -882,6 +882,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
scoped_ptr<Callback0::Type> swap_buffers_callback_;
+ // The last error message set.
+ std::string last_error_;
+
DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl);
};
@@ -1673,7 +1676,7 @@ error::Error GLES2DecoderImpl::DoCommand(
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
// TODO(gman): Change output to something useful for NaCl.
- SetGLError(error);
+ SetGLError(error, NULL);
printf("GL ERROR b4: %s\n", GetCommandName(command));
}
}
@@ -1720,7 +1723,7 @@ bool GLES2DecoderImpl::ValidateGLenumCompressedTextureInternalFormat(GLenum) {
void GLES2DecoderImpl::DoActiveTexture(GLenum texture_unit) {
GLuint texture_index = texture_unit - GL_TEXTURE0;
if (texture_index > group_->max_texture_units()) {
- SetGLError(GL_INVALID_ENUM);
+ SetGLError(GL_INVALID_ENUM, "glActiveTexture: texture_unit out of range.");
return;
}
active_texture_unit_ = texture_index;
@@ -1743,7 +1746,8 @@ void GLES2DecoderImpl::DoBindBuffer(GLenum target, GLuint client_id) {
// Check the buffer exists
// Check that we are not trying to bind it to a different target.
if ((info->target() != 0 && info->target() != target)) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glBindBuffer: buffer bound to more than 1 target");
return;
}
if (info->target() == 0) {
@@ -1824,7 +1828,8 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
// Check the texture exists
// Check that we are not trying to bind it to a different target.
if (info->target() != 0 && info->target() != target) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glBindTexture: texture bound to more than 1 target.");
return;
}
if (info->target() == 0) {
@@ -1851,7 +1856,8 @@ void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
vertex_attrib_infos_[index].set_enabled(false);
glDisableVertexAttribArray(index);
} else {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE,
+ "glDisableVertexAttribArray: index out of range");
}
}
@@ -1860,14 +1866,16 @@ void GLES2DecoderImpl::DoEnableVertexAttribArray(GLuint index) {
vertex_attrib_infos_[index].set_enabled(true);
glEnableVertexAttribArray(index);
} else {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE,
+ "glEnableVertexAttribArray: index out of range");
}
}
void GLES2DecoderImpl::DoGenerateMipmap(GLenum target) {
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info || !info->MarkMipmapsGenerated()) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glGenerateMipmaps: Can not generate mips for npot textures");
return;
}
glGenerateMipmapEXT(target);
@@ -1963,7 +1971,7 @@ void GLES2DecoderImpl::DoGetProgramiv(
GLuint program_id, GLenum pname, GLint* params) {
ProgramManager::ProgramInfo* info = GetProgramInfo(program_id);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE, "glGetProgramiv: unknown program");
return;
}
info->GetProgramiv(pname, params);
@@ -1973,7 +1981,7 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocation(
uint32 immediate_data_size, const gles2::BindAttribLocation& c) {
ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
return error::kNoError;
}
GLuint index = static_cast<GLuint>(c.index);
@@ -1992,7 +2000,7 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocationImmediate(
uint32 immediate_data_size, const gles2::BindAttribLocationImmediate& c) {
ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
return error::kNoError;
}
GLuint index = static_cast<GLuint>(c.index);
@@ -2011,7 +2019,7 @@ error::Error GLES2DecoderImpl::HandleBindAttribLocationBucket(
uint32 immediate_data_size, const gles2::BindAttribLocationBucket& c) {
ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glBindAttribLocation: unknown program");
return error::kNoError;
}
GLuint index = static_cast<GLuint>(c.index);
@@ -2034,7 +2042,7 @@ error::Error GLES2DecoderImpl::HandleDeleteShader(
glDeleteShader(info->service_id());
RemoveShaderInfo(client_id);
} else {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glDeleteShader: unknown shader");
}
}
return error::kNoError;
@@ -2049,7 +2057,7 @@ error::Error GLES2DecoderImpl::HandleDeleteProgram(
glDeleteProgram(info->service_id());
RemoveProgramInfo(client_id);
} else {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glDeleteProgram: unknown program");
}
}
return error::kNoError;
@@ -2071,7 +2079,8 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
GLenum target, GLenum attachment, GLenum renderbuffertarget,
GLuint client_renderbuffer_id) {
if (!bound_framebuffer_) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer: no framebuffer bound");
return;
}
GLuint service_id = 0;
@@ -2079,7 +2088,8 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer(
RenderbufferManager::RenderbufferInfo* info =
GetRenderbufferInfo(client_renderbuffer_id);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glFramebufferRenderbuffer: unknown renderbuffer");
return;
}
service_id = info->service_id();
@@ -2099,14 +2109,16 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
GLenum target, GLenum attachment, GLenum textarget,
GLuint client_texture_id, GLint level) {
if (!bound_framebuffer_) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glFramebufferTexture2D: no framebuffer bound.");
return;
}
GLuint service_id = 0;
if (client_texture_id) {
TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glFramebufferTexture2D: unknown texture");
return;
}
service_id = info->service_id();
@@ -2117,7 +2129,8 @@ void GLES2DecoderImpl::DoFramebufferTexture2D(
void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
GLenum target, GLenum attachment, GLenum pname, GLint* params) {
if (!bound_framebuffer_) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glFramebufferAttachmentParameteriv: no framebuffer bound");
return;
}
glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
@@ -2126,7 +2139,8 @@ void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv(
void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
GLenum target, GLenum pname, GLint* params) {
if (!bound_renderbuffer_) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glGetRenderbufferParameteriv: no renderbuffer bound");
return;
}
glGetRenderbufferParameterivEXT(target, pname, params);
@@ -2135,7 +2149,8 @@ void GLES2DecoderImpl::DoGetRenderbufferParameteriv(
void GLES2DecoderImpl::DoRenderbufferStorage(
GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
if (!bound_renderbuffer_) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glGetRenderbufferStorage: no renderbuffer bound");
return;
}
glRenderbufferStorageEXT(target, internalformat, width, height);
@@ -2144,7 +2159,7 @@ void GLES2DecoderImpl::DoRenderbufferStorage(
void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
ProgramManager::ProgramInfo* info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glLinkProgram: unknown program");
return;
}
CopyRealGLErrorsToWrapper();
@@ -2152,7 +2167,7 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) {
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
info->Reset();
- SetGLError(error);
+ SetGLError(error, NULL);
} else {
info->Update();
}
@@ -2162,7 +2177,7 @@ void GLES2DecoderImpl::DoTexParameterf(
GLenum target, GLenum pname, GLfloat param) {
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glTexParameterf: unknown texture");
} else {
info->SetParameter(pname, static_cast<GLint>(param));
glTexParameterf(target, pname, param);
@@ -2173,7 +2188,7 @@ void GLES2DecoderImpl::DoTexParameteri(
GLenum target, GLenum pname, GLint param) {
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glTexParameteri: unknown texture");
} else {
info->SetParameter(pname, param);
glTexParameteri(target, pname, param);
@@ -2184,7 +2199,7 @@ void GLES2DecoderImpl::DoTexParameterfv(
GLenum target, GLenum pname, const GLfloat* params) {
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glTexParameterfv: unknown texture");
} else {
info->SetParameter(pname, *reinterpret_cast<const GLint*>(params));
glTexParameterfv(target, pname, params);
@@ -2195,7 +2210,7 @@ void GLES2DecoderImpl::DoTexParameteriv(
GLenum target, GLenum pname, const GLint* params) {
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glTexParameteriv: unknown texture");
} else {
info->SetParameter(pname, *params);
glTexParameteriv(target, pname, params);
@@ -2205,7 +2220,7 @@ void GLES2DecoderImpl::DoTexParameteriv(
void GLES2DecoderImpl::DoUniform1i(GLint location, GLint v0) {
if (!current_program_ || current_program_->IsDeleted()) {
// The program does not exist.
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glUniform1i: no program in use");
return;
}
current_program_->SetSamplers(location, 1, &v0);
@@ -2216,7 +2231,7 @@ void GLES2DecoderImpl::DoUniform1iv(
GLint location, GLsizei count, const GLint *value) {
if (!current_program_ || current_program_->IsDeleted()) {
// The program does not exist.
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glUniform1iv: no program in use");
return;
}
current_program_->SetSamplers(location, count, value);
@@ -2229,12 +2244,12 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program) {
if (program) {
info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glUseProgram: unknown program");
return;
}
if (!info->IsValid()) {
// Program was not linked successfully. (ie, glLinkProgram)
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glUseProgram: program not linked");
return;
}
service_id = info->service_id();
@@ -2262,14 +2277,18 @@ GLenum GLES2DecoderImpl::GetGLError() {
return error;
}
-void GLES2DecoderImpl::SetGLError(GLenum error) {
+void GLES2DecoderImpl::SetGLError(GLenum error, const char* msg) {
+ if (msg) {
+ last_error_ = msg;
+ DLOG(ERROR) << last_error_;
+ }
error_bits_ |= GLES2Util::GLErrorToErrorBit(error);
}
void GLES2DecoderImpl::CopyRealGLErrorsToWrapper() {
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR) {
- SetGLError(error);
+ SetGLError(error, NULL);
}
}
@@ -2386,7 +2405,8 @@ bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
}
DCHECK_LT(static_cast<GLuint>(location), group_->max_vertex_attribs());
if (!vertex_attrib_infos_[location].CanAccess(max_vertex_accessed)) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glDrawXXX: attempt to access out of range vertices");
return false;
}
}
@@ -2397,34 +2417,48 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
uint32 immediate_data_size, const gles2::DrawElements& c) {
if (!bound_element_array_buffer_ ||
bound_element_array_buffer_->IsDeleted()) {
- SetGLError(GL_INVALID_OPERATION);
- } else {
- GLenum mode = c.mode;
- GLsizei count = c.count;
- GLenum type = c.type;
- int32 offset = c.index_offset;
- if (count < 0 || offset < 0) {
- SetGLError(GL_INVALID_VALUE);
- } else if (!ValidateGLenumDrawMode(mode) ||
- !ValidateGLenumIndexType(type)) {
- SetGLError(GL_INVALID_ENUM);
- } else {
- GLuint max_vertex_accessed;
- if (!bound_element_array_buffer_->GetMaxValueForRange(
- offset, count, type, &max_vertex_accessed)) {
- SetGLError(GL_INVALID_OPERATION);
- } else {
- if (IsDrawValid(max_vertex_accessed)) {
- bool has_non_renderable_textures;
- SetBlackTextureForNonRenderableTextures(
- &has_non_renderable_textures);
- const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
- glDrawElements(mode, count, type, indices);
- if (has_non_renderable_textures) {
- RestoreStateForNonRenderableTextures();
- }
- }
- }
+ SetGLError(GL_INVALID_OPERATION,
+ "glDrawElements: No element array buffer bound");
+ return error::kNoError;
+ }
+
+ GLenum mode = c.mode;
+ GLsizei count = c.count;
+ GLenum type = c.type;
+ int32 offset = c.index_offset;
+ if (count < 0) {
+ SetGLError(GL_INVALID_VALUE, "glDrawElements: count < 0");
+ return error::kNoError;
+ }
+ if (offset < 0) {
+ SetGLError(GL_INVALID_VALUE, "glDrawElements: offset < 0");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumDrawMode(mode)) {
+ SetGLError(GL_INVALID_ENUM, "glDrawElements: mode GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumIndexType(type)) {
+ SetGLError(GL_INVALID_ENUM, "glDrawElements: type GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+
+ GLuint max_vertex_accessed;
+ if (!bound_element_array_buffer_->GetMaxValueForRange(
+ offset, count, type, &max_vertex_accessed)) {
+ SetGLError(GL_INVALID_OPERATION,
+ "glDrawElements: range out of bounds for buffer");
+ return error::kNoError;
+ }
+
+ if (IsDrawValid(max_vertex_accessed)) {
+ bool has_non_renderable_textures;
+ SetBlackTextureForNonRenderableTextures(
+ &has_non_renderable_textures);
+ const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
+ glDrawElements(mode, count, type, indices);
+ if (has_non_renderable_textures) {
+ RestoreStateForNonRenderableTextures();
}
}
return error::kNoError;
@@ -2434,13 +2468,19 @@ GLuint GLES2DecoderImpl::DoGetMaxValueInBuffer(
GLuint buffer_id, GLsizei count, GLenum type, GLuint offset) {
GLuint max_vertex_accessed = 0;
BufferManager::BufferInfo* info = GetBufferInfo(buffer_id);
- if (!info || info->target() != GL_ELEMENT_ARRAY_BUFFER) {
+ if (!info) {
// TODO(gman): Should this be a GL error or a command buffer error?
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE,
+ "GetMaxValueInBuffer: unknown buffer");
+ } else if (info->target() != GL_ELEMENT_ARRAY_BUFFER) {
+ // TODO(gman): Should this be a GL error or a command buffer error?
+ SetGLError(GL_INVALID_OPERATION,
+ "GetMaxValueInBuffer: buffer not element array buffer");
} else {
if (!info->GetMaxValueForRange(offset, count, type, &max_vertex_accessed)) {
// TODO(gman): Should this be a GL error or a command buffer error?
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "GetMaxValueInBuffer: range out of bounds for buffer");
}
}
return max_vertex_accessed;
@@ -2454,7 +2494,7 @@ error::Error GLES2DecoderImpl::ShaderSourceHelper(
GLuint client_id, const char* data, uint32 data_size) {
ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glShaderSource: unknown shader");
return error::kNoError;
}
// Note: We don't actually call glShaderSource here. We wait until
@@ -2499,7 +2539,7 @@ error::Error GLES2DecoderImpl::HandleShaderSourceBucket(
void GLES2DecoderImpl::DoCompileShader(GLuint client_id) {
ShaderManager::ShaderInfo* info = GetShaderInfo(client_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glCompileShader: unknown shader");
return;
}
// Translate GL ES 2.0 shader to Desktop GL shader and pass that to
@@ -2547,7 +2587,7 @@ void GLES2DecoderImpl::DoGetShaderiv(
GLuint shader, GLenum pname, GLint* params) {
ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE, "glGetShaderiv: unknown shader");
return;
}
if (pname == GL_SHADER_SOURCE_LENGTH) {
@@ -2561,12 +2601,13 @@ error::Error GLES2DecoderImpl::HandleGetShaderSource(
uint32 immediate_data_size, const gles2::GetShaderSource& c) {
GLuint shader = c.shader;
ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
+ uint32 bucket_id = static_cast<uint32>(c.bucket_id);
+ Bucket* bucket = CreateBucket(bucket_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ bucket->SetSize(0);
+ SetGLError(GL_INVALID_VALUE, "glGetShaderSource: unknown shader");
return error::kNoError;
}
- uint32 bucket_id = static_cast<uint32>(c.bucket_id);
- Bucket* bucket = CreateBucket(bucket_id);
bucket->SetFromString(info->source());
return error::kNoError;
}
@@ -2576,7 +2617,7 @@ error::Error GLES2DecoderImpl::HandleGetProgramInfoLog(
GLuint program = c.program;
ProgramManager::ProgramInfo* info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetProgramInfoLog: unknown program");
return error::kNoError;
}
uint32 bucket_id = static_cast<uint32>(c.bucket_id);
@@ -2595,7 +2636,7 @@ error::Error GLES2DecoderImpl::HandleGetShaderInfoLog(
GLuint shader = c.shader;
ShaderManager::ShaderInfo* info = GetShaderInfo(shader);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetShaderInfoLog: unknown shader");
return error::kNoError;
}
uint32 bucket_id = static_cast<uint32>(c.bucket_id);
@@ -2637,12 +2678,12 @@ void GLES2DecoderImpl::DoAttachShader(
GLuint program_client_id, GLint shader_client_id) {
ProgramManager::ProgramInfo* program_info = GetProgramInfo(program_client_id);
if (!program_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glAttachShader: unknown program");
return;
}
ShaderManager::ShaderInfo* shader_info = GetShaderInfo(shader_client_id);
if (!shader_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glAttachShader: unknown shader");
return;
}
glAttachShader(program_info->service_id(), shader_info->service_id());
@@ -2652,12 +2693,12 @@ void GLES2DecoderImpl::DoDetachShader(
GLuint program_client_id, GLint shader_client_id) {
ProgramManager::ProgramInfo* program_info = GetProgramInfo(program_client_id);
if (!program_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glDetachShader: unknown program");
return;
}
ShaderManager::ShaderInfo* shader_info = GetShaderInfo(shader_client_id);
if (!shader_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glDetachShader: unknown shader");
return;
}
glDetachShader(program_info->service_id(), shader_info->service_id());
@@ -2666,7 +2707,7 @@ void GLES2DecoderImpl::DoDetachShader(
void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
ProgramManager::ProgramInfo* info = GetProgramInfo(program_client_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glValidateProgram: unknown program");
return;
}
glValidateProgram(info->service_id());
@@ -2674,42 +2715,63 @@ void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
- if (bound_array_buffer_ && !bound_array_buffer_->IsDeleted()) {
- GLuint indx = c.indx;
- GLint size = c.size;
- GLenum type = c.type;
- GLboolean normalized = c.normalized;
- GLsizei stride = c.stride;
- GLsizei offset = c.offset;
- const void* ptr = reinterpret_cast<const void*>(offset);
- if (!ValidateGLenumVertexAttribType(type) ||
- !ValidateGLintVertexAttribSize(size)) {
- SetGLError(GL_INVALID_ENUM);
- return error::kNoError;
- }
- if (indx >= group_->max_vertex_attribs() ||
- stride < 0 ||
- offset < 0) {
- SetGLError(GL_INVALID_VALUE);
- return error::kNoError;
- }
- GLsizei component_size =
- GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
- GLsizei real_stride = stride != 0 ? stride : component_size * size;
- if (offset % component_size > 0) {
- SetGLError(GL_INVALID_VALUE);
- return error::kNoError;
- }
- vertex_attrib_infos_[indx].SetInfo(
- bound_array_buffer_,
- size,
- type,
- real_stride,
- offset);
- glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
- } else {
- SetGLError(GL_INVALID_VALUE);
+ if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
+ SetGLError(GL_INVALID_VALUE,
+ "glVertexAttribPointer: no array buffer bound");
+ return error::kNoError;
}
+
+ GLuint indx = c.indx;
+ GLint size = c.size;
+ GLenum type = c.type;
+ GLboolean normalized = c.normalized;
+ GLsizei stride = c.stride;
+ GLsizei offset = c.offset;
+ const void* ptr = reinterpret_cast<const void*>(offset);
+ if (!ValidateGLenumVertexAttribType(type)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glVertexAttribPointer: type GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLintVertexAttribSize(size)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glVertexAttribPointer: size GL_INVALID_VALUE");
+ return error::kNoError;
+ }
+ if (indx >= group_->max_vertex_attribs()) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttribPointer: index out of range");
+ return error::kNoError;
+ }
+ if (stride < 0) {
+ SetGLError(GL_INVALID_VALUE,
+ "glVertexAttribPointer: stride < 0");
+ return error::kNoError;
+ }
+ if (stride > 255) {
+ SetGLError(GL_INVALID_VALUE,
+ "glVertexAttribPointer: stride > 255");
+ return error::kNoError;
+ }
+ if (offset < 0) {
+ SetGLError(GL_INVALID_VALUE,
+ "glVertexAttribPointer: offset < 0");
+ return error::kNoError;
+ }
+ GLsizei component_size =
+ GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
+ GLsizei real_stride = stride != 0 ? stride : component_size * size;
+ if (offset % component_size > 0) {
+ SetGLError(GL_INVALID_VALUE,
+ "glVertexAttribPointer: stride not valid for type");
+ return error::kNoError;
+ }
+ vertex_attrib_infos_[indx].SetInfo(
+ bound_array_buffer_,
+ size,
+ type,
+ real_stride,
+ offset);
+ glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
return error::kNoError;
}
@@ -2722,7 +2784,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
GLenum format = c.format;
GLenum type = c.type;
if (width < 0 || height < 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions < 0");
return error::kNoError;
}
typedef gles2::ReadPixels::Result Result;
@@ -2739,9 +2801,12 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
return error::kOutOfBounds;
}
- if (!ValidateGLenumReadPixelFormat(format) ||
- !ValidateGLenumPixelType(type)) {
- SetGLError(GL_INVALID_ENUM);
+ if (!ValidateGLenumReadPixelFormat(format)) {
+ SetGLError(GL_INVALID_ENUM, "glReadPixels: format GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumPixelType(type)) {
+ SetGLError(GL_INVALID_ENUM, "glReadPixels: type GL_INVALID_ENUM");
return error::kNoError;
}
if (width == 0 || height == 0) {
@@ -2756,7 +2821,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
GLint max_x;
GLint max_y;
if (!SafeAdd(x, width, &max_x) || !SafeAdd(y, height, &max_y)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
return error::kNoError;
}
@@ -2766,18 +2831,18 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
uint32 temp_size;
if (!GLES2Util::ComputeImageDataSize(
width, 1, format, type, pack_alignment_, &temp_size)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
return error::kNoError;
}
GLsizei unpadded_row_size = temp_size;
if (!GLES2Util::ComputeImageDataSize(
width, 2, format, type, pack_alignment_, &temp_size)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
return error::kNoError;
}
GLsizei padded_row_size = temp_size - unpadded_row_size;
if (padded_row_size < 0 || unpadded_row_size < 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
return error::kNoError;
}
@@ -2785,7 +2850,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
uint32 dest_row_offset;
if (!GLES2Util::ComputeImageDataSize(
dest_x_offset, 1, format, type, pack_alignment_, &dest_row_offset)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glReadPixels: dimensions out of range");
return error::kNoError;
}
@@ -2814,7 +2879,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
if (error == GL_NO_ERROR) {
*result = true;
} else {
- SetGLError(error);
+ SetGLError(error, NULL);
}
return error::kNoError;
}
@@ -2824,11 +2889,11 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(
GLenum pname = c.pname;
GLenum param = c.param;
if (!ValidateGLenumPixelStore(pname)) {
- SetGLError(GL_INVALID_ENUM);
+ SetGLError(GL_INVALID_ENUM, "glPixelStorei: pname GL_INVALID_ENUM");
return error::kNoError;
}
if (!ValidateGLintPixelStoreAlignment(param)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glPixelSTore: param GL_INVALID_VALUE");
return error::kNoError;
}
glPixelStorei(pname, param);
@@ -2852,11 +2917,11 @@ error::Error GLES2DecoderImpl::GetAttribLocationHelper(
const std::string& name_str) {
ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetAttribLocation: unknown program");
return error::kNoError;
}
if (!info->IsValid()) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glGetAttribLocation: program not linked");
return error::kNoError;
}
GLint* location = GetSharedMemoryAs<GLint*>(
@@ -2916,11 +2981,12 @@ error::Error GLES2DecoderImpl::GetUniformLocationHelper(
const std::string& name_str) {
ProgramManager::ProgramInfo* info = GetProgramInfo(client_id);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetUniformLocation: unknown program");
return error::kNoError;
}
if (!info->IsValid()) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glGetUniformLocation: program not linked");
return error::kNoError;
}
GLint* location = GetSharedMemoryAs<GLint*>(
@@ -2979,7 +3045,7 @@ error::Error GLES2DecoderImpl::HandleGetString(
uint32 immediate_data_size, const gles2::GetString& c) {
GLenum name = static_cast<GLenum>(c.name);
if (!ValidateGLenumStringType(name)) {
- SetGLError(GL_INVALID_ENUM);
+ SetGLError(GL_INVALID_ENUM, "glGetString: name GL_INVALID_ENUM");
return error::kNoError;
}
const char* gl_str = reinterpret_cast<const char*>(glGetString(name));
@@ -3005,18 +3071,21 @@ error::Error GLES2DecoderImpl::HandleGetString(
void GLES2DecoderImpl::DoBufferData(
GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
- if (!ValidateGLenumBufferTarget(target) ||
- !ValidateGLenumBufferUsage(usage)) {
- SetGLError(GL_INVALID_ENUM);
+ if (!ValidateGLenumBufferTarget(target)) {
+ SetGLError(GL_INVALID_ENUM, "glBufferData: target GL_INVALID_ENUM");
+ return;
+ }
+ if (!ValidateGLenumBufferUsage(usage)) {
+ SetGLError(GL_INVALID_ENUM, "glBufferData: usage GL_INVALID_ENUM");
return;
}
if (size < 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glBufferData: size < 0");
return;
}
BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE, "glBufferData: unknown buffer");
return;
}
// Clear the buffer to 0 if no initial data was passed in.
@@ -3030,7 +3099,7 @@ void GLES2DecoderImpl::DoBufferData(
glBufferData(target, size, data, usage);
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
- SetGLError(error);
+ SetGLError(error, NULL);
} else {
info->SetSize(size);
info->SetRange(0, size, data);
@@ -3073,11 +3142,11 @@ void GLES2DecoderImpl::DoBufferSubData(
GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
BufferManager::BufferInfo* info = GetBufferInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE, "glBufferSubData: unknown buffer");
return;
}
if (!info->SetRange(offset, size, data)) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glBufferSubData: out of range");
} else {
glBufferSubData(target, offset, size, data);
}
@@ -3093,19 +3162,26 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage2D(
GLsizei image_size,
const void* data) {
// TODO(gman): Validate image_size is correct for width, height and format.
- if (!ValidateGLenumTextureTarget(target) ||
- !ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
- SetGLError(GL_INVALID_ENUM);
+ if (!ValidateGLenumTextureTarget(target)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glCompressedTexImage2D: target GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumCompressedTextureInternalFormat(internal_format)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glCompressedTexImage2D: internal_format GL_INVALID_ENUM");
return error::kNoError;
}
if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
border != 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE,
+ "glCompressedTexImage2D: dimensions out of range");
return error::kNoError;
}
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_VALUE,
+ "glCompressedTexImage2D: unknown texture target");
return error::kNoError;
}
scoped_array<int8> zero;
@@ -3173,21 +3249,32 @@ error::Error GLES2DecoderImpl::DoTexImage2D(
GLenum type,
const void* pixels,
uint32 pixels_size) {
- if (!ValidateGLenumTextureTarget(target) ||
- !ValidateGLenumTextureFormat(internal_format) ||
- !ValidateGLenumTextureFormat(format) ||
- !ValidateGLenumPixelType(type)) {
- SetGLError(GL_INVALID_ENUM);
+ if (!ValidateGLenumTextureTarget(target)) {
+ SetGLError(GL_INVALID_ENUM, "glTexImage2D: target GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumTextureFormat(internal_format)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glTexImage2D: internal_format GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumTextureFormat(format)) {
+ SetGLError(GL_INVALID_ENUM, "glTexImage2D: format GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumPixelType(type)) {
+ SetGLError(GL_INVALID_ENUM, "glTexImage2D: type GL_INVALID_ENUM");
return error::kNoError;
}
if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
border != 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glTexImage2D: dimensions out of range");
return error::kNoError;
}
TextureManager::TextureInfo* info = GetTextureInfoForTarget(target);
if (!info) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION,
+ "glTexImage2D: unknown texture for target");
return error::kNoError;
}
scoped_array<int8> zero;
@@ -3275,11 +3362,13 @@ error::Error GLES2DecoderImpl::HandleGetVertexAttribPointerv(
return error::kInvalidArguments;
}
if (!ValidateGLenumVertexPointer(pname)) {
- SetGLError(GL_INVALID_ENUM);
+ SetGLError(GL_INVALID_ENUM,
+ "glGetVertexAttribPointerv: pname GL_INVALID_ENUM");
return error::kNoError;
}
if (index >= group_->max_vertex_attribs()) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE,
+ "glGetVertexAttribPointerv: index out of range.");
return error::kNoError;
}
result->SetNumResults(1);
@@ -3305,24 +3394,24 @@ bool GLES2DecoderImpl::GetUniformSetup(
result->SetNumResults(0);
ProgramManager::ProgramInfo* info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetUniform: unknown program");
return false;
}
if (!info->IsValid()) {
// Program was not linked successfully. (ie, glLinkProgram)
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glGetUniform: program not linked");
return false;
}
*service_id = info->service_id();
GLenum type;
if (!info->GetUniformTypeByLocation(location, &type)) {
// No such location.
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown location");
return false;
}
GLsizei size = GLES2Util::GetGLDataTypeSizeForUniforms(type);
if (size == 0) {
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glGetUniform: unknown type");
return false;
}
result = GetSharedMemoryAs<SizedResult<GLint>*>(
@@ -3385,29 +3474,35 @@ error::Error GLES2DecoderImpl::HandleGetShaderPrecisionFormat(
if (result->success != 0) {
return error::kInvalidArguments;
}
- if (!ValidateGLenumShaderType(shader_type) ||
- !ValidateGLenumShaderPrecision(precision_type)) {
- SetGLError(GL_INVALID_ENUM);
- } else {
- result->success = 1; // true
- switch (precision_type) {
- case GL_LOW_INT:
- case GL_MEDIUM_INT:
- case GL_HIGH_INT:
- result->min_range = -31;
- result->max_range = 31;
- result->precision = 0;
- case GL_LOW_FLOAT:
- case GL_MEDIUM_FLOAT:
- case GL_HIGH_FLOAT:
- result->min_range = -62;
- result->max_range = 62;
- result->precision = -16;
- break;
- default:
- NOTREACHED();
- break;
- }
+ if (!ValidateGLenumShaderType(shader_type)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glGetShaderPrecisionFormat: shader_type GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+ if (!ValidateGLenumShaderPrecision(precision_type)) {
+ SetGLError(GL_INVALID_ENUM,
+ "glGetShaderPrecisionFormat: precision_type GL_INVALID_ENUM");
+ return error::kNoError;
+ }
+
+ result->success = 1; // true
+ switch (precision_type) {
+ case GL_LOW_INT:
+ case GL_MEDIUM_INT:
+ case GL_HIGH_INT:
+ result->min_range = -31;
+ result->max_range = 31;
+ result->precision = 0;
+ case GL_LOW_FLOAT:
+ case GL_MEDIUM_FLOAT:
+ case GL_HIGH_FLOAT:
+ result->min_range = -62;
+ result->max_range = 62;
+ result->precision = -16;
+ break;
+ default:
+ NOTREACHED();
+ break;
}
return error::kNoError;
}
@@ -3417,7 +3512,7 @@ error::Error GLES2DecoderImpl::HandleGetAttachedShaders(
uint32 result_size = c.result_size;
ProgramManager::ProgramInfo* info = GetProgramInfo(c.program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetAttachedShaders: unknown program");
return error::kNoError;
}
typedef gles2::GetAttachedShaders::Result Result;
@@ -3462,18 +3557,18 @@ error::Error GLES2DecoderImpl::HandleGetActiveUniform(
}
ProgramManager::ProgramInfo* info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: unknown program");
return error::kNoError;
}
if (!info->IsValid()) {
// Program was not linked successfully. (ie, glLinkProgram)
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_OPERATION, "glGetActiveUniform: program not linked");
return error::kNoError;
}
const ProgramManager::ProgramInfo::UniformInfo* uniform_info =
info->GetUniformInfo(index);
if (!uniform_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetActiveUniform: index out of range");
return error::kNoError;
}
result->success = 1; // true.
@@ -3501,18 +3596,18 @@ error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
}
ProgramManager::ProgramInfo* info = GetProgramInfo(program);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: unknown program");
return error::kNoError;
}
if (!info->IsValid()) {
// Program was not linked successfully. (ie, glLinkProgram)
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glGetActiveAttrib: program not linked");
return error::kNoError;
}
const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
info->GetAttribInfo(index);
if (!attrib_info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glGetActiveAttrib: index out of range");
return error::kNoError;
}
result->success = 1; // true.
@@ -3526,17 +3621,17 @@ error::Error GLES2DecoderImpl::HandleGetActiveAttrib(
error::Error GLES2DecoderImpl::HandleShaderBinary(
uint32 immediate_data_size, const gles2::ShaderBinary& c) {
#if 1 // No binary shader support.
- SetGLError(GL_INVALID_OPERATION);
+ SetGLError(GL_INVALID_OPERATION, "glShaderBinary: not supported");
return error::kNoError;
#else
GLsizei n = static_cast<GLsizei>(c.n);
if (n < 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glShaderBinary: n < 0");
return error::kNoError;
}
GLsizei length = static_cast<GLsizei>(c.length);
if (length < 0) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glShaderBinary: length < 0");
return error::kNoError;
}
uint32 data_size;
@@ -3555,7 +3650,7 @@ error::Error GLES2DecoderImpl::HandleShaderBinary(
for (GLsizei ii = 0; ii < n; ++ii) {
ShaderManager::ShaderInfo* info = GetShaderInfo(shaders[ii]);
if (!info) {
- SetGLError(GL_INVALID_VALUE);
+ SetGLError(GL_INVALID_VALUE, "glShaderBinary: unknown shader");
return error::kNoError;
}
service_ids[ii] = info->service_id();