blob: c4206a983e67b1c3fa3d068e26459a1104b4be5c [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// 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/SurfaceTexture_jni.h"
14#include "ui/gl/android/scoped_java_surface.h"
15#include "ui/gl/android/surface_texture_listener.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010016#include "ui/gl/gl_bindings.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010017
18using base::android::AttachCurrentThread;
19using base::android::CheckException;
20using base::android::GetClass;
21using base::android::ScopedJavaLocalRef;
22
23namespace {
24bool g_jni_initialized = false;
25
26void RegisterNativesIfNeeded(JNIEnv* env) {
27 if (!g_jni_initialized) {
28 JNI_SurfaceTexture::RegisterNativesImpl(env);
29 g_jni_initialized = true;
30 }
31}
32
33// TODO(boliu): Remove this method when when we move off ICS. See
34// http://crbug.com/161864.
35bool GlContextMethodsAvailable() {
36 bool available = base::android::BuildInfo::GetInstance()->sdk_int() >= 16;
37 if (!available)
38 LOG(WARNING) << "Running on unsupported device: rendering may not work";
39 return available;
40}
41
42} // namespace
43
44namespace gfx {
45
Ben Murdochbb1529c2013-08-08 10:24:53 +010046SurfaceTextureBridge::SurfaceTextureBridge(int texture_id) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010047 JNIEnv* env = AttachCurrentThread();
48 CHECK(env);
49 RegisterNativesIfNeeded(env);
50
51 ScopedJavaLocalRef<jobject> tmp(
52 JNI_SurfaceTexture::Java_SurfaceTexture_Constructor(
53 env, texture_id));
54 DCHECK(!tmp.is_null());
55 j_surface_texture_.Reset(tmp);
56}
57
58SurfaceTextureBridge::~SurfaceTextureBridge() {
59 JNIEnv* env = AttachCurrentThread();
60 CHECK(env);
61
62 // Release the listener.
63 JNI_SurfaceTexture::Java_SurfaceTexture_setOnFrameAvailableListener(
64 env, j_surface_texture_.obj(), NULL);
65
66 // Release graphics memory.
67 JNI_SurfaceTexture::Java_SurfaceTexture_release(
68 env, j_surface_texture_.obj());
69}
70
71void SurfaceTextureBridge::SetFrameAvailableCallback(
72 const base::Closure& callback) {
73 JNIEnv* env = AttachCurrentThread();
74 CHECK(env);
75
76 // Since the listener is owned by the Java SurfaceTexture object, setting
77 // a new listener here will release an existing one at the same time.
78 ScopedJavaLocalRef<jobject> j_listener(
79 env,
80 SurfaceTextureListener::CreateSurfaceTextureListener(env, callback));
81 DCHECK(!j_listener.is_null());
82
83 // Set it as the onFrameAvailableListener for our SurfaceTexture instance.
84 JNI_SurfaceTexture::Java_SurfaceTexture_setOnFrameAvailableListener(
85 env, j_surface_texture_.obj(), j_listener.obj());
86}
87
88void SurfaceTextureBridge::UpdateTexImage() {
89 JNIEnv* env = AttachCurrentThread();
90 CHECK(env);
91
92 JNI_SurfaceTexture::Java_SurfaceTexture_updateTexImage(
93 env, j_surface_texture_.obj());
94}
95
96void SurfaceTextureBridge::GetTransformMatrix(float mtx[16]) {
97 JNIEnv* env = AttachCurrentThread();
98 CHECK(env);
99
100 ScopedJavaLocalRef<jfloatArray> jmatrix(env, env->NewFloatArray(16));
101 JNI_SurfaceTexture::Java_SurfaceTexture_getTransformMatrix(
102 env, j_surface_texture_.obj(), jmatrix.obj());
103
104 jboolean is_copy;
105 jfloat* elements = env->GetFloatArrayElements(jmatrix.obj(), &is_copy);
106 for (int i = 0; i < 16; ++i) {
107 mtx[i] = static_cast<float>(elements[i]);
108 }
109 env->ReleaseFloatArrayElements(jmatrix.obj(), elements, JNI_ABORT);
110}
111
112void SurfaceTextureBridge::SetDefaultBufferSize(int width, int height) {
113 JNIEnv* env = AttachCurrentThread();
114 CHECK(env);
115
116 if (width > 0 && height > 0) {
117 JNI_SurfaceTexture::Java_SurfaceTexture_setDefaultBufferSize(
118 env, j_surface_texture_.obj(), static_cast<jint>(width),
119 static_cast<jint>(height));
120 } else {
121 LOG(WARNING) << "Not setting surface texture buffer size - "
122 "width or height is 0";
123 }
124}
125
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100126void SurfaceTextureBridge::AttachToGLContext() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100127 if (GlContextMethodsAvailable()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100128 int texture_id;
129 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id);
130 DCHECK(texture_id);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100131 JNIEnv* env = AttachCurrentThread();
132 // Note: This method is only available on JB and greater.
133 JNI_SurfaceTexture::Java_SurfaceTexture_attachToGLContext(
134 env, j_surface_texture_.obj(), texture_id);
135 }
136}
137
138void SurfaceTextureBridge::DetachFromGLContext() {
139 if (GlContextMethodsAvailable()) {
140 JNIEnv* env = AttachCurrentThread();
141 // Note: This method is only available on JB and greater.
142 JNI_SurfaceTexture::Java_SurfaceTexture_detachFromGLContext(
143 env, j_surface_texture_.obj());
144 }
145}
146
147ANativeWindow* SurfaceTextureBridge::CreateSurface() {
148 JNIEnv* env = AttachCurrentThread();
149 ScopedJavaSurface surface(this);
150 ANativeWindow* native_window =
151 ANativeWindow_fromSurface(env, surface.j_surface().obj());
152 return native_window;
153}
154
155} // namespace gfx