1 // Copyright 2019 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 "components/thin_webview/internal/compositor_view_impl.h"
6 
7 #include <android/native_window_jni.h>
8 
9 #include <memory>
10 
11 #include "base/android/jni_android.h"
12 #include "cc/layers/solid_color_layer.h"
13 #include "components/thin_webview/internal/jni_headers/CompositorViewImpl_jni.h"
14 #include "content/public/browser/android/compositor.h"
15 #include "third_party/skia/include/core/SkColor.h"
16 #include "ui/android/window_android.h"
17 
18 using base::android::JavaParamRef;
19 using base::android::JavaRef;
20 
21 namespace thin_webview {
22 namespace android {
23 namespace {
24 const int kPixelFormatUnknown = 0;
25 }  // namespace
26 
JNI_CompositorViewImpl_Init(JNIEnv * env,const JavaParamRef<jobject> & obj,const JavaParamRef<jobject> & jwindow_android,jint java_background_color)27 jlong JNI_CompositorViewImpl_Init(JNIEnv* env,
28                                   const JavaParamRef<jobject>& obj,
29                                   const JavaParamRef<jobject>& jwindow_android,
30                                   jint java_background_color) {
31   ui::WindowAndroid* window_android =
32       ui::WindowAndroid::FromJavaWindowAndroid(jwindow_android);
33   auto compositor_view = std::make_unique<CompositorViewImpl>(
34       env, obj, window_android, java_background_color);
35   return reinterpret_cast<intptr_t>(compositor_view.release());
36 }
37 
38 // static
FromJavaObject(const base::android::JavaRef<jobject> & jcompositor_view)39 CompositorView* CompositorView::FromJavaObject(
40     const base::android::JavaRef<jobject>& jcompositor_view) {
41   if (jcompositor_view.is_null())
42     return nullptr;
43 
44   return reinterpret_cast<CompositorViewImpl*>(
45       Java_CompositorViewImpl_getNativePtr(base::android::AttachCurrentThread(),
46                                            jcompositor_view));
47 }
48 
CompositorViewImpl(JNIEnv * env,jobject obj,ui::WindowAndroid * window_android,int64_t java_background_color)49 CompositorViewImpl::CompositorViewImpl(JNIEnv* env,
50                                        jobject obj,
51                                        ui::WindowAndroid* window_android,
52                                        int64_t java_background_color)
53     : obj_(env, obj),
54       root_layer_(cc::SolidColorLayer::Create()),
55       current_surface_format_(kPixelFormatUnknown) {
56   compositor_.reset(content::Compositor::Create(this, window_android));
57   root_layer_->SetIsDrawable(true);
58   root_layer_->SetBackgroundColor(static_cast<SkColor>(java_background_color));
59 }
60 
61 CompositorViewImpl::~CompositorViewImpl() = default;
62 
Destroy(JNIEnv * env,const JavaParamRef<jobject> & object)63 void CompositorViewImpl::Destroy(JNIEnv* env,
64                                  const JavaParamRef<jobject>& object) {
65   delete this;
66 }
67 
SurfaceCreated(JNIEnv * env,const JavaParamRef<jobject> & object)68 void CompositorViewImpl::SurfaceCreated(JNIEnv* env,
69                                         const JavaParamRef<jobject>& object) {
70   compositor_->SetRootLayer(root_layer_);
71   current_surface_format_ = kPixelFormatUnknown;
72 }
73 
SurfaceDestroyed(JNIEnv * env,const JavaParamRef<jobject> & object)74 void CompositorViewImpl::SurfaceDestroyed(JNIEnv* env,
75                                           const JavaParamRef<jobject>& object) {
76   compositor_->SetSurface(nullptr, false);
77   current_surface_format_ = kPixelFormatUnknown;
78 }
79 
SurfaceChanged(JNIEnv * env,const JavaParamRef<jobject> & object,jint format,jint width,jint height,bool can_be_used_with_surface_control,const JavaParamRef<jobject> & surface)80 void CompositorViewImpl::SurfaceChanged(JNIEnv* env,
81                                         const JavaParamRef<jobject>& object,
82                                         jint format,
83                                         jint width,
84                                         jint height,
85                                         bool can_be_used_with_surface_control,
86                                         const JavaParamRef<jobject>& surface) {
87   DCHECK(surface);
88   if (current_surface_format_ != format) {
89     current_surface_format_ = format;
90     compositor_->SetSurface(surface, can_be_used_with_surface_control);
91   }
92 
93   gfx::Size content_size(width, height);
94   compositor_->SetWindowBounds(content_size);
95   root_layer_->SetBounds(content_size);
96 }
97 
SetNeedsComposite(JNIEnv * env,const JavaParamRef<jobject> & object)98 void CompositorViewImpl::SetNeedsComposite(
99     JNIEnv* env,
100     const JavaParamRef<jobject>& object) {
101   compositor_->SetNeedsComposite();
102 }
103 
SetRootLayer(scoped_refptr<cc::Layer> layer)104 void CompositorViewImpl::SetRootLayer(scoped_refptr<cc::Layer> layer) {
105   const cc::LayerList& children = root_layer_->children();
106   DCHECK(children.size() <= 1);
107   if (!children.empty() && children[0]->id() == layer->id())
108     return;
109 
110   root_layer_->RemoveAllChildren();
111   root_layer_->InsertChild(layer, 0);
112 }
113 
RecreateSurface()114 void CompositorViewImpl::RecreateSurface() {
115   JNIEnv* env = base::android::AttachCurrentThread();
116   compositor_->SetSurface(nullptr, false);
117   Java_CompositorViewImpl_recreateSurface(env, obj_);
118 }
119 
UpdateLayerTreeHost()120 void CompositorViewImpl::UpdateLayerTreeHost() {
121   JNIEnv* env = base::android::AttachCurrentThread();
122   Java_CompositorViewImpl_onCompositorLayout(env, obj_);
123 }
124 
125 }  // namespace android
126 }  // namespace thin_webview
127