DISALLOW_COPY_AND_ASSIGN(ScopedGLErrorSuppressor);
};
-// Temporarily changes a decoder's bound 2D texture and restore it when this
+// Temporarily changes a decoder's bound texture and restore it when this
// object goes out of scope. Also temporarily switches to using active texture
// unit zero in case the client has changed that to something invalid.
-class ScopedTexture2DBinder {
+class ScopedTextureBinder {
public:
- ScopedTexture2DBinder(ContextState* state, GLuint id);
- ~ScopedTexture2DBinder();
+ ScopedTextureBinder(ContextState* state, GLuint id, GLenum target);
+ ~ScopedTextureBinder();
private:
ContextState* state_;
- DISALLOW_COPY_AND_ASSIGN(ScopedTexture2DBinder);
+ GLenum target_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedTextureBinder);
};
// Temporarily changes a decoder's bound render buffer and restore it when this
virtual void Destroy(bool have_context) OVERRIDE;
virtual void SetSurface(
const scoped_refptr<gfx::GLSurface>& surface) OVERRIDE;
- virtual bool ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
+ virtual void ProduceFrontBuffer(const Mailbox& mailbox) OVERRIDE;
virtual bool ResizeOffscreenFrameBuffer(const gfx::Size& size) OVERRIDE;
void UpdateParentTextureInfo();
virtual bool MakeCurrent() OVERRIDE;
virtual void RestoreFramebufferBindings() const OVERRIDE;
virtual void RestoreTextureState(unsigned service_id) const OVERRIDE;
+ virtual void ClearAllAttributes() const OVERRIDE;
+ virtual void RestoreAllAttributes() const OVERRIDE;
+
virtual QueryManager* GetQueryManager() OVERRIDE {
return query_manager_.get();
}
ERRORSTATE_CLEAR_REAL_GL_ERRORS(error_state_, function_name_);
}
-static void RestoreCurrentTexture2DBindings(ContextState* state) {
+static void RestoreCurrentTextureBindings(ContextState* state, GLenum target) {
TextureUnit& info = state->texture_units[0];
GLuint last_id;
- if (info.bound_texture_2d.get()) {
- last_id = info.bound_texture_2d->service_id();
+ scoped_refptr<TextureRef> texture_ref;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ texture_ref = info.bound_texture_2d;
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ texture_ref = info.bound_texture_cube_map;
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ texture_ref = info.bound_texture_external_oes;
+ break;
+ case GL_TEXTURE_RECTANGLE_ARB:
+ texture_ref = info.bound_texture_rectangle_arb;
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ if (texture_ref.get()) {
+ last_id = texture_ref->service_id();
} else {
last_id = 0;
}
- glBindTexture(GL_TEXTURE_2D, last_id);
+ glBindTexture(target, last_id);
glActiveTexture(GL_TEXTURE0 + state->active_texture_unit);
}
-ScopedTexture2DBinder::ScopedTexture2DBinder(ContextState* state,
- GLuint id)
- : state_(state) {
+ScopedTextureBinder::ScopedTextureBinder(ContextState* state,
+ GLuint id,
+ GLenum target)
+ : state_(state),
+ target_(target) {
ScopedGLErrorSuppressor suppressor(
- "ScopedTexture2DBinder::ctor", state_->GetErrorState());
+ "ScopedTextureBinder::ctor", state_->GetErrorState());
// TODO(apatrick): Check if there are any other states that need to be reset
// before binding a new texture.
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, id);
+ glBindTexture(target, id);
}
-ScopedTexture2DBinder::~ScopedTexture2DBinder() {
+ScopedTextureBinder::~ScopedTextureBinder() {
ScopedGLErrorSuppressor suppressor(
- "ScopedTexture2DBinder::dtor", state_->GetErrorState());
- RestoreCurrentTexture2DBindings(state_);
+ "ScopedTextureBinder::dtor", state_->GetErrorState());
+ RestoreCurrentTextureBindings(state_, target_);
}
ScopedRenderBufferBinder::ScopedRenderBufferBinder(ContextState* state,
state_->GetErrorState());
Destroy();
glGenTextures(1, &id_);
- ScopedTexture2DBinder binder(state_, id_);
+ ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
DCHECK_NE(id_, 0u);
ScopedGLErrorSuppressor suppressor("BackTexture::AllocateStorage",
state_->GetErrorState());
- ScopedTexture2DBinder binder(state_, id_);
+ ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
uint32 image_size = 0;
GLES2Util::ComputeImageDataSizes(
size.width(), size.height(), format, GL_UNSIGNED_BYTE, 8, &image_size,
DCHECK_NE(id_, 0u);
ScopedGLErrorSuppressor suppressor("BackTexture::Copy",
state_->GetErrorState());
- ScopedTexture2DBinder binder(state_, id_);
+ ScopedTextureBinder binder(state_, id_, GL_TEXTURE_2D);
glCopyTexImage2D(GL_TEXTURE_2D,
0, // level
format,
driver_bug_workarounds |= SH_INIT_GL_POSITION;
if (workarounds().unfold_short_circuit_as_ternary_operation)
driver_bug_workarounds |= SH_UNFOLD_SHORT_CIRCUIT;
+ if (workarounds().init_varyings_without_static_use)
+ driver_bug_workarounds |= SH_INIT_VARYINGS_WITHOUT_STATIC_USE;
ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
vertex_translator_ = cache->GetTranslator(
RestoreCurrentFramebufferBindings();
}
-bool GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
- if (!offscreen_saved_color_texture_.get())
- return false;
+void GLES2DecoderImpl::ProduceFrontBuffer(const Mailbox& mailbox) {
+ if (!offscreen_saved_color_texture_.get()) {
+ LOG(ERROR) << "Called ProduceFrontBuffer on a non-offscreen context";
+ return;
+ }
if (!offscreen_saved_color_texture_info_.get()) {
GLuint service_id = offscreen_saved_color_texture_->id();
offscreen_saved_color_texture_info_ = TextureRef::Create(
GL_TEXTURE_2D);
UpdateParentTextureInfo();
}
- gpu::gles2::MailboxName name;
- memcpy(name.key, mailbox.name, sizeof(mailbox.name));
- return mailbox_manager()->ProduceTexture(
- GL_TEXTURE_2D, name, offscreen_saved_color_texture_info_->texture());
+ mailbox_manager()->ProduceTexture(
+ GL_TEXTURE_2D, mailbox, offscreen_saved_color_texture_info_->texture());
}
bool GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
buffer = GetBuffer(client_id);
if (!buffer) {
if (!group_->bind_generates_resource()) {
- LOG(ERROR) << "glBindBuffer: id not generated by glGenBuffers";
- current_decoder_error_ = error::kGenericError;
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBindBuffer",
+ "id not generated by glGenBuffers");
return;
}
}
}
+void GLES2DecoderImpl::ClearAllAttributes() const {
+ for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
+ if (i != 0) // Never disable attribute 0
+ glDisableVertexAttribArray(i);
+ if(features().angle_instanced_arrays)
+ glVertexAttribDivisorANGLE(i, 0);
+ }
+}
+
+void GLES2DecoderImpl::RestoreAllAttributes() const {
+ for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
+ RestoreAttribute(i);
+}
+
void GLES2DecoderImpl::OnFboChanged() const {
if (workarounds().restore_scissor_on_fbo_change)
state_.fbo_binding_for_scissor_workaround_dirty_ = true;
framebuffer = GetFramebuffer(client_id);
if (!framebuffer) {
if (!group_->bind_generates_resource()) {
- LOG(ERROR)
- << "glBindFramebuffer: id not generated by glGenFramebuffers";
- current_decoder_error_ = error::kGenericError;
- return;
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBindFramebuffer",
+ "id not generated by glGenFramebuffers");
+ return;
}
// It's a new id so make a framebuffer framebuffer for it.
renderbuffer = GetRenderbuffer(client_id);
if (!renderbuffer) {
if (!group_->bind_generates_resource()) {
- LOG(ERROR)
- << "glBindRenderbuffer: id not generated by glGenRenderbuffers";
- current_decoder_error_ = error::kGenericError;
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBindRenderbuffer",
+ "id not generated by glGenRenderbuffers");
return;
}
}
renderbuffer->MarkAsValid();
}
- LogClientServiceForInfo(renderbuffer, client_id, "glBindRenerbuffer");
+ LogClientServiceForInfo(renderbuffer, client_id, "glBindRenderbuffer");
state_.bound_renderbuffer = renderbuffer;
glBindRenderbufferEXT(target, service_id);
}
texture_ref = GetTexture(client_id);
if (!texture_ref) {
if (!group_->bind_generates_resource()) {
- LOG(ERROR) << "glBindTexture: id not generated by glGenTextures";
- current_decoder_error_ = error::kGenericError;
- return;
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBindTexture",
+ "id not generated by glGenTextures");
+ return;
}
// It's a new id so make a texture texture for it.
if (!framebuffer) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
- "glFramebufferAttachmentParameteriv", "no framebuffer bound");
+ "glGetFramebufferAttachmentParameteriv", "no framebuffer bound");
return;
}
if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) {
width, height, samples, internalformat, &estimated_size)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
- "glRenderbufferStorageMultsample", "dimensions too large");
+ "glRenderbufferStorageMultisample", "dimensions too large");
return false;
}
if (!EnsureGPUMemoryAvailable(estimated_size)) {
LOCAL_SET_GL_ERROR(
GL_OUT_OF_MEMORY,
- "glRenderbufferStorageMultsample", "out of memory");
+ "glRenderbufferStorageMultisample", "out of memory");
return false;
}
if (program->Link(shader_manager(),
vertex_translator,
fragment_translator,
- feature_info_.get(),
+ workarounds().count_all_in_varyings_packing ?
+ Program::kCountAll : Program::kCountOnlyStaticallyUsed,
shader_cache_callback_)) {
if (program == state_.current_program.get()) {
- if (workarounds().use_current_program_after_successful_link) {
+ if (workarounds().use_current_program_after_successful_link)
glUseProgram(program->service_id());
- }
- program_manager()->ClearUniforms(program);
+ if (workarounds().clear_uniforms_before_first_program_use)
+ program_manager()->ClearUniforms(program);
}
}
};
GLsizei count = 1;
GLint real_location = -1;
if (!PrepForSetUniformByLocation(
- fake_location, "glUniform1iv", valid_int_vec1_base_info,
+ fake_location, "glUniform1i", valid_int_vec1_base_info,
&real_location, &type, &count)) {
return;
}
glUseProgram(service_id);
if (state_.current_program.get()) {
program_manager()->UseProgram(state_.current_program.get());
+ if (workarounds().clear_uniforms_before_first_program_use)
+ program_manager()->ClearUniforms(program);
}
}
void GLES2DecoderImpl::DoWillUseTexImageIfNeeded(
Texture* texture, GLenum textarget) {
- // This might be supported in the future.
- if (textarget != GL_TEXTURE_2D)
- return;
// Image is already in use if texture is attached to a framebuffer.
if (texture && !texture->IsAttachedToFramebuffer()) {
gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
GetErrorState());
glBindTexture(textarget, texture->service_id());
image->WillUseTexImage();
- RestoreCurrentTexture2DBindings(&state_);
+ RestoreCurrentTextureBindings(&state_, textarget);
}
}
}
void GLES2DecoderImpl::DoDidUseTexImageIfNeeded(
Texture* texture, GLenum textarget) {
- // This might be supported in the future.
- if (textarget != GL_TEXTURE_2D)
- return;
// Image is still in use if texture is attached to a framebuffer.
if (texture && !texture->IsAttachedToFramebuffer()) {
gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
GetErrorState());
glBindTexture(textarget, texture->service_id());
image->DidUseTexImage();
- RestoreCurrentTexture2DBindings(&state_);
+ RestoreCurrentTextureBindings(&state_, textarget);
}
}
}
continue;
}
- Texture* texture = texture_ref->texture();
- gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
- if (image && !texture->IsAttachedToFramebuffer()) {
- ScopedGLErrorSuppressor suppressor(
- "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
- textures_set = true;
- glActiveTexture(GL_TEXTURE0 + texture_unit_index);
- image->WillUseTexImage();
- continue;
+ if (textarget != GL_TEXTURE_CUBE_MAP) {
+ Texture* texture = texture_ref->texture();
+ gfx::GLImage* image = texture->GetLevelImage(textarget, 0);
+ if (image && !texture->IsAttachedToFramebuffer()) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::PrepareTexturesForRender", GetErrorState());
+ textures_set = true;
+ glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+ image->WillUseTexImage();
+ continue;
+ }
}
}
// else: should this be an error?
continue;
}
- Texture* texture = texture_ref->texture();
- gfx::GLImage* image =
- texture->GetLevelImage(texture_unit.bind_target, 0);
- if (image && !texture->IsAttachedToFramebuffer()) {
- ScopedGLErrorSuppressor suppressor(
- "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
- glActiveTexture(GL_TEXTURE0 + texture_unit_index);
- image->DidUseTexImage();
- continue;
+ if (texture_unit.bind_target != GL_TEXTURE_CUBE_MAP) {
+ Texture* texture = texture_ref->texture();
+ gfx::GLImage* image =
+ texture->GetLevelImage(texture_unit.bind_target, 0);
+ if (image && !texture->IsAttachedToFramebuffer()) {
+ ScopedGLErrorSuppressor suppressor(
+ "GLES2DecoderImpl::RestoreStateForTextures", GetErrorState());
+ glActiveTexture(GL_TEXTURE0 + texture_unit_index);
+ image->DidUseTexImage();
+ continue;
+ }
}
}
}
vertex_translator_.get() : fragment_translator_.get();
}
- program_manager()->DoCompileShader(shader, translator, feature_info_.get());
+ program_manager()->DoCompileShader(
+ shader,
+ translator,
+ feature_info_->feature_flags().angle_translated_shader_source ?
+ ProgramManager::kANGLE : ProgramManager::kGL);
};
void GLES2DecoderImpl::DoGetShaderiv(
uint32 bucket_id = static_cast<uint32>(c.bucket_id);
Bucket* bucket = CreateBucket(bucket_id);
Shader* shader = GetShaderInfoNotProgram(
- shader_id, "glTranslatedGetShaderSourceANGLE");
+ shader_id, "glGetTranslatedShaderSourceANGLE");
if (!shader) {
bucket->SetSize(0);
return error::kNoError;
return error::kNoError;
}
- LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixel");
+ LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glReadPixels");
ScopedResolvedFrameBufferBinder binder(this, false, true);
case GL_UNPACK_ALIGNMENT:
if (!validators_->pixel_store_alignment.IsValid(param)) {
LOCAL_SET_GL_ERROR(
- GL_INVALID_VALUE, "glPixelStore", "param GL_INVALID_VALUE");
+ GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE");
return error::kNoError;
}
break;
return error::kNoError;
}
Program* program = GetProgramInfoNotShader(
- client_id, "glUniformLocation");
+ client_id, "glGetUniformLocation");
if (!program) {
return error::kNoError;
}
case GL_ETC1_RGB8_OES: {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name,
- "TexsubImage2d not supported for ECT1_RGB8_OES textures");
+ "not supported for ECT1_RGB8_OES textures");
return false;
}
default:
return;
}
if (!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glCompressedTexSubImage2D", "bad dimensions.");
return;
GL_INVALID_VALUE, "glCopyTexImage2D", "dimensions out of range");
return;
}
- if (!texture_manager()->ValidateTextureParameters(
- state_.GetErrorState(), "glCopyTexImage2D", target, internal_format,
- GL_UNSIGNED_BYTE, level)) {
+ if (!texture_manager()->ValidateFormatAndTypeCombination(
+ state_.GetErrorState(), "glCopyTexImage2D", internal_format,
+ GL_UNSIGNED_BYTE)) {
return;
}
GLenum format = 0;
if (!texture->GetLevelType(target, level, &type, &format) ||
!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glCopyTexSubImage2D", "bad dimensions.");
return;
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "height < 0");
return false;
}
- if (!validators_->texture_format.IsValid(format)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, format, "format");
- return false;
- }
- if (!validators_->pixel_type.IsValid(type)) {
- LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, type, "type");
- return false;
- }
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
if (!texture_ref) {
GL_INVALID_OPERATION, function_name, "level does not exist.");
return false;
}
- if (format != internal_format) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- function_name, "format does not match internal format.");
+ if (!texture_manager()->ValidateTextureParameters(state_.GetErrorState(),
+ function_name, format, type, internal_format, level)) {
return false;
}
if (type != current_type) {
return false;
}
if (!texture->ValidForTexture(
- target, level, xoffset, yoffset, width, height, format, type)) {
+ target, level, xoffset, yoffset, width, height, type)) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name, "bad dimensions.");
return false;
}
uint32 num = util_.GLGetNumValuesReturned(enums[ii]);
if (num == 0) {
LOCAL_SET_GL_ERROR_INVALID_ENUM(
- "glGetMulitpleCHROMIUM", enums[ii], "pname");
+ "glGetMultipleCHROMIUM", enums[ii], "pname");
return error::kNoError;
}
// Num will never be more than 4.
if (result_size != static_cast<uint32>(c.size)) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE,
- "glGetMulitpleCHROMIUM", "bad size GL_INVALID_VALUE");
+ "glGetMultipleCHROMIUM", "bad size GL_INVALID_VALUE");
return error::kNoError;
}
int source_width, source_height, dest_width, dest_height;
- if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) {
- gfx::GLImage* image =
- source_texture->GetLevelImage(source_texture->target(), 0);
- if (!image) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glCopyTextureChromium", "No external image");
- return;
- }
+ gfx::GLImage* image =
+ source_texture->GetLevelImage(source_texture->target(), 0);
+ if (image) {
gfx::Size size = image->GetSize();
source_width = size.width();
source_height = size.height();
}
}
+ // Clear the source texture if necessary.
+ if (!texture_manager()->ClearTextureLevel(
+ this, source_texture_ref, source_texture->target(), 0)) {
+ LOCAL_SET_GL_ERROR(
+ GL_OUT_OF_MEMORY, "glCopyTextureCHROMIUM", "dimensions too big");
+ return;
+ }
+
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
// needed because it takes 10s of milliseconds to initialize.
if (!copy_texture_CHROMIUM_.get()) {
0, internal_format, dest_type, NULL);
GLenum error = LOCAL_PEEK_GL_ERROR("glCopyTextureCHROMIUM");
if (error != GL_NO_ERROR) {
- RestoreCurrentTexture2DBindings(&state_);
+ RestoreCurrentTextureBindings(&state_, GL_TEXTURE_2D);
return;
}
}
void GLES2DecoderImpl::DoProduceTextureCHROMIUM(GLenum target,
- const GLbyte* mailbox) {
+ const GLbyte* data) {
TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoProduceTextureCHROMIUM",
"context", logger_.GetLogPrefix(),
- "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
+ "mailbox[0]", static_cast<unsigned char>(data[0]));
+
+ const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
+ DLOG_IF(ERROR, !mailbox.Verify()) << "ProduceTextureCHROMIUM was passed a "
+ "mailbox that was not generated by "
+ "GenMailboxCHROMIUM.";
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
&state_, target);
return;
}
- if (!group_->mailbox_manager()->ProduceTexture(
- target,
- *reinterpret_cast<const MailboxName*>(mailbox),
- produced)) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glProduceTextureCHROMIUM", "invalid mailbox name");
- return;
- }
+ group_->mailbox_manager()->ProduceTexture(target, mailbox, produced);
}
void GLES2DecoderImpl::DoConsumeTextureCHROMIUM(GLenum target,
- const GLbyte* mailbox) {
+ const GLbyte* data) {
TRACE_EVENT2("gpu", "GLES2DecoderImpl::DoConsumeTextureCHROMIUM",
"context", logger_.GetLogPrefix(),
- "mailbox[0]", static_cast<unsigned char>(mailbox[0]));
+ "mailbox[0]", static_cast<unsigned char>(data[0]));
+ const Mailbox& mailbox = *reinterpret_cast<const Mailbox*>(data);
+ DLOG_IF(ERROR, !mailbox.Verify()) << "ConsumeTextureCHROMIUM was passed a "
+ "mailbox that was not generated by "
+ "GenMailboxCHROMIUM.";
scoped_refptr<TextureRef> texture_ref =
texture_manager()->GetTextureInfoForTargetUnlessDefault(&state_, target);
"glConsumeTextureCHROMIUM", "unknown texture for target");
return;
}
- Texture* texture =
- group_->mailbox_manager()->ConsumeTexture(
- target,
- *reinterpret_cast<const MailboxName*>(mailbox));
+ Texture* texture = group_->mailbox_manager()->ConsumeTexture(target, mailbox);
if (!texture) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
GLenum target, GLint image_id) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoBindTexImage2DCHROMIUM");
+ if (target == GL_TEXTURE_CUBE_MAP) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_ENUM,
+ "glBindTexImage2DCHROMIUM", "invalid target");
+ return;
+ }
+
// Default target might be conceptually valid, but disallow it to avoid
// accidents.
TextureRef* texture_ref =