12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/surface_texture_transport_client_android.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <android/native_window_jni.h> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/video_layer.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/gpu/gpu_surface_tracker.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/compositor_impl_android.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/renderer_host/image_transport_factory_android.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h" 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2ext.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gl/android/surface_texture_bridge.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace content { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const uint32 kGLTextureExternalOES = 0x8D65; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SurfaceRefAndroid( 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const scoped_refptr<gfx::SurfaceTextureBridge>& surface, 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ANativeWindow* window) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : surface_(surface), 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) window_(window) { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ANativeWindow_acquire(window_); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~SurfaceRefAndroid() { 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(window_); 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ANativeWindow_release(window_); 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<gfx::SurfaceTextureBridge> surface_; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ANativeWindow* window_; 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // anonymous namespace 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SurfaceTextureTransportClient::SurfaceTextureTransportClient() 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : window_(NULL), 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) texture_id_(0), 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch texture_mailbox_sync_point_(0), 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) surface_id_(0), 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_(this) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SurfaceTextureTransportClient::~SurfaceTextureTransportClient() { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() { 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Use a SurfaceTexture to stream frames to the UI thread. 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_layer_ = cc::VideoLayer::Create(this); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) surface_texture_ = new gfx::SurfaceTextureBridge(0); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) surface_texture_->SetFrameAvailableCallback( 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind( 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable, 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_factory_.GetWeakPtr())); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) surface_texture_->DetachFromGLContext(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return video_layer_.get(); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::GLSurfaceHandle 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SurfaceTextureTransportClient::GetCompositingSurface(int surface_id) { 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(surface_id); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) surface_id_ = surface_id; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!window_) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) window_ = surface_texture_->CreateSurface(); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GpuSurfaceTracker::Get()->SetNativeWidget( 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) surface_id, window_, new SurfaceRefAndroid(surface_texture_, window_)); 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // SurfaceRefAndroid took ownership (and an extra ref to) window_. 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ANativeWindow_release(window_); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SurfaceTextureTransportClient::SetSize(const gfx::Size& size) { 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (size.width() > 0 && size.height() > 0) { 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) surface_texture_->SetDefaultBufferSize(size.width(), size.height()); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_layer_->SetBounds(size); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_frame_ = NULL; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_refptr<media::VideoFrame> SurfaceTextureTransportClient:: 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetCurrentFrame() { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!texture_id_) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebKit::WebGraphicsContext3D* context = 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ImageTransportFactoryAndroid::GetInstance()->GetContext3D(); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) context->makeContextCurrent(); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) texture_id_ = context->createTexture(); 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context->bindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_); 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) context->flush(); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) surface_texture_->AttachToGLContext(); 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch context->genMailboxCHROMIUM(texture_mailbox_.name); 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch context->produceTextureCHROMIUM(kGLTextureExternalOES, 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch texture_mailbox_.name); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch texture_mailbox_sync_point_ = context->insertSyncPoint(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!video_frame_.get()) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size size = video_layer_->bounds(); 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_frame_ = media::VideoFrame::WrapNativeTexture( 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new media::VideoFrame::MailboxHolder( 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch texture_mailbox_, 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch texture_mailbox_sync_point_, 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch media::VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()), 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch kGLTextureExternalOES, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect(gfx::Point(), size), 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta(), 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) media::VideoFrame::ReadPixelsCB(), 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Closure()); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) surface_texture_->UpdateTexImage(); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return video_frame_; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SurfaceTextureTransportClient::PutCurrentFrame( 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const scoped_refptr<media::VideoFrame>& frame) { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable() { 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) video_layer_->SetNeedsDisplay(); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace content 144