GoogleGit

blob: 7f6c50fc248f10286740894fb851481439d44c9a [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. #include <AnimationContext.h>
  40. #include <DisplayListRenderer.h>
  41. #include <RenderNode.h>
  42. #include <renderthread/RenderProxy.h>
  43. // ----------------------------------------------------------------------------
  44. namespace android {
  45. static const char* const OutOfResourcesException =
  46. "android/view/Surface$OutOfResourcesException";
  47. static struct {
  48. jclass clazz;
  49. jfieldID mNativeObject;
  50. jfieldID mLock;
  51. jmethodID ctor;
  52. } gSurfaceClassInfo;
  53. static struct {
  54. jfieldID left;
  55. jfieldID top;
  56. jfieldID right;
  57. jfieldID bottom;
  58. } gRectClassInfo;
  59. static struct {
  60. jfieldID mSurfaceFormat;
  61. jmethodID setNativeBitmap;
  62. } gCanvasClassInfo;
  63. // ----------------------------------------------------------------------------
  64. // this is just a pointer we use to pass to inc/decStrong
  65. static const void *sRefBaseOwner;
  66. bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
  67. return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
  68. }
  69. sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
  70. return android_view_Surface_getSurface(env, surfaceObj);
  71. }
  72. sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
  73. sp<Surface> sur;
  74. jobject lock = env->GetObjectField(surfaceObj,
  75. gSurfaceClassInfo.mLock);
  76. if (env->MonitorEnter(lock) == JNI_OK) {
  77. sur = reinterpret_cast<Surface *>(
  78. env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
  79. env->MonitorExit(lock);
  80. }
  81. env->DeleteLocalRef(lock);
  82. return sur;
  83. }
  84. jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
  85. const sp<IGraphicBufferProducer>& bufferProducer) {
  86. if (bufferProducer == NULL) {
  87. return NULL;
  88. }
  89. sp<Surface> surface(new Surface(bufferProducer, true));
  90. if (surface == NULL) {
  91. return NULL;
  92. }
  93. jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
  94. gSurfaceClassInfo.ctor, (jlong)surface.get());
  95. if (surfaceObj == NULL) {
  96. if (env->ExceptionCheck()) {
  97. ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
  98. LOGE_EX(env);
  99. env->ExceptionClear();
  100. }
  101. return NULL;
  102. }
  103. surface->incStrong(&sRefBaseOwner);
  104. return surfaceObj;
  105. }
  106. // ----------------------------------------------------------------------------
  107. static inline bool isSurfaceValid(const sp<Surface>& sur) {
  108. return Surface::isValid(sur);
  109. }
  110. // ----------------------------------------------------------------------------
  111. static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
  112. jobject surfaceTextureObj) {
  113. sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
  114. if (producer == NULL) {
  115. jniThrowException(env, "java/lang/IllegalArgumentException",
  116. "SurfaceTexture has already been released");
  117. return 0;
  118. }
  119. sp<Surface> surface(new Surface(producer, true));
  120. if (surface == NULL) {
  121. jniThrowException(env, OutOfResourcesException, NULL);
  122. return 0;
  123. }
  124. surface->incStrong(&sRefBaseOwner);
  125. return jlong(surface.get());
  126. }
  127. static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
  128. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  129. sur->decStrong(&sRefBaseOwner);
  130. }
  131. static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
  132. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  133. return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
  134. }
  135. static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
  136. sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
  137. if (!isSurfaceValid(sur)) {
  138. doThrowIAE(env);
  139. return JNI_FALSE;
  140. }
  141. int value = 0;
  142. ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
  143. anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
  144. return value;
  145. }
  146. static inline SkColorType convertPixelFormat(PixelFormat format) {
  147. /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
  148. we can map to kN32_SkColorType, and optionally call
  149. bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
  150. (as an accelerator)
  151. */
  152. switch (format) {
  153. case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
  154. case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
  155. case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
  156. default: return kUnknown_SkColorType;
  157. }
  158. }
  159. static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
  160. jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
  161. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  162. if (!isSurfaceValid(surface)) {
  163. doThrowIAE(env);
  164. return 0;
  165. }
  166. Rect dirtyRect;
  167. Rect* dirtyRectPtr = NULL;
  168. if (dirtyRectObj) {
  169. dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
  170. dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
  171. dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
  172. dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
  173. dirtyRectPtr = &dirtyRect;
  174. }
  175. ANativeWindow_Buffer outBuffer;
  176. status_t err = surface->lock(&outBuffer, dirtyRectPtr);
  177. if (err < 0) {
  178. const char* const exception = (err == NO_MEMORY) ?
  179. OutOfResourcesException :
  180. "java/lang/IllegalArgumentException";
  181. jniThrowException(env, exception, NULL);
  182. return 0;
  183. }
  184. // Associate a SkCanvas object to this surface
  185. env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
  186. SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
  187. convertPixelFormat(outBuffer.format),
  188. kPremul_SkAlphaType);
  189. if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
  190. info.fAlphaType = kOpaque_SkAlphaType;
  191. }
  192. SkBitmap bitmap;
  193. ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
  194. bitmap.setInfo(info, bpr);
  195. if (outBuffer.width > 0 && outBuffer.height > 0) {
  196. bitmap.setPixels(outBuffer.bits);
  197. } else {
  198. // be safe with an empty bitmap.
  199. bitmap.setPixels(NULL);
  200. }
  201. env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap,
  202. reinterpret_cast<jlong>(&bitmap));
  203. if (dirtyRectPtr) {
  204. SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
  205. nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
  206. }
  207. if (dirtyRectObj) {
  208. env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
  209. env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
  210. env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
  211. env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
  212. }
  213. // Create another reference to the surface and return it. This reference
  214. // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
  215. // because the latter could be replaced while the surface is locked.
  216. sp<Surface> lockedSurface(surface);
  217. lockedSurface->incStrong(&sRefBaseOwner);
  218. return (jlong) lockedSurface.get();
  219. }
  220. static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
  221. jlong nativeObject, jobject canvasObj) {
  222. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  223. if (!isSurfaceValid(surface)) {
  224. return;
  225. }
  226. // detach the canvas from the surface
  227. env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)0);
  228. // unlock surface
  229. status_t err = surface->unlockAndPost();
  230. if (err < 0) {
  231. doThrowIAE(env);
  232. }
  233. }
  234. static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
  235. jlong nativeObject) {
  236. sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
  237. if (!isSurfaceValid(surface)) {
  238. return;
  239. }
  240. surface->allocateBuffers();
  241. }
  242. // ----------------------------------------------------------------------------
  243. static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
  244. jlong surfaceControlNativeObj) {
  245. /*
  246. * This is used by the WindowManagerService just after constructing
  247. * a Surface and is necessary for returning the Surface reference to
  248. * the caller. At this point, we should only have a SurfaceControl.
  249. */
  250. sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
  251. sp<Surface> surface(ctrl->getSurface());
  252. if (surface != NULL) {
  253. surface->incStrong(&sRefBaseOwner);
  254. }
  255. return reinterpret_cast<jlong>(surface.get());
  256. }
  257. static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
  258. jlong nativeObject, jobject parcelObj) {
  259. Parcel* parcel = parcelForJavaObject(env, parcelObj);
  260. if (parcel == NULL) {
  261. doThrowNPE(env);
  262. return 0;
  263. }
  264. sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
  265. sp<IBinder> binder(parcel->readStrongBinder());
  266. // update the Surface only if the underlying IGraphicBufferProducer
  267. // has changed.
  268. if (self != NULL
  269. && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
  270. // same IGraphicBufferProducer, return ourselves
  271. return jlong(self.get());
  272. }
  273. sp<Surface> sur;
  274. sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
  275. if (gbp != NULL) {
  276. // we have a new IGraphicBufferProducer, create a new Surface for it
  277. sur = new Surface(gbp, true);
  278. // and keep a reference before passing to java
  279. sur->incStrong(&sRefBaseOwner);
  280. }
  281. if (self != NULL) {
  282. // and loose the java reference to ourselves
  283. self->decStrong(&sRefBaseOwner);
  284. }
  285. return jlong(sur.get());
  286. }
  287. static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
  288. jlong nativeObject, jobject parcelObj) {
  289. Parcel* parcel = parcelForJavaObject(env, parcelObj);
  290. if (parcel == NULL) {
  291. doThrowNPE(env);
  292. return;
  293. }
  294. sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
  295. parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL);
  296. }
  297. static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
  298. Surface* surface = reinterpret_cast<Surface*>(nativeObject);
  299. ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
  300. int value = 0;
  301. anw->query(anw, NATIVE_WINDOW_WIDTH, &value);
  302. return value;
  303. }
  304. static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
  305. Surface* surface = reinterpret_cast<Surface*>(nativeObject);
  306. ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
  307. int value = 0;
  308. anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
  309. return value;
  310. }
  311. namespace uirenderer {
  312. using namespace android::uirenderer::renderthread;
  313. class ContextFactory : public IContextFactory {
  314. public:
  315. virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
  316. return new AnimationContext(clock);
  317. }
  318. };
  319. static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) {
  320. RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
  321. sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
  322. ContextFactory factory;
  323. RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
  324. proxy->loadSystemProperties();
  325. proxy->setSwapBehavior(kSwap_discardBuffer);
  326. proxy->initialize(surface);
  327. // Shadows can't be used via this interface, so just set the light source
  328. // to all 0s. (and width & height are unused, TODO remove them)
  329. proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
  330. return (jlong) proxy;
  331. }
  332. static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
  333. RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
  334. sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
  335. proxy->updateSurface(surface);
  336. }
  337. static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
  338. RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
  339. nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
  340. proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
  341. }
  342. static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
  343. RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
  344. delete proxy;
  345. }
  346. } // uirenderer
  347. // ----------------------------------------------------------------------------
  348. namespace hwui = android::uirenderer;
  349. static JNINativeMethod gSurfaceMethods[] = {
  350. {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
  351. (void*)nativeCreateFromSurfaceTexture },
  352. {"nativeRelease", "(J)V",
  353. (void*)nativeRelease },
  354. {"nativeIsValid", "(J)Z",
  355. (void*)nativeIsValid },
  356. {"nativeIsConsumerRunningBehind", "(J)Z",
  357. (void*)nativeIsConsumerRunningBehind },
  358. {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
  359. (void*)nativeLockCanvas },
  360. {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
  361. (void*)nativeUnlockCanvasAndPost },
  362. {"nativeAllocateBuffers", "(J)V",
  363. (void*)nativeAllocateBuffers },
  364. {"nativeCreateFromSurfaceControl", "(J)J",
  365. (void*)nativeCreateFromSurfaceControl },
  366. {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
  367. (void*)nativeReadFromParcel },
  368. {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
  369. (void*)nativeWriteToParcel },
  370. {"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
  371. {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
  372. // HWUI context
  373. {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
  374. {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
  375. {"nHwuiDraw", "(J)V", (void*) hwui::draw },
  376. {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
  377. };
  378. int register_android_view_Surface(JNIEnv* env)
  379. {
  380. int err = RegisterMethodsOrDie(env, "android/view/Surface",
  381. gSurfaceMethods, NELEM(gSurfaceMethods));
  382. jclass clazz = FindClassOrDie(env, "android/view/Surface");
  383. gSurfaceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
  384. gSurfaceClassInfo.mNativeObject = GetFieldIDOrDie(env,
  385. gSurfaceClassInfo.clazz, "mNativeObject", "J");
  386. gSurfaceClassInfo.mLock = GetFieldIDOrDie(env,
  387. gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
  388. gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
  389. clazz = FindClassOrDie(env, "android/graphics/Canvas");
  390. gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I");
  391. gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V");
  392. clazz = FindClassOrDie(env, "android/graphics/Rect");
  393. gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
  394. gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
  395. gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
  396. gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
  397. return err;
  398. }
  399. };