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/android/content_view_render_view.h"
6
7#include "base/android/jni_android.h"
8#include "base/android/jni_string.h"
9#include "base/android/scoped_java_ref.h"
10#include "base/bind.h"
11#include "base/lazy_instance.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/message_loop/message_loop.h"
14#include "cc/layers/layer.h"
15#include "content/browser/android/content_view_core_impl.h"
16#include "content/public/browser/android/compositor.h"
17#include "content/public/browser/android/content_view_layer_renderer.h"
18#include "jni/ContentViewRenderView_jni.h"
19#include "ui/gfx/android/java_bitmap.h"
20#include "ui/gfx/size.h"
21
22#include <android/bitmap.h>
23#include <android/native_window_jni.h>
24
25using base::android::ScopedJavaLocalRef;
26
27namespace content {
28
29// static
30bool ContentViewRenderView::RegisterContentViewRenderView(JNIEnv* env) {
31  return RegisterNativesImpl(env);
32}
33
34ContentViewRenderView::ContentViewRenderView(JNIEnv* env,
35                                             jobject obj,
36                                             gfx::NativeWindow root_window)
37    : buffers_swapped_during_composite_(false),
38      root_window_(root_window) {
39  java_obj_.Reset(env, obj);
40}
41
42ContentViewRenderView::~ContentViewRenderView() {
43}
44
45// static
46static jlong Init(JNIEnv* env, jobject obj, jlong native_root_window) {
47  gfx::NativeWindow root_window =
48      reinterpret_cast<gfx::NativeWindow>(native_root_window);
49  ContentViewRenderView* content_view_render_view =
50      new ContentViewRenderView(env, obj, root_window);
51  return reinterpret_cast<intptr_t>(content_view_render_view);
52}
53
54void ContentViewRenderView::Destroy(JNIEnv* env, jobject obj) {
55  delete this;
56}
57
58void ContentViewRenderView::SetCurrentContentView(
59    JNIEnv* env, jobject obj, int native_content_view) {
60  InitCompositor();
61  ContentViewCoreImpl* content_view =
62      reinterpret_cast<ContentViewCoreImpl*>(native_content_view);
63  if (content_view)
64    compositor_->SetRootLayer(content_view->GetLayer());
65  else
66    compositor_->SetRootLayer(cc::Layer::Create());
67}
68
69void ContentViewRenderView::SurfaceCreated(
70    JNIEnv* env, jobject obj, jobject jsurface) {
71  InitCompositor();
72  compositor_->SetSurface(jsurface);
73}
74
75void ContentViewRenderView::SurfaceDestroyed(JNIEnv* env, jobject obj) {
76  compositor_->SetSurface(NULL);
77}
78
79void ContentViewRenderView::SurfaceSetSize(
80    JNIEnv* env, jobject obj, jint width, jint height) {
81  compositor_->SetWindowBounds(gfx::Size(width, height));
82}
83
84jboolean ContentViewRenderView::Composite(JNIEnv* env, jobject obj) {
85  if (!compositor_)
86    return false;
87
88  buffers_swapped_during_composite_ = false;
89  compositor_->Composite();
90  return buffers_swapped_during_composite_;
91}
92
93jboolean ContentViewRenderView::CompositeToBitmap(JNIEnv* env, jobject obj,
94                                                  jobject java_bitmap) {
95  gfx::JavaBitmap bitmap(java_bitmap);
96  if (!compositor_ || bitmap.format() != ANDROID_BITMAP_FORMAT_RGBA_8888)
97    return false;
98  return compositor_->CompositeAndReadback(bitmap.pixels(),
99                                           gfx::Rect(bitmap.size()));
100}
101
102void ContentViewRenderView::ScheduleComposite() {
103  JNIEnv* env = base::android::AttachCurrentThread();
104  Java_ContentViewRenderView_requestRender(env, java_obj_.obj());
105}
106
107void ContentViewRenderView::OnSwapBuffersPosted() {
108  buffers_swapped_during_composite_ = true;
109}
110
111void ContentViewRenderView::OnSwapBuffersCompleted() {
112  JNIEnv* env = base::android::AttachCurrentThread();
113  Java_ContentViewRenderView_onSwapBuffersCompleted(env, java_obj_.obj());
114}
115
116void ContentViewRenderView::InitCompositor() {
117  if (!compositor_)
118    compositor_.reset(Compositor::Create(this, root_window_));
119}
120
121}  // namespace content
122