| Index: content/renderer/media/android/webmediaplayer_android.cc
|
| diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc
|
| index 7adb15e764c5066242f2bc070c7ab1abe9077474..2cca558ec100237d1511ad1e2020d9b74b069182 100644
|
| --- a/content/renderer/media/android/webmediaplayer_android.cc
|
| +++ b/content/renderer/media/android/webmediaplayer_android.cc
|
| @@ -65,10 +65,9 @@
|
| #include "third_party/WebKit/public/web/WebFrame.h"
|
| #include "third_party/WebKit/public/web/WebView.h"
|
| #include "third_party/skia/include/core/SkCanvas.h"
|
| +#include "third_party/skia/include/core/SkImage.h"
|
| #include "third_party/skia/include/core/SkPaint.h"
|
| #include "third_party/skia/include/core/SkTypeface.h"
|
| -#include "third_party/skia/include/gpu/GrContext.h"
|
| -#include "third_party/skia/include/gpu/SkGrPixelRef.h"
|
| #include "ui/gfx/image/image.h"
|
|
|
| static const uint32_t kGLTextureExternalOES = 0x8D65;
|
| @@ -109,40 +108,6 @@ void OnReleaseTexture(
|
| gl->ShallowFlushCHROMIUM();
|
| }
|
|
|
| -bool IsSkBitmapProperlySizedTexture(const SkBitmap* bitmap,
|
| - const gfx::Size& size) {
|
| - return bitmap->getTexture() && bitmap->width() == size.width() &&
|
| - bitmap->height() == size.height();
|
| -}
|
| -
|
| -bool AllocateSkBitmapTexture(GrContext* gr,
|
| - SkBitmap* bitmap,
|
| - const gfx::Size& size) {
|
| - DCHECK(gr);
|
| - GrTextureDesc desc;
|
| - // Use kRGBA_8888_GrPixelConfig, not kSkia8888_GrPixelConfig, to avoid
|
| - // RGBA to BGRA conversion.
|
| - desc.fConfig = kRGBA_8888_GrPixelConfig;
|
| - // kRenderTarget_GrTextureFlagBit avoids a copy before readback in skia.
|
| - desc.fFlags = kRenderTarget_GrSurfaceFlag;
|
| - desc.fSampleCnt = 0;
|
| - desc.fOrigin = kTopLeft_GrSurfaceOrigin;
|
| - desc.fWidth = size.width();
|
| - desc.fHeight = size.height();
|
| - sk_sp<GrTexture> texture(gr->textureProvider()->refScratchTexture(
|
| - desc, GrTextureProvider::kExact_ScratchTexMatch));
|
| - if (!texture.get())
|
| - return false;
|
| -
|
| - SkImageInfo info = SkImageInfo::MakeN32Premul(desc.fWidth, desc.fHeight);
|
| - SkGrPixelRef* pixel_ref = new SkGrPixelRef(info, texture.get());
|
| - if (!pixel_ref)
|
| - return false;
|
| - bitmap->setInfo(info);
|
| - bitmap->setPixelRef(pixel_ref)->unref();
|
| - return true;
|
| -}
|
| -
|
| class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient {
|
| public:
|
| explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
|
| @@ -659,31 +624,40 @@ void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
|
| return;
|
| gpu::gles2::GLES2Interface* gl = provider->contextGL();
|
|
|
| - // Copy video texture into a RGBA texture based bitmap first as video texture
|
| - // on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet.
|
| - // The bitmap's size needs to be the same as the video and use naturalSize()
|
| - // here. Check if we could reuse existing texture based bitmap.
|
| - // Otherwise, release existing texture based bitmap and allocate
|
| - // a new one based on video size.
|
| - if (!IsSkBitmapProperlySizedTexture(&bitmap_, naturalSize())) {
|
| - if (!AllocateSkBitmapTexture(provider->grContext(), &bitmap_,
|
| - naturalSize())) {
|
| - return;
|
| - }
|
| + scoped_refptr<VideoFrame> video_frame;
|
| + {
|
| + base::AutoLock auto_lock(current_frame_lock_);
|
| + video_frame = current_frame_;
|
| }
|
|
|
| - unsigned textureId = skia::GrBackendObjectToGrGLTextureInfo(
|
| - (bitmap_.getTexture())->getTextureHandle())
|
| - ->fID;
|
| - if (!copyVideoTextureToPlatformTexture(gl, textureId, GL_RGBA,
|
| - GL_UNSIGNED_BYTE, true, false)) {
|
| + if (!video_frame.get() || !video_frame->HasTextures())
|
| return;
|
| - }
|
| + DCHECK_EQ(1u, media::VideoFrame::NumPlanes(video_frame->format()));
|
| + const gpu::MailboxHolder& mailbox_holder = video_frame->mailbox_holder(0);
|
| +
|
| + gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
|
| +
|
| + uint32_t src_texture = gl->CreateAndConsumeTextureCHROMIUM(
|
| + mailbox_holder.texture_target, mailbox_holder.mailbox.name);
|
| +
|
| + GrGLTextureInfo texture_info;
|
| + texture_info.fID = src_texture;
|
| + texture_info.fTarget = mailbox_holder.texture_target;
|
| +
|
| + GrBackendTextureDesc desc;
|
| + desc.fWidth = naturalSize().width;
|
| + desc.fHeight = naturalSize().height;
|
| + desc.fOrigin = kTopLeft_GrSurfaceOrigin;
|
| + desc.fConfig = kRGBA_8888_GrPixelConfig;
|
| + desc.fSampleCnt = 0;
|
| + desc.fTextureHandle = skia::GrGLTextureInfoToGrBackendObject(texture_info);
|
|
|
| - // Ensure SkBitmap to make the latest change by external source visible.
|
| - bitmap_.notifyPixelsChanged();
|
| + sk_sp<SkImage> image(SkImage::MakeFromTexture(provider->grContext(), desc,
|
| + kOpaque_SkAlphaType));
|
| + if (!image)
|
| + return;
|
|
|
| - // Draw the texture based bitmap onto the Canvas. If the canvas is
|
| + // Draw the texture based image onto the Canvas. If the canvas is
|
| // hardware based, this will do a GPU-GPU texture copy.
|
| // If the canvas is software based, the texture based bitmap will be
|
| // readbacked to system memory then draw onto the canvas.
|
| @@ -694,8 +668,16 @@ void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
|
| paint.setXfermodeMode(mode);
|
| // It is not necessary to pass the dest into the drawBitmap call since all
|
| // the context have been set up before calling paintCurrentFrameInContext.
|
| - canvas->drawBitmapRect(bitmap_, dest, &paint);
|
| + canvas->drawImageRect(image, dest, &paint);
|
| +
|
| + // Ensure the Skia draw of the GL texture is flushed to GL, delete the
|
| + // mailboxed texture from this context, and then signal that we're done with
|
| + // the video frame.
|
| canvas->flush();
|
| + gl->DeleteTextures(1, &src_texture);
|
| + gl->Flush();
|
| + SyncTokenClientImpl client(gl);
|
| + video_frame->UpdateReleaseSyncToken(&client);
|
| }
|
|
|
| bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
|
|
|