| Index: content/common/gpu/media/gpu_video_decode_accelerator.cc
|
| diff --git a/content/common/gpu/media/gpu_video_decode_accelerator.cc b/content/common/gpu/media/gpu_video_decode_accelerator.cc
|
| index e180f06788303c4d0e02f2bddfb13674d739f8eb..08e23a33e310b087d8a0874c9e77b768d3bb058a 100644
|
| --- a/content/common/gpu/media/gpu_video_decode_accelerator.cc
|
| +++ b/content/common/gpu/media/gpu_video_decode_accelerator.cc
|
| @@ -34,7 +34,6 @@
|
| #include "content/common/gpu/media/android_video_decode_accelerator.h"
|
| #endif
|
|
|
| -#include "gpu/command_buffer/service/texture_manager.h"
|
| #include "ui/gfx/size.h"
|
|
|
| namespace content {
|
| @@ -54,6 +53,27 @@ static bool MakeDecoderContextCurrent(
|
| return true;
|
| }
|
|
|
| +// A helper class that works like AutoLock but only acquires the lock when
|
| +// DCHECK is on.
|
| +class DebugAutoLock {
|
| + public:
|
| + explicit DebugAutoLock(base::Lock& lock) : lock_(lock) {
|
| + if (DCHECK_IS_ON())
|
| + lock_.Acquire();
|
| + }
|
| +
|
| + ~DebugAutoLock() {
|
| + if (DCHECK_IS_ON()) {
|
| + lock_.AssertAcquired();
|
| + lock_.Release();
|
| + }
|
| + }
|
| +
|
| + private:
|
| + base::Lock& lock_;
|
| + DISALLOW_COPY_AND_ASSIGN(DebugAutoLock);
|
| +};
|
| +
|
| class GpuVideoDecodeAccelerator::MessageFilter
|
| : public IPC::ChannelProxy::MessageFilter {
|
| public:
|
| @@ -176,10 +196,25 @@ void GpuVideoDecodeAccelerator::DismissPictureBuffer(
|
| DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer) "
|
| << "failed";
|
| }
|
| + DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
| + uncleared_textures_.erase(picture_buffer_id);
|
| }
|
|
|
| void GpuVideoDecodeAccelerator::PictureReady(
|
| const media::Picture& picture) {
|
| + // VDA may call PictureReady on IO thread. SetTextureCleared should run on
|
| + // the child thread. VDA is responsible to call PictureReady on the child
|
| + // thread when a picture buffer is delivered the first time.
|
| + if (child_message_loop_->BelongsToCurrentThread()) {
|
| + SetTextureCleared(picture);
|
| + } else {
|
| + DCHECK(io_message_loop_->BelongsToCurrentThread());
|
| + if (DCHECK_IS_ON()) {
|
| + DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
| + DCHECK_EQ(0u, uncleared_textures_.count(picture.picture_buffer_id()));
|
| + }
|
| + }
|
| +
|
| if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
|
| host_route_id_,
|
| picture.picture_buffer_id(),
|
| @@ -305,6 +340,7 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
| command_decoder->GetContextGroup()->texture_manager();
|
|
|
| std::vector<media::PictureBuffer> buffers;
|
| + std::vector<scoped_refptr<gpu::gles2::TextureRef> > textures;
|
| for (uint32 i = 0; i < buffer_ids.size(); ++i) {
|
| if (buffer_ids[i] < 0) {
|
| DLOG(ERROR) << "Buffer id " << buffer_ids[i] << " out of range";
|
| @@ -327,9 +363,7 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
| }
|
| if (texture_target_ == GL_TEXTURE_EXTERNAL_OES) {
|
| // GL_TEXTURE_EXTERNAL_OES textures have their dimensions defined by the
|
| - // underlying EGLImage. Use |texture_dimensions_| for this size. The
|
| - // textures cannot be rendered to or cleared, so we set |cleared| true to
|
| - // skip clearing.
|
| + // underlying EGLImage. Use |texture_dimensions_| for this size.
|
| texture_manager->SetLevelInfo(texture_ref,
|
| GL_TEXTURE_EXTERNAL_OES,
|
| 0,
|
| @@ -340,7 +374,7 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
| 0,
|
| 0,
|
| 0,
|
| - true);
|
| + false);
|
| } else {
|
| // For other targets, texture dimensions should already be defined.
|
| GLsizei width = 0, height = 0;
|
| @@ -352,11 +386,6 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
| return;
|
| }
|
| }
|
| - if (!texture_manager->ClearRenderableLevels(command_decoder, texture_ref)) {
|
| - DLOG(ERROR) << "Failed to Clear texture id " << texture_ids[i];
|
| - NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
|
| - return;
|
| - }
|
| uint32 service_texture_id;
|
| if (!command_decoder->GetServiceTextureId(
|
| texture_ids[i], &service_texture_id)) {
|
| @@ -366,8 +395,12 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
|
| }
|
| buffers.push_back(media::PictureBuffer(
|
| buffer_ids[i], texture_dimensions_, service_texture_id));
|
| + textures.push_back(texture_ref);
|
| }
|
| video_decode_accelerator_->AssignPictureBuffers(buffers);
|
| + DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
| + for (uint32 i = 0; i < buffer_ids.size(); ++i)
|
| + uncleared_textures_[buffer_ids[i]] = textures[i];
|
| }
|
|
|
| void GpuVideoDecodeAccelerator::OnReusePictureBuffer(
|
| @@ -446,4 +479,22 @@ bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
|
| return stub_->channel()->Send(message);
|
| }
|
|
|
| +void GpuVideoDecodeAccelerator::SetTextureCleared(
|
| + const media::Picture& picture) {
|
| + DCHECK(child_message_loop_->BelongsToCurrentThread());
|
| + DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
|
| + std::map<int32, scoped_refptr<gpu::gles2::TextureRef> >::iterator it;
|
| + it = uncleared_textures_.find(picture.picture_buffer_id());
|
| + if (it == uncleared_textures_.end())
|
| + return; // the texture has been cleared
|
| +
|
| + scoped_refptr<gpu::gles2::TextureRef> texture_ref = it->second;
|
| + GLenum target = texture_ref->texture()->target();
|
| + gpu::gles2::TextureManager* texture_manager =
|
| + stub_->decoder()->GetContextGroup()->texture_manager();
|
| + DCHECK(!texture_ref->texture()->IsLevelCleared(target, 0));
|
| + texture_manager->SetLevelCleared(texture_ref, target, 0, true);
|
| + uncleared_textures_.erase(it);
|
| +}
|
| +
|
| } // namespace content
|
|
|