2 * Copyright (C) 2012 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "OpenGLRenderer"
18 #define ATRACE_TAG ATRACE_TAG_VIEW
23 #include "GraphicsJNI.h"
24 #include <nativehelper/JNIHelp.h>
25 #include <android_runtime/AndroidRuntime.h>
28 #include <DamageAccumulator.h>
30 #include <RenderNode.h>
31 #include <renderthread/CanvasContext.h>
33 #include <hwui/Paint.h>
35 #include "core_jni_helpers.h"
39 using namespace uirenderer;
41 #define SET_AND_DIRTY(prop, val, dirtyFlag) \
42 (reinterpret_cast<RenderNode*>(renderNodePtr)->mutateStagingProperties().prop(val) \
43 ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
46 static JNIEnv* getenv(JavaVM* vm) {
48 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
49 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
54 static jmethodID gOnRenderNodeDetached;
56 class RenderNodeContext : public VirtualLightRefBase {
58 RenderNodeContext(JNIEnv* env, jobject jobjRef) {
60 // This holds a weak ref because otherwise there's a cyclic global ref
61 // with this holding a strong global ref to the view which holds
62 // a strong ref to RenderNode which holds a strong ref to this.
63 mWeakRef = env->NewWeakGlobalRef(jobjRef);
66 virtual ~RenderNodeContext() {
67 JNIEnv* env = getenv(mVm);
68 env->DeleteWeakGlobalRef(mWeakRef);
71 jobject acquireLocalRef(JNIEnv* env) {
72 return env->NewLocalRef(mWeakRef);
80 // Called by ThreadedRenderer's JNI layer
81 void onRenderNodeRemoved(JNIEnv* env, RenderNode* node) {
82 auto context = reinterpret_cast<RenderNodeContext*>(node->getUserContext());
84 jobject jnode = context->acquireLocalRef(env);
86 // The owning node has been GC'd, release the context
87 node->setUserContext(nullptr);
90 env->CallVoidMethod(jnode, gOnRenderNodeDetached);
91 env->DeleteLocalRef(jnode);
94 // ----------------------------------------------------------------------------
95 // DisplayList view properties
96 // ----------------------------------------------------------------------------
98 static void android_view_RenderNode_output(JNIEnv* env,
99 jobject clazz, jlong renderNodePtr) {
100 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
101 renderNode->output();
104 static jint android_view_RenderNode_getDebugSize(JNIEnv* env,
105 jobject clazz, jlong renderNodePtr) {
106 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
107 return renderNode->getDebugSize();
110 static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz,
112 RenderNode* renderNode = new RenderNode();
113 renderNode->incStrong(0);
115 const char* textArray = env->GetStringUTFChars(name, NULL);
116 renderNode->setName(textArray);
117 env->ReleaseStringUTFChars(name, textArray);
119 renderNode->setUserContext(new RenderNodeContext(env, thiz));
120 return reinterpret_cast<jlong>(renderNode);
123 static void android_view_RenderNode_destroyRenderNode(JNIEnv* env,
124 jobject clazz, jlong renderNodePtr) {
125 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
126 renderNode->decStrong(0);
129 static void android_view_RenderNode_setDisplayList(JNIEnv* env,
130 jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
131 class RemovedObserver : public TreeObserver {
133 virtual void onMaybeRemovedFromTree(RenderNode* node) override {
134 maybeRemovedNodes.insert(sp<RenderNode>(node));
136 std::set< sp<RenderNode> > maybeRemovedNodes;
139 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
140 DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
141 RemovedObserver observer;
142 renderNode->setStagingDisplayList(newData, &observer);
143 for (auto& node : observer.maybeRemovedNodes) {
144 if (node->hasParents()) continue;
145 onRenderNodeRemoved(env, node.get());
149 // ----------------------------------------------------------------------------
150 // RenderProperties - setters
151 // ----------------------------------------------------------------------------
153 static jboolean android_view_RenderNode_setLayerType(JNIEnv* env,
154 jobject clazz, jlong renderNodePtr, jint jlayerType) {
155 LayerType layerType = static_cast<LayerType>(jlayerType);
156 return SET_AND_DIRTY(mutateLayerProperties().setType, layerType, RenderNode::GENERIC);
159 static jboolean android_view_RenderNode_setLayerPaint(JNIEnv* env,
160 jobject clazz, jlong renderNodePtr, jlong paintPtr) {
161 Paint* paint = reinterpret_cast<Paint*>(paintPtr);
162 return SET_AND_DIRTY(mutateLayerProperties().setFromPaint, paint, RenderNode::GENERIC);
165 static jboolean android_view_RenderNode_setStaticMatrix(JNIEnv* env,
166 jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
167 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
168 return SET_AND_DIRTY(setStaticMatrix, matrix, RenderNode::GENERIC);
171 static jboolean android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
172 jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
173 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
174 return SET_AND_DIRTY(setAnimationMatrix, matrix, RenderNode::GENERIC);
177 static jboolean android_view_RenderNode_setClipToBounds(JNIEnv* env,
178 jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
179 return SET_AND_DIRTY(setClipToBounds, clipToBounds, RenderNode::GENERIC);
182 static jboolean android_view_RenderNode_setClipBounds(JNIEnv* env,
183 jobject clazz, jlong renderNodePtr, jint left, jint top, jint right, jint bottom) {
184 android::uirenderer::Rect clipBounds(left, top, right, bottom);
185 return SET_AND_DIRTY(setClipBounds, clipBounds, RenderNode::GENERIC);
188 static jboolean android_view_RenderNode_setClipBoundsEmpty(JNIEnv* env,
189 jobject clazz, jlong renderNodePtr) {
190 return SET_AND_DIRTY(setClipBoundsEmpty,, RenderNode::GENERIC);
193 static jboolean android_view_RenderNode_setProjectBackwards(JNIEnv* env,
194 jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
195 return SET_AND_DIRTY(setProjectBackwards, shouldProject, RenderNode::GENERIC);
198 static jboolean android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
199 jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
200 return SET_AND_DIRTY(setProjectionReceiver, shouldRecieve, RenderNode::GENERIC);
203 static jboolean android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
204 jobject clazz, jlong renderNodePtr, jint left, jint top,
205 jint right, jint bottom, jfloat radius, jfloat alpha) {
206 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
207 renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom,
209 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
213 static jboolean android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
214 jobject clazz, jlong renderNodePtr, jlong outlinePathPtr, jfloat alpha) {
215 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
216 SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
217 renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath, alpha);
218 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
222 static jboolean android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
223 jobject clazz, jlong renderNodePtr) {
224 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
225 renderNode->mutateStagingProperties().mutableOutline().setEmpty();
226 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
230 static jboolean android_view_RenderNode_setOutlineNone(JNIEnv* env,
231 jobject clazz, jlong renderNodePtr) {
232 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
233 renderNode->mutateStagingProperties().mutableOutline().setNone();
234 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
238 static jboolean android_view_RenderNode_hasShadow(JNIEnv* env,
239 jobject clazz, jlong renderNodePtr) {
240 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
241 return renderNode->stagingProperties().hasShadow();
244 static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
245 jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
246 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
247 renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
248 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
252 static jboolean android_view_RenderNode_setRevealClip(JNIEnv* env,
253 jobject clazz, jlong renderNodePtr, jboolean shouldClip,
254 jfloat x, jfloat y, jfloat radius) {
255 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
256 renderNode->mutateStagingProperties().mutableRevealClip().set(
257 shouldClip, x, y, radius);
258 renderNode->setPropertyFieldsDirty(RenderNode::GENERIC);
262 static jboolean android_view_RenderNode_setAlpha(JNIEnv* env,
263 jobject clazz, jlong renderNodePtr, float alpha) {
264 return SET_AND_DIRTY(setAlpha, alpha, RenderNode::ALPHA);
267 static jboolean android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
268 jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
269 return SET_AND_DIRTY(setHasOverlappingRendering, hasOverlappingRendering,
270 RenderNode::GENERIC);
273 static jboolean android_view_RenderNode_setElevation(JNIEnv* env,
274 jobject clazz, jlong renderNodePtr, float elevation) {
275 return SET_AND_DIRTY(setElevation, elevation, RenderNode::Z);
278 static jboolean android_view_RenderNode_setTranslationX(JNIEnv* env,
279 jobject clazz, jlong renderNodePtr, float tx) {
280 return SET_AND_DIRTY(setTranslationX, tx, RenderNode::TRANSLATION_X | RenderNode::X);
283 static jboolean android_view_RenderNode_setTranslationY(JNIEnv* env,
284 jobject clazz, jlong renderNodePtr, float ty) {
285 return SET_AND_DIRTY(setTranslationY, ty, RenderNode::TRANSLATION_Y | RenderNode::Y);
288 static jboolean android_view_RenderNode_setTranslationZ(JNIEnv* env,
289 jobject clazz, jlong renderNodePtr, float tz) {
290 return SET_AND_DIRTY(setTranslationZ, tz, RenderNode::TRANSLATION_Z | RenderNode::Z);
293 static jboolean android_view_RenderNode_setRotation(JNIEnv* env,
294 jobject clazz, jlong renderNodePtr, float rotation) {
295 return SET_AND_DIRTY(setRotation, rotation, RenderNode::ROTATION);
298 static jboolean android_view_RenderNode_setRotationX(JNIEnv* env,
299 jobject clazz, jlong renderNodePtr, float rx) {
300 return SET_AND_DIRTY(setRotationX, rx, RenderNode::ROTATION_X);
303 static jboolean android_view_RenderNode_setRotationY(JNIEnv* env,
304 jobject clazz, jlong renderNodePtr, float ry) {
305 return SET_AND_DIRTY(setRotationY, ry, RenderNode::ROTATION_Y);
308 static jboolean android_view_RenderNode_setScaleX(JNIEnv* env,
309 jobject clazz, jlong renderNodePtr, float sx) {
310 return SET_AND_DIRTY(setScaleX, sx, RenderNode::SCALE_X);
313 static jboolean android_view_RenderNode_setScaleY(JNIEnv* env,
314 jobject clazz, jlong renderNodePtr, float sy) {
315 return SET_AND_DIRTY(setScaleY, sy, RenderNode::SCALE_Y);
318 static jboolean android_view_RenderNode_setPivotX(JNIEnv* env,
319 jobject clazz, jlong renderNodePtr, float px) {
320 return SET_AND_DIRTY(setPivotX, px, RenderNode::GENERIC);
323 static jboolean android_view_RenderNode_setPivotY(JNIEnv* env,
324 jobject clazz, jlong renderNodePtr, float py) {
325 return SET_AND_DIRTY(setPivotY, py, RenderNode::GENERIC);
328 static jboolean android_view_RenderNode_setCameraDistance(JNIEnv* env,
329 jobject clazz, jlong renderNodePtr, float distance) {
330 return SET_AND_DIRTY(setCameraDistance, distance, RenderNode::GENERIC);
333 static jboolean android_view_RenderNode_setLeft(JNIEnv* env,
334 jobject clazz, jlong renderNodePtr, int left) {
335 return SET_AND_DIRTY(setLeft, left, RenderNode::X);
338 static jboolean android_view_RenderNode_setTop(JNIEnv* env,
339 jobject clazz, jlong renderNodePtr, int top) {
340 return SET_AND_DIRTY(setTop, top, RenderNode::Y);
343 static jboolean android_view_RenderNode_setRight(JNIEnv* env,
344 jobject clazz, jlong renderNodePtr, int right) {
345 return SET_AND_DIRTY(setRight, right, RenderNode::X);
348 static jboolean android_view_RenderNode_setBottom(JNIEnv* env,
349 jobject clazz, jlong renderNodePtr, int bottom) {
350 return SET_AND_DIRTY(setBottom, bottom, RenderNode::Y);
353 static jboolean android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
354 jobject clazz, jlong renderNodePtr, int left, int top,
355 int right, int bottom) {
356 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
357 if (renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom)) {
358 renderNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
364 static jboolean android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
365 jobject clazz, jlong renderNodePtr, jint offset) {
366 return SET_AND_DIRTY(offsetLeftRight, offset, RenderNode::X);
369 static jboolean android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
370 jobject clazz, jlong renderNodePtr, jint offset) {
371 return SET_AND_DIRTY(offsetTopBottom, offset, RenderNode::Y);
374 // ----------------------------------------------------------------------------
375 // RenderProperties - getters
376 // ----------------------------------------------------------------------------
378 static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
379 jobject clazz, jlong renderNodePtr) {
380 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
381 return renderNode->stagingProperties().hasOverlappingRendering();
384 static jboolean android_view_RenderNode_getClipToOutline(JNIEnv* env,
385 jobject clazz, jlong renderNodePtr) {
386 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
387 return renderNode->stagingProperties().getOutline().getShouldClip();
390 static jfloat android_view_RenderNode_getAlpha(JNIEnv* env,
391 jobject clazz, jlong renderNodePtr) {
392 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
393 return renderNode->stagingProperties().getAlpha();
396 static jfloat android_view_RenderNode_getCameraDistance(JNIEnv* env,
397 jobject clazz, jlong renderNodePtr) {
398 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
399 return renderNode->stagingProperties().getCameraDistance();
402 static jfloat android_view_RenderNode_getScaleX(JNIEnv* env,
403 jobject clazz, jlong renderNodePtr) {
404 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
405 return renderNode->stagingProperties().getScaleX();
408 static jfloat android_view_RenderNode_getScaleY(JNIEnv* env,
409 jobject clazz, jlong renderNodePtr) {
410 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
411 return renderNode->stagingProperties().getScaleY();
414 static jfloat android_view_RenderNode_getElevation(JNIEnv* env,
415 jobject clazz, jlong renderNodePtr) {
416 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
417 return renderNode->stagingProperties().getElevation();
420 static jfloat android_view_RenderNode_getTranslationX(JNIEnv* env,
421 jobject clazz, jlong renderNodePtr) {
422 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
423 return renderNode->stagingProperties().getTranslationX();
426 static jfloat android_view_RenderNode_getTranslationY(JNIEnv* env,
427 jobject clazz, jlong renderNodePtr) {
428 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
429 return renderNode->stagingProperties().getTranslationY();
432 static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env,
433 jobject clazz, jlong renderNodePtr) {
434 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
435 return renderNode->stagingProperties().getTranslationZ();
438 static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
439 jobject clazz, jlong renderNodePtr) {
440 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
441 return renderNode->stagingProperties().getRotation();
444 static jfloat android_view_RenderNode_getRotationX(JNIEnv* env,
445 jobject clazz, jlong renderNodePtr) {
446 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
447 return renderNode->stagingProperties().getRotationX();
450 static jfloat android_view_RenderNode_getRotationY(JNIEnv* env,
451 jobject clazz, jlong renderNodePtr) {
452 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
453 return renderNode->stagingProperties().getRotationY();
456 static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env,
457 jobject clazz, jlong renderNodePtr) {
458 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
459 return renderNode->stagingProperties().isPivotExplicitlySet();
462 static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env,
463 jobject clazz, jlong renderNodePtr) {
464 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
465 renderNode->mutateStagingProperties().updateMatrix();
466 return !renderNode->stagingProperties().hasTransformMatrix();
469 // ----------------------------------------------------------------------------
470 // RenderProperties - computed getters
471 // ----------------------------------------------------------------------------
473 static void android_view_RenderNode_getTransformMatrix(JNIEnv* env,
474 jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
475 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
476 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
478 renderNode->mutateStagingProperties().updateMatrix();
479 const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
481 if (transformMatrix) {
482 *outMatrix = *transformMatrix;
484 outMatrix->setIdentity();
488 static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
489 jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
490 // load transform matrix
491 android_view_RenderNode_getTransformMatrix(env, clazz, renderNodePtr, outMatrixPtr);
492 SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
494 // return it inverted
495 if (!outMatrix->invert(outMatrix)) {
496 // failed to load inverse, pass back identity
497 outMatrix->setIdentity();
501 static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
502 jobject clazz, jlong renderNodePtr) {
503 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
504 renderNode->mutateStagingProperties().updateMatrix();
505 return renderNode->stagingProperties().getPivotX();
508 static jfloat android_view_RenderNode_getPivotY(JNIEnv* env,
509 jobject clazz, jlong renderNodePtr) {
510 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
511 renderNode->mutateStagingProperties().updateMatrix();
512 return renderNode->stagingProperties().getPivotY();
515 // ----------------------------------------------------------------------------
516 // RenderProperties - Animations
517 // ----------------------------------------------------------------------------
519 static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
520 jlong renderNodePtr, jlong animatorPtr) {
521 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
522 RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
523 renderNode->addAnimator(animator);
526 static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
527 jlong renderNodePtr) {
528 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
529 renderNode->animators().endAllStagingAnimators();
532 // ----------------------------------------------------------------------------
533 // SurfaceView position callback
534 // ----------------------------------------------------------------------------
536 jmethodID gSurfaceViewPositionUpdateMethod;
537 jmethodID gSurfaceViewPositionLostMethod;
539 static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
540 jlong renderNodePtr, jobject surfaceview) {
541 class SurfaceViewPositionUpdater : public RenderNode::PositionListener {
543 SurfaceViewPositionUpdater(JNIEnv* env, jobject surfaceview) {
544 env->GetJavaVM(&mVm);
545 mWeakRef = env->NewWeakGlobalRef(surfaceview);
548 virtual ~SurfaceViewPositionUpdater() {
549 jnienv()->DeleteWeakGlobalRef(mWeakRef);
553 virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
554 if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return;
557 info.damageAccumulator->computeCurrentTransform(&transform);
558 const RenderProperties& props = node.properties();
559 uirenderer::Rect bounds(props.getWidth(), props.getHeight());
560 transform.mapRect(bounds);
561 bounds.left -= info.windowInsetLeft;
562 bounds.right -= info.windowInsetLeft;
563 bounds.top -= info.windowInsetTop;
564 bounds.bottom -= info.windowInsetTop;
566 if (CC_LIKELY(transform.isPureTranslate())) {
567 // snap/round the computed bounds, so they match the rounding behavior
568 // of the clear done in SurfaceView#draw().
569 bounds.snapToPixelBoundaries();
571 // Conservatively round out so the punched hole (in the ZOrderOnTop = true case)
572 // doesn't extend beyond the other window
577 auto functor = std::bind(
578 std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePositionAsync), this,
579 (jlong) info.canvasContext.getFrameNumber(),
580 (jint) bounds.left, (jint) bounds.top,
581 (jint) bounds.right, (jint) bounds.bottom);
583 info.canvasContext.enqueueFrameWork(std::move(functor));
586 virtual void onPositionLost(RenderNode& node, const TreeInfo* info) override {
587 if (CC_UNLIKELY(!mWeakRef || (info && !info->updateWindowPositions))) return;
589 ATRACE_NAME("SurfaceView position lost");
590 JNIEnv* env = jnienv();
591 jobject localref = env->NewLocalRef(mWeakRef);
592 if (CC_UNLIKELY(!localref)) {
593 jnienv()->DeleteWeakGlobalRef(mWeakRef);
598 env->CallVoidMethod(localref, gSurfaceViewPositionLostMethod,
599 info ? info->canvasContext.getFrameNumber() : 0);
600 env->DeleteLocalRef(localref);
606 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
607 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
612 void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
613 jint right, jint bottom) {
614 ATRACE_NAME("Update SurfaceView position");
616 JNIEnv* env = jnienv();
617 jobject localref = env->NewLocalRef(mWeakRef);
618 if (CC_UNLIKELY(!localref)) {
619 env->DeleteWeakGlobalRef(mWeakRef);
622 env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod,
623 frameNumber, left, top, right, bottom);
624 env->DeleteLocalRef(localref);
627 // We need to release ourselves here
635 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
636 renderNode->setPositionListener(new SurfaceViewPositionUpdater(env, surfaceview));
639 // ----------------------------------------------------------------------------
641 // ----------------------------------------------------------------------------
643 const char* const kClassPathName = "android/view/RenderNode";
645 static const JNINativeMethod gMethods[] = {
646 { "nCreate", "(Ljava/lang/String;)J", (void*) android_view_RenderNode_create },
647 { "nDestroyRenderNode", "(J)V", (void*) android_view_RenderNode_destroyRenderNode },
648 { "nSetDisplayList", "(JJ)V", (void*) android_view_RenderNode_setDisplayList },
649 { "nOutput", "(J)V", (void*) android_view_RenderNode_output },
650 { "nGetDebugSize", "(J)I", (void*) android_view_RenderNode_getDebugSize },
652 { "nSetLayerType", "!(JI)Z", (void*) android_view_RenderNode_setLayerType },
653 { "nSetLayerPaint", "!(JJ)Z", (void*) android_view_RenderNode_setLayerPaint },
654 { "nSetStaticMatrix", "!(JJ)Z", (void*) android_view_RenderNode_setStaticMatrix },
655 { "nSetAnimationMatrix", "!(JJ)Z", (void*) android_view_RenderNode_setAnimationMatrix },
656 { "nSetClipToBounds", "!(JZ)Z", (void*) android_view_RenderNode_setClipToBounds },
657 { "nSetClipBounds", "!(JIIII)Z", (void*) android_view_RenderNode_setClipBounds },
658 { "nSetClipBoundsEmpty", "!(J)Z", (void*) android_view_RenderNode_setClipBoundsEmpty },
659 { "nSetProjectBackwards", "!(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards },
660 { "nSetProjectionReceiver","!(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver },
662 { "nSetOutlineRoundRect", "!(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect },
663 { "nSetOutlineConvexPath", "!(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
664 { "nSetOutlineEmpty", "!(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
665 { "nSetOutlineNone", "!(J)Z", (void*) android_view_RenderNode_setOutlineNone },
666 { "nHasShadow", "!(J)Z", (void*) android_view_RenderNode_hasShadow },
667 { "nSetClipToOutline", "!(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
668 { "nSetRevealClip", "!(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
670 { "nSetAlpha", "!(JF)Z", (void*) android_view_RenderNode_setAlpha },
671 { "nSetHasOverlappingRendering", "!(JZ)Z",
672 (void*) android_view_RenderNode_setHasOverlappingRendering },
673 { "nSetElevation", "!(JF)Z", (void*) android_view_RenderNode_setElevation },
674 { "nSetTranslationX", "!(JF)Z", (void*) android_view_RenderNode_setTranslationX },
675 { "nSetTranslationY", "!(JF)Z", (void*) android_view_RenderNode_setTranslationY },
676 { "nSetTranslationZ", "!(JF)Z", (void*) android_view_RenderNode_setTranslationZ },
677 { "nSetRotation", "!(JF)Z", (void*) android_view_RenderNode_setRotation },
678 { "nSetRotationX", "!(JF)Z", (void*) android_view_RenderNode_setRotationX },
679 { "nSetRotationY", "!(JF)Z", (void*) android_view_RenderNode_setRotationY },
680 { "nSetScaleX", "!(JF)Z", (void*) android_view_RenderNode_setScaleX },
681 { "nSetScaleY", "!(JF)Z", (void*) android_view_RenderNode_setScaleY },
682 { "nSetPivotX", "!(JF)Z", (void*) android_view_RenderNode_setPivotX },
683 { "nSetPivotY", "!(JF)Z", (void*) android_view_RenderNode_setPivotY },
684 { "nSetCameraDistance", "!(JF)Z", (void*) android_view_RenderNode_setCameraDistance },
685 { "nSetLeft", "!(JI)Z", (void*) android_view_RenderNode_setLeft },
686 { "nSetTop", "!(JI)Z", (void*) android_view_RenderNode_setTop },
687 { "nSetRight", "!(JI)Z", (void*) android_view_RenderNode_setRight },
688 { "nSetBottom", "!(JI)Z", (void*) android_view_RenderNode_setBottom },
689 { "nSetLeftTopRightBottom","!(JIIII)Z", (void*) android_view_RenderNode_setLeftTopRightBottom },
690 { "nOffsetLeftAndRight", "!(JI)Z", (void*) android_view_RenderNode_offsetLeftAndRight },
691 { "nOffsetTopAndBottom", "!(JI)Z", (void*) android_view_RenderNode_offsetTopAndBottom },
693 { "nHasOverlappingRendering", "!(J)Z", (void*) android_view_RenderNode_hasOverlappingRendering },
694 { "nGetClipToOutline", "!(J)Z", (void*) android_view_RenderNode_getClipToOutline },
695 { "nGetAlpha", "!(J)F", (void*) android_view_RenderNode_getAlpha },
696 { "nGetCameraDistance", "!(J)F", (void*) android_view_RenderNode_getCameraDistance },
697 { "nGetScaleX", "!(J)F", (void*) android_view_RenderNode_getScaleX },
698 { "nGetScaleY", "!(J)F", (void*) android_view_RenderNode_getScaleY },
699 { "nGetElevation", "!(J)F", (void*) android_view_RenderNode_getElevation },
700 { "nGetTranslationX", "!(J)F", (void*) android_view_RenderNode_getTranslationX },
701 { "nGetTranslationY", "!(J)F", (void*) android_view_RenderNode_getTranslationY },
702 { "nGetTranslationZ", "!(J)F", (void*) android_view_RenderNode_getTranslationZ },
703 { "nGetRotation", "!(J)F", (void*) android_view_RenderNode_getRotation },
704 { "nGetRotationX", "!(J)F", (void*) android_view_RenderNode_getRotationX },
705 { "nGetRotationY", "!(J)F", (void*) android_view_RenderNode_getRotationY },
706 { "nIsPivotExplicitlySet", "!(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet },
707 { "nHasIdentityMatrix", "!(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix },
709 { "nGetTransformMatrix", "!(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
710 { "nGetInverseTransformMatrix","!(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
712 { "nGetPivotX", "!(J)F", (void*) android_view_RenderNode_getPivotX },
713 { "nGetPivotY", "!(J)F", (void*) android_view_RenderNode_getPivotY },
715 { "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator },
716 { "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators },
718 { "nRequestPositionUpdates", "(JLandroid/view/SurfaceView;)V", (void*) android_view_RenderNode_requestPositionUpdates },
721 int register_android_view_RenderNode(JNIEnv* env) {
722 jclass clazz = FindClassOrDie(env, "android/view/SurfaceView");
723 gSurfaceViewPositionUpdateMethod = GetMethodIDOrDie(env, clazz,
724 "updateWindowPositionRT", "(JIIII)V");
725 gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
726 "windowPositionLostRT", "(J)V");
727 clazz = FindClassOrDie(env, "android/view/RenderNode");
728 gOnRenderNodeDetached = GetMethodIDOrDie(env, clazz,
729 "onRenderNodeDetached", "()V");
730 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));