1 /*
2 * Copyright (C) 2010 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 #undef LOG_TAG
18 #define LOG_TAG "ThreadedRenderer"
19 #define ATRACE_TAG ATRACE_TAG_VIEW
20
21 #include <FrameInfo.h>
22 #include <GraphicsJNI.h>
23 #include <Picture.h>
24 #include <Properties.h>
25 #include <RootRenderNode.h>
26 #include <SkImagePriv.h>
27 #include <SkSerialProcs.h>
28 #include <dlfcn.h>
29 #include <gui/TraceUtils.h>
30 #include <inttypes.h>
31 #include <media/NdkImage.h>
32 #include <media/NdkImageReader.h>
33 #include <nativehelper/JNIPlatformHelp.h>
34 #include <pipeline/skia/ShaderCache.h>
35 #include <private/EGL/cache.h>
36 #include <renderthread/CanvasContext.h>
37 #include <renderthread/RenderProxy.h>
38 #include <renderthread/RenderTask.h>
39 #include <renderthread/RenderThread.h>
40 #include <src/image/SkImage_Base.h>
41 #include <thread/CommonPool.h>
42 #include <utils/Color.h>
43 #include <utils/RefBase.h>
44 #include <utils/StrongPointer.h>
45 #include <utils/Timers.h>
46
47 #include <algorithm>
48 #include <atomic>
49 #include <vector>
50
51 #include "android_graphics_HardwareRendererObserver.h"
52
53 namespace android {
54
55 using namespace android::uirenderer;
56 using namespace android::uirenderer::renderthread;
57
58 struct {
59 jclass clazz;
60 jmethodID invokePictureCapturedCallback;
61 } gHardwareRenderer;
62
63 struct {
64 jmethodID onMergeTransaction;
65 } gASurfaceTransactionCallback;
66
67 struct {
68 jmethodID prepare;
69 } gPrepareSurfaceControlForWebviewCallback;
70
71 struct {
72 jmethodID onFrameDraw;
73 } gFrameDrawingCallback;
74
75 struct {
76 jmethodID onFrameCommit;
77 } gFrameCommitCallback;
78
79 struct {
80 jmethodID onFrameComplete;
81 } gFrameCompleteCallback;
82
getenv(JavaVM * vm)83 static JNIEnv* getenv(JavaVM* vm) {
84 JNIEnv* env;
85 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
86 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
87 }
88 return env;
89 }
90
91 typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
92 ANW_fromSurface fromSurface;
93
94 class JvmErrorReporter : public ErrorHandler {
95 public:
JvmErrorReporter(JNIEnv * env)96 JvmErrorReporter(JNIEnv* env) {
97 env->GetJavaVM(&mVm);
98 }
99
onError(const std::string & message)100 virtual void onError(const std::string& message) override {
101 JNIEnv* env = getenv(mVm);
102 jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
103 }
104 private:
105 JavaVM* mVm;
106 };
107
108 class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
109 public:
FrameCommitWrapper(JNIEnv * env,jobject jobject)110 explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
111 env->GetJavaVM(&mVm);
112 mObject = env->NewGlobalRef(jobject);
113 LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
114 }
115
~FrameCommitWrapper()116 ~FrameCommitWrapper() { releaseObject(); }
117
onFrameCommit(bool didProduceBuffer)118 void onFrameCommit(bool didProduceBuffer) {
119 if (mObject) {
120 ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
121 getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
122 didProduceBuffer);
123 releaseObject();
124 }
125 }
126
127 private:
128 JavaVM* mVm;
129 jobject mObject;
130
releaseObject()131 void releaseObject() {
132 if (mObject) {
133 getenv(mVm)->DeleteGlobalRef(mObject);
134 mObject = nullptr;
135 }
136 }
137 };
138
android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv * env,jobject clazz)139 static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
140 RenderProxy::rotateProcessStatsBuffer();
141 }
142
android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv * env,jobject clazz,jint fd)143 static void android_view_ThreadedRenderer_setProcessStatsBuffer(JNIEnv* env, jobject clazz,
144 jint fd) {
145 RenderProxy::setProcessStatsBuffer(fd);
146 }
147
android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv * env,jobject clazz,jlong proxyPtr)148 static jint android_view_ThreadedRenderer_getRenderThreadTid(JNIEnv* env, jobject clazz,
149 jlong proxyPtr) {
150 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
151 return proxy->getRenderThreadTid();
152 }
153
android_view_ThreadedRenderer_createRootRenderNode(JNIEnv * env,jobject clazz)154 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
155 RootRenderNode* node = new RootRenderNode(std::make_unique<JvmErrorReporter>(env));
156 node->incStrong(0);
157 node->setName("RootRenderNode");
158 return reinterpret_cast<jlong>(node);
159 }
160
android_view_ThreadedRenderer_createProxy(JNIEnv * env,jobject clazz,jboolean translucent,jlong rootRenderNodePtr)161 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
162 jboolean translucent, jlong rootRenderNodePtr) {
163 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
164 ContextFactoryImpl factory(rootRenderNode);
165 RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
166 return (jlong) proxy;
167 }
168
android_view_ThreadedRenderer_deleteProxy(JNIEnv * env,jobject clazz,jlong proxyPtr)169 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
170 jlong proxyPtr) {
171 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
172 delete proxy;
173 }
174
android_view_ThreadedRenderer_loadSystemProperties(JNIEnv * env,jobject clazz,jlong proxyPtr)175 static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
176 jlong proxyPtr) {
177 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
178 return proxy->loadSystemProperties();
179 }
180
android_view_ThreadedRenderer_setName(JNIEnv * env,jobject clazz,jlong proxyPtr,jstring jname)181 static void android_view_ThreadedRenderer_setName(JNIEnv* env, jobject clazz,
182 jlong proxyPtr, jstring jname) {
183 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
184 const char* name = env->GetStringUTFChars(jname, NULL);
185 proxy->setName(name);
186 env->ReleaseStringUTFChars(jname, name);
187 }
188
android_view_ThreadedRenderer_setSurface(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject jsurface,jboolean discardBuffer)189 static void android_view_ThreadedRenderer_setSurface(JNIEnv* env, jobject clazz,
190 jlong proxyPtr, jobject jsurface, jboolean discardBuffer) {
191 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
192 ANativeWindow* window = nullptr;
193 if (jsurface) {
194 window = fromSurface(env, jsurface);
195 }
196 bool enableTimeout = true;
197 if (discardBuffer) {
198 // Currently only Surface#lockHardwareCanvas takes this path
199 enableTimeout = false;
200 proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
201 }
202 proxy->setSurface(window, enableTimeout);
203 if (window) {
204 ANativeWindow_release(window);
205 }
206 }
207
android_view_ThreadedRenderer_setSurfaceControl(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong surfaceControlPtr)208 static void android_view_ThreadedRenderer_setSurfaceControl(JNIEnv* env, jobject clazz,
209 jlong proxyPtr, jlong surfaceControlPtr) {
210 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
211 ASurfaceControl* surfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControlPtr);
212 proxy->setSurfaceControl(surfaceControl);
213 }
214
android_view_ThreadedRenderer_pause(JNIEnv * env,jobject clazz,jlong proxyPtr)215 static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
216 jlong proxyPtr) {
217 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
218 return proxy->pause();
219 }
220
android_view_ThreadedRenderer_setStopped(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean stopped)221 static void android_view_ThreadedRenderer_setStopped(JNIEnv* env, jobject clazz,
222 jlong proxyPtr, jboolean stopped) {
223 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
224 proxy->setStopped(stopped);
225 }
226
android_view_ThreadedRenderer_setLightAlpha(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat ambientShadowAlpha,jfloat spotShadowAlpha)227 static void android_view_ThreadedRenderer_setLightAlpha(JNIEnv* env, jobject clazz, jlong proxyPtr,
228 jfloat ambientShadowAlpha, jfloat spotShadowAlpha) {
229 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
230 proxy->setLightAlpha((uint8_t) (255 * ambientShadowAlpha), (uint8_t) (255 * spotShadowAlpha));
231 }
232
android_view_ThreadedRenderer_setLightGeometry(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat lightX,jfloat lightY,jfloat lightZ,jfloat lightRadius)233 static void android_view_ThreadedRenderer_setLightGeometry(JNIEnv* env, jobject clazz,
234 jlong proxyPtr, jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius) {
235 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
236 proxy->setLightGeometry((Vector3){lightX, lightY, lightZ}, lightRadius);
237 }
238
android_view_ThreadedRenderer_setOpaque(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean opaque)239 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
240 jlong proxyPtr, jboolean opaque) {
241 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
242 proxy->setOpaque(opaque);
243 }
244
android_view_ThreadedRenderer_setColorMode(JNIEnv * env,jobject clazz,jlong proxyPtr,jint colorMode)245 static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz,
246 jlong proxyPtr, jint colorMode) {
247 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
248 proxy->setColorMode(static_cast<ColorMode>(colorMode));
249 }
250
android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv * env,jobject clazz,jlong proxyPtr,jfloat sdrWhitePoint)251 static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz,
252 jlong proxyPtr, jfloat sdrWhitePoint) {
253 Properties::defaultSdrWhitePoint = sdrWhitePoint;
254 }
255
android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv * env,jobject clazz,jboolean jIsHighEndGfx)256 static void android_view_ThreadedRenderer_setIsHighEndGfx(JNIEnv* env, jobject clazz,
257 jboolean jIsHighEndGfx) {
258 Properties::setIsHighEndGfx(jIsHighEndGfx);
259 }
260
android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv * env,jobject clazz,jlong proxyPtr,jlongArray frameInfo,jint frameInfoSize)261 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
262 jlong proxyPtr, jlongArray frameInfo,
263 jint frameInfoSize) {
264 LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
265 "Mismatched size expectations, given %d expected %zu", frameInfoSize,
266 UI_THREAD_FRAME_INFO_SIZE);
267 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
268 env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
269 return proxy->syncAndDrawFrame();
270 }
271
android_view_ThreadedRenderer_destroy(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong rootNodePtr)272 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
273 jlong proxyPtr, jlong rootNodePtr) {
274 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
275 rootRenderNode->destroy();
276 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
277 proxy->destroy();
278 }
279
android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatingNodePtr)280 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
281 jlong rootNodePtr, jlong animatingNodePtr) {
282 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
283 RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr);
284 rootRenderNode->attachAnimatingNode(animatingNode);
285 }
286
android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv * env,jobject clazz,jlong rootNodePtr,jlong animatorPtr)287 static void android_view_ThreadedRenderer_registerVectorDrawableAnimator(JNIEnv* env, jobject clazz,
288 jlong rootNodePtr, jlong animatorPtr) {
289 RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
290 PropertyValuesAnimatorSet* animator = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr);
291 rootRenderNode->addVectorDrawableAnimator(animator);
292 }
293
android_view_ThreadedRenderer_createTextureLayer(JNIEnv * env,jobject clazz,jlong proxyPtr)294 static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
295 jlong proxyPtr) {
296 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
297 DeferredLayerUpdater* layer = proxy->createTextureLayer();
298 return reinterpret_cast<jlong>(layer);
299 }
300
android_view_ThreadedRenderer_buildLayer(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong nodePtr)301 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
302 jlong proxyPtr, jlong nodePtr) {
303 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
304 RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
305 proxy->buildLayer(node);
306 }
307
android_view_ThreadedRenderer_copyLayerInto(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr,jlong bitmapPtr)308 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
309 jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
310 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
311 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
312 SkBitmap bitmap;
313 bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
314 return proxy->copyLayerInto(layer, bitmap);
315 }
316
android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)317 static void android_view_ThreadedRenderer_pushLayerUpdate(JNIEnv* env, jobject clazz,
318 jlong proxyPtr, jlong layerPtr) {
319 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
320 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
321 proxy->pushLayerUpdate(layer);
322 }
323
android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)324 static void android_view_ThreadedRenderer_cancelLayerUpdate(JNIEnv* env, jobject clazz,
325 jlong proxyPtr, jlong layerPtr) {
326 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
327 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
328 proxy->cancelLayerUpdate(layer);
329 }
330
android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong layerPtr)331 static void android_view_ThreadedRenderer_detachSurfaceTexture(JNIEnv* env, jobject clazz,
332 jlong proxyPtr, jlong layerPtr) {
333 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
334 DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
335 proxy->detachSurfaceTexture(layer);
336 }
337
android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv * env,jobject clazz,jlong proxyPtr)338 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
339 jlong proxyPtr) {
340 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
341 proxy->destroyHardwareResources();
342 }
343
android_view_ThreadedRenderer_trimMemory(JNIEnv * env,jobject clazz,jint level)344 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
345 jint level) {
346 RenderProxy::trimMemory(level);
347 }
348
android_view_ThreadedRenderer_overrideProperty(JNIEnv * env,jobject clazz,jstring name,jstring value)349 static void android_view_ThreadedRenderer_overrideProperty(JNIEnv* env, jobject clazz,
350 jstring name, jstring value) {
351 const char* nameCharArray = env->GetStringUTFChars(name, NULL);
352 const char* valueCharArray = env->GetStringUTFChars(value, NULL);
353 RenderProxy::overrideProperty(nameCharArray, valueCharArray);
354 env->ReleaseStringUTFChars(name, nameCharArray);
355 env->ReleaseStringUTFChars(name, valueCharArray);
356 }
357
android_view_ThreadedRenderer_fence(JNIEnv * env,jobject clazz,jlong proxyPtr)358 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
359 jlong proxyPtr) {
360 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
361 proxy->fence();
362 }
363
android_view_ThreadedRenderer_stopDrawing(JNIEnv * env,jobject clazz,jlong proxyPtr)364 static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
365 jlong proxyPtr) {
366 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
367 proxy->stopDrawing();
368 }
369
android_view_ThreadedRenderer_notifyFramePending(JNIEnv * env,jobject clazz,jlong proxyPtr)370 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
371 jlong proxyPtr) {
372 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
373 proxy->notifyFramePending();
374 }
375
android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject javaFileDescriptor,jint dumpFlags)376 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
377 jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
378 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
379 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
380 proxy->dumpProfileInfo(fd, dumpFlags);
381 }
382
android_view_ThreadedRenderer_dumpGlobalProfileInfo(JNIEnv * env,jobject clazz,jobject javaFileDescriptor,jint dumpFlags)383 static void android_view_ThreadedRenderer_dumpGlobalProfileInfo(JNIEnv* env, jobject clazz,
384 jobject javaFileDescriptor,
385 jint dumpFlags) {
386 int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
387 RenderProxy::dumpGraphicsMemory(fd, true, dumpFlags & DumpFlags::Reset);
388 }
389
android_view_ThreadedRenderer_addRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr,jboolean placeFront)390 static void android_view_ThreadedRenderer_addRenderNode(JNIEnv* env, jobject clazz,
391 jlong proxyPtr, jlong renderNodePtr, jboolean placeFront) {
392 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
393 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
394 proxy->addRenderNode(renderNode, placeFront);
395 }
396
android_view_ThreadedRenderer_removeRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)397 static void android_view_ThreadedRenderer_removeRenderNode(JNIEnv* env, jobject clazz,
398 jlong proxyPtr, jlong renderNodePtr) {
399 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
400 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
401 proxy->removeRenderNode(renderNode);
402 }
403
android_view_ThreadedRendererd_drawRenderNode(JNIEnv * env,jobject clazz,jlong proxyPtr,jlong renderNodePtr)404 static void android_view_ThreadedRendererd_drawRenderNode(JNIEnv* env, jobject clazz,
405 jlong proxyPtr, jlong renderNodePtr) {
406 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
407 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
408 proxy->drawRenderNode(renderNode);
409 }
410
android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv * env,jobject clazz,jlong proxyPtr,jint left,jint top,jint right,jint bottom)411 static void android_view_ThreadedRenderer_setContentDrawBounds(JNIEnv* env,
412 jobject clazz, jlong proxyPtr, jint left, jint top, jint right, jint bottom) {
413 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
414 proxy->setContentDrawBounds(left, top, right, bottom);
415 }
416
android_view_ThreadedRenderer_forceDrawNextFrame(JNIEnv * env,jobject clazz,jlong proxyPtr)417 static void android_view_ThreadedRenderer_forceDrawNextFrame(JNIEnv* env, jobject clazz,
418 jlong proxyPtr) {
419 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
420 proxy->forceDrawNextFrame();
421 }
422
423 class JGlobalRefHolder {
424 public:
JGlobalRefHolder(JavaVM * vm,jobject object)425 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
426
~JGlobalRefHolder()427 virtual ~JGlobalRefHolder() {
428 getenv(mVm)->DeleteGlobalRef(mObject);
429 mObject = nullptr;
430 }
431
object()432 jobject object() { return mObject; }
vm()433 JavaVM* vm() { return mVm; }
434
435 private:
436 JGlobalRefHolder(const JGlobalRefHolder&) = delete;
437 void operator=(const JGlobalRefHolder&) = delete;
438
439 JavaVM* mVm;
440 jobject mObject;
441 };
442
443 using TextureMap = std::unordered_map<uint32_t, sk_sp<SkImage>>;
444
445 struct PictureCaptureState {
446 // Each frame we move from the active map to the previous map, essentially an LRU of 1 frame
447 // This avoids repeated readbacks of the same image, but avoids artificially extending the
448 // lifetime of any particular image.
449 TextureMap mActiveMap;
450 TextureMap mPreviousActiveMap;
451 };
452
453 // TODO: This & Multi-SKP & Single-SKP should all be de-duped into
454 // a single "make a SkPicture serailizable-safe" utility somewhere
455 class PictureWrapper : public Picture {
456 public:
PictureWrapper(sk_sp<SkPicture> && src,const std::shared_ptr<PictureCaptureState> & state)457 PictureWrapper(sk_sp<SkPicture>&& src, const std::shared_ptr<PictureCaptureState>& state)
458 : Picture(), mPicture(std::move(src)) {
459 ATRACE_NAME("Preparing SKP for capture");
460 // Move the active to previous active
461 state->mPreviousActiveMap = std::move(state->mActiveMap);
462 state->mActiveMap.clear();
463 SkSerialProcs tempProc;
464 tempProc.fImageCtx = state.get();
465 tempProc.fImageProc = collectNonTextureImagesProc;
466 auto ns = SkNullWStream();
467 mPicture->serialize(&ns, &tempProc);
468 state->mPreviousActiveMap.clear();
469
470 // Now snapshot a copy of the active map so this PictureWrapper becomes self-sufficient
471 mTextureMap = state->mActiveMap;
472 }
473
imageForCache(SkImage * img)474 static sk_sp<SkImage> imageForCache(SkImage* img) {
475 const SkBitmap* bitmap = as_IB(img)->onPeekBitmap();
476 // This is a mutable bitmap pretending to be an immutable SkImage. As we're going to
477 // actually cross thread boundaries here, make a copy so it's immutable proper
478 if (bitmap && !bitmap->isImmutable()) {
479 ATRACE_NAME("Copying mutable bitmap");
480 return SkImage::MakeFromBitmap(*bitmap);
481 }
482 if (img->isTextureBacked()) {
483 ATRACE_NAME("Readback of texture image");
484 return img->makeNonTextureImage();
485 }
486 SkPixmap pm;
487 if (img->isLazyGenerated() && !img->peekPixels(&pm)) {
488 ATRACE_NAME("Readback of HW bitmap");
489 // This is a hardware bitmap probably
490 SkBitmap bm;
491 if (!bm.tryAllocPixels(img->imageInfo())) {
492 // Failed to allocate, just see what happens
493 return sk_ref_sp(img);
494 }
495 if (RenderProxy::copyImageInto(sk_ref_sp(img), &bm)) {
496 // Failed to readback
497 return sk_ref_sp(img);
498 }
499 bm.setImmutable();
500 return SkMakeImageFromRasterBitmap(bm, kNever_SkCopyPixelsMode);
501 }
502 return sk_ref_sp(img);
503 }
504
collectNonTextureImagesProc(SkImage * img,void * ctx)505 static sk_sp<SkData> collectNonTextureImagesProc(SkImage* img, void* ctx) {
506 PictureCaptureState* context = reinterpret_cast<PictureCaptureState*>(ctx);
507 const uint32_t originalId = img->uniqueID();
508 auto it = context->mActiveMap.find(originalId);
509 if (it == context->mActiveMap.end()) {
510 auto pit = context->mPreviousActiveMap.find(originalId);
511 if (pit == context->mPreviousActiveMap.end()) {
512 context->mActiveMap[originalId] = imageForCache(img);
513 } else {
514 context->mActiveMap[originalId] = pit->second;
515 }
516 }
517 return SkData::MakeEmpty();
518 }
519
serializeImage(SkImage * img,void * ctx)520 static sk_sp<SkData> serializeImage(SkImage* img, void* ctx) {
521 PictureWrapper* context = reinterpret_cast<PictureWrapper*>(ctx);
522 const uint32_t id = img->uniqueID();
523 auto iter = context->mTextureMap.find(id);
524 if (iter != context->mTextureMap.end()) {
525 img = iter->second.get();
526 }
527 return img->encodeToData();
528 }
529
serialize(SkWStream * stream) const530 void serialize(SkWStream* stream) const override {
531 SkSerialProcs procs;
532 procs.fImageProc = serializeImage;
533 procs.fImageCtx = const_cast<PictureWrapper*>(this);
534 procs.fTypefaceProc = [](SkTypeface* tf, void* ctx) {
535 return tf->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
536 };
537 mPicture->serialize(stream, &procs);
538 }
539
540 private:
541 sk_sp<SkPicture> mPicture;
542 TextureMap mTextureMap;
543 };
544
android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject pictureCallback)545 static void android_view_ThreadedRenderer_setPictureCapturedCallbackJNI(JNIEnv* env,
546 jobject clazz, jlong proxyPtr, jobject pictureCallback) {
547 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
548 if (!pictureCallback) {
549 proxy->setPictureCapturedCallback(nullptr);
550 } else {
551 JavaVM* vm = nullptr;
552 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
553 auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
554 env->NewGlobalRef(pictureCallback));
555 auto pictureState = std::make_shared<PictureCaptureState>();
556 proxy->setPictureCapturedCallback([globalCallbackRef,
557 pictureState](sk_sp<SkPicture>&& picture) {
558 JNIEnv* env = getenv(globalCallbackRef->vm());
559 Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
560 env->CallStaticVoidMethod(gHardwareRenderer.clazz,
561 gHardwareRenderer.invokePictureCapturedCallback,
562 static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
563 globalCallbackRef->object());
564 });
565 }
566 }
567
android_view_ThreadedRenderer_setASurfaceTransactionCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject aSurfaceTransactionCallback)568 static void android_view_ThreadedRenderer_setASurfaceTransactionCallback(
569 JNIEnv* env, jobject clazz, jlong proxyPtr, jobject aSurfaceTransactionCallback) {
570 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
571 if (!aSurfaceTransactionCallback) {
572 proxy->setASurfaceTransactionCallback(nullptr);
573 } else {
574 JavaVM* vm = nullptr;
575 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
576 auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(
577 vm, env->NewGlobalRef(aSurfaceTransactionCallback));
578 proxy->setASurfaceTransactionCallback(
579 [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) -> bool {
580 JNIEnv* env = getenv(globalCallbackRef->vm());
581 jboolean ret = env->CallBooleanMethod(
582 globalCallbackRef->object(),
583 gASurfaceTransactionCallback.onMergeTransaction,
584 static_cast<jlong>(transObj), static_cast<jlong>(scObj),
585 static_cast<jlong>(frameNr));
586 return ret;
587 });
588 }
589 }
590
android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)591 static void android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback(
592 JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) {
593 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
594 if (!callback) {
595 proxy->setPrepareSurfaceControlForWebviewCallback(nullptr);
596 } else {
597 JavaVM* vm = nullptr;
598 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
599 auto globalCallbackRef =
600 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
601 proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
602 JNIEnv* env = getenv(globalCallbackRef->vm());
603 env->CallVoidMethod(globalCallbackRef->object(),
604 gPrepareSurfaceControlForWebviewCallback.prepare);
605 });
606 }
607 }
608
android_view_ThreadedRenderer_setFrameCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject frameCallback)609 static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env,
610 jobject clazz, jlong proxyPtr, jobject frameCallback) {
611 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
612 if (!frameCallback) {
613 proxy->setFrameCallback(nullptr);
614 } else {
615 JavaVM* vm = nullptr;
616 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
617 auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(vm,
618 env->NewGlobalRef(frameCallback));
619 proxy->setFrameCallback([globalCallbackRef](int32_t syncResult,
620 int64_t frameNr) -> std::function<void(bool)> {
621 JNIEnv* env = getenv(globalCallbackRef->vm());
622 ScopedLocalRef<jobject> frameCommitCallback(
623 env, env->CallObjectMethod(
624 globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
625 static_cast<jint>(syncResult), static_cast<jlong>(frameNr)));
626 if (frameCommitCallback == nullptr) {
627 return nullptr;
628 }
629 sp<FrameCommitWrapper> wrapper =
630 sp<FrameCommitWrapper>::make(env, frameCommitCallback.get());
631 return [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); };
632 });
633 }
634 }
635
android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)636 static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz,
637 jlong proxyPtr, jobject callback) {
638 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
639 if (!callback) {
640 proxy->setFrameCommitCallback(nullptr);
641 } else {
642 sp<FrameCommitWrapper> wrapper = sp<FrameCommitWrapper>::make(env, callback);
643 proxy->setFrameCommitCallback(
644 [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); });
645 }
646 }
647
android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv * env,jobject clazz,jlong proxyPtr,jobject callback)648 static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env,
649 jobject clazz, jlong proxyPtr, jobject callback) {
650 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
651 if (!callback) {
652 proxy->setFrameCompleteCallback(nullptr);
653 } else {
654 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
655 JavaVM* vm = nullptr;
656 LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
657 auto globalCallbackRef =
658 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
659 proxy->setFrameCompleteCallback([globalCallbackRef]() {
660 JNIEnv* env = getenv(globalCallbackRef->vm());
661 env->CallVoidMethod(globalCallbackRef->object(),
662 gFrameCompleteCallback.onFrameComplete);
663 });
664 }
665 }
666
android_view_ThreadedRenderer_copySurfaceInto(JNIEnv * env,jobject clazz,jobject jsurface,jint left,jint top,jint right,jint bottom,jlong bitmapPtr)667 static jint android_view_ThreadedRenderer_copySurfaceInto(JNIEnv* env,
668 jobject clazz, jobject jsurface, jint left, jint top,
669 jint right, jint bottom, jlong bitmapPtr) {
670 SkBitmap bitmap;
671 bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
672 ANativeWindow* window = fromSurface(env, jsurface);
673 jint result = RenderProxy::copySurfaceInto(window, left, top, right, bottom, &bitmap);
674 ANativeWindow_release(window);
675 return result;
676 }
677
678 class ContextFactory : public IContextFactory {
679 public:
createAnimationContext(renderthread::TimeLord & clock)680 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
681 return new AnimationContext(clock);
682 }
683 };
684
android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv * env,jobject clazz,jlong renderNodePtr,jint jwidth,jint jheight)685 static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
686 jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
687 RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
688 if (jwidth <= 0 || jheight <= 0) {
689 ALOGW("Invalid width %d or height %d", jwidth, jheight);
690 return nullptr;
691 }
692
693 uint32_t width = jwidth;
694 uint32_t height = jheight;
695
696 // Create an ImageReader wired up to a BufferItemConsumer
697 AImageReader* rawReader;
698 constexpr auto usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
699 AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER |
700 AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY;
701 media_status_t result =
702 AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, usage, 2, &rawReader);
703 std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader,
704 AImageReader_delete);
705
706 if (result != AMEDIA_OK) {
707 ALOGW("Error creating image reader!");
708 return nullptr;
709 }
710
711 // Note that ownership of this window is maintained by AImageReader, so we
712 // shouldn't need to wrap around a smart pointer.
713 ANativeWindow* window;
714 result = AImageReader_getWindow(rawReader, &window);
715
716 if (result != AMEDIA_OK) {
717 ALOGW("Error retrieving the native window!");
718 return nullptr;
719 }
720
721 // Render into the surface
722 {
723 ContextFactory factory;
724 RenderProxy proxy{true, renderNode, &factory};
725 proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
726 proxy.setSurface(window);
727 // Shadows can't be used via this interface, so just set the light source
728 // to all 0s.
729 proxy.setLightAlpha(0, 0);
730 proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
731 nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
732 UiFrameInfoBuilder(proxy.frameInfo())
733 .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
734 UiFrameInfoBuilder::UNKNOWN_DEADLINE,
735 UiFrameInfoBuilder::UNKNOWN_FRAME_INTERVAL)
736 .addFlag(FrameInfoFlags::SurfaceCanvas);
737 proxy.syncAndDrawFrame();
738 }
739
740 AImage* rawImage;
741 result = AImageReader_acquireNextImage(rawReader, &rawImage);
742 std::unique_ptr<AImage, decltype(&AImage_delete)> image(rawImage, AImage_delete);
743 if (result != AMEDIA_OK) {
744 ALOGW("Error reading image: %d!", result);
745 return nullptr;
746 }
747
748 AHardwareBuffer* buffer;
749 result = AImage_getHardwareBuffer(rawImage, &buffer);
750
751 AHardwareBuffer_Desc desc;
752 AHardwareBuffer_describe(buffer, &desc);
753
754 if (desc.width != width || desc.height != height) {
755 ALOGW("AHardwareBuffer size mismatch, got %dx%d expected %dx%d", desc.width, desc.height,
756 width, height);
757 // Continue I guess?
758 }
759
760 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(
761 static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window)));
762 if (cs == nullptr) {
763 // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure
764 // the returned bitmap has a color space.
765 cs = SkColorSpace::MakeSRGB();
766 }
767 sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs);
768 return bitmap::createBitmap(env, bitmap.release(),
769 android::bitmap::kBitmapCreateFlag_Premultiplied);
770 }
771
android_view_ThreadedRenderer_disableVsync(JNIEnv *,jclass)772 static void android_view_ThreadedRenderer_disableVsync(JNIEnv*, jclass) {
773 RenderProxy::disableVsync();
774 }
775
android_view_ThreadedRenderer_setHighContrastText(JNIEnv *,jclass,jboolean enable)776 static void android_view_ThreadedRenderer_setHighContrastText(JNIEnv*, jclass, jboolean enable) {
777 Properties::enableHighContrastText = enable;
778 }
779
android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv *,jclass,jboolean enable)780 static void android_view_ThreadedRenderer_setDebuggingEnabled(JNIEnv*, jclass, jboolean enable) {
781 Properties::debuggingEnabled = enable;
782 }
783
android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv *,jclass,jboolean isolated)784 static void android_view_ThreadedRenderer_setIsolatedProcess(JNIEnv*, jclass, jboolean isolated) {
785 Properties::isolatedProcess = isolated;
786 }
787
android_view_ThreadedRenderer_setContextPriority(JNIEnv *,jclass,jint contextPriority)788 static void android_view_ThreadedRenderer_setContextPriority(JNIEnv*, jclass,
789 jint contextPriority) {
790 Properties::contextPriority = contextPriority;
791 }
792
android_view_ThreadedRenderer_allocateBuffers(JNIEnv * env,jobject clazz,jlong proxyPtr)793 static void android_view_ThreadedRenderer_allocateBuffers(JNIEnv* env, jobject clazz,
794 jlong proxyPtr) {
795 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
796 proxy->allocateBuffers();
797 }
798
android_view_ThreadedRenderer_setForceDark(JNIEnv * env,jobject clazz,jlong proxyPtr,jboolean enable)799 static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject clazz,
800 jlong proxyPtr, jboolean enable) {
801 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
802 proxy->setForceDark(enable);
803 }
804
android_view_ThreadedRenderer_preload(JNIEnv *,jclass)805 static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
806 RenderProxy::preload();
807 }
808
android_view_ThreadedRenderer_setRtAnimationsEnabled(JNIEnv * env,jobject clazz,jboolean enabled)809 static void android_view_ThreadedRenderer_setRtAnimationsEnabled(JNIEnv* env, jobject clazz,
810 jboolean enabled) {
811 RenderProxy::setRtAnimationsEnabled(enabled);
812 }
813
814 // Plumbs the display density down to DeviceInfo.
android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv *,jclass,jint densityDpi)815 static void android_view_ThreadedRenderer_setDisplayDensityDpi(JNIEnv*, jclass, jint densityDpi) {
816 // Convert from dpi to density-independent pixels.
817 const float density = densityDpi / 160.0;
818 DeviceInfo::setDensity(density);
819 }
820
android_view_ThreadedRenderer_initDisplayInfo(JNIEnv *,jclass,jint physicalWidth,jint physicalHeight,jfloat refreshRate,jint wideColorDataspace,jlong appVsyncOffsetNanos,jlong presentationDeadlineNanos)821 static void android_view_ThreadedRenderer_initDisplayInfo(JNIEnv*, jclass, jint physicalWidth,
822 jint physicalHeight, jfloat refreshRate,
823 jint wideColorDataspace,
824 jlong appVsyncOffsetNanos,
825 jlong presentationDeadlineNanos) {
826 DeviceInfo::setWidth(physicalWidth);
827 DeviceInfo::setHeight(physicalHeight);
828 DeviceInfo::setRefreshRate(refreshRate);
829 DeviceInfo::setWideColorDataspace(static_cast<ADataSpace>(wideColorDataspace));
830 DeviceInfo::setAppVsyncOffsetNanos(appVsyncOffsetNanos);
831 DeviceInfo::setPresentationDeadlineNanos(presentationDeadlineNanos);
832 }
833
android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv *,jclass,jboolean enabled)834 static void android_view_ThreadedRenderer_setDrawingEnabled(JNIEnv*, jclass, jboolean enabled) {
835 Properties::setDrawingEnabled(enabled);
836 }
837
android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv *,jclass)838 static jboolean android_view_ThreadedRenderer_isDrawingEnabled(JNIEnv*, jclass) {
839 return Properties::isDrawingEnabled();
840 }
841
842 // ----------------------------------------------------------------------------
843 // HardwareRendererObserver
844 // ----------------------------------------------------------------------------
845
android_view_ThreadedRenderer_addObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)846 static void android_view_ThreadedRenderer_addObserver(JNIEnv* env, jclass clazz,
847 jlong proxyPtr, jlong observerPtr) {
848 HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
849 renderthread::RenderProxy* renderProxy =
850 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
851
852 renderProxy->addFrameMetricsObserver(observer);
853 }
854
android_view_ThreadedRenderer_removeObserver(JNIEnv * env,jclass clazz,jlong proxyPtr,jlong observerPtr)855 static void android_view_ThreadedRenderer_removeObserver(JNIEnv* env, jclass clazz,
856 jlong proxyPtr, jlong observerPtr) {
857 HardwareRendererObserver* observer = reinterpret_cast<HardwareRendererObserver*>(observerPtr);
858 renderthread::RenderProxy* renderProxy =
859 reinterpret_cast<renderthread::RenderProxy*>(proxyPtr);
860
861 renderProxy->removeFrameMetricsObserver(observer);
862 }
863
864 // ----------------------------------------------------------------------------
865 // Shaders
866 // ----------------------------------------------------------------------------
867
android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv * env,jobject clazz,jstring diskCachePath,jstring skiaDiskCachePath)868 static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
869 jstring diskCachePath, jstring skiaDiskCachePath) {
870 const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
871 android::egl_set_cache_filename(cacheArray);
872 env->ReleaseStringUTFChars(diskCachePath, cacheArray);
873
874 const char* skiaCacheArray = env->GetStringUTFChars(skiaDiskCachePath, NULL);
875 uirenderer::skiapipeline::ShaderCache::get().setFilename(skiaCacheArray);
876 env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
877 }
878
android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv * env,jobject clazz)879 static jboolean android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv* env, jobject clazz) {
880 // this value is valid only after loadSystemProperties() is called
881 return Properties::enableWebViewOverlays;
882 }
883
884 // ----------------------------------------------------------------------------
885 // JNI Glue
886 // ----------------------------------------------------------------------------
887
888 const char* const kClassPathName = "android/graphics/HardwareRenderer";
889
890 static const JNINativeMethod gMethods[] = {
891 {"nRotateProcessStatsBuffer", "()V",
892 (void*)android_view_ThreadedRenderer_rotateProcessStatsBuffer},
893 {"nSetProcessStatsBuffer", "(I)V",
894 (void*)android_view_ThreadedRenderer_setProcessStatsBuffer},
895 {"nGetRenderThreadTid", "(J)I", (void*)android_view_ThreadedRenderer_getRenderThreadTid},
896 {"nCreateRootRenderNode", "()J", (void*)android_view_ThreadedRenderer_createRootRenderNode},
897 {"nCreateProxy", "(ZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
898 {"nDeleteProxy", "(J)V", (void*)android_view_ThreadedRenderer_deleteProxy},
899 {"nLoadSystemProperties", "(J)Z",
900 (void*)android_view_ThreadedRenderer_loadSystemProperties},
901 {"nSetName", "(JLjava/lang/String;)V", (void*)android_view_ThreadedRenderer_setName},
902 {"nSetSurface", "(JLandroid/view/Surface;Z)V",
903 (void*)android_view_ThreadedRenderer_setSurface},
904 {"nSetSurfaceControl", "(JJ)V", (void*)android_view_ThreadedRenderer_setSurfaceControl},
905 {"nPause", "(J)Z", (void*)android_view_ThreadedRenderer_pause},
906 {"nSetStopped", "(JZ)V", (void*)android_view_ThreadedRenderer_setStopped},
907 {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
908 {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
909 {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
910 {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
911 {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint},
912 {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx},
913 {"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
914 {"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
915 {"nRegisterAnimatingRenderNode", "(JJ)V",
916 (void*)android_view_ThreadedRenderer_registerAnimatingRenderNode},
917 {"nRegisterVectorDrawableAnimator", "(JJ)V",
918 (void*)android_view_ThreadedRenderer_registerVectorDrawableAnimator},
919 {"nCreateTextureLayer", "(J)J", (void*)android_view_ThreadedRenderer_createTextureLayer},
920 {"nBuildLayer", "(JJ)V", (void*)android_view_ThreadedRenderer_buildLayer},
921 {"nCopyLayerInto", "(JJJ)Z", (void*)android_view_ThreadedRenderer_copyLayerInto},
922 {"nPushLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_pushLayerUpdate},
923 {"nCancelLayerUpdate", "(JJ)V", (void*)android_view_ThreadedRenderer_cancelLayerUpdate},
924 {"nDetachSurfaceTexture", "(JJ)V",
925 (void*)android_view_ThreadedRenderer_detachSurfaceTexture},
926 {"nDestroyHardwareResources", "(J)V",
927 (void*)android_view_ThreadedRenderer_destroyHardwareResources},
928 {"nTrimMemory", "(I)V", (void*)android_view_ThreadedRenderer_trimMemory},
929 {"nOverrideProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
930 (void*)android_view_ThreadedRenderer_overrideProperty},
931 {"nFence", "(J)V", (void*)android_view_ThreadedRenderer_fence},
932 {"nStopDrawing", "(J)V", (void*)android_view_ThreadedRenderer_stopDrawing},
933 {"nNotifyFramePending", "(J)V", (void*)android_view_ThreadedRenderer_notifyFramePending},
934 {"nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V",
935 (void*)android_view_ThreadedRenderer_dumpProfileInfo},
936 {"nDumpGlobalProfileInfo", "(Ljava/io/FileDescriptor;I)V",
937 (void*)android_view_ThreadedRenderer_dumpGlobalProfileInfo},
938 {"setupShadersDiskCache", "(Ljava/lang/String;Ljava/lang/String;)V",
939 (void*)android_view_ThreadedRenderer_setupShadersDiskCache},
940 {"nAddRenderNode", "(JJZ)V", (void*)android_view_ThreadedRenderer_addRenderNode},
941 {"nRemoveRenderNode", "(JJ)V", (void*)android_view_ThreadedRenderer_removeRenderNode},
942 {"nDrawRenderNode", "(JJ)V", (void*)android_view_ThreadedRendererd_drawRenderNode},
943 {"nSetContentDrawBounds", "(JIIII)V",
944 (void*)android_view_ThreadedRenderer_setContentDrawBounds},
945 {"nForceDrawNextFrame", "(J)V", (void*)android_view_ThreadedRenderer_forceDrawNextFrame},
946 {"nSetPictureCaptureCallback",
947 "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V",
948 (void*)android_view_ThreadedRenderer_setPictureCapturedCallbackJNI},
949 {"nSetASurfaceTransactionCallback",
950 "(JLandroid/graphics/HardwareRenderer$ASurfaceTransactionCallback;)V",
951 (void*)android_view_ThreadedRenderer_setASurfaceTransactionCallback},
952 {"nSetPrepareSurfaceControlForWebviewCallback",
953 "(JLandroid/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback;)V",
954 (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback},
955 {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V",
956 (void*)android_view_ThreadedRenderer_setFrameCallback},
957 {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V",
958 (void*)android_view_ThreadedRenderer_setFrameCommitCallback},
959 {"nSetFrameCompleteCallback",
960 "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V",
961 (void*)android_view_ThreadedRenderer_setFrameCompleteCallback},
962 {"nAddObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_addObserver},
963 {"nRemoveObserver", "(JJ)V", (void*)android_view_ThreadedRenderer_removeObserver},
964 {"nCopySurfaceInto", "(Landroid/view/Surface;IIIIJ)I",
965 (void*)android_view_ThreadedRenderer_copySurfaceInto},
966 {"nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
967 (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode},
968 {"disableVsync", "()V", (void*)android_view_ThreadedRenderer_disableVsync},
969 {"nSetHighContrastText", "(Z)V", (void*)android_view_ThreadedRenderer_setHighContrastText},
970 {"nSetDebuggingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDebuggingEnabled},
971 {"nSetIsolatedProcess", "(Z)V", (void*)android_view_ThreadedRenderer_setIsolatedProcess},
972 {"nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority},
973 {"nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers},
974 {"nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark},
975 {"nSetDisplayDensityDpi", "(I)V",
976 (void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
977 {"nInitDisplayInfo", "(IIFIJJ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
978 {"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
979 {"isWebViewOverlaysEnabled", "()Z",
980 (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
981 {"nSetDrawingEnabled", "(Z)V", (void*)android_view_ThreadedRenderer_setDrawingEnabled},
982 {"nIsDrawingEnabled", "()Z", (void*)android_view_ThreadedRenderer_isDrawingEnabled},
983 {"nSetRtAnimationsEnabled", "(Z)V",
984 (void*)android_view_ThreadedRenderer_setRtAnimationsEnabled},
985 };
986
987 static JavaVM* mJvm = nullptr;
988
attachRenderThreadToJvm(const char * name)989 static void attachRenderThreadToJvm(const char* name) {
990 LOG_ALWAYS_FATAL_IF(!mJvm, "No jvm but we set the hook??");
991
992 JavaVMAttachArgs args;
993 args.version = JNI_VERSION_1_4;
994 args.name = name;
995 args.group = NULL;
996 JNIEnv* env;
997 mJvm->AttachCurrentThreadAsDaemon(&env, (void*) &args);
998 }
999
register_android_view_ThreadedRenderer(JNIEnv * env)1000 int register_android_view_ThreadedRenderer(JNIEnv* env) {
1001 env->GetJavaVM(&mJvm);
1002 RenderThread::setOnStartHook(&attachRenderThreadToJvm);
1003
1004 jclass hardwareRenderer = FindClassOrDie(env,
1005 "android/graphics/HardwareRenderer");
1006 gHardwareRenderer.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(hardwareRenderer));
1007 gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
1008 "invokePictureCapturedCallback",
1009 "(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
1010
1011 jclass aSurfaceTransactionCallbackClass =
1012 FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
1013 gASurfaceTransactionCallback.onMergeTransaction =
1014 GetMethodIDOrDie(env, aSurfaceTransactionCallbackClass, "onMergeTransaction", "(JJJ)Z");
1015
1016 jclass prepareSurfaceControlForWebviewCallbackClass = FindClassOrDie(
1017 env, "android/graphics/HardwareRenderer$PrepareSurfaceControlForWebviewCallback");
1018 gPrepareSurfaceControlForWebviewCallback.prepare =
1019 GetMethodIDOrDie(env, prepareSurfaceControlForWebviewCallbackClass, "prepare", "()V");
1020
1021 jclass frameCallbackClass = FindClassOrDie(env,
1022 "android/graphics/HardwareRenderer$FrameDrawingCallback");
1023 gFrameDrawingCallback.onFrameDraw =
1024 GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw",
1025 "(IJ)Landroid/graphics/HardwareRenderer$FrameCommitCallback;");
1026
1027 jclass frameCommitClass =
1028 FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback");
1029 gFrameCommitCallback.onFrameCommit =
1030 GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V");
1031
1032 jclass frameCompleteClass = FindClassOrDie(env,
1033 "android/graphics/HardwareRenderer$FrameCompleteCallback");
1034 gFrameCompleteCallback.onFrameComplete =
1035 GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V");
1036
1037 void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
1038 fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface");
1039 LOG_ALWAYS_FATAL_IF(fromSurface == nullptr,
1040 "Failed to find required symbol ANativeWindow_fromSurface!");
1041
1042 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1043 }
1044
1045 }; // namespace android
1046