GoogleGit

blob: 3fe50a5fd3bdffa13d5ee0fc9a759c612d29d3c1 [file] [log] [blame]
  1. /*
  2. * Copyright (C) 2007 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. #define LOG_TAG "Surface"
  17. #include <stdio.h>
  18. #include "jni.h"
  19. #include "JNIHelp.h"
  20. #include "android_os_Parcel.h"
  21. #include "android/graphics/GraphicsJNI.h"
  22. #include "core_jni_helpers.h"
  23. #include <android_runtime/android_view_Surface.h>
  24. #include <android_runtime/android_graphics_SurfaceTexture.h>
  25. #include <android_runtime/Log.h>
  26. #include <binder/Parcel.h>
  27. #include <gui/Surface.h>
  28. #include <gui/SurfaceControl.h>
  29. #include <gui/GLConsumer.h>
  30. #include <ui/Rect.h>
  31. #include <ui/Region.h>
  32. #include <SkCanvas.h>
  33. #include <SkBitmap.h>
  34. #include <SkImage.h>
  35. #include <SkRegion.h>
  36. #include <utils/misc.h>
  37. #include <utils/Log.h>
  38. #include <ScopedUtfChars.h>
  39. // ----------------------------------------------------------------------------
  40. namespace android {
  41. static const char* const OutOfResourcesException =
  42. "android/view/Surface$OutOfResourcesException";
  43. static struct {
  44. jclass clazz;
  45. jfieldID mNativeObject;
  46. jfieldID mLock;
  47. jmethodID ctor;
  48. } gSurfaceClassInfo;
  49. static struct {
  50. jfieldID left;
  51. jfieldID top;
  52. jfieldID right;
  53. jfieldID bottom;
  54. } gRectClassInfo;
  55. static struct {
  56. jfieldID mSurfaceFormat;
  57. jmethodID setNativeBitmap;
  58. } gCanvasClassInfo;
  59. // ----------------------------------------------------------------------------
  60. // this is just a pointer we use to pass to inc/decStrong
  61. static const void *sRefBaseOwner;
  62. bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
  63. return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
  64. }
  65. sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
  66. return android_view_Surface_getSurface(env, surfaceObj);
  67. }
  68. sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
  69. sp<Surface> sur;
  70. jobject lock = env->GetObjectField(surfaceObj,
  71. gSurfaceClassInfo.mLock);
  72. if (env->MonitorEnter(lock) == JNI_OK) {
  73. sur = reinterpret_cast<Surface *>(
  74. env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
  75. env->MonitorExit(lock);
  76. }
  77. env->DeleteLocalRef(lock);
  78. return sur;
  79. }
  80. jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
  81. const sp<IGraphicBufferProducer>& bufferProducer) {
  82. if (bufferProducer == NULL) {
  83. return NULL;
  84. }
  85. sp<Surface> surface(new Surface(bufferProducer, true));
  86. if (surface == NULL) {
  87. return NULL;
  88. }
  89. jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
  90. gSurfaceClassInfo.ctor, (jlong)surface.get());
  91. if (surfaceObj == NULL) {
  92. if (env->ExceptionCheck()) {
  93. ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
  94. LOGE_EX(env);
  95. env->ExceptionClear();
  96. }
  97. return NULL;
  98. }
  99. surface->incStrong(&sRefBaseOwner);
  100. return surfaceObj;
  101. }
  102. // ----------------------------------------------------------------------------
  103. static inline bool isSurfaceValid(const sp<Surface>& sur) {
  104. return Surface::isValid(sur);
  105. }
  106. // ----------------------------------------------------------------------------
  107. static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
  108. jobject surfaceTextureObj) {
  109. sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
  110. if (producer == NULL) {
  111. jniThrowException(env, "java/lang/IllegalArgumentException",
  112. "SurfaceTexture has already been released");
  113. return 0;
  114. }
  115. sp<Surface> surface(new Surface(producer, true));
  116. if (surface == NULL) {
  117. jniThrowException(env, OutOfResourcesException, NULL);
  118. return 0;
  119. }
  120. surface->incStrong(&sRefBaseOwner);
  121. return jlong(surface.get());
  122. }
  123. static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
  124. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  125. sur->decStrong(&sRefBaseOwner);
  126. }
  127. static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
  128. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  129. return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
  130. }
  131. static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
  132. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  133. if (!isSurfaceValid(sur)) {
  134. doThrowIAE(env);
  135. return JNI_FALSE;
  136. }
  137. int value = 0;
  138. ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
  139. anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
  140. return value;
  141. }
  142. static inline SkColorType convertPixelFormat(PixelFormat format) {
  143. /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
  144. we can map to kN32_SkColorType, and optionally call
  145. bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
  146. (as an accelerator)
  147. */
  148. switch (format) {
  149. case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
  150. case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
  151. case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
  152. default: return kUnknown_SkColorType;
  153. }
  154. }
  155. static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
  156. jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
  157. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  158. if (!isSurfaceValid(surface)) {
  159. doThrowIAE(env);
  160. return 0;
  161. }
  162. Rect dirtyRect;
  163. Rect* dirtyRectPtr = NULL;
  164. if (dirtyRectObj) {
  165. dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
  166. dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
  167. dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
  168. dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
  169. dirtyRectPtr = &dirtyRect;
  170. }
  171. ANativeWindow_Buffer outBuffer;
  172. status_t err = surface->lock(&outBuffer, dirtyRectPtr);
  173. if (err < 0) {
  174. const char* const exception = (err == NO_MEMORY) ?
  175. OutOfResourcesException :
  176. "java/lang/IllegalArgumentException";
  177. jniThrowException(env, exception, NULL);
  178. return 0;
  179. }
  180. // Associate a SkCanvas object to this surface
  181. env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
  182. SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
  183. convertPixelFormat(outBuffer.format),
  184. kPremul_SkAlphaType);
  185. if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
  186. info.fAlphaType = kOpaque_SkAlphaType;
  187. }
  188. SkBitmap bitmap;
  189. ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
  190. bitmap.setInfo(info, bpr);
  191. if (outBuffer.width > 0 && outBuffer.height > 0) {
  192. bitmap.setPixels(outBuffer.bits);
  193. } else {
  194. // be safe with an empty bitmap.
  195. bitmap.setPixels(NULL);
  196. }
  197. env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap,
  198. reinterpret_cast<jlong>(&bitmap));
  199. if (dirtyRectPtr) {
  200. SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
  201. nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
  202. }
  203. if (dirtyRectObj) {
  204. env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
  205. env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
  206. env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
  207. env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
  208. }
  209. // Create another reference to the surface and return it. This reference
  210. // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
  211. // because the latter could be replaced while the surface is locked.
  212. sp<Surface> lockedSurface(surface);
  213. lockedSurface->incStrong(&sRefBaseOwner);
  214. return (jlong) lockedSurface.get();
  215. }
  216. static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
  217. jlong nativeObject, jobject canvasObj) {
  218. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  219. if (!isSurfaceValid(surface)) {
  220. return;
  221. }
  222. // detach the canvas from the surface
  223. env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)0);
  224. // unlock surface
  225. status_t err = surface->unlockAndPost();
  226. if (err < 0) {
  227. doThrowIAE(env);
  228. }
  229. }
  230. static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
  231. jlong nativeObject) {
  232. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  233. if (!isSurfaceValid(surface)) {
  234. return;
  235. }
  236. surface->allocateBuffers();
  237. }
  238. // ----------------------------------------------------------------------------
  239. static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
  240. jlong surfaceControlNativeObj) {
  241. /*
  242. * This is used by the WindowManagerService just after constructing
  243. * a Surface and is necessary for returning the Surface reference to
  244. * the caller. At this point, we should only have a SurfaceControl.
  245. */
  246. sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
  247. sp<Surface> surface(ctrl->getSurface());
  248. if (surface != NULL) {
  249. surface->incStrong(&sRefBaseOwner);
  250. }
  251. return reinterpret_cast<jlong>(surface.get());
  252. }
  253. static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
  254. jlong nativeObject, jobject parcelObj) {
  255. Parcel* parcel = parcelForJavaObject(env, parcelObj);
  256. if (parcel == NULL) {
  257. doThrowNPE(env);
  258. return 0;
  259. }
  260. sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
  261. sp<IBinder> binder(parcel->readStrongBinder());
  262. // update the Surface only if the underlying IGraphicBufferProducer
  263. // has changed.
  264. if (self != NULL
  265. && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
  266. // same IGraphicBufferProducer, return ourselves
  267. return jlong(self.get());
  268. }
  269. sp<Surface> sur;
  270. sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
  271. if (gbp != NULL) {
  272. // we have a new IGraphicBufferProducer, create a new Surface for it
  273. sur = new Surface(gbp, true);
  274. // and keep a reference before passing to java
  275. sur->incStrong(&sRefBaseOwner);
  276. }
  277. if (self != NULL) {
  278. // and loose the java reference to ourselves
  279. self->decStrong(&sRefBaseOwner);
  280. }
  281. return jlong(sur.get());
  282. }
  283. static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
  284. jlong nativeObject, jobject parcelObj) {
  285. Parcel* parcel = parcelForJavaObject(env, parcelObj);
  286. if (parcel == NULL) {
  287. doThrowNPE(env);
  288. return;
  289. }
  290. sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
  291. parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL);
  292. }
  293. // ----------------------------------------------------------------------------
  294. static JNINativeMethod gSurfaceMethods[] = {
  295. {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
  296. (void*)nativeCreateFromSurfaceTexture },
  297. {"nativeRelease", "(J)V",
  298. (void*)nativeRelease },
  299. {"nativeIsValid", "(J)Z",
  300. (void*)nativeIsValid },
  301. {"nativeIsConsumerRunningBehind", "(J)Z",
  302. (void*)nativeIsConsumerRunningBehind },
  303. {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
  304. (void*)nativeLockCanvas },
  305. {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
  306. (void*)nativeUnlockCanvasAndPost },
  307. {"nativeAllocateBuffers", "(J)V",
  308. (void*)nativeAllocateBuffers },
  309. {"nativeCreateFromSurfaceControl", "(J)J",
  310. (void*)nativeCreateFromSurfaceControl },
  311. {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
  312. (void*)nativeReadFromParcel },
  313. {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
  314. (void*)nativeWriteToParcel },
  315. };
  316. int register_android_view_Surface(JNIEnv* env)
  317. {
  318. int err = RegisterMethodsOrDie(env, "android/view/Surface",
  319. gSurfaceMethods, NELEM(gSurfaceMethods));
  320. jclass clazz = FindClassOrDie(env, "android/view/Surface");
  321. gSurfaceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
  322. gSurfaceClassInfo.mNativeObject = GetFieldIDOrDie(env,
  323. gSurfaceClassInfo.clazz, "mNativeObject", "J");
  324. gSurfaceClassInfo.mLock = GetFieldIDOrDie(env,
  325. gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
  326. gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
  327. clazz = FindClassOrDie(env, "android/graphics/Canvas");
  328. gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I");
  329. gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V");
  330. clazz = FindClassOrDie(env, "android/graphics/Rect");
  331. gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
  332. gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
  333. gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
  334. gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
  335. return err;
  336. }
  337. };