| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/command_buffer/service/validating_abstract_texture_impl.h" |
| |
| #include "gpu/command_buffer/service/context_group.h" |
| #include "gpu/command_buffer/service/error_state.h" |
| #include "gpu/command_buffer/service/texture_manager.h" |
| #include "ui/gl/gl_context.h" |
| #include "ui/gl/scoped_binders.h" |
| #include "ui/gl/scoped_make_current.h" |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| ValidatingAbstractTextureImpl::ValidatingAbstractTextureImpl( |
| scoped_refptr<TextureRef> texture_ref, |
| DecoderContext* decoder_context, |
| DestructionCB destruction_cb) |
| : texture_ref_(std::move(texture_ref)), |
| decoder_context_(decoder_context), |
| destruction_cb_(std::move(destruction_cb)) {} |
| |
| ValidatingAbstractTextureImpl::~ValidatingAbstractTextureImpl() { |
| if (cleanup_cb_) { |
| DCHECK(texture_ref_); |
| std::move(cleanup_cb_).Run(this); |
| } |
| |
| if (destruction_cb_) |
| std::move(destruction_cb_).Run(this, std::move(texture_ref_)); |
| |
| DCHECK(!texture_ref_); |
| } |
| |
| TextureBase* ValidatingAbstractTextureImpl::GetTextureBase() const { |
| if (!texture_ref_) |
| return nullptr; |
| return texture_ref_->texture(); |
| } |
| |
| void ValidatingAbstractTextureImpl::SetParameteri(GLenum pname, GLint param) { |
| if (!texture_ref_) |
| return; |
| |
| gl::ScopedTextureBinder binder(texture_ref_->texture()->target(), |
| service_id()); |
| GetTextureManager()->SetParameteri(__func__, GetErrorState(), |
| texture_ref_.get(), pname, param); |
| } |
| |
| void ValidatingAbstractTextureImpl::BindImage(gl::GLImage* image, |
| bool client_managed) { |
| if (!texture_ref_) |
| return; |
| |
| const GLuint target = texture_ref_->texture()->target(); |
| const GLint level = 0; |
| |
| // If there is a decoder-managed image bound, release it. |
| if (decoder_managed_image_) { |
| Texture::ImageState image_state; |
| gl::GLImage* current_image = |
| texture_ref_->texture()->GetLevelImage(target, 0, &image_state); |
| if (current_image && image_state == Texture::BOUND) |
| current_image->ReleaseTexImage(target); |
| } |
| |
| // Configure the new image. |
| decoder_managed_image_ = image && !client_managed; |
| Texture::ImageState state = image && client_managed |
| ? Texture::ImageState::BOUND |
| : Texture::ImageState::UNBOUND; |
| GetTextureManager()->SetLevelImage(texture_ref_.get(), target, level, image, |
| state); |
| GetTextureManager()->SetLevelCleared(texture_ref_.get(), target, level, |
| image); |
| } |
| |
| void ValidatingAbstractTextureImpl::BindStreamTextureImage( |
| GLStreamTextureImage* image, |
| GLuint service_id) { |
| DCHECK(image); |
| DCHECK(!decoder_managed_image_); |
| |
| if (!texture_ref_) |
| return; |
| |
| const GLint level = 0; |
| const GLuint target = texture_ref_->texture()->target(); |
| |
| // We set the state to UNBOUND, so that CopyTexImage is called. |
| GetTextureManager()->SetLevelStreamTextureImage( |
| texture_ref_.get(), target, level, image, Texture::ImageState::UNBOUND, |
| service_id); |
| SetCleared(); |
| } |
| |
| gl::GLImage* ValidatingAbstractTextureImpl::GetImage() const { |
| if (!texture_ref_) |
| return nullptr; |
| |
| const GLuint target = texture_ref_->texture()->target(); |
| const GLint level = 0; |
| return texture_ref_->texture()->GetLevelImage(target, level, nullptr); |
| } |
| |
| void ValidatingAbstractTextureImpl::SetCleared() { |
| if (!texture_ref_) |
| return; |
| |
| const GLint level = 0; |
| GetTextureManager()->SetLevelCleared( |
| texture_ref_.get(), texture_ref_->texture()->target(), level, true); |
| } |
| |
| void ValidatingAbstractTextureImpl::SetCleanupCallback(CleanupCallback cb) { |
| cleanup_cb_ = std::move(cb); |
| } |
| |
| TextureManager* ValidatingAbstractTextureImpl::GetTextureManager() const { |
| DCHECK(decoder_context_); |
| return GetContextGroup()->texture_manager(); |
| } |
| |
| ContextGroup* ValidatingAbstractTextureImpl::GetContextGroup() const { |
| DCHECK(decoder_context_); |
| return decoder_context_->GetContextGroup(); |
| } |
| |
| ErrorState* ValidatingAbstractTextureImpl::GetErrorState() const { |
| DCHECK(decoder_context_); |
| return decoder_context_->GetErrorState(); |
| } |
| |
| void ValidatingAbstractTextureImpl::OnDecoderWillDestroy(bool have_context) { |
| // If we don't have a context, then notify the TextureRef not to delete itself |
| // if this is the last reference. |
| destruction_cb_ = DestructionCB(); |
| decoder_context_ = nullptr; |
| |
| // If we already got rid of the texture ref, then there's nothing to do. |
| if (!texture_ref_) |
| return; |
| |
| if (cleanup_cb_) |
| std::move(cleanup_cb_).Run(this); |
| |
| // If we have no context, then notify the TextureRef in case it's the last |
| // ref to the texture. |
| if (!have_context) |
| texture_ref_->ForceContextLost(); |
| texture_ref_ = nullptr; |
| } |
| |
| TextureRef* ValidatingAbstractTextureImpl::GetTextureRefForTesting() { |
| return texture_ref_.get(); |
| } |
| |
| } // namespace gles2 |
| } // namespace gpu |