blob: 4f5909d0ad988bf83abd5b009d76a18a13a426c5 [file] [log] [blame]
// 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 "media/gpu/android/texture_pool.h"
#include "base/bind.h"
#include "gpu/command_buffer/service/abstract_texture.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "media/gpu/command_buffer_helper.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/scoped_make_current.h"
using gpu::gles2::AbstractTexture;
namespace media {
TexturePool::TexturePool(scoped_refptr<CommandBufferHelper> helper)
: helper_(std::move(helper)), weak_factory_(this) {
if (helper_) {
helper_->SetWillDestroyStubCB(base::BindOnce(
&TexturePool::OnWillDestroyStub, weak_factory_.GetWeakPtr()));
}
}
TexturePool::~TexturePool() {
// We'll drop all textures from the pool, if any. It's okay if we don't have
// a current context, since AbstractTexture handles it.
}
void TexturePool::AddTexture(std::unique_ptr<AbstractTexture> texture) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(pool_.find(texture.get()) == pool_.end());
// Don't permit additions after we've lost the stub.
// TODO(liberato): consider making this fail gracefully. However, nobody
// should be doing this, so for now it's a DCHECK.
DCHECK(helper_);
pool_.insert(std::move(texture));
}
void TexturePool::ReleaseTexture(AbstractTexture* texture,
const gpu::SyncToken& sync_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// If we don't have a sync token, or if we have no stub, then just finish.
if (!sync_token.HasData() || !helper_) {
OnSyncTokenReleased(texture);
return;
}
// We keep a strong ref to |this| in the callback, so that we are guaranteed
// to receive it. It's common for the last ref to us to be our caller, as
// a callback. We need to stick around a bit longer than that if there's a
// sync token. Plus, we're required to keep |helper_| around while a wait is
// still pending.
helper_->WaitForSyncToken(
sync_token, base::BindOnce(&TexturePool::OnSyncTokenReleased,
scoped_refptr<TexturePool>(this), texture));
}
void TexturePool::OnSyncTokenReleased(AbstractTexture* texture) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto iter = pool_.find(texture);
DCHECK(iter != pool_.end());
// Drop the texture. This is safe without the context being current. It's
// also safe if the stub has been destroyed.
pool_.erase(iter);
}
void TexturePool::OnWillDestroyStub(bool have_context) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(helper_);
// TODO(liberato): Should we drop all unrendered codec buffers here? It seems
// like a good idea, just to release the resources. However, they won't block
// decoding, since decoding requires the stub too. More generally, it might
// be worthwhile to have a callback on AbstractTexture that's called when it
// transitions to not owning a texture.
// Note that we don't have to do anything with |pool_|, since AbstractTextures
// can outlive the stub that created them. They just don't have a texture.
helper_ = nullptr;
}
} // namespace media