Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 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/SurfaceTexture_jni.h" |
| 14 | #include "ui/gl/android/scoped_java_surface.h" |
| 15 | #include "ui/gl/android/surface_texture_listener.h" |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 16 | #include "ui/gl/gl_bindings.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 17 | |
| 18 | using base::android::AttachCurrentThread; |
| 19 | using base::android::CheckException; |
| 20 | using base::android::GetClass; |
| 21 | using base::android::ScopedJavaLocalRef; |
| 22 | |
| 23 | namespace { |
| 24 | bool g_jni_initialized = false; |
| 25 | |
| 26 | void 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. |
| 35 | bool 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 | |
| 44 | namespace gfx { |
| 45 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 46 | SurfaceTextureBridge::SurfaceTextureBridge(int texture_id) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 47 | 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 | |
| 58 | SurfaceTextureBridge::~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 | |
| 71 | void 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 | |
| 88 | void SurfaceTextureBridge::UpdateTexImage() { |
| 89 | JNIEnv* env = AttachCurrentThread(); |
| 90 | CHECK(env); |
| 91 | |
| 92 | JNI_SurfaceTexture::Java_SurfaceTexture_updateTexImage( |
| 93 | env, j_surface_texture_.obj()); |
| 94 | } |
| 95 | |
| 96 | void 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 | |
| 112 | void 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) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 126 | void SurfaceTextureBridge::AttachToGLContext() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 127 | if (GlContextMethodsAvailable()) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 128 | int texture_id; |
| 129 | glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id); |
| 130 | DCHECK(texture_id); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 131 | 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 | |
| 138 | void 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 | |
| 147 | ANativeWindow* 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 |