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

Unified Diff: content/common/gpu/media/android_deferred_rendering_backing_strategy.cc

Issue 1785153004: Made full screen video with DevTools not flash black on Android. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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: content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
diff --git a/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc b/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
index 67aa497f5483f7cf0b2a8a9f359fbcd3d66c0c1b..bd55f0080e15622d2068978316af25646ffb67bc 100644
--- a/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
+++ b/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
@@ -41,7 +41,9 @@ const float kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f,
AndroidDeferredRenderingBackingStrategy::
AndroidDeferredRenderingBackingStrategy(AVDAStateProvider* state_provider)
- : state_provider_(state_provider), media_codec_(nullptr) {}
+ : state_provider_(state_provider),
+ transparent_image_(EGL_NO_IMAGE_KHR),
+ media_codec_(nullptr) {}
AndroidDeferredRenderingBackingStrategy::
~AndroidDeferredRenderingBackingStrategy() {}
@@ -61,6 +63,13 @@ gfx::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize(
if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) {
surface =
GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_view_id);
+
+ // We will attach a transparent image to the PictureBuffer textures, so
+ // that the device inspector still works. In addition to drawing them
+ // as overlays, it will draw them as normal quads, too. The transparent
+ // image lets the SurfaceView show through on the device.
+ transparent_image_ = CreateImageFromTexture(
+ &AndroidDeferredRenderingBackingStrategy::InitTransparentTexture);
} else {
if (DoesSurfaceTextureDetachWork()) {
// Create a detached SurfaceTexture. Detaching it will silently fail to
@@ -86,6 +95,15 @@ void AndroidDeferredRenderingBackingStrategy::Cleanup(
if (!shared_state_)
return;
+ if (have_context && transparent_image_ != EGL_NO_IMAGE_KHR) {
+ EGLBoolean result = eglDestroyImageKHR(
+ gfx::GLSurfaceEGL::GetHardwareDisplay(), transparent_image_);
+ if (result == EGL_FALSE) {
+ DLOG(ERROR) << "Error destroying transparent EGLImage: "
DaleCurtis 2016/03/11 19:23:36 Return?
liberato (no reviews please) 2016/03/11 19:53:57 we want to continune with cleanup. i'll add a com
+ << ui::GetLastEGLErrorString();
+ }
+ }
+
// 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)
@@ -187,13 +205,28 @@ void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer(
}
void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer(
- const media::PictureBuffer& picture_buffer) {
+ const media::PictureBuffer& picture_buffer,
+ bool have_context) {
// Attach a GLImage to each texture that will use the surface texture.
// We use a refptr here in case SetImageForPicture fails.
scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image =
new AVDACodecImage(shared_state_, media_codec_,
state_provider_->GetGlDecoder(), surface_texture_);
SetImageForPicture(picture_buffer, gl_image);
+
+ if (!surface_texture_ && transparent_image_ != EGL_NO_IMAGE_KHR) {
+ // Attach a transparent image if we're using SurfaceView, so that devtools
+ // draws that. It lets us see through to the SV on the device, since it's
+ // drawn there too. Without devtools, this image is never drawn.
+ gpu::gles2::TextureRef* texture_ref =
+ state_provider_->GetTextureForPicture(picture_buffer);
+ if (have_context && texture_ref) {
+ gfx::ScopedTextureBinder texture_binder(
+ GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id());
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, transparent_image_);
+ DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ }
+ }
}
void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture(
@@ -262,6 +295,37 @@ void AndroidDeferredRenderingBackingStrategy::UpdatePictureBufferSize(
picture_buffer->set_size(new_size);
}
+bool AndroidDeferredRenderingBackingStrategy::InitTextureWithCopy(
+ GLint source_id) {
+ gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get();
+ if (!gl_decoder)
+ return false;
+
+ const gfx::Size size = state_provider_->GetSize();
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ 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, source_id,
+ size.width(), size.height(), false, false, false, kIdentityMatrix);
+
+ return true;
+}
+
+bool AndroidDeferredRenderingBackingStrategy::InitTransparentTexture(
+ GLint source_id) {
+ unsigned char rgba[] = {0, 0, 0, 0};
+ const gfx::Size size(1, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+ return true;
+}
+
void AndroidDeferredRenderingBackingStrategy::CopySurfaceTextureToPictures(
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {
DVLOG(3) << __FUNCTION__;
@@ -271,55 +335,17 @@ void AndroidDeferredRenderingBackingStrategy::CopySurfaceTextureToPictures(
if (!shared_state_->surface_texture_is_attached())
return;
- gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get();
- if (!gl_decoder)
- return;
-
// Mali + <= KitKat crashes when we try to do this. We don't know if it's
// due to detaching a surface texture, but it's the same set of devices.
if (!DoesSurfaceTextureDetachWork())
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);
- }
-
- // TODO(liberato,watk): Use the SurfaceTexture matrix when copying.
- 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(), false, false, false,
- kIdentityMatrix);
-
- // 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());
+ EGLImageKHR egl_image = CreateImageFromTexture(
+ &AndroidDeferredRenderingBackingStrategy::InitTextureWithCopy);
if (egl_image == EGL_NO_IMAGE_KHR) {
- DLOG(ERROR) << "Failed creating EGLImage: " << ui::GetLastEGLErrorString();
+ DLOG(ERROR) << "Failed creating EGLImage for full screen transition: "
+ << ui::GetLastEGLErrorString();
return;
}
@@ -337,7 +363,7 @@ void AndroidDeferredRenderingBackingStrategy::CopySurfaceTextureToPictures(
EGLBoolean result =
eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image);
if (result == EGL_FALSE) {
- DLOG(ERROR) << "Error destroying EGLImage: "
+ DLOG(ERROR) << "Error destroying EGLImage for transition: "
<< ui::GetLastEGLErrorString();
}
}
@@ -358,4 +384,42 @@ bool AndroidDeferredRenderingBackingStrategy::DoesSurfaceTextureDetachWork()
return surface_texture_detach_works;
}
+EGLImageKHR AndroidDeferredRenderingBackingStrategy::CreateImageFromTexture(
+ bool (AndroidDeferredRenderingBackingStrategy::*init_texture)(GLint)) {
+ // 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);
+
+ if (!(this->*init_texture)(tmp_texture_id)) {
+ glDeleteTextures(1, &tmp_texture_id);
+ return EGL_NO_IMAGE_KHR;
+ }
+ // Note that tmp_texture_id might not be bound, which is okay.
+ }
+
+ // 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 egl_image;
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698