Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Unified Diff: media/gpu/android_deferred_rendering_backing_strategy.cc

Issue 2005103004: AVDACodecImages keep their backing SurfaceTexture alive (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@neverdetach
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/gpu/android_deferred_rendering_backing_strategy.cc
diff --git a/media/gpu/android_deferred_rendering_backing_strategy.cc b/media/gpu/android_deferred_rendering_backing_strategy.cc
index ed04334cfbbbc6c76db06489e29421de6bfda406..75f2b49c7eb2c4bb2ca48abd6c83e8f489c5ca19 100644
--- a/media/gpu/android_deferred_rendering_backing_strategy.cc
+++ b/media/gpu/android_deferred_rendering_backing_strategy.cc
@@ -41,45 +41,24 @@ gfx::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize(
int surface_view_id) {
shared_state_ = new AVDASharedState();
- // Create a texture for the SurfaceTexture to use.
- GLuint service_id;
- glGenTextures(1, &service_id);
- shared_state_->set_surface_texture_service_id(service_id);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- state_provider_->GetGlDecoder()->RestoreTextureUnitBindings(0);
- state_provider_->GetGlDecoder()->RestoreActiveTexture();
- DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-
- gfx::ScopedJavaSurface surface;
+ // Acquire the SurfaceView surface if given a valid id.
if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) {
- surface = gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(
+ return gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(
surface_view_id);
- } else {
- bool using_virtual_context = false;
- if (gfx::GLContext* context = gfx::GLContext::GetCurrent()) {
- if (gfx::GLShareGroup* share_group = context->share_group())
- using_virtual_context = !!share_group->GetSharedContext();
- }
- UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context);
- // Detach doesn't work so well on all platforms. Just attach the
- // SurfaceTexture here, and probably context switch later.
- // Detaching might save us a context switch, since AVDACodecImage will
- // attach when needed. However, given that it also fails a lot, we just
- // don't do it at all. If virtual contexts are in use, then it doesn't
- // even save us a context switch.
- surface_texture_ = gfx::SurfaceTexture::Create(service_id);
- shared_state_->DidAttachSurfaceTexture();
- surface = gfx::ScopedJavaSurface(surface_texture_.get());
}
- return surface;
+ // Create a SurfaceTexture.
+ bool using_virtual_context = false;
+ if (gfx::GLContext* context = gfx::GLContext::GetCurrent()) {
+ if (gfx::GLShareGroup* share_group = context->share_group())
+ using_virtual_context = !!share_group->GetSharedContext();
+ }
+ UMA_HISTOGRAM_BOOLEAN("Media.AVDA.VirtualContext", using_virtual_context);
+
+ GLuint service_id = 0;
+ surface_texture_ = state_provider_->CreateAttachedSurfaceTexture(&service_id);
+ shared_state_->SetSurfaceTexture(surface_texture_, service_id);
+ return gfx::ScopedJavaSurface(surface_texture_.get());
}
void AndroidDeferredRenderingBackingStrategy::Cleanup(
@@ -89,23 +68,7 @@ void AndroidDeferredRenderingBackingStrategy::Cleanup(
if (!shared_state_)
return;
- // Make sure that no PictureBuffer textures refer to the SurfaceTexture or to
- // the service_id that we created for it.
- for (const std::pair<int, media::PictureBuffer>& entry : buffers) {
- ReleaseCodecBufferForPicture(entry.second);
- SetImageForPicture(entry.second, nullptr);
- }
-
- // If we're rendering to a SurfaceTexture we can make a copy of the current
- // front buffer so that the PictureBuffer textures are still valid.
- if (surface_texture_ && have_context && ShouldCopyPictures())
- CopySurfaceTextureToPictures(buffers);
-
- // Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete
- // the texture name.
- GLuint service_id = shared_state_->surface_texture_service_id();
- if (service_id > 0 && have_context)
- glDeleteTextures(1, &service_id);
+ CodecChanged(nullptr);
}
scoped_refptr<gfx::SurfaceTexture>
@@ -153,10 +116,11 @@ void AndroidDeferredRenderingBackingStrategy::SetImageForPicture(
GL_UNSIGNED_BYTE, gfx::Rect());
// Override the texture's service_id, so that it will use the one that
- // will be / is attached to the SurfaceTexture.
- DCHECK(shared_state_->surface_texture_service_id());
- texture_ref->texture()->SetUnownedServiceId(
- shared_state_->surface_texture_service_id());
+ // is attached to the SurfaceTexture.
+ if (shared_state_->surface_texture_service_id()) {
+ texture_ref->texture()->SetUnownedServiceId(
+ shared_state_->surface_texture_service_id());
+ }
static_cast<AVDACodecImage*>(image.get())
->set_texture(texture_ref->texture());
@@ -336,117 +300,4 @@ void AndroidDeferredRenderingBackingStrategy::UpdatePictureBufferSize(
picture_buffer->set_size(new_size);
}
-void AndroidDeferredRenderingBackingStrategy::CopySurfaceTextureToPictures(
- const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {
- DVLOG(3) << __FUNCTION__;
-
- // Don't try to copy if the SurfaceTexture was never attached because that
- // means it was never updated.
- if (!shared_state_->surface_texture_is_attached())
- return;
-
- gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get();
- if (!gl_decoder)
- return;
-
- const gfx::Size size = state_provider_->GetSize();
-
- // Create a 2D texture to hold a copy of the SurfaceTexture's front buffer.
- GLuint tmp_texture_id;
- glGenTextures(1, &tmp_texture_id);
- {
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id);
- // The target texture's size will exactly match the source.
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- }
-
- float transform_matrix[16];
- surface_texture_->GetTransformMatrix(transform_matrix);
-
- gpu::CopyTextureCHROMIUMResourceManager copier;
- copier.Initialize(
- gl_decoder,
- gl_decoder->GetContextGroup()->feature_info()->feature_flags());
- copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES,
- shared_state_->surface_texture_service_id(),
- GL_TEXTURE_2D, tmp_texture_id, size.width(),
- size.height(), true, false, false,
- transform_matrix);
-
- // Create an EGLImage from the 2D texture we just copied into. By associating
- // the EGLImage with the PictureBuffer textures they will remain valid even
- // after we delete the 2D texture and EGLImage.
- const EGLImageKHR egl_image = eglCreateImageKHR(
- gfx::GLSurfaceEGL::GetHardwareDisplay(), eglGetCurrentContext(),
- EGL_GL_TEXTURE_2D_KHR, reinterpret_cast<EGLClientBuffer>(tmp_texture_id),
- nullptr /* attrs */);
-
- glDeleteTextures(1, &tmp_texture_id);
- DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-
- if (egl_image == EGL_NO_IMAGE_KHR) {
- DLOG(ERROR) << "Failed creating EGLImage: " << ui::GetLastEGLErrorString();
- return;
- }
-
- for (const std::pair<int, media::PictureBuffer>& entry : buffers) {
- gpu::gles2::TextureRef* texture_ref =
- state_provider_->GetTextureForPicture(entry.second);
- if (!texture_ref)
- continue;
- gfx::ScopedTextureBinder texture_binder(
- GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id());
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
- DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
- }
-
- EGLBoolean result =
- eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image);
- if (result == EGL_FALSE) {
- DLOG(ERROR) << "Error destroying EGLImage: " << ui::GetLastEGLErrorString();
- }
-}
-
-bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const {
- // See if there's a workaround.
- if (gpu::gles2::GLES2Decoder* gl_decoder =
- state_provider_->GetGlDecoder().get()) {
- if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) {
- if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) {
- if (feature_info->workarounds().avda_dont_copy_pictures)
- return false;
- }
- }
- }
-
- // Samsung Galaxy Tab A, J3, and J1 Mini all like to crash on Lollipop in
- // glEGLImageTargetTexture2DOES . These include SM-J105, SM-J111, SM-J120,
- // SM-T280, SM-T285, and SM-J320 with various suffixes. All run lollipop and
- // and have a Mali-400 gpu.
- // For these devices, we must check based on the brand / model
- // number, since the strings used by FeatureInfo aren't populated.
- if (base::android::BuildInfo::GetInstance()->sdk_int() <= 22) { // L MR1
- const std::string brand(
- base::ToLowerASCII(base::android::BuildInfo::GetInstance()->brand()));
- if (brand == "samsung") {
- const std::string model(
- base::ToLowerASCII(base::android::BuildInfo::GetInstance()->model()));
- if (model.find("sm-j105") != std::string::npos ||
- model.find("sm-j111") != std::string::npos ||
- model.find("sm-j120") != std::string::npos ||
- model.find("sm-t280") != std::string::npos ||
- model.find("sm-t285") != std::string::npos ||
- model.find("sm-j320") != std::string::npos)
- return false;
- }
- }
-
- return true;
-}
-
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698