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