diff options
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 131 |
1 files changed, 113 insertions, 18 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index dd02c9c..c8148a0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -521,7 +521,8 @@ bool GLES2Decoder::IsAngle() { // This class implements GLES2Decoder so we don't have to expose all the GLES2 // cmd stuff to outside this class. -class GLES2DecoderImpl : public GLES2Decoder { +class GLES2DecoderImpl : public GLES2Decoder, + public FramebufferManager::TextureDetachObserver { public: // Used by PrepForSetUniformByLocation to validate types. struct BaseUniformInfo { @@ -642,6 +643,10 @@ class GLES2DecoderImpl : public GLES2Decoder { virtual error::ContextLostReason GetContextLostReason() OVERRIDE; + // Overridden from FramebufferManager::TextureDetachObserver: + virtual void OnTextureRefDetachedFromFramebuffer( + TextureRef* texture) OVERRIDE; + private: friend class ScopedFrameBufferBinder; friend class ScopedResolvedFrameBufferBinder; @@ -1377,9 +1382,14 @@ class GLES2DecoderImpl : public GLES2Decoder { // buffer and bind the texture implicitly. void UpdateStreamTextureIfNeeded(Texture* texture, GLuint texture_unit_index); - // Returns false if unrenderable textures were replaced. + // If an image is bound to texture, this will call Will/DidUseTexImage + // if needed. + void DoWillUseTexImageIfNeeded(Texture* texture, GLenum textarget); + void DoDidUseTexImageIfNeeded(Texture* texture, GLenum textarget); + + // Returns false if textures were replaced. bool PrepareTexturesForRender(); - void RestoreStateForNonRenderableTextures(); + void RestoreStateForTextures(); // Returns true if GL_FIXED attribs were simulated. bool SimulateFixedAttribs( @@ -2472,6 +2482,8 @@ bool GLES2DecoderImpl::Initialize( AsyncPixelTransferManager::Create(context.get())); async_pixel_transfer_manager_->Initialize(texture_manager()); + framebuffer_manager()->AddObserver(this); + return true; } @@ -3203,6 +3215,8 @@ void GLES2DecoderImpl::Destroy(bool have_context) { // by the context group. async_pixel_transfer_manager_.reset(); + framebuffer_manager()->RemoveObserver(this); + if (group_.get()) { group_->Destroy(this, have_context); group_ = NULL; @@ -4866,6 +4880,9 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( return; } + if (texture_ref) + DoWillUseTexImageIfNeeded(texture_ref->texture(), textarget); + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(name); if (0 == samples) { glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level); @@ -4886,6 +4903,10 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon( if (framebuffer == framebuffer_state_.bound_draw_framebuffer.get()) { framebuffer_state_.clear_state_dirty = true; } + + if (texture_ref) + DoDidUseTexImageIfNeeded(texture_ref->texture(), textarget); + OnFboChanged(); } @@ -5723,11 +5744,49 @@ void GLES2DecoderImpl::UpdateStreamTextureIfNeeded(Texture* texture, } } +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); + if (image) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoWillUseTexImageIfNeeded", + GetErrorState()); + glBindTexture(textarget, texture->service_id()); + image->WillUseTexImage(); + RestoreCurrentTexture2DBindings(); + } + } +} + +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); + if (image) { + ScopedGLErrorSuppressor suppressor( + "GLES2DecoderImpl::DoDidUseTexImageIfNeeded", + GetErrorState()); + glBindTexture(textarget, texture->service_id()); + image->DidUseTexImage(); + RestoreCurrentTexture2DBindings(); + } + } +} + bool GLES2DecoderImpl::PrepareTexturesForRender() { DCHECK(state_.current_program.get()); - bool have_unrenderable_textures = - texture_manager()->HaveUnrenderableTextures(); - if (!have_unrenderable_textures && !features().oes_egl_image_external) { + if (!texture_manager()->HaveUnrenderableTextures() && + !texture_manager()->HaveImages() && + !features().oes_egl_image_external) { return true; } @@ -5742,16 +5801,14 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { GLuint texture_unit_index = uniform_info->texture_units[jj]; if (texture_unit_index < state_.texture_units.size()) { TextureUnit& texture_unit = state_.texture_units[texture_unit_index]; - TextureRef* texture = + TextureRef* texture_ref = texture_unit.GetInfoForSamplerType(uniform_info->type).get(); - if (texture) - UpdateStreamTextureIfNeeded(texture->texture(), texture_unit_index); - if (have_unrenderable_textures && - (!texture || !texture_manager()->CanRender(texture))) { + GLenum textarget = GetBindTargetForSamplerType(uniform_info->type); + if (!texture_ref || !texture_manager()->CanRender(texture_ref)) { textures_set = true; glActiveTexture(GL_TEXTURE0 + texture_unit_index); glBindTexture( - GetBindTargetForSamplerType(uniform_info->type), + textarget, texture_manager()->black_texture_id(uniform_info->type)); LOCAL_RENDER_WARNING( std::string("texture bound to texture unit ") + @@ -5759,7 +5816,23 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { " is not renderable. It maybe non-power-of-2 and have" " incompatible texture filtering or is not" " 'texture complete'"); + continue; } + + Texture* texture = texture_ref->texture(); + if (textarget == GL_TEXTURE_2D) { + 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; + } + } + + UpdateStreamTextureIfNeeded(texture, texture_unit_index); } // else: should this be an error? } @@ -5767,7 +5840,7 @@ bool GLES2DecoderImpl::PrepareTexturesForRender() { return !textures_set; } -void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() { +void GLES2DecoderImpl::RestoreStateForTextures() { DCHECK(state_.current_program.get()); const Program::SamplerIndices& sampler_indices = state_.current_program->sampler_indices(); @@ -5780,9 +5853,7 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() { if (texture_unit_index < state_.texture_units.size()) { TextureUnit& texture_unit = state_.texture_units[texture_unit_index]; TextureRef* texture_ref = - uniform_info->type == GL_SAMPLER_2D - ? texture_unit.bound_texture_2d.get() - : texture_unit.bound_texture_cube_map.get(); + texture_unit.GetInfoForSamplerType(uniform_info->type).get(); if (!texture_ref || !texture_manager()->CanRender(texture_ref)) { glActiveTexture(GL_TEXTURE0 + texture_unit_index); // Get the texture_ref info that was previously bound here. @@ -5791,6 +5862,20 @@ void GLES2DecoderImpl::RestoreStateForNonRenderableTextures() { : texture_unit.bound_texture_cube_map.get(); glBindTexture(texture_unit.bind_target, texture_ref ? texture_ref->service_id() : 0); + continue; + } + + Texture* texture = texture_ref->texture(); + if (texture_unit.bind_target == GL_TEXTURE_2D) { + 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; + } } } } @@ -6133,7 +6218,7 @@ error::Error GLES2DecoderImpl::DoDrawArrays( } ProcessPendingQueries(); if (textures_set) { - RestoreStateForNonRenderableTextures(); + RestoreStateForTextures(); } if (simulated_fixed_attribs) { RestoreStateForSimulatedFixedAttribs(); @@ -6267,7 +6352,7 @@ error::Error GLES2DecoderImpl::DoDrawElements( ProcessPendingQueries(); if (textures_set) { - RestoreStateForNonRenderableTextures(); + RestoreStateForTextures(); } if (simulated_fixed_attribs) { RestoreStateForSimulatedFixedAttribs(); @@ -9601,6 +9686,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( dest_texture_ref, GL_TEXTURE_2D, level, true); } + DoWillUseTexImageIfNeeded(source_texture, source_texture->target()); + // GL_TEXTURE_EXTERNAL_OES texture requires apply a transform matrix // before presenting. if (source_texture->target() == GL_TEXTURE_EXTERNAL_OES) { @@ -9633,6 +9720,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM( unpack_premultiply_alpha_, unpack_unpremultiply_alpha_); } + + DoDidUseTexImageIfNeeded(source_texture, source_texture->target()); } static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) { @@ -10298,6 +10387,12 @@ error::Error GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM( return error::kNoError; } +void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer( + TextureRef* texture_ref) { + Texture* texture = texture_ref->texture(); + DoDidUseTexImageIfNeeded(texture, texture->target()); +} + // Include the auto-generated part of this file. We split this because it means // we can easily edit the non-auto generated parts right here in this file // instead of having to edit some template or the code generator. |