summaryrefslogtreecommitdiff
path: root/chromium/components/webxr/android/arcore_java_utils.cc
blob: 028a8711db1e4a938a062cd8ca45bb2ed28057c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/webxr/android/arcore_java_utils.h"

#include <memory>
#include <utility>

#include "base/android/jni_string.h"
#include "components/webxr/android/ar_jni_headers/ArCoreJavaUtils_jni.h"
#include "components/webxr/android/webxr_utils.h"
#include "device/vr/android/arcore/arcore_shim.h"
#include "gpu/ipc/common/gpu_surface_tracker.h"
#include "ui/android/window_android.h"

using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;

namespace webxr {

ArCoreJavaUtils::ArCoreJavaUtils(
    webxr::ArCompositorDelegateProvider compositor_delegate_provider)
    : compositor_delegate_provider_(compositor_delegate_provider) {
  JNIEnv* env = AttachCurrentThread();
  if (!env)
    return;
  ScopedJavaLocalRef<jobject> j_arcore_java_utils =
      Java_ArCoreJavaUtils_create(env, (jlong)this);
  if (j_arcore_java_utils.is_null())
    return;
  j_arcore_java_utils_.Reset(j_arcore_java_utils);
}

ArCoreJavaUtils::~ArCoreJavaUtils() {
  JNIEnv* env = AttachCurrentThread();
  Java_ArCoreJavaUtils_onNativeDestroy(env, j_arcore_java_utils_);
}

void ArCoreJavaUtils::RequestArSession(
    int render_process_id,
    int render_frame_id,
    bool use_overlay,
    bool can_render_dom_content,
    device::SurfaceReadyCallback ready_callback,
    device::SurfaceTouchCallback touch_callback,
    device::SurfaceDestroyedCallback destroyed_callback) {
  DVLOG(1) << __func__;
  JNIEnv* env = AttachCurrentThread();

  surface_ready_callback_ = std::move(ready_callback);
  surface_touch_callback_ = std::move(touch_callback);
  surface_destroyed_callback_ = std::move(destroyed_callback);

  Java_ArCoreJavaUtils_startSession(
      env, j_arcore_java_utils_, compositor_delegate_provider_.GetJavaObject(),
      webxr::GetJavaWebContents(render_process_id, render_frame_id),
      use_overlay, can_render_dom_content);
}

void ArCoreJavaUtils::EndSession() {
  DVLOG(1) << __func__;
  JNIEnv* env = AttachCurrentThread();

  Java_ArCoreJavaUtils_endSession(env, j_arcore_java_utils_);
}

void ArCoreJavaUtils::OnDrawingSurfaceReady(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    const base::android::JavaParamRef<jobject>& surface,
    const base::android::JavaParamRef<jobject>& java_root_window,
    int rotation,
    int width,
    int height) {
  DVLOG(1) << __func__ << ": width=" << width << " height=" << height
           << " rotation=" << rotation;
  gfx::AcceleratedWidget window =
      ANativeWindow_fromSurface(base::android::AttachCurrentThread(), surface);
  gpu::SurfaceHandle surface_handle =
      gpu::GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
          gpu::GpuSurfaceTracker::SurfaceRecord(
              window, surface, /*can_be_used_with_surface_control=*/false));
  ui::WindowAndroid* root_window =
      ui::WindowAndroid::FromJavaWindowAndroid(java_root_window);
  display::Display::Rotation display_rotation =
      static_cast<display::Display::Rotation>(rotation);
  surface_ready_callback_.Run(window, surface_handle, root_window,
                              display_rotation, {width, height});
}

void ArCoreJavaUtils::OnDrawingSurfaceTouch(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    bool primary,
    bool touching,
    int32_t pointer_id,
    float x,
    float y) {
  DVLOG(3) << __func__ << ": pointer_id=" << pointer_id
           << " primary=" << primary << " touching=" << touching;
  surface_touch_callback_.Run(primary, touching, pointer_id, {x, y});
}

void ArCoreJavaUtils::OnDrawingSurfaceDestroyed(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj) {
  DVLOG(1) << __func__ << ":::";
  if (surface_destroyed_callback_) {
    std::move(surface_destroyed_callback_).Run();
  }
}

bool ArCoreJavaUtils::EnsureLoaded() {
  DCHECK(device::IsArCoreSupported());

  JNIEnv* env = AttachCurrentThread();

  // TODO(crbug.com/884780): Allow loading the ARCore shim by name instead of by
  // absolute path.
  ScopedJavaLocalRef<jstring> java_path =
      Java_ArCoreJavaUtils_getArCoreShimLibraryPath(env);

  // Crash in debug builds if `java_path` is a null pointer but handle this
  // situation in release builds. This is done by design - the `java_path` will
  // be null only if there was a regression introduced to our gn/gni files w/o
  // causing a build break. In release builds, this approach will result in the
  // site not being able to request an AR session.
  DCHECK(java_path)
      << "Unable to find path to ARCore SDK library - please ensure that "
         "loadable_modules and secondary_abi_loadable_modules are set "
         "correctly when building";
  if (!java_path) {
    LOG(ERROR) << "Unable to find path to ARCore SDK library";
    return false;
  }

  return device::LoadArCoreSdk(
      base::android::ConvertJavaStringToUTF8(env, java_path));
}

ScopedJavaLocalRef<jobject> ArCoreJavaUtils::GetApplicationContext() {
  JNIEnv* env = AttachCurrentThread();
  return Java_ArCoreJavaUtils_getApplicationContext(env);
}

}  // namespace webxr