android_view_Surface.cpp revision a0398430fcf365fba6e42ad0bdca2fbf45ed6fe0
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Surface" 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "jni.h" 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "android_os_Parcel.h" 247650259a597dd24137420d32acc35efc44db381eSvetoslav Ganov#include "android/graphics/GraphicsJNI.h" 258a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 267650259a597dd24137420d32acc35efc44db381eSvetoslav Ganov#include <android_runtime/AndroidRuntime.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/android_view_Surface.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/android_graphics_SurfaceTexture.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/Log.h> 3041ec65355bd6ded652769725b276d47c54a0d913Scott Main 314c359b76f9a030f92a302ba74a528faa170bad4eScott Main#include <binder/Parcel.h> 324c359b76f9a030f92a302ba74a528faa170bad4eScott Main 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <gui/Surface.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <gui/SurfaceControl.h> 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <gui/GLConsumer.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Rect.h> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <ui/Region.h> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <SkCanvas.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <SkBitmap.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <SkRegion.h> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/misc.h> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 46617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 47617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette#include <ScopedUtfChars.h> 48617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 49617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette// ---------------------------------------------------------------------------- 50617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 51617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverettenamespace android { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char* const OutOfResourcesException = 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/view/Surface$OutOfResourcesException"; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID mNativeObject; 59617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette jfieldID mLock; 60617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette jmethodID ctor; 61617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette} gSurfaceClassInfo; 62617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID left; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID top; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID right; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID bottom; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gRectClassInfo; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID mFinalizer; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID mNativeCanvas; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID mSurfaceFormat; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gCanvasClassInfo; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct { 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jfieldID mNativeCanvas; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gCanvasFinalizerClassInfo; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// this is just a pointer we use to pass to inc/decStrong 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const void *sRefBaseOwner; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectbool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) { 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return android_view_Surface_getSurface(env, surfaceObj); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<Surface> sur; 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject lock = env->GetObjectField(surfaceObj, 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gSurfaceClassInfo.mLock); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->MonitorEnter(lock) == JNI_OK) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sur = reinterpret_cast<Surface *>( 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject)); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->MonitorExit(lock); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sur; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectjobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env, 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const sp<IGraphicBufferProducer>& bufferProducer) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bufferProducer == NULL) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<Surface> surface(new Surface(bufferProducer, true)); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (surface == NULL) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get()); 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (surfaceObj == NULL) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (env->ExceptionCheck()) { 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ALOGE("Could not create instance of Surface from IGraphicBufferProducer."); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE_EX(env); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env->ExceptionClear(); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project surface->incStrong(&sRefBaseOwner); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return surfaceObj; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline bool isSurfaceValid(const sp<Surface>& sur) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Surface::isValid(sur); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// ---------------------------------------------------------------------------- 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz, 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject surfaceTextureObj) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj)); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (producer == NULL) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", 142aa1c88de0232e0ed9d741895ce2e67356c1b120fRomain Guy "SurfaceTexture has already been released"); 143aa1c88de0232e0ed9d741895ce2e67356c1b120fRomain Guy return 0; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<Surface> surface(new Surface(producer, true)); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (surface == NULL) { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, OutOfResourcesException, NULL); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project surface->incStrong(&sRefBaseOwner); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return jlong(surface.get()); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1557650259a597dd24137420d32acc35efc44db381eSvetoslav Ganov 1567650259a597dd24137420d32acc35efc44db381eSvetoslav Ganovstatic void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) { 1578a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); 1588a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov sur->decStrong(&sRefBaseOwner); 1598a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov} 1608a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 1618a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovstatic jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) { 1628a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); 1638a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE; 1648a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov} 1658a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 1668a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovstatic jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject)); 168 if (!isSurfaceValid(sur)) { 169 doThrowIAE(env); 170 return JNI_FALSE; 171 } 172 int value = 0; 173 ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get()); 174 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value); 175 return value; 176} 177 178static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { 179 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then 180 we can map to SkBitmap::kARGB_8888_Config, and optionally call 181 bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator) 182 */ 183 switch (format) { 184 case PIXEL_FORMAT_RGBX_8888: return SkBitmap::kARGB_8888_Config; 185 case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; 186 case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; 187 default: return SkBitmap::kNo_Config; 188 } 189} 190 191static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) { 192 jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer); 193 SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>( 194 env->GetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas)); 195 env->SetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas, (jlong)newCanvas); 196 env->SetLongField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (jlong)newCanvas); 197 SkSafeUnref(previousCanvas); 198} 199 200static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, 201 jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) { 202 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); 203 204 if (!isSurfaceValid(surface)) { 205 doThrowIAE(env); 206 return 0; 207 } 208 209 Rect dirtyRect; 210 Rect* dirtyRectPtr = NULL; 211 212 if (dirtyRectObj) { 213 dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left); 214 dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top); 215 dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right); 216 dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom); 217 dirtyRectPtr = &dirtyRect; 218 } 219 220 ANativeWindow_Buffer outBuffer; 221 status_t err = surface->lock(&outBuffer, dirtyRectPtr); 222 if (err < 0) { 223 const char* const exception = (err == NO_MEMORY) ? 224 OutOfResourcesException : 225 "java/lang/IllegalArgumentException"; 226 jniThrowException(env, exception, NULL); 227 return 0; 228 } 229 230 // Associate a SkCanvas object to this surface 231 env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format); 232 233 SkBitmap bitmap; 234 ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); 235 bitmap.setConfig(convertPixelFormat(outBuffer.format), outBuffer.width, outBuffer.height, bpr); 236 if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) { 237 bitmap.setIsOpaque(true); 238 } 239 if (outBuffer.width > 0 && outBuffer.height > 0) { 240 bitmap.setPixels(outBuffer.bits); 241 } else { 242 // be safe with an empty bitmap. 243 bitmap.setPixels(NULL); 244 } 245 246 SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap)); 247 swapCanvasPtr(env, canvasObj, nativeCanvas); 248 249 if (dirtyRectPtr) { 250 nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) ); 251 } 252 253 if (dirtyRectObj) { 254 env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left); 255 env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top); 256 env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right); 257 env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom); 258 } 259 260 // Create another reference to the surface and return it. This reference 261 // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject, 262 // because the latter could be replaced while the surface is locked. 263 sp<Surface> lockedSurface(surface); 264 lockedSurface->incStrong(&sRefBaseOwner); 265 return (jlong) lockedSurface.get(); 266} 267 268static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, 269 jlong nativeObject, jobject canvasObj) { 270 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject)); 271 if (!isSurfaceValid(surface)) { 272 return; 273 } 274 275 // detach the canvas from the surface 276 SkCanvas* nativeCanvas = SkNEW(SkCanvas); 277 swapCanvasPtr(env, canvasObj, nativeCanvas); 278 279 // unlock surface 280 status_t err = surface->unlockAndPost(); 281 if (err < 0) { 282 doThrowIAE(env); 283 } 284} 285 286// ---------------------------------------------------------------------------- 287 288static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz, 289 jlong surfaceControlNativeObj) { 290 /* 291 * This is used by the WindowManagerService just after constructing 292 * a Surface and is necessary for returning the Surface reference to 293 * the caller. At this point, we should only have a SurfaceControl. 294 */ 295 296 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); 297 sp<Surface> surface(ctrl->getSurface()); 298 if (surface != NULL) { 299 surface->incStrong(&sRefBaseOwner); 300 } 301 return reinterpret_cast<jlong>(surface.get()); 302} 303 304static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz, 305 jlong nativeObject, jobject parcelObj) { 306 Parcel* parcel = parcelForJavaObject(env, parcelObj); 307 if (parcel == NULL) { 308 doThrowNPE(env); 309 return 0; 310 } 311 312 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); 313 sp<IBinder> binder(parcel->readStrongBinder()); 314 315 // update the Surface only if the underlying IGraphicBufferProducer 316 // has changed. 317 if (self != NULL 318 && (self->getIGraphicBufferProducer()->asBinder() == binder)) { 319 // same IGraphicBufferProducer, return ourselves 320 return jlong(self.get()); 321 } 322 323 sp<Surface> sur; 324 sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder)); 325 if (gbp != NULL) { 326 // we have a new IGraphicBufferProducer, create a new Surface for it 327 sur = new Surface(gbp, true); 328 // and keep a reference before passing to java 329 sur->incStrong(&sRefBaseOwner); 330 } 331 332 if (self != NULL) { 333 // and loose the java reference to ourselves 334 self->decStrong(&sRefBaseOwner); 335 } 336 337 return jlong(sur.get()); 338} 339 340static void nativeWriteToParcel(JNIEnv* env, jclass clazz, 341 jlong nativeObject, jobject parcelObj) { 342 Parcel* parcel = parcelForJavaObject(env, parcelObj); 343 if (parcel == NULL) { 344 doThrowNPE(env); 345 return; 346 } 347 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject)); 348 parcel->writeStrongBinder( self != 0 ? self->getIGraphicBufferProducer()->asBinder() : NULL); 349} 350 351// ---------------------------------------------------------------------------- 352 353static JNINativeMethod gSurfaceMethods[] = { 354 {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J", 355 (void*)nativeCreateFromSurfaceTexture }, 356 {"nativeRelease", "(J)V", 357 (void*)nativeRelease }, 358 {"nativeIsValid", "(J)Z", 359 (void*)nativeIsValid }, 360 {"nativeIsConsumerRunningBehind", "(J)Z", 361 (void*)nativeIsConsumerRunningBehind }, 362 {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J", 363 (void*)nativeLockCanvas }, 364 {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V", 365 (void*)nativeUnlockCanvasAndPost }, 366 {"nativeCreateFromSurfaceControl", "(J)J", 367 (void*)nativeCreateFromSurfaceControl }, 368 {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J", 369 (void*)nativeReadFromParcel }, 370 {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", 371 (void*)nativeWriteToParcel }, 372}; 373 374int register_android_view_Surface(JNIEnv* env) 375{ 376 int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface", 377 gSurfaceMethods, NELEM(gSurfaceMethods)); 378 379 jclass clazz = env->FindClass("android/view/Surface"); 380 gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz)); 381 gSurfaceClassInfo.mNativeObject = 382 env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeObject", "J"); 383 gSurfaceClassInfo.mLock = 384 env->GetFieldID(gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;"); 385 gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(J)V"); 386 387 clazz = env->FindClass("android/graphics/Canvas"); 388 gCanvasClassInfo.mFinalizer = env->GetFieldID(clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;"); 389 gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "J"); 390 gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I"); 391 392 clazz = env->FindClass("android/graphics/Canvas$CanvasFinalizer"); 393 gCanvasFinalizerClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "J"); 394 395 clazz = env->FindClass("android/graphics/Rect"); 396 gRectClassInfo.left = env->GetFieldID(clazz, "left", "I"); 397 gRectClassInfo.top = env->GetFieldID(clazz, "top", "I"); 398 gRectClassInfo.right = env->GetFieldID(clazz, "right", "I"); 399 gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I"); 400 401 return err; 402} 403 404}; 405