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
17 #define LOG_TAG "Surface"
18
19 #include <stdio.h>
20
21 #include "jni.h"
22 #include <nativehelper/JNIHelp.h>
23 #include "android_os_Parcel.h"
24 #include "android/graphics/GraphicBuffer.h"
25 #include "android/graphics/GraphicsJNI.h"
26
27 #include "core_jni_helpers.h"
28 #include <android_runtime/android_view_Surface.h>
29 #include <android_runtime/android_graphics_SurfaceTexture.h>
30 #include <android_runtime/Log.h>
31
32 #include <binder/Parcel.h>
33
34 #include <gui/Surface.h>
35 #include <gui/view/Surface.h>
36 #include <gui/SurfaceControl.h>
37 #include <gui/GLConsumer.h>
38
39 #include <ui/Rect.h>
40 #include <ui/Region.h>
41
42 #include <SkCanvas.h>
43 #include <SkBitmap.h>
44 #include <SkImage.h>
45 #include <SkRegion.h>
46
47 #include <utils/misc.h>
48 #include <utils/Log.h>
49
50 #include <nativehelper/ScopedUtfChars.h>
51
52 #include <AnimationContext.h>
53 #include <FrameInfo.h>
54 #include <RenderNode.h>
55 #include <renderthread/RenderProxy.h>
56
57 // ----------------------------------------------------------------------------
58
59 namespace android {
60
61 static const char* const OutOfResourcesException =
62 "android/view/Surface$OutOfResourcesException";
63
64 static struct {
65 jclass clazz;
66 jfieldID mNativeObject;
67 jfieldID mLock;
68 jmethodID ctor;
69 } gSurfaceClassInfo;
70
71 static struct {
72 jfieldID left;
73 jfieldID top;
74 jfieldID right;
75 jfieldID bottom;
76 } gRectClassInfo;
77
78 // ----------------------------------------------------------------------------
79
80 // this is just a pointer we use to pass to inc/decStrong
81 static const void *sRefBaseOwner;
82
android_view_Surface_isInstanceOf(JNIEnv * env,jobject obj)83 bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
84 return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
85 }
86
android_view_Surface_getNativeWindow(JNIEnv * env,jobject surfaceObj)87 sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
88 return android_view_Surface_getSurface(env, surfaceObj);
89 }
90
android_view_Surface_getSurface(JNIEnv * env,jobject surfaceObj)91 sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
92 sp<Surface> sur;
93 jobject lock = env->GetObjectField(surfaceObj,
94 gSurfaceClassInfo.mLock);
95 if (env->MonitorEnter(lock) == JNI_OK) {
96 sur = reinterpret_cast<Surface *>(
97 env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
98 env->MonitorExit(lock);
99 }
100 env->DeleteLocalRef(lock);
101 return sur;
102 }
103
android_view_Surface_createFromSurface(JNIEnv * env,const sp<Surface> & surface)104 jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
105 jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
106 gSurfaceClassInfo.ctor, (jlong)surface.get());
107 if (surfaceObj == NULL) {
108 if (env->ExceptionCheck()) {
109 ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
110 LOGE_EX(env);
111 env->ExceptionClear();
112 }
113 return NULL;
114 }
115 surface->incStrong(&sRefBaseOwner);
116 return surfaceObj;
117 }
118
android_view_Surface_createFromIGraphicBufferProducer(JNIEnv * env,const sp<IGraphicBufferProducer> & bufferProducer)119 jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env,
120 const sp<IGraphicBufferProducer>& bufferProducer) {
121 if (bufferProducer == NULL) {
122 return NULL;
123 }
124
125 sp<Surface> surface(new Surface(bufferProducer, true));
126 return android_view_Surface_createFromSurface(env, surface);
127 }
128
android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f)129 int android_view_Surface_mapPublicFormatToHalFormat(PublicFormat f) {
130
131 switch(f) {
132 case PublicFormat::JPEG:
133 case PublicFormat::DEPTH_POINT_CLOUD:
134 return HAL_PIXEL_FORMAT_BLOB;
135 case PublicFormat::DEPTH16:
136 return HAL_PIXEL_FORMAT_Y16;
137 case PublicFormat::RAW_SENSOR:
138 case PublicFormat::RAW_DEPTH:
139 return HAL_PIXEL_FORMAT_RAW16;
140 default:
141 // Most formats map 1:1
142 return static_cast<int>(f);
143 }
144 }
145
android_view_Surface_mapPublicFormatToHalDataspace(PublicFormat f)146 android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
147 PublicFormat f) {
148 switch(f) {
149 case PublicFormat::JPEG:
150 return HAL_DATASPACE_V0_JFIF;
151 case PublicFormat::DEPTH_POINT_CLOUD:
152 case PublicFormat::DEPTH16:
153 case PublicFormat::RAW_DEPTH:
154 return HAL_DATASPACE_DEPTH;
155 case PublicFormat::RAW_SENSOR:
156 case PublicFormat::RAW_PRIVATE:
157 case PublicFormat::RAW10:
158 case PublicFormat::RAW12:
159 return HAL_DATASPACE_ARBITRARY;
160 case PublicFormat::YUV_420_888:
161 case PublicFormat::NV21:
162 case PublicFormat::YV12:
163 return HAL_DATASPACE_V0_JFIF;
164 default:
165 // Most formats map to UNKNOWN
166 return HAL_DATASPACE_UNKNOWN;
167 }
168 }
169
android_view_Surface_mapHalFormatDataspaceToPublicFormat(int format,android_dataspace dataSpace)170 PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
171 int format, android_dataspace dataSpace) {
172 switch(format) {
173 case HAL_PIXEL_FORMAT_RGBA_8888:
174 case HAL_PIXEL_FORMAT_RGBX_8888:
175 case HAL_PIXEL_FORMAT_RGBA_FP16:
176 case HAL_PIXEL_FORMAT_RGBA_1010102:
177 case HAL_PIXEL_FORMAT_RGB_888:
178 case HAL_PIXEL_FORMAT_RGB_565:
179 case HAL_PIXEL_FORMAT_Y8:
180 case HAL_PIXEL_FORMAT_RAW10:
181 case HAL_PIXEL_FORMAT_RAW12:
182 case HAL_PIXEL_FORMAT_YCbCr_420_888:
183 case HAL_PIXEL_FORMAT_YV12:
184 // Enums overlap in both name and value
185 return static_cast<PublicFormat>(format);
186 case HAL_PIXEL_FORMAT_RAW16:
187 switch (dataSpace) {
188 case HAL_DATASPACE_DEPTH:
189 return PublicFormat::RAW_DEPTH;
190 default:
191 return PublicFormat::RAW_SENSOR;
192 }
193 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
194 // Name differs, though value is the same
195 return PublicFormat::RAW_PRIVATE;
196 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
197 // Name differs, though the value is the same
198 return PublicFormat::NV16;
199 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
200 // Name differs, though the value is the same
201 return PublicFormat::NV21;
202 case HAL_PIXEL_FORMAT_YCbCr_422_I:
203 // Name differs, though the value is the same
204 return PublicFormat::YUY2;
205 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
206 // Name differs, though the value is the same
207 return PublicFormat::PRIVATE;
208 case HAL_PIXEL_FORMAT_Y16:
209 // Dataspace-dependent
210 switch (dataSpace) {
211 case HAL_DATASPACE_DEPTH:
212 return PublicFormat::DEPTH16;
213 default:
214 // Assume non-depth Y16 is just Y16.
215 return PublicFormat::Y16;
216 }
217 break;
218 case HAL_PIXEL_FORMAT_BLOB:
219 // Dataspace-dependent
220 switch (dataSpace) {
221 case HAL_DATASPACE_DEPTH:
222 return PublicFormat::DEPTH_POINT_CLOUD;
223 case HAL_DATASPACE_V0_JFIF:
224 return PublicFormat::JPEG;
225 default:
226 // Assume otherwise-marked blobs are also JPEG
227 return PublicFormat::JPEG;
228 }
229 break;
230 case HAL_PIXEL_FORMAT_BGRA_8888:
231 // Not defined in public API
232 return PublicFormat::UNKNOWN;
233
234 default:
235 return PublicFormat::UNKNOWN;
236 }
237 }
238 // ----------------------------------------------------------------------------
239
isSurfaceValid(const sp<Surface> & sur)240 static inline bool isSurfaceValid(const sp<Surface>& sur) {
241 return Surface::isValid(sur);
242 }
243
244 // ----------------------------------------------------------------------------
245
nativeCreateFromSurfaceTexture(JNIEnv * env,jclass clazz,jobject surfaceTextureObj)246 static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
247 jobject surfaceTextureObj) {
248 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
249 if (producer == NULL) {
250 jniThrowException(env, "java/lang/IllegalArgumentException",
251 "SurfaceTexture has already been released");
252 return 0;
253 }
254
255 sp<Surface> surface(new Surface(producer, true));
256 if (surface == NULL) {
257 jniThrowException(env, OutOfResourcesException, NULL);
258 return 0;
259 }
260
261 surface->incStrong(&sRefBaseOwner);
262 return jlong(surface.get());
263 }
264
nativeRelease(JNIEnv * env,jclass clazz,jlong nativeObject)265 static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
266 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
267 sur->decStrong(&sRefBaseOwner);
268 }
269
nativeIsValid(JNIEnv * env,jclass clazz,jlong nativeObject)270 static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
271 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
272 return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
273 }
274
nativeIsConsumerRunningBehind(JNIEnv * env,jclass clazz,jlong nativeObject)275 static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
276 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
277 if (!isSurfaceValid(sur)) {
278 doThrowIAE(env);
279 return JNI_FALSE;
280 }
281 int value = 0;
282 ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
283 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
284 return value;
285 }
286
convertPixelFormat(PixelFormat format)287 static inline SkColorType convertPixelFormat(PixelFormat format) {
288 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
289 we can map to kN32_SkColorType, and optionally call
290 bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
291 (as an accelerator)
292 */
293 switch (format) {
294 case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
295 case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
296 case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType;
297 case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
298 default: return kUnknown_SkColorType;
299 }
300 }
301
nativeLockCanvas(JNIEnv * env,jclass clazz,jlong nativeObject,jobject canvasObj,jobject dirtyRectObj)302 static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
303 jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
304 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
305
306 if (!isSurfaceValid(surface)) {
307 doThrowIAE(env);
308 return 0;
309 }
310
311 Rect dirtyRect(Rect::EMPTY_RECT);
312 Rect* dirtyRectPtr = NULL;
313
314 if (dirtyRectObj) {
315 dirtyRect.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
316 dirtyRect.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
317 dirtyRect.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
318 dirtyRect.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
319 dirtyRectPtr = &dirtyRect;
320 }
321
322 ANativeWindow_Buffer outBuffer;
323 status_t err = surface->lock(&outBuffer, dirtyRectPtr);
324 if (err < 0) {
325 const char* const exception = (err == NO_MEMORY) ?
326 OutOfResourcesException :
327 "java/lang/IllegalArgumentException";
328 jniThrowException(env, exception, NULL);
329 return 0;
330 }
331
332 SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
333 convertPixelFormat(outBuffer.format),
334 outBuffer.format == PIXEL_FORMAT_RGBX_8888
335 ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
336 GraphicsJNI::defaultColorSpace());
337
338 SkBitmap bitmap;
339 ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
340 bitmap.setInfo(info, bpr);
341 if (outBuffer.width > 0 && outBuffer.height > 0) {
342 bitmap.setPixels(outBuffer.bits);
343 } else {
344 // be safe with an empty bitmap.
345 bitmap.setPixels(NULL);
346 }
347
348 Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
349 nativeCanvas->setBitmap(bitmap);
350
351 if (dirtyRectPtr) {
352 nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
353 dirtyRect.right, dirtyRect.bottom, SkClipOp::kIntersect);
354 }
355
356 if (dirtyRectObj) {
357 env->SetIntField(dirtyRectObj, gRectClassInfo.left, dirtyRect.left);
358 env->SetIntField(dirtyRectObj, gRectClassInfo.top, dirtyRect.top);
359 env->SetIntField(dirtyRectObj, gRectClassInfo.right, dirtyRect.right);
360 env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, dirtyRect.bottom);
361 }
362
363 // Create another reference to the surface and return it. This reference
364 // should be passed to nativeUnlockCanvasAndPost in place of mNativeObject,
365 // because the latter could be replaced while the surface is locked.
366 sp<Surface> lockedSurface(surface);
367 lockedSurface->incStrong(&sRefBaseOwner);
368 return (jlong) lockedSurface.get();
369 }
370
nativeUnlockCanvasAndPost(JNIEnv * env,jclass clazz,jlong nativeObject,jobject canvasObj)371 static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
372 jlong nativeObject, jobject canvasObj) {
373 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
374 if (!isSurfaceValid(surface)) {
375 return;
376 }
377
378 // detach the canvas from the surface
379 Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
380 nativeCanvas->setBitmap(SkBitmap());
381
382 // unlock surface
383 status_t err = surface->unlockAndPost();
384 if (err < 0) {
385 doThrowIAE(env);
386 }
387 }
388
nativeAllocateBuffers(JNIEnv *,jclass,jlong nativeObject)389 static void nativeAllocateBuffers(JNIEnv* /* env */ , jclass /* clazz */,
390 jlong nativeObject) {
391 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
392 if (!isSurfaceValid(surface)) {
393 return;
394 }
395
396 surface->allocateBuffers();
397 }
398
399 // ----------------------------------------------------------------------------
400
nativeCreateFromSurfaceControl(JNIEnv * env,jclass clazz,jlong surfaceControlNativeObj)401 static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
402 jlong surfaceControlNativeObj) {
403 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
404 sp<Surface> surface(ctrl->createSurface());
405 if (surface != NULL) {
406 surface->incStrong(&sRefBaseOwner);
407 }
408 return reinterpret_cast<jlong>(surface.get());
409 }
410
nativeGetFromSurfaceControl(JNIEnv * env,jclass clazz,jlong surfaceControlNativeObj)411 static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
412 jlong surfaceControlNativeObj) {
413 /*
414 * This is used by the WindowManagerService just after constructing
415 * a Surface and is necessary for returning the Surface reference to
416 * the caller. At this point, we should only have a SurfaceControl.
417 */
418
419 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
420 sp<Surface> surface(ctrl->getSurface());
421 if (surface != NULL) {
422 surface->incStrong(&sRefBaseOwner);
423 }
424 return reinterpret_cast<jlong>(surface.get());
425 }
426
nativeReadFromParcel(JNIEnv * env,jclass clazz,jlong nativeObject,jobject parcelObj)427 static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
428 jlong nativeObject, jobject parcelObj) {
429 Parcel* parcel = parcelForJavaObject(env, parcelObj);
430 if (parcel == NULL) {
431 doThrowNPE(env);
432 return 0;
433 }
434
435 android::view::Surface surfaceShim;
436
437 // Calling code in Surface.java has already read the name of the Surface
438 // from the Parcel
439 surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
440
441 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
442
443 // update the Surface only if the underlying IGraphicBufferProducer
444 // has changed.
445 if (self != nullptr
446 && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
447 IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
448 // same IGraphicBufferProducer, return ourselves
449 return jlong(self.get());
450 }
451
452 sp<Surface> sur;
453 if (surfaceShim.graphicBufferProducer != nullptr) {
454 // we have a new IGraphicBufferProducer, create a new Surface for it
455 sur = new Surface(surfaceShim.graphicBufferProducer, true);
456 // and keep a reference before passing to java
457 sur->incStrong(&sRefBaseOwner);
458 }
459
460 if (self != NULL) {
461 // and loose the java reference to ourselves
462 self->decStrong(&sRefBaseOwner);
463 }
464
465 return jlong(sur.get());
466 }
467
nativeWriteToParcel(JNIEnv * env,jclass clazz,jlong nativeObject,jobject parcelObj)468 static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
469 jlong nativeObject, jobject parcelObj) {
470 Parcel* parcel = parcelForJavaObject(env, parcelObj);
471 if (parcel == NULL) {
472 doThrowNPE(env);
473 return;
474 }
475 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
476 android::view::Surface surfaceShim;
477 if (self != nullptr) {
478 surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
479 }
480 // Calling code in Surface.java has already written the name of the Surface
481 // to the Parcel
482 surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
483 }
484
nativeGetWidth(JNIEnv * env,jclass clazz,jlong nativeObject)485 static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
486 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
487 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
488 int value = 0;
489 anw->query(anw, NATIVE_WINDOW_WIDTH, &value);
490 return value;
491 }
492
nativeGetHeight(JNIEnv * env,jclass clazz,jlong nativeObject)493 static jint nativeGetHeight(JNIEnv* env, jclass clazz, jlong nativeObject) {
494 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
495 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
496 int value = 0;
497 anw->query(anw, NATIVE_WINDOW_HEIGHT, &value);
498 return value;
499 }
500
nativeGetNextFrameNumber(JNIEnv * env,jclass clazz,jlong nativeObject)501 static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) {
502 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
503 return surface->getNextFrameNumber();
504 }
505
nativeSetScalingMode(JNIEnv * env,jclass clazz,jlong nativeObject,jint scalingMode)506 static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, jint scalingMode) {
507 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
508 return surface->setScalingMode(scalingMode);
509 }
510
nativeForceScopedDisconnect(JNIEnv * env,jclass clazz,jlong nativeObject)511 static jint nativeForceScopedDisconnect(JNIEnv *env, jclass clazz, jlong nativeObject) {
512 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
513 return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
514 }
515
nativeAttachAndQueueBuffer(JNIEnv * env,jclass clazz,jlong nativeObject,jobject graphicBuffer)516 static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeObject,
517 jobject graphicBuffer) {
518 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
519 sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
520 int err = Surface::attachAndQueueBuffer(surface, bp);
521 return err;
522 }
523
nativeSetSharedBufferModeEnabled(JNIEnv * env,jclass clazz,jlong nativeObject,jboolean enabled)524 static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
525 jboolean enabled) {
526 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
527 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
528 return anw->perform(surface, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, int(enabled));
529 }
530
nativeSetAutoRefreshEnabled(JNIEnv * env,jclass clazz,jlong nativeObject,jboolean enabled)531 static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
532 jboolean enabled) {
533 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
534 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
535 return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
536 }
537
538 namespace uirenderer {
539
540 using namespace android::uirenderer::renderthread;
541
542 class ContextFactory : public IContextFactory {
543 public:
createAnimationContext(renderthread::TimeLord & clock)544 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
545 return new AnimationContext(clock);
546 }
547 };
548
create(JNIEnv * env,jclass clazz,jlong rootNodePtr,jlong surfacePtr,jboolean isWideColorGamut)549 static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr,
550 jboolean isWideColorGamut) {
551 RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
552 sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
553 ContextFactory factory;
554 RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
555 proxy->loadSystemProperties();
556 if (isWideColorGamut) {
557 proxy->setWideGamut(true);
558 }
559 proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
560 proxy->initialize(surface);
561 // Shadows can't be used via this interface, so just set the light source
562 // to all 0s.
563 proxy->setup(0, 0, 0);
564 proxy->setLightCenter((Vector3){0, 0, 0});
565 return (jlong) proxy;
566 }
567
setSurface(JNIEnv * env,jclass clazz,jlong rendererPtr,jlong surfacePtr)568 static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
569 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
570 sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
571 proxy->updateSurface(surface);
572 }
573
draw(JNIEnv * env,jclass clazz,jlong rendererPtr)574 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
575 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
576 nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
577 UiFrameInfoBuilder(proxy->frameInfo())
578 .setVsync(vsync, vsync)
579 .addFlag(FrameInfoFlags::SurfaceCanvas);
580 proxy->syncAndDrawFrame();
581 }
582
destroy(JNIEnv * env,jclass clazz,jlong rendererPtr)583 static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
584 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
585 delete proxy;
586 }
587
588 } // uirenderer
589
590 // ----------------------------------------------------------------------------
591
592 namespace hwui = android::uirenderer;
593
594 static const JNINativeMethod gSurfaceMethods[] = {
595 {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
596 (void*)nativeCreateFromSurfaceTexture },
597 {"nativeRelease", "(J)V",
598 (void*)nativeRelease },
599 {"nativeIsValid", "(J)Z",
600 (void*)nativeIsValid },
601 {"nativeIsConsumerRunningBehind", "(J)Z",
602 (void*)nativeIsConsumerRunningBehind },
603 {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
604 (void*)nativeLockCanvas },
605 {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
606 (void*)nativeUnlockCanvasAndPost },
607 {"nativeAllocateBuffers", "(J)V",
608 (void*)nativeAllocateBuffers },
609 {"nativeCreateFromSurfaceControl", "(J)J",
610 (void*)nativeCreateFromSurfaceControl },
611 {"nativeGetFromSurfaceControl", "(J)J",
612 (void*)nativeGetFromSurfaceControl },
613 {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
614 (void*)nativeReadFromParcel },
615 {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
616 (void*)nativeWriteToParcel },
617 {"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
618 {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
619 {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
620 {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
621 {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
622 {"nativeAttachAndQueueBuffer", "(JLandroid/graphics/GraphicBuffer;)I", (void*)nativeAttachAndQueueBuffer},
623 {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
624 {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
625
626 // HWUI context
627 {"nHwuiCreate", "(JJZ)J", (void*) hwui::create },
628 {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
629 {"nHwuiDraw", "(J)V", (void*) hwui::draw },
630 {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
631 };
632
register_android_view_Surface(JNIEnv * env)633 int register_android_view_Surface(JNIEnv* env)
634 {
635 int err = RegisterMethodsOrDie(env, "android/view/Surface",
636 gSurfaceMethods, NELEM(gSurfaceMethods));
637
638 jclass clazz = FindClassOrDie(env, "android/view/Surface");
639 gSurfaceClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
640 gSurfaceClassInfo.mNativeObject = GetFieldIDOrDie(env,
641 gSurfaceClassInfo.clazz, "mNativeObject", "J");
642 gSurfaceClassInfo.mLock = GetFieldIDOrDie(env,
643 gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
644 gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
645
646 clazz = FindClassOrDie(env, "android/graphics/Rect");
647 gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
648 gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
649 gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
650 gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
651
652 return err;
653 }
654
655 };
656