android_view_TextureView.cpp revision 9d4efdf2802f06ccf7031610891f75af70ea5538
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "jni.h" 18#include <nativehelper/JNIHelp.h> 19#include <android_runtime/AndroidRuntime.h> 20#include <android_runtime/android_graphics_SurfaceTexture.h> 21 22#include <ui/Region.h> 23#include <ui/Rect.h> 24 25#include <gui/GLConsumer.h> 26#include <gui/Surface.h> 27 28#include <SkBitmap.h> 29#include <SkCanvas.h> 30#include <SkImage.h> 31 32#include "android/graphics/GraphicsJNI.h" 33 34#include "core_jni_helpers.h" 35 36namespace android { 37 38// ---------------------------------------------------------------------------- 39// JNI Glue 40// ---------------------------------------------------------------------------- 41 42static struct { 43 jmethodID set; 44 jfieldID left; 45 jfieldID top; 46 jfieldID right; 47 jfieldID bottom; 48} gRectClassInfo; 49 50static struct { 51 jfieldID mSurfaceFormat; 52 jmethodID setNativeBitmap; 53} gCanvasClassInfo; 54 55static struct { 56 jfieldID nativeWindow; 57} gTextureViewClassInfo; 58 59#define GET_INT(object, field) \ 60 env->GetIntField(object, field) 61 62#define GET_LONG(object, field) \ 63 env->GetLongField(object, field) 64 65#define SET_INT(object, field, value) \ 66 env->SetIntField(object, field, value) 67 68#define SET_LONG(object, field, value) \ 69 env->SetLongField(object, field, value) 70 71#define INVOKEV(object, method, ...) \ 72 env->CallVoidMethod(object, method, __VA_ARGS__) 73 74// ---------------------------------------------------------------------------- 75// Native layer 76// ---------------------------------------------------------------------------- 77 78// FIXME: consider exporting this to share (e.g. android_view_Surface.cpp) 79static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer) { 80 SkImageInfo info; 81 info.fWidth = buffer.width; 82 info.fHeight = buffer.height; 83 switch (buffer.format) { 84 case WINDOW_FORMAT_RGBA_8888: 85 info.fColorType = kN32_SkColorType; 86 info.fAlphaType = kPremul_SkAlphaType; 87 break; 88 case WINDOW_FORMAT_RGBX_8888: 89 info.fColorType = kN32_SkColorType; 90 info.fAlphaType = kOpaque_SkAlphaType; 91 break; 92 case WINDOW_FORMAT_RGB_565: 93 info.fColorType = kRGB_565_SkColorType; 94 info.fAlphaType = kOpaque_SkAlphaType; 95 break; 96 default: 97 info.fColorType = kUnknown_SkColorType; 98 // switch to kUnknown_SkAlphaType when its in skia 99 info.fAlphaType = kOpaque_SkAlphaType; 100 break; 101 } 102 return info; 103} 104 105/** 106 * This is a private API, and this implementation is also provided in the NDK. 107 * However, the NDK links against android_runtime, which means that using the 108 * NDK implementation would create a circular dependency between the libraries. 109 */ 110static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, 111 Rect* inOutDirtyBounds) { 112 return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); 113} 114 115static int32_t native_window_unlockAndPost(ANativeWindow* window) { 116 return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); 117} 118 119static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, 120 jobject surface) { 121 122 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surface)); 123 sp<ANativeWindow> window = new Surface(producer, true); 124 125 window->incStrong((void*)android_view_TextureView_createNativeWindow); 126 SET_LONG(textureView, gTextureViewClassInfo.nativeWindow, jlong(window.get())); 127} 128 129static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { 130 131 ANativeWindow* nativeWindow = (ANativeWindow*) 132 GET_LONG(textureView, gTextureViewClassInfo.nativeWindow); 133 134 if (nativeWindow) { 135 sp<ANativeWindow> window(nativeWindow); 136 window->decStrong((void*)android_view_TextureView_createNativeWindow); 137 SET_LONG(textureView, gTextureViewClassInfo.nativeWindow, 0); 138 } 139} 140 141static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject, 142 jlong nativeWindow, jobject canvas, jobject dirtyRect) { 143 144 if (!nativeWindow) { 145 return JNI_FALSE; 146 } 147 148 ANativeWindow_Buffer buffer; 149 150 Rect rect; 151 if (dirtyRect) { 152 rect.left = GET_INT(dirtyRect, gRectClassInfo.left); 153 rect.top = GET_INT(dirtyRect, gRectClassInfo.top); 154 rect.right = GET_INT(dirtyRect, gRectClassInfo.right); 155 rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); 156 } else { 157 rect.set(Rect(0x3FFF, 0x3FFF)); 158 } 159 160 sp<ANativeWindow> window((ANativeWindow*) nativeWindow); 161 int32_t status = native_window_lock(window.get(), &buffer, &rect); 162 if (status) return JNI_FALSE; 163 164 ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); 165 166 SkBitmap bitmap; 167 bitmap.setInfo(convertPixelFormat(buffer), bytesCount); 168 169 if (buffer.width > 0 && buffer.height > 0) { 170 bitmap.setPixels(buffer.bits); 171 } else { 172 bitmap.setPixels(NULL); 173 } 174 175 SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format); 176 INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap)); 177 178 SkRect clipRect; 179 clipRect.set(rect.left, rect.top, rect.right, rect.bottom); 180 SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); 181 nativeCanvas->clipRect(clipRect); 182 183 if (dirtyRect) { 184 INVOKEV(dirtyRect, gRectClassInfo.set, 185 int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); 186 } 187 188 return JNI_TRUE; 189} 190 191static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, 192 jlong nativeWindow, jobject canvas) { 193 194 INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); 195 196 if (nativeWindow) { 197 sp<ANativeWindow> window((ANativeWindow*) nativeWindow); 198 native_window_unlockAndPost(window.get()); 199 } 200} 201 202// ---------------------------------------------------------------------------- 203// JNI Glue 204// ---------------------------------------------------------------------------- 205 206const char* const kClassPathName = "android/view/TextureView"; 207 208static JNINativeMethod gMethods[] = { 209 { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", 210 (void*) android_view_TextureView_createNativeWindow }, 211 { "nDestroyNativeWindow", "()V", 212 (void*) android_view_TextureView_destroyNativeWindow }, 213 214 { "nLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)Z", 215 (void*) android_view_TextureView_lockCanvas }, 216 { "nUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V", 217 (void*) android_view_TextureView_unlockCanvasAndPost }, 218}; 219 220int register_android_view_TextureView(JNIEnv* env) { 221 jclass clazz = FindClassOrDie(env, "android/graphics/Rect"); 222 gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V"); 223 gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I"); 224 gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I"); 225 gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I"); 226 gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I"); 227 228 clazz = FindClassOrDie(env, "android/graphics/Canvas"); 229 gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I"); 230 gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V"); 231 232 clazz = FindClassOrDie(env, "android/view/TextureView"); 233 gTextureViewClassInfo.nativeWindow = GetFieldIDOrDie(env, clazz, "mNativeWindow", "J"); 234 235 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 236} 237 238}; 239