Commit 5ad8df60 authored by Dan Sanders's avatar Dan Sanders Committed by Commit Bot

Fix unbind and teardown behavior of media::CommandBufferHelper.

At stub destruction, CommandBufferHelper forgets all of its textures,
which leads to crashes on Mac. The fix is to stop doing that, now that
AbstractTextures remove the need to do so.

Additionally, the behavior of calling BindImage(nullptr) was changed in
the conversion to AbstractTexture; this change restores the original
behavior.

Bug: 869186
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I27fb81408ac90d28752a6bb6cfbb5e3c56975c70
Reviewed-on: https://chromium-review.googlesource.com/1155812Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: Dan Sanders <sandersd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#580384}
parent b5b1e845
...@@ -77,12 +77,6 @@ class GPU_GLES2_EXPORT AbstractTexture { ...@@ -77,12 +77,6 @@ class GPU_GLES2_EXPORT AbstractTexture {
// The context must be current. // The context must be current.
virtual void BindImage(gl::GLImage* image, bool client_managed) = 0; virtual void BindImage(gl::GLImage* image, bool client_managed) = 0;
// Unbind and release any image bound to this texture, and return it to an
// uncleared state.
//
// The context must be current.
virtual void ReleaseImage() = 0;
// Return the image, if any. // Return the image, if any.
virtual gl::GLImage* GetImage() const = 0; virtual gl::GLImage* GetImage() const = 0;
......
...@@ -325,7 +325,7 @@ TEST_P(GLES2DecoderTest, CreateAbstractTexture) { ...@@ -325,7 +325,7 @@ TEST_P(GLES2DecoderTest, CreateAbstractTexture) {
EXPECT_EQ(texture->GetLevelImage(target, 0), image.get()); EXPECT_EQ(texture->GetLevelImage(target, 0), image.get());
// Unbinding should make it not renderable. // Unbinding should make it not renderable.
abstract_texture->ReleaseImage(); abstract_texture->BindImage(nullptr, false);
EXPECT_EQ(texture->SafeToRenderFrom(), false); EXPECT_EQ(texture->SafeToRenderFrom(), false);
EXPECT_EQ(abstract_texture->GetImage(), nullptr); EXPECT_EQ(abstract_texture->GetImage(), nullptr);
......
...@@ -51,8 +51,23 @@ void PassthroughAbstractTextureImpl::BindImage(gl::GLImage* image, ...@@ -51,8 +51,23 @@ void PassthroughAbstractTextureImpl::BindImage(gl::GLImage* image,
if (!texture_passthrough_) if (!texture_passthrough_)
return; return;
texture_passthrough_->set_is_bind_pending(!client_managed); const GLuint target = texture_passthrough_->target();
texture_passthrough_->SetLevelImage(texture_passthrough_->target(), 0, image); const GLuint level = 0;
// If there is a decoder-managed image bound, release it.
if (decoder_managed_image_) {
gl::GLImage* current_image =
texture_passthrough_->GetLevelImage(target, level);
// TODO(sandersd): This isn't correct if CopyTexImage() was used.
bool is_bound = !texture_passthrough_->is_bind_pending();
if (current_image && is_bound)
current_image->ReleaseTexImage(target);
}
// Configure the new image.
decoder_managed_image_ = image && !client_managed;
texture_passthrough_->set_is_bind_pending(decoder_managed_image_);
texture_passthrough_->SetLevelImage(target, level, image);
} }
void PassthroughAbstractTextureImpl::BindStreamTextureImage( void PassthroughAbstractTextureImpl::BindStreamTextureImage(
...@@ -61,19 +76,6 @@ void PassthroughAbstractTextureImpl::BindStreamTextureImage( ...@@ -61,19 +76,6 @@ void PassthroughAbstractTextureImpl::BindStreamTextureImage(
NOTREACHED(); NOTREACHED();
} }
void PassthroughAbstractTextureImpl::ReleaseImage() {
if (!texture_passthrough_)
return;
texture_passthrough_->set_is_bind_pending(false);
const GLuint target = texture_passthrough_->target();
const GLuint level = 0;
if (gl::GLImage* image = GetImage()) {
image->ReleaseTexImage(target);
texture_passthrough_->SetLevelImage(target, level, nullptr);
}
}
gl::GLImage* PassthroughAbstractTextureImpl::GetImage() const { gl::GLImage* PassthroughAbstractTextureImpl::GetImage() const {
if (!texture_passthrough_) if (!texture_passthrough_)
return nullptr; return nullptr;
......
...@@ -33,7 +33,6 @@ class GPU_GLES2_EXPORT PassthroughAbstractTextureImpl : public AbstractTexture { ...@@ -33,7 +33,6 @@ class GPU_GLES2_EXPORT PassthroughAbstractTextureImpl : public AbstractTexture {
void BindImage(gl::GLImage* image, bool client_managed) override; void BindImage(gl::GLImage* image, bool client_managed) override;
void BindStreamTextureImage(GLStreamTextureImage* image, void BindStreamTextureImage(GLStreamTextureImage* image,
GLuint service_id) override; GLuint service_id) override;
void ReleaseImage() override;
gl::GLImage* GetImage() const override; gl::GLImage* GetImage() const override;
void SetCleared() override; void SetCleared() override;
void SetCleanupCallback(CleanupCallback cb) override; void SetCleanupCallback(CleanupCallback cb) override;
...@@ -43,6 +42,7 @@ class GPU_GLES2_EXPORT PassthroughAbstractTextureImpl : public AbstractTexture { ...@@ -43,6 +42,7 @@ class GPU_GLES2_EXPORT PassthroughAbstractTextureImpl : public AbstractTexture {
private: private:
scoped_refptr<TexturePassthrough> texture_passthrough_; scoped_refptr<TexturePassthrough> texture_passthrough_;
bool decoder_managed_image_ = false;
gl::GLApi* gl_api_; gl::GLApi* gl_api_;
GLES2DecoderPassthroughImpl* decoder_; GLES2DecoderPassthroughImpl* decoder_;
CleanupCallback cleanup_cb_; CleanupCallback cleanup_cb_;
......
...@@ -52,26 +52,37 @@ void ValidatingAbstractTextureImpl::SetParameteri(GLenum pname, GLint param) { ...@@ -52,26 +52,37 @@ void ValidatingAbstractTextureImpl::SetParameteri(GLenum pname, GLint param) {
void ValidatingAbstractTextureImpl::BindImage(gl::GLImage* image, void ValidatingAbstractTextureImpl::BindImage(gl::GLImage* image,
bool client_managed) { bool client_managed) {
DCHECK(image);
if (!texture_ref_) if (!texture_ref_)
return; return;
const GLuint target = texture_ref_->texture()->target();
const GLint level = 0; const GLint level = 0;
Texture::ImageState state = client_managed ? Texture::ImageState::BOUND // If there is a decoder-managed image bound, release it.
: Texture::ImageState::UNBOUND; 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);
}
GetTextureManager()->SetLevelImage(texture_ref_.get(), // Configure the new image.
texture_ref_->texture()->target(), level, decoder_managed_image_ = image && !client_managed;
image, state); Texture::ImageState state = image && client_managed
SetCleared(); ? 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( void ValidatingAbstractTextureImpl::BindStreamTextureImage(
GLStreamTextureImage* image, GLStreamTextureImage* image,
GLuint service_id) { GLuint service_id) {
DCHECK(image); DCHECK(image);
DCHECK(!decoder_managed_image_);
if (!texture_ref_) if (!texture_ref_)
return; return;
...@@ -86,31 +97,6 @@ void ValidatingAbstractTextureImpl::BindStreamTextureImage( ...@@ -86,31 +97,6 @@ void ValidatingAbstractTextureImpl::BindStreamTextureImage(
SetCleared(); SetCleared();
} }
void ValidatingAbstractTextureImpl::ReleaseImage() {
if (!texture_ref_)
return;
GLuint target = texture_ref_->texture()->target();
Texture::ImageState image_state;
gl::GLImage* image =
texture_ref_->texture()->GetLevelImage(target, 0, &image_state);
if (!image)
return;
// TODO(liberato): Suppress errors here?
if (image_state == Texture::BOUND)
image->ReleaseTexImage(target);
GetTextureManager()->SetLevelImage(texture_ref_.get(), target, 0, nullptr,
Texture::UNBOUND);
// Mark the texture as uncleared, in case it's only cleared because of the
// image binding.
const GLint level = 0;
GetTextureManager()->SetLevelCleared(texture_ref_.get(), target, level,
false);
}
gl::GLImage* ValidatingAbstractTextureImpl::GetImage() const { gl::GLImage* ValidatingAbstractTextureImpl::GetImage() const {
if (!texture_ref_) if (!texture_ref_)
return nullptr; return nullptr;
......
...@@ -38,7 +38,6 @@ class GPU_GLES2_EXPORT ValidatingAbstractTextureImpl : public AbstractTexture { ...@@ -38,7 +38,6 @@ class GPU_GLES2_EXPORT ValidatingAbstractTextureImpl : public AbstractTexture {
void BindStreamTextureImage(GLStreamTextureImage* image, void BindStreamTextureImage(GLStreamTextureImage* image,
GLuint service_id) override; GLuint service_id) override;
void BindImage(gl::GLImage* image, bool client_managed) override; void BindImage(gl::GLImage* image, bool client_managed) override;
void ReleaseImage() override;
gl::GLImage* GetImage() const override; gl::GLImage* GetImage() const override;
void SetCleared() override; void SetCleared() override;
void SetCleanupCallback(CleanupCallback cb) override; void SetCleanupCallback(CleanupCallback cb) override;
...@@ -58,6 +57,7 @@ class GPU_GLES2_EXPORT ValidatingAbstractTextureImpl : public AbstractTexture { ...@@ -58,6 +57,7 @@ class GPU_GLES2_EXPORT ValidatingAbstractTextureImpl : public AbstractTexture {
void SetLevelInfo(); void SetLevelInfo();
scoped_refptr<TextureRef> texture_ref_; scoped_refptr<TextureRef> texture_ref_;
bool decoder_managed_image_ = false;
DecoderContext* decoder_context_ = nullptr; DecoderContext* decoder_context_ = nullptr;
DestructionCB destruction_cb_; DestructionCB destruction_cb_;
......
...@@ -174,10 +174,6 @@ class CommandBufferHelperImpl ...@@ -174,10 +174,6 @@ class CommandBufferHelperImpl
DVLOG(3) << __func__; DVLOG(3) << __func__;
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Drop all textures. Note that it's okay if the context isn't current,
// since AbstractTexture handles that case.
textures_.clear();
decoder_helper_ = nullptr; decoder_helper_ = nullptr;
// If the last reference to |this| is in a |done_cb|, destroying the wait // If the last reference to |this| is in a |done_cb|, destroying the wait
......
...@@ -28,7 +28,6 @@ void FakeCommandBufferHelper::StubLost() { ...@@ -28,7 +28,6 @@ void FakeCommandBufferHelper::StubLost() {
has_stub_ = false; has_stub_ = false;
is_context_lost_ = true; is_context_lost_ = true;
is_context_current_ = false; is_context_current_ = false;
service_ids_.clear();
waits_.clear(); waits_.clear();
} }
...@@ -110,7 +109,6 @@ bool FakeCommandBufferHelper::BindImage(GLuint service_id, ...@@ -110,7 +109,6 @@ bool FakeCommandBufferHelper::BindImage(GLuint service_id,
DVLOG(2) << __func__ << "(" << service_id << ")"; DVLOG(2) << __func__ << "(" << service_id << ")";
DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(service_ids_.count(service_id)); DCHECK(service_ids_.count(service_id));
DCHECK(image);
return has_stub_; return has_stub_;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment