1// Copyright (c) 2013 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 "ui/gl/android/surface_texture_bridge.h"
6
7#include <android/native_window_jni.h>
8
9// TODO(boliu): Remove this include when we move off ICS.
10#include "base/android/build_info.h"
11#include "base/android/jni_android.h"
12#include "base/logging.h"
13#include "jni/SurfaceTextureBridge_jni.h"
14#include "ui/gl/android/scoped_java_surface.h"
15#include "ui/gl/android/surface_texture_listener.h"
16#include "ui/gl/gl_bindings.h"
17
18// TODO(boliu): Remove this method when when we move off ICS. See
19// http://crbug.com/161864.
20bool GlContextMethodsAvailable() {
21  bool available = base::android::BuildInfo::GetInstance()->sdk_int() >= 16;
22  if (!available)
23    LOG(WARNING) << "Running on unsupported device: rendering may not work";
24  return available;
25}
26
27namespace gfx {
28
29SurfaceTextureBridge::SurfaceTextureBridge(int texture_id) {
30  JNIEnv* env = base::android::AttachCurrentThread();
31  j_surface_texture_.Reset(Java_SurfaceTextureBridge_create(env, texture_id));
32}
33
34SurfaceTextureBridge::~SurfaceTextureBridge() {
35  JNIEnv* env = base::android::AttachCurrentThread();
36  Java_SurfaceTextureBridge_destroy(env, j_surface_texture_.obj());
37}
38
39void SurfaceTextureBridge::SetFrameAvailableCallback(
40    const base::Closure& callback) {
41  JNIEnv* env = base::android::AttachCurrentThread();
42  Java_SurfaceTextureBridge_setFrameAvailableCallback(
43      env,
44      j_surface_texture_.obj(),
45      reinterpret_cast<int>(new SurfaceTextureListener(callback)));
46}
47
48void SurfaceTextureBridge::UpdateTexImage() {
49  JNIEnv* env = base::android::AttachCurrentThread();
50  Java_SurfaceTextureBridge_updateTexImage(env, j_surface_texture_.obj());
51}
52
53void SurfaceTextureBridge::GetTransformMatrix(float mtx[16]) {
54  JNIEnv* env = base::android::AttachCurrentThread();
55
56  base::android::ScopedJavaLocalRef<jfloatArray> jmatrix(
57      env, env->NewFloatArray(16));
58  Java_SurfaceTextureBridge_getTransformMatrix(
59      env, j_surface_texture_.obj(), jmatrix.obj());
60
61  jboolean is_copy;
62  jfloat* elements = env->GetFloatArrayElements(jmatrix.obj(), &is_copy);
63  for (int i = 0; i < 16; ++i) {
64    mtx[i] = static_cast<float>(elements[i]);
65  }
66  env->ReleaseFloatArrayElements(jmatrix.obj(), elements, JNI_ABORT);
67}
68
69void SurfaceTextureBridge::SetDefaultBufferSize(int width, int height) {
70  JNIEnv* env = base::android::AttachCurrentThread();
71
72  if (width > 0 && height > 0) {
73    Java_SurfaceTextureBridge_setDefaultBufferSize(
74        env, j_surface_texture_.obj(), static_cast<jint>(width),
75        static_cast<jint>(height));
76  } else {
77    LOG(WARNING) << "Not setting surface texture buffer size - "
78                    "width or height is 0";
79  }
80}
81
82void SurfaceTextureBridge::AttachToGLContext() {
83  if (GlContextMethodsAvailable()) {
84    int texture_id;
85    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id);
86    DCHECK(texture_id);
87    JNIEnv* env = base::android::AttachCurrentThread();
88    Java_SurfaceTextureBridge_attachToGLContext(
89        env, j_surface_texture_.obj(), texture_id);
90  }
91}
92
93void SurfaceTextureBridge::DetachFromGLContext() {
94  if (GlContextMethodsAvailable()) {
95    JNIEnv* env = base::android::AttachCurrentThread();
96    Java_SurfaceTextureBridge_detachFromGLContext(
97        env, j_surface_texture_.obj());
98  }
99}
100
101ANativeWindow* SurfaceTextureBridge::CreateSurface() {
102  JNIEnv* env = base::android::AttachCurrentThread();
103  ScopedJavaSurface surface(this);
104  ANativeWindow* native_window = ANativeWindow_fromSurface(
105      env, surface.j_surface().obj());
106  return native_window;
107}
108
109// static
110bool SurfaceTextureBridge::RegisterSurfaceTextureBridge(JNIEnv* env) {
111  return RegisterNativesImpl(env);
112}
113
114}  // namespace gfx
115