Home | History | Annotate | Download | only in renderer_host
      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