android_view_TextureView.cpp revision 76f6a86de25e1bf74717e047e55fd44b089673f3
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 case WINDOW_FORMAT_RGB_565: 92 info.fColorType = kRGB_565_SkColorType; 93 info.fAlphaType = kOpaque_SkAlphaType; 94 default: 95 info.fColorType = kUnknown_SkColorType; 96 info.fAlphaType = kIgnore_SkAlphaType; 97 break; 98 } 99 return info; 100} 101 102/** 103 * This is a private API, and this implementation is also provided in the NDK. 104 * However, the NDK links against android_runtime, which means that using the 105 * NDK implementation would create a circular dependency between the libraries. 106 */ 107static int32_t native_window_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer, 108 Rect* inOutDirtyBounds) { 109 return window->perform(window, NATIVE_WINDOW_LOCK, outBuffer, inOutDirtyBounds); 110} 111 112static int32_t native_window_unlockAndPost(ANativeWindow* window) { 113 return window->perform(window, NATIVE_WINDOW_UNLOCK_AND_POST); 114} 115 116static void android_view_TextureView_createNativeWindow(JNIEnv* env, jobject textureView, 117 jobject surface) { 118 119 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surface)); 120 sp<ANativeWindow> window = new Surface(producer, true); 121 122 window->incStrong((void*)android_view_TextureView_createNativeWindow); 123 SET_LONG(textureView, gTextureViewClassInfo.nativeWindow, jlong(window.get())); 124} 125 126static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject textureView) { 127 128 ANativeWindow* nativeWindow = (ANativeWindow*) 129 GET_LONG(textureView, gTextureViewClassInfo.nativeWindow); 130 131 if (nativeWindow) { 132 sp<ANativeWindow> window(nativeWindow); 133 window->decStrong((void*)android_view_TextureView_createNativeWindow); 134 SET_LONG(textureView, gTextureViewClassInfo.nativeWindow, 0); 135 } 136} 137 138static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject, 139 jlong nativeWindow, jobject canvas, jobject dirtyRect) { 140 141 if (!nativeWindow) { 142 return JNI_FALSE; 143 } 144 145 ANativeWindow_Buffer buffer; 146 147 Rect rect; 148 if (dirtyRect) { 149 rect.left = GET_INT(dirtyRect, gRectClassInfo.left); 150 rect.top = GET_INT(dirtyRect, gRectClassInfo.top); 151 rect.right = GET_INT(dirtyRect, gRectClassInfo.right); 152 rect.bottom = GET_INT(dirtyRect, gRectClassInfo.bottom); 153 } else { 154 rect.set(Rect(0x3FFF, 0x3FFF)); 155 } 156 157 sp<ANativeWindow> window((ANativeWindow*) nativeWindow); 158 int32_t status = native_window_lock(window.get(), &buffer, &rect); 159 if (status) return JNI_FALSE; 160 161 ssize_t bytesCount = buffer.stride * bytesPerPixel(buffer.format); 162 163 SkBitmap bitmap; 164 bitmap.setInfo(convertPixelFormat(buffer), bytesCount); 165 166 if (buffer.width > 0 && buffer.height > 0) { 167 bitmap.setPixels(buffer.bits); 168 } else { 169 bitmap.setPixels(NULL); 170 } 171 172 SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format); 173 INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap)); 174 175 SkRect clipRect; 176 clipRect.set(rect.left, rect.top, rect.right, rect.bottom); 177 SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas); 178 nativeCanvas->clipRect(clipRect); 179 180 if (dirtyRect) { 181 INVOKEV(dirtyRect, gRectClassInfo.set, 182 int(rect.left), int(rect.top), int(rect.right), int(rect.bottom)); 183 } 184 185 return JNI_TRUE; 186} 187 188static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, 189 jlong nativeWindow, jobject canvas) { 190 191 INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0); 192 193 if (nativeWindow) { 194 sp<ANativeWindow> window((ANativeWindow*) nativeWindow); 195 native_window_unlockAndPost(window.get()); 196 } 197} 198 199// ---------------------------------------------------------------------------- 200// JNI Glue 201// ---------------------------------------------------------------------------- 202 203const char* const kClassPathName = "android/view/TextureView"; 204 205static const JNINativeMethod gMethods[] = { 206 { "nCreateNativeWindow", "(Landroid/graphics/SurfaceTexture;)V", 207 (void*) android_view_TextureView_createNativeWindow }, 208 { "nDestroyNativeWindow", "()V", 209 (void*) android_view_TextureView_destroyNativeWindow }, 210 211 { "nLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)Z", 212 (void*) android_view_TextureView_lockCanvas }, 213 { "nUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V", 214 (void*) android_view_TextureView_unlockCanvasAndPost }, 215}; 216 217int register_android_view_TextureView(JNIEnv* env) { 218 jclass clazz = FindClassOrDie(env, "android/graphics/Rect"); 219 gRectClassInfo.set = GetMethodIDOrDie(env, clazz, "set", "(IIII)V"); 220 gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I"); 221 gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I"); 222 gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I"); 223 gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I"); 224 225 clazz = FindClassOrDie(env, "android/graphics/Canvas"); 226 gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I"); 227 gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V"); 228 229 clazz = FindClassOrDie(env, "android/view/TextureView"); 230 gTextureViewClassInfo.nativeWindow = GetFieldIDOrDie(env, clazz, "mNativeWindow", "J"); 231 232 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 233} 234 235}; 236