Index: media/gpu/avda_picture_buffer_manager.cc |
diff --git a/media/gpu/avda_picture_buffer_manager.cc b/media/gpu/avda_picture_buffer_manager.cc |
index d0f13136ffdcf6ad3ca788f5592bbcc5551bb60b..4fe59e2df372d18632176cac163cca8cb23aece8 100644 |
--- a/media/gpu/avda_picture_buffer_manager.cc |
+++ b/media/gpu/avda_picture_buffer_manager.cc |
@@ -84,8 +84,13 @@ gl::ScopedJavaSurface AVDAPictureBufferManager::Initialize(int surface_id) { |
shared_state_ = new AVDASharedState(); |
// Acquire the SurfaceView surface if given a valid id. |
- if (surface_id != SurfaceManager::kNoSurfaceID) |
+ if (surface_id != SurfaceManager::kNoSurfaceID) { |
+ if (surface_texture_) { |
+ surface_texture_->ReleaseSurfaceTexture(); |
+ surface_texture_ = nullptr; |
+ } |
return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_id); |
+ } |
// Otherwise create a SurfaceTexture. |
GLuint service_id; |
@@ -109,34 +114,14 @@ void AVDAPictureBufferManager::Destroy(const PictureBufferMap& buffers) { |
surface_texture_->ReleaseSurfaceTexture(); |
} |
-uint32_t AVDAPictureBufferManager::GetTextureTarget() const { |
- // If we're using a surface texture, then we need an external texture target |
- // to sample from it. If not, then we'll use 2D transparent textures to draw |
- // a transparent hole through which to see the SurfaceView. This is normally |
- // needed only for the devtools inspector, since the overlay mechanism handles |
- // it otherwise. |
- return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; |
-} |
- |
-gfx::Size AVDAPictureBufferManager::GetPictureBufferSize() const { |
- // For SurfaceView, request a 1x1 2D texture to reduce memory during |
- // initialization. For SurfaceTexture, allocate a picture buffer that is the |
- // actual frame size. Note that it will be an external texture anyway, so it |
- // doesn't allocate an image of that size. However, it's still important to |
- // get the coded size right, so that VideoLayerImpl doesn't try to scale the |
- // texture when building the quad for it. |
- return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1); |
-} |
- |
void AVDAPictureBufferManager::SetImageForPicture( |
const PictureBuffer& picture_buffer, |
gpu::gles2::GLStreamTextureImage* image) { |
auto gles_decoder = state_provider_->GetGlDecoder(); |
RETURN_IF_NULL(gles_decoder); |
- RETURN_IF_NULL(gles_decoder->GetContextGroup()); |
- |
- gpu::gles2::TextureManager* texture_manager = |
- gles_decoder->GetContextGroup()->texture_manager(); |
+ auto* context_group = gles_decoder->GetContextGroup(); |
+ RETURN_IF_NULL(context_group); |
+ auto* texture_manager = context_group->texture_manager(); |
RETURN_IF_NULL(texture_manager); |
DCHECK_LE(1u, picture_buffer.client_texture_ids().size()); |
@@ -154,7 +139,7 @@ void AVDAPictureBufferManager::SetImageForPicture( |
// Also set the parameters for the level if we're not clearing the image. |
const gfx::Size size = state_provider_->GetSize(); |
- texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA, |
+ texture_manager->SetLevelInfo(texture_ref, kTextureTarget, 0, GL_RGBA, |
size.width(), size.height(), 1, 0, GL_RGBA, |
GL_UNSIGNED_BYTE, gfx::Rect()); |
@@ -172,34 +157,35 @@ void AVDAPictureBufferManager::SetImageForPicture( |
// matter. |
if (image && !surface_texture_) |
image_state = gpu::gles2::Texture::BOUND; |
- texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(), |
- 0, image, image_state, |
+ texture_manager->SetLevelStreamTextureImage(texture_ref, kTextureTarget, 0, |
+ image, image_state, |
stream_texture_service_id); |
- texture_manager->SetLevelCleared(texture_ref, GetTextureTarget(), 0, true); |
+ texture_manager->SetLevelCleared(texture_ref, kTextureTarget, 0, true); |
} |
AVDACodecImage* AVDAPictureBufferManager::GetImageForPicture( |
int picture_buffer_id) const { |
auto it = codec_images_.find(picture_buffer_id); |
- return it == codec_images_.end() ? nullptr : it->second.get(); |
+ DCHECK(it != codec_images_.end()); |
+ return it->second.get(); |
} |
void AVDAPictureBufferManager::UseCodecBufferForPictureBuffer( |
int32_t codec_buf_index, |
const PictureBuffer& picture_buffer) { |
- // Make sure that the decoder is available. |
- RETURN_IF_NULL(state_provider_->GetGlDecoder()); |
- |
// Notify the AVDACodecImage for picture_buffer that it should use the |
// decoded buffer codec_buf_index to render this frame. |
AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); |
- RETURN_IF_NULL(avda_image); |
// Note that this is not a race, since we do not re-use a PictureBuffer |
// until after the CC is done drawing it. |
pictures_out_for_display_.push_back(picture_buffer.id()); |
- avda_image->set_media_codec_buffer_index(codec_buf_index); |
- avda_image->set_size(state_provider_->GetSize()); |
+ avda_image->SetBufferMetadata(codec_buf_index, !!surface_texture_, |
+ state_provider_->GetSize()); |
+ |
+ // If the shared state has changed for this image, retarget its texture. |
+ if (avda_image->SetSharedState(shared_state_)) |
+ SetImageForPicture(picture_buffer, avda_image); |
MaybeRenderEarly(); |
} |
@@ -212,29 +198,12 @@ void AVDAPictureBufferManager::AssignOnePictureBuffer( |
codec_images_[picture_buffer.id()] = new AVDACodecImage( |
shared_state_, media_codec_, state_provider_->GetGlDecoder()); |
SetImageForPicture(picture_buffer, gl_image.get()); |
- |
- if (!surface_texture_ && have_context) { |
- // To make devtools work, we're using a 2D texture. Make it transparent, |
- // so that it draws a hole for the SV to show through. This is only |
- // because devtools draws and reads back, which skips overlay processing. |
- // It's unclear why devtools renders twice -- once normally, and once |
- // including a readback layer. The result is that the device screen |
- // flashes as we alternately draw the overlay hole and this texture, |
- // unless we make the texture transparent. |
- static const uint8_t rgba[] = {0, 0, 0, 0}; |
- const gfx::Size size(1, 1); |
- DCHECK_LE(1u, picture_buffer.service_texture_ids().size()); |
- glBindTexture(GL_TEXTURE_2D, picture_buffer.service_texture_ids()[0]); |
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, |
- GL_RGBA, GL_UNSIGNED_BYTE, rgba); |
- } |
} |
void AVDAPictureBufferManager::ReleaseCodecBufferForPicture( |
const PictureBuffer& picture_buffer) { |
- AVDACodecImage* avda_image = GetImageForPicture(picture_buffer.id()); |
- RETURN_IF_NULL(avda_image); |
- avda_image->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
+ GetImageForPicture(picture_buffer.id()) |
+ ->UpdateSurface(AVDACodecImage::UpdateMode::DISCARD_CODEC_BUFFER); |
} |
void AVDAPictureBufferManager::ReuseOnePictureBuffer( |
@@ -270,8 +239,6 @@ void AVDAPictureBufferManager::MaybeRenderEarly() { |
for (int i = front_index; i >= 0; --i) { |
const int id = pictures_out_for_display_[i]; |
AVDACodecImage* avda_image = GetImageForPicture(id); |
- if (!avda_image) |
- continue; |
// Update the front buffer index as we move along to shorten the number of |
// candidate images we look at for back buffer rendering. |
@@ -302,10 +269,8 @@ void AVDAPictureBufferManager::MaybeRenderEarly() { |
// first unrendered frame if there is back buffer space. |
first_renderable_image = |
GetImageForPicture(pictures_out_for_display_[backbuffer_index]); |
- if (!first_renderable_image || |
- first_renderable_image->was_rendered_to_back_buffer()) { |
+ if (first_renderable_image->was_rendered_to_back_buffer()) |
return; |
- } |
// Due to the loop in the beginning this should never be true. |
DCHECK(!first_renderable_image->was_rendered_to_front_buffer()); |
@@ -326,4 +291,12 @@ bool AVDAPictureBufferManager::ArePicturesOverlayable() { |
return !surface_texture_; |
} |
+bool AVDAPictureBufferManager::HasUnrenderedPictures() const { |
+ for (int id : pictures_out_for_display_) { |
+ if (GetImageForPicture(id)->is_unrendered()) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
} // namespace media |