1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "content/browser/renderer_host/surface_texture_transport_client_android.h" 6 7 #include <android/native_window_jni.h> 8 9 #include "base/bind.h" 10 #include "cc/layers/video_layer.h" 11 #include "content/browser/gpu/gpu_surface_tracker.h" 12 #include "content/browser/renderer_host/compositor_impl_android.h" 13 #include "content/browser/renderer_host/image_transport_factory_android.h" 14 #include "content/public/browser/browser_thread.h" 15 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" 16 #include "third_party/khronos/GLES2/gl2.h" 17 #include "third_party/khronos/GLES2/gl2ext.h" 18 #include "ui/gl/android/surface_texture_bridge.h" 19 20 namespace content { 21 22 namespace { 23 24 static const uint32 kGLTextureExternalOES = 0x8D65; 25 26 class SurfaceRefAndroid : public GpuSurfaceTracker::SurfaceRef { 27 public: 28 SurfaceRefAndroid( 29 const scoped_refptr<gfx::SurfaceTextureBridge>& surface, 30 ANativeWindow* window) 31 : surface_(surface), 32 window_(window) { 33 ANativeWindow_acquire(window_); 34 } 35 36 private: 37 virtual ~SurfaceRefAndroid() { 38 DCHECK(window_); 39 ANativeWindow_release(window_); 40 } 41 42 scoped_refptr<gfx::SurfaceTextureBridge> surface_; 43 ANativeWindow* window_; 44 }; 45 46 } // anonymous namespace 47 48 SurfaceTextureTransportClient::SurfaceTextureTransportClient() 49 : window_(NULL), 50 texture_id_(0), 51 texture_mailbox_sync_point_(0), 52 surface_id_(0), 53 weak_factory_(this) { 54 } 55 56 SurfaceTextureTransportClient::~SurfaceTextureTransportClient() { 57 } 58 59 scoped_refptr<cc::Layer> SurfaceTextureTransportClient::Initialize() { 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 61 // Use a SurfaceTexture to stream frames to the UI thread. 62 video_layer_ = cc::VideoLayer::Create(this); 63 64 surface_texture_ = new gfx::SurfaceTextureBridge(0); 65 surface_texture_->SetFrameAvailableCallback( 66 base::Bind( 67 &SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable, 68 weak_factory_.GetWeakPtr())); 69 surface_texture_->DetachFromGLContext(); 70 return video_layer_.get(); 71 } 72 73 gfx::GLSurfaceHandle 74 SurfaceTextureTransportClient::GetCompositingSurface(int surface_id) { 75 DCHECK(surface_id); 76 surface_id_ = surface_id; 77 78 if (!window_) { 79 window_ = surface_texture_->CreateSurface(); 80 81 GpuSurfaceTracker::Get()->SetNativeWidget( 82 surface_id, window_, new SurfaceRefAndroid(surface_texture_, window_)); 83 // SurfaceRefAndroid took ownership (and an extra ref to) window_. 84 ANativeWindow_release(window_); 85 } 86 87 return gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT); 88 } 89 90 void SurfaceTextureTransportClient::SetSize(const gfx::Size& size) { 91 if (size.width() > 0 && size.height() > 0) { 92 surface_texture_->SetDefaultBufferSize(size.width(), size.height()); 93 } 94 video_layer_->SetBounds(size); 95 video_frame_ = NULL; 96 } 97 98 scoped_refptr<media::VideoFrame> SurfaceTextureTransportClient:: 99 GetCurrentFrame() { 100 if (!texture_id_) { 101 WebKit::WebGraphicsContext3D* context = 102 ImageTransportFactoryAndroid::GetInstance()->GetContext3D(); 103 context->makeContextCurrent(); 104 texture_id_ = context->createTexture(); 105 context->bindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id_); 106 context->flush(); 107 surface_texture_->AttachToGLContext(); 108 109 context->genMailboxCHROMIUM(texture_mailbox_.name); 110 context->produceTextureCHROMIUM(kGLTextureExternalOES, 111 texture_mailbox_.name); 112 texture_mailbox_sync_point_ = context->insertSyncPoint(); 113 } 114 if (!video_frame_.get()) { 115 const gfx::Size size = video_layer_->bounds(); 116 video_frame_ = media::VideoFrame::WrapNativeTexture( 117 new media::VideoFrame::MailboxHolder( 118 texture_mailbox_, 119 texture_mailbox_sync_point_, 120 media::VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()), 121 kGLTextureExternalOES, 122 size, 123 gfx::Rect(gfx::Point(), size), 124 size, 125 base::TimeDelta(), 126 media::VideoFrame::ReadPixelsCB(), 127 base::Closure()); 128 } 129 surface_texture_->UpdateTexImage(); 130 131 return video_frame_; 132 } 133 134 void SurfaceTextureTransportClient::PutCurrentFrame( 135 const scoped_refptr<media::VideoFrame>& frame) { 136 } 137 138 void SurfaceTextureTransportClient::OnSurfaceTextureFrameAvailable() { 139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 140 video_layer_->SetNeedsDisplay(); 141 } 142 143 } // namespace content 144