blob: f70cf07b9535fa70ac6ab716afecedff4455a0f1 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Mathias Agopianfae5cb22010-06-04 18:26:32 -070017#define LOG_TAG "Surface"
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#include <stdio.h>
20
Mathias Agopian3866f0d2013-02-11 22:08:48 -080021#include "jni.h"
Steven Moreland2279b252017-07-19 09:50:45 -070022#include <nativehelper/JNIHelp.h>
Jeff Brown64a55af2012-08-26 02:47:39 -070023#include "android_os_Parcel.h"
Robert Carra35e5de2017-03-03 17:04:54 -080024#include "android/graphics/GraphicBuffer.h"
Dianne Hackborna1111872010-11-23 20:55:11 -080025#include "android/graphics/GraphicsJNI.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
Andreas Gampeed6b9df2014-11-20 22:02:20 -080027#include "core_jni_helpers.h"
Mathias Agopian3866f0d2013-02-11 22:08:48 -080028#include <android_runtime/android_view_Surface.h>
29#include <android_runtime/android_graphics_SurfaceTexture.h>
Ruben Brunk87eac992013-09-09 17:44:59 -070030#include <android_runtime/Log.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080031
Mathias Agopian4a05f432013-03-12 18:43:34 -070032#include <binder/Parcel.h>
33
Mathias Agopian8335f1c2012-02-25 18:48:35 -080034#include <gui/Surface.h>
Mathias Agopian7a1e28d2017-02-08 17:07:13 -080035#include <gui/view/Surface.h>
Mathias Agopian52800612013-02-14 17:11:20 -080036#include <gui/SurfaceControl.h>
Andy McFaddend47f7d82012-12-18 09:48:38 -080037#include <gui/GLConsumer.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039#include <ui/Rect.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080040#include <ui/Region.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041
42#include <SkCanvas.h>
43#include <SkBitmap.h>
Leon Scroggins III8790be62013-12-03 16:26:51 -050044#include <SkImage.h>
Mathias Agopian6158b1b2009-05-11 00:03:41 -070045#include <SkRegion.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047#include <utils/misc.h>
Jeff Brown9e316a12012-10-08 19:17:06 -070048#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
Steven Moreland2279b252017-07-19 09:50:45 -070050#include <nativehelper/ScopedUtfChars.h>
Jeff Brown64a55af2012-08-26 02:47:39 -070051
John Reckbb2d0cc2014-10-21 10:09:36 -070052#include <AnimationContext.h>
John Reckba6adf62015-02-19 14:36:50 -080053#include <FrameInfo.h>
John Reckbb2d0cc2014-10-21 10:09:36 -070054#include <RenderNode.h>
55#include <renderthread/RenderProxy.h>
56
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057// ----------------------------------------------------------------------------
58
59namespace android {
60
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061static const char* const OutOfResourcesException =
62 "android/view/Surface$OutOfResourcesException";
63
Jeff Brown64a55af2012-08-26 02:47:39 -070064static struct {
65 jclass clazz;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080066 jfieldID mNativeObject;
Jeff Brownfc0ebd72013-04-30 16:33:00 -070067 jfieldID mLock;
Jeff Browncbad9762012-09-04 21:57:59 -070068 jmethodID ctor;
Jeff Brown64a55af2012-08-26 02:47:39 -070069} gSurfaceClassInfo;
tedbo05031612011-06-06 16:02:47 -070070
Jeff Brown64a55af2012-08-26 02:47:39 -070071static struct {
72 jfieldID left;
73 jfieldID top;
74 jfieldID right;
75 jfieldID bottom;
76} gRectClassInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077
Jeff Brown64a55af2012-08-26 02:47:39 -070078// ----------------------------------------------------------------------------
79
Mathias Agopianb1d90c82013-03-06 17:45:42 -080080// this is just a pointer we use to pass to inc/decStrong
81static const void *sRefBaseOwner;
82
Jeff Brown64a55af2012-08-26 02:47:39 -070083bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
84 return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
85}
86
Mathias Agopian3866f0d2013-02-11 22:08:48 -080087sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
88 return android_view_Surface_getSurface(env, surfaceObj);
89}
90
Jeff Brown64a55af2012-08-26 02:47:39 -070091sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
Mathias Agopian7c116b52013-03-18 20:27:02 -070092 sp<Surface> sur;
93 jobject lock = env->GetObjectField(surfaceObj,
Jeff Brownfc0ebd72013-04-30 16:33:00 -070094 gSurfaceClassInfo.mLock);
Mathias Agopian7c116b52013-03-18 20:27:02 -070095 if (env->MonitorEnter(lock) == JNI_OK) {
96 sur = reinterpret_cast<Surface *>(
Ashok Bhat36bef0b2014-01-20 20:08:01 +000097 env->GetLongField(surfaceObj, gSurfaceClassInfo.mNativeObject));
Mathias Agopian7c116b52013-03-18 20:27:02 -070098 env->MonitorExit(lock);
99 }
Andy McFadden5ad3ab82014-06-11 15:22:32 -0700100 env->DeleteLocalRef(lock);
Mathias Agopian7c116b52013-03-18 20:27:02 -0700101 return sur;
Jeff Browncbad9762012-09-04 21:57:59 -0700102}
103
Jiwen 'Steve' Caid28e8282017-03-31 11:19:50 -0700104jobject android_view_Surface_createFromSurface(JNIEnv* env, const sp<Surface>& surface) {
Chong Zhangaf608e82014-01-29 12:52:15 -0800105 jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz,
106 gSurfaceClassInfo.ctor, (jlong)surface.get());
Jeff Browncbad9762012-09-04 21:57:59 -0700107 if (surfaceObj == NULL) {
108 if (env->ExceptionCheck()) {
Andy McFaddend47f7d82012-12-18 09:48:38 -0800109 ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
Jeff Browncbad9762012-09-04 21:57:59 -0700110 LOGE_EX(env);
111 env->ExceptionClear();
112 }
113 return NULL;
114 }
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800115 surface->incStrong(&sRefBaseOwner);
Jeff Browncbad9762012-09-04 21:57:59 -0700116 return surfaceObj;
117}
118
Jiwen 'Steve' Caid28e8282017-03-31 11:19:50 -0700119jobject 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
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800129int 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:
Emilian Peevf7fec732017-03-17 19:54:30 +0000138 case PublicFormat::RAW_DEPTH:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800139 return HAL_PIXEL_FORMAT_RAW16;
140 default:
141 // Most formats map 1:1
142 return static_cast<int>(f);
143 }
144}
145
146android_dataspace android_view_Surface_mapPublicFormatToHalDataspace(
147 PublicFormat f) {
148 switch(f) {
149 case PublicFormat::JPEG:
Eino-Ville Talvala7966d442016-03-14 13:21:03 -0700150 return HAL_DATASPACE_V0_JFIF;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800151 case PublicFormat::DEPTH_POINT_CLOUD:
152 case PublicFormat::DEPTH16:
Emilian Peevf7fec732017-03-17 19:54:30 +0000153 case PublicFormat::RAW_DEPTH:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800154 return HAL_DATASPACE_DEPTH;
155 case PublicFormat::RAW_SENSOR:
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800156 case PublicFormat::RAW_PRIVATE:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800157 case PublicFormat::RAW10:
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800158 case PublicFormat::RAW12:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800159 return HAL_DATASPACE_ARBITRARY;
160 case PublicFormat::YUV_420_888:
161 case PublicFormat::NV21:
162 case PublicFormat::YV12:
Eino-Ville Talvala7966d442016-03-14 13:21:03 -0700163 return HAL_DATASPACE_V0_JFIF;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800164 default:
165 // Most formats map to UNKNOWN
166 return HAL_DATASPACE_UNKNOWN;
167 }
168}
169
170PublicFormat 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:
Romain Guy9505a652016-12-14 09:43:50 -0800175 case HAL_PIXEL_FORMAT_RGBA_FP16:
Romain Guy8ec21062017-02-10 18:49:33 -0800176 case HAL_PIXEL_FORMAT_RGBA_1010102:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800177 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:
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800181 case HAL_PIXEL_FORMAT_RAW12:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800182 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:
Emilian Peevf7fec732017-03-17 19:54:30 +0000187 switch (dataSpace) {
188 case HAL_DATASPACE_DEPTH:
189 return PublicFormat::RAW_DEPTH;
190 default:
191 return PublicFormat::RAW_SENSOR;
192 }
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800193 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
194 // Name differs, though value is the same
195 return PublicFormat::RAW_PRIVATE;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800196 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;
Zhijun He2f174312015-03-20 11:39:55 -0700205 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
206 // Name differs, though the value is the same
207 return PublicFormat::PRIVATE;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800208 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;
Eino-Ville Talvala7966d442016-03-14 13:21:03 -0700223 case HAL_DATASPACE_V0_JFIF:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800224 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:
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800231 // Not defined in public API
232 return PublicFormat::UNKNOWN;
233
234 default:
235 return PublicFormat::UNKNOWN;
236 }
237}
Jeff Brown64a55af2012-08-26 02:47:39 -0700238// ----------------------------------------------------------------------------
239
Mathias Agopianf3d3b4d2013-02-19 18:26:15 -0800240static inline bool isSurfaceValid(const sp<Surface>& sur) {
241 return Surface::isValid(sur);
Mathias Agopian52800612013-02-14 17:11:20 -0800242}
243
244// ----------------------------------------------------------------------------
245
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000246static jlong nativeCreateFromSurfaceTexture(JNIEnv* env, jclass clazz,
Jeff Brown64a55af2012-08-26 02:47:39 -0700247 jobject surfaceTextureObj) {
Mathias Agopian52a9a102013-08-02 01:38:38 -0700248 sp<IGraphicBufferProducer> producer(SurfaceTexture_getProducer(env, surfaceTextureObj));
249 if (producer == NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700250 jniThrowException(env, "java/lang/IllegalArgumentException",
251 "SurfaceTexture has already been released");
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800252 return 0;
Jeff Brown64a55af2012-08-26 02:47:39 -0700253 }
254
Mathias Agopian52a9a102013-08-02 01:38:38 -0700255 sp<Surface> surface(new Surface(producer, true));
Jeff Brown64a55af2012-08-26 02:47:39 -0700256 if (surface == NULL) {
257 jniThrowException(env, OutOfResourcesException, NULL);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800258 return 0;
Jeff Brown64a55af2012-08-26 02:47:39 -0700259 }
260
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800261 surface->incStrong(&sRefBaseOwner);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000262 return jlong(surface.get());
Jeff Brown64a55af2012-08-26 02:47:39 -0700263}
264
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000265static void nativeRelease(JNIEnv* env, jclass clazz, jlong nativeObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800266 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800267 sur->decStrong(&sRefBaseOwner);
Jeff Brown64a55af2012-08-26 02:47:39 -0700268}
269
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000270static jboolean nativeIsValid(JNIEnv* env, jclass clazz, jlong nativeObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800271 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
Mathias Agopian52800612013-02-14 17:11:20 -0800272 return isSurfaceValid(sur) ? JNI_TRUE : JNI_FALSE;
Jeff Brown64a55af2012-08-26 02:47:39 -0700273}
274
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000275static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jclass clazz, jlong nativeObject) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800276 sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
Mathias Agopian52800612013-02-14 17:11:20 -0800277 if (!isSurfaceValid(sur)) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700278 doThrowIAE(env);
279 return JNI_FALSE;
280 }
Jeff Brown64a55af2012-08-26 02:47:39 -0700281 int value = 0;
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800282 ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
Jeff Brown64a55af2012-08-26 02:47:39 -0700283 anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
284 return value;
285}
286
Mike Reedb9330552014-06-16 17:31:48 -0400287static inline SkColorType convertPixelFormat(PixelFormat format) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700288 /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
Mike Reedb9330552014-06-16 17:31:48 -0400289 we can map to kN32_SkColorType, and optionally call
Leon Scroggins III8790be62013-12-03 16:26:51 -0500290 bitmap.setAlphaType(kOpaque_SkAlphaType) on the resulting SkBitmap
291 (as an accelerator)
Jeff Brown64a55af2012-08-26 02:47:39 -0700292 */
293 switch (format) {
Mike Reedb9330552014-06-16 17:31:48 -0400294 case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
295 case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
Romain Guy9505a652016-12-14 09:43:50 -0800296 case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType;
Mike Reedb9330552014-06-16 17:31:48 -0400297 case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
298 default: return kUnknown_SkColorType;
Jeff Brown64a55af2012-08-26 02:47:39 -0700299 }
300}
301
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000302static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
303 jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800304 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
305
Mathias Agopian52800612013-02-14 17:11:20 -0800306 if (!isSurfaceValid(surface)) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700307 doThrowIAE(env);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700308 return 0;
Jeff Brown64a55af2012-08-26 02:47:39 -0700309 }
310
Pablo Ceballos82702922015-08-07 17:28:03 -0700311 Rect dirtyRect(Rect::EMPTY_RECT);
Mathias Agopian667809e2013-04-17 14:57:41 -0700312 Rect* dirtyRectPtr = NULL;
313
Jeff Brown64a55af2012-08-26 02:47:39 -0700314 if (dirtyRectObj) {
Mathias Agopian667809e2013-04-17 14:57:41 -0700315 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;
Jeff Brown64a55af2012-08-26 02:47:39 -0700320 }
321
Mathias Agopian52800612013-02-14 17:11:20 -0800322 ANativeWindow_Buffer outBuffer;
Mathias Agopian667809e2013-04-17 14:57:41 -0700323 status_t err = surface->lock(&outBuffer, dirtyRectPtr);
Jeff Brown64a55af2012-08-26 02:47:39 -0700324 if (err < 0) {
325 const char* const exception = (err == NO_MEMORY) ?
326 OutOfResourcesException :
327 "java/lang/IllegalArgumentException";
328 jniThrowException(env, exception, NULL);
Andy McFaddened55c8d2013-08-20 10:05:51 -0700329 return 0;
Jeff Brown64a55af2012-08-26 02:47:39 -0700330 }
331
Mike Reedb9330552014-06-16 17:31:48 -0400332 SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
333 convertPixelFormat(outBuffer.format),
Romain Guy253f2c22016-09-28 17:34:42 -0700334 outBuffer.format == PIXEL_FORMAT_RGBX_8888
335 ? kOpaque_SkAlphaType : kPremul_SkAlphaType,
336 GraphicsJNI::defaultColorSpace());
Mike Reedb9330552014-06-16 17:31:48 -0400337
Jeff Brown64a55af2012-08-26 02:47:39 -0700338 SkBitmap bitmap;
Mathias Agopian52800612013-02-14 17:11:20 -0800339 ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
Mike Reedb9330552014-06-16 17:31:48 -0400340 bitmap.setInfo(info, bpr);
Mathias Agopian52800612013-02-14 17:11:20 -0800341 if (outBuffer.width > 0 && outBuffer.height > 0) {
342 bitmap.setPixels(outBuffer.bits);
Jeff Brown64a55af2012-08-26 02:47:39 -0700343 } else {
344 // be safe with an empty bitmap.
345 bitmap.setPixels(NULL);
346 }
Derek Sollenbergerfc615a02012-12-20 14:39:57 -0500347
John Reckc1b33d62015-04-22 09:04:45 -0700348 Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
349 nativeCanvas->setBitmap(bitmap);
Jeff Brown64a55af2012-08-26 02:47:39 -0700350
Mathias Agopian667809e2013-04-17 14:57:41 -0700351 if (dirtyRectPtr) {
John Reckc1b33d62015-04-22 09:04:45 -0700352 nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
Mike Reed6c67f1d2016-12-14 10:29:54 -0500353 dirtyRect.right, dirtyRect.bottom, SkClipOp::kIntersect);
Jeff Brown64a55af2012-08-26 02:47:39 -0700354 }
355
Jeff Brown64a55af2012-08-26 02:47:39 -0700356 if (dirtyRectObj) {
Mathias Agopian667809e2013-04-17 14:57:41 -0700357 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);
Jeff Brown64a55af2012-08-26 02:47:39 -0700361 }
Andy McFaddened55c8d2013-08-20 10:05:51 -0700362
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);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000368 return (jlong) lockedSurface.get();
Jeff Brown64a55af2012-08-26 02:47:39 -0700369}
370
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700371static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000372 jlong nativeObject, jobject canvasObj) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800373 sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
Mathias Agopian52800612013-02-14 17:11:20 -0800374 if (!isSurfaceValid(surface)) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700375 return;
376 }
377
378 // detach the canvas from the surface
John Reckc1b33d62015-04-22 09:04:45 -0700379 Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
380 nativeCanvas->setBitmap(SkBitmap());
Jeff Brown64a55af2012-08-26 02:47:39 -0700381
382 // unlock surface
383 status_t err = surface->unlockAndPost();
384 if (err < 0) {
385 doThrowIAE(env);
386 }
387}
388
Dan Stoza5795d642014-06-20 13:01:36 -0700389static 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
Mathias Agopian17f638b2009-04-16 20:04:08 -0700399// ----------------------------------------------------------------------------
400
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000401static jlong nativeCreateFromSurfaceControl(JNIEnv* env, jclass clazz,
402 jlong surfaceControlNativeObj) {
Bryce Lee02949f12017-06-16 07:20:34 -0700403 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
411static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
412 jlong surfaceControlNativeObj) {
Mathias Agopian17f638b2009-04-16 20:04:08 -0700413 /*
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.
Mathias Agopian17f638b2009-04-16 20:04:08 -0700417 */
Mathias Agopianfae5cb22010-06-04 18:26:32 -0700418
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800419 sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700420 sp<Surface> surface(ctrl->getSurface());
421 if (surface != NULL) {
422 surface->incStrong(&sRefBaseOwner);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000424 return reinterpret_cast<jlong>(surface.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425}
426
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000427static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
428 jlong nativeObject, jobject parcelObj) {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800429 Parcel* parcel = parcelForJavaObject(env, parcelObj);
430 if (parcel == NULL) {
431 doThrowNPE(env);
432 return 0;
433 }
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700434
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800435 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
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800441 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700442
443 // update the Surface only if the underlying IGraphicBufferProducer
444 // has changed.
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800445 if (self != nullptr
446 && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
447 IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700448 // same IGraphicBufferProducer, return ourselves
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000449 return jlong(self.get());
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800450 }
Mathias Agopian4a05f432013-03-12 18:43:34 -0700451
452 sp<Surface> sur;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800453 if (surfaceShim.graphicBufferProducer != nullptr) {
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700454 // we have a new IGraphicBufferProducer, create a new Surface for it
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800455 sur = new Surface(surfaceShim.graphicBufferProducer, true);
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700456 // and keep a reference before passing to java
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800457 sur->incStrong(&sRefBaseOwner);
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800458 }
Mathias Agopian4a05f432013-03-12 18:43:34 -0700459
Mathias Agopianc3b9cd62013-03-13 16:07:57 -0700460 if (self != NULL) {
461 // and loose the java reference to ourselves
462 self->decStrong(&sRefBaseOwner);
463 }
464
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000465 return jlong(sur.get());
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800466}
467
Mathias Agopian29479eb2013-02-14 14:36:04 -0800468static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000469 jlong nativeObject, jobject parcelObj) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700470 Parcel* parcel = parcelForJavaObject(env, parcelObj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 if (parcel == NULL) {
Elliott Hughes8451b252011-04-07 19:17:57 -0700472 doThrowNPE(env);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 return;
474 }
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800475 sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800476 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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483}
484
John Reckb35c9602014-11-13 16:15:08 -0800485static 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
493static 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}
Robert Carrcd9a18c2015-12-16 18:16:21 -0800500
Rob Carr64e516f2015-10-29 00:20:45 +0000501static jlong nativeGetNextFrameNumber(JNIEnv *env, jclass clazz, jlong nativeObject) {
502 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
503 return surface->getNextFrameNumber();
504}
John Reckb35c9602014-11-13 16:15:08 -0800505
Robert Carrcd9a18c2015-12-16 18:16:21 -0800506static jint nativeSetScalingMode(JNIEnv *env, jclass clazz, jlong nativeObject, jint scalingMode) {
507 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
508 return surface->setScalingMode(scalingMode);
509}
510
Robert Carr387838b2016-09-07 14:12:44 -0700511static 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
Robert Carra35e5de2017-03-03 17:04:54 -0800516static 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);
Chavi Weingartend7ec64c2017-11-30 01:52:01 +0000520 int err = Surface::attachAndQueueBuffer(surface, bp);
Robert Carra35e5de2017-03-03 17:04:54 -0800521 return err;
522}
523
Romain Guy0bbf0b42017-07-20 08:57:07 -0700524static jint nativeSetSharedBufferModeEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
525 jboolean enabled) {
526 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
Adrian Roosc43dfdf2018-01-29 17:55:44 +0100527 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
528 return anw->perform(surface, NATIVE_WINDOW_SET_SHARED_BUFFER_MODE, int(enabled));
Romain Guy0bbf0b42017-07-20 08:57:07 -0700529}
530
531static jint nativeSetAutoRefreshEnabled(JNIEnv* env, jclass clazz, jlong nativeObject,
532 jboolean enabled) {
533 Surface* surface = reinterpret_cast<Surface*>(nativeObject);
Adrian Roosc43dfdf2018-01-29 17:55:44 +0100534 ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
535 return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
Romain Guy0bbf0b42017-07-20 08:57:07 -0700536}
537
John Reckbb2d0cc2014-10-21 10:09:36 -0700538namespace uirenderer {
539
540using namespace android::uirenderer::renderthread;
541
542class ContextFactory : public IContextFactory {
543public:
544 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
545 return new AnimationContext(clock);
546 }
547};
548
Peiyong Lind8b68712018-03-06 18:34:21 -0800549static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr,
550 jboolean isWideColorGamut) {
John Reckbb2d0cc2014-10-21 10:09:36 -0700551 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();
Peiyong Lind8b68712018-03-06 18:34:21 -0800556 if (isWideColorGamut) {
557 proxy->setWideGamut(true);
558 }
Stan Iliev768e3932016-07-08 21:34:52 -0400559 proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
John Reckbb2d0cc2014-10-21 10:09:36 -0700560 proxy->initialize(surface);
561 // Shadows can't be used via this interface, so just set the light source
John Reckab1080c2016-06-21 16:24:20 -0700562 // to all 0s.
563 proxy->setup(0, 0, 0);
Alan Viverette50210d92015-05-14 18:05:36 -0700564 proxy->setLightCenter((Vector3){0, 0, 0});
John Reckbb2d0cc2014-10-21 10:09:36 -0700565 return (jlong) proxy;
566}
567
568static 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
574static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
575 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
John Reckba6adf62015-02-19 14:36:50 -0800576 nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
577 UiFrameInfoBuilder(proxy->frameInfo())
578 .setVsync(vsync, vsync)
Chris Craik1b54fb22015-06-02 17:40:58 -0700579 .addFlag(FrameInfoFlags::SurfaceCanvas);
John Reck2de950d2017-01-25 10:58:30 -0800580 proxy->syncAndDrawFrame();
John Reckbb2d0cc2014-10-21 10:09:36 -0700581}
582
583static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
584 RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
585 delete proxy;
586}
587
588} // uirenderer
589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591
John Reckbb2d0cc2014-10-21 10:09:36 -0700592namespace hwui = android::uirenderer;
593
Daniel Micay76f6a862015-09-19 17:31:01 -0400594static const JNINativeMethod gSurfaceMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000595 {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
Jeff Brown64a55af2012-08-26 02:47:39 -0700596 (void*)nativeCreateFromSurfaceTexture },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000597 {"nativeRelease", "(J)V",
Jeff Brown64a55af2012-08-26 02:47:39 -0700598 (void*)nativeRelease },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000599 {"nativeIsValid", "(J)Z",
Jeff Brown64a55af2012-08-26 02:47:39 -0700600 (void*)nativeIsValid },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000601 {"nativeIsConsumerRunningBehind", "(J)Z",
Jeff Brown64a55af2012-08-26 02:47:39 -0700602 (void*)nativeIsConsumerRunningBehind },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000603 {"nativeLockCanvas", "(JLandroid/graphics/Canvas;Landroid/graphics/Rect;)J",
Jeff Brown64a55af2012-08-26 02:47:39 -0700604 (void*)nativeLockCanvas },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000605 {"nativeUnlockCanvasAndPost", "(JLandroid/graphics/Canvas;)V",
Jeff Brown64a55af2012-08-26 02:47:39 -0700606 (void*)nativeUnlockCanvasAndPost },
Dan Stoza5795d642014-06-20 13:01:36 -0700607 {"nativeAllocateBuffers", "(J)V",
608 (void*)nativeAllocateBuffers },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000609 {"nativeCreateFromSurfaceControl", "(J)J",
Jeff Brownfc0ebd72013-04-30 16:33:00 -0700610 (void*)nativeCreateFromSurfaceControl },
Bryce Lee02949f12017-06-16 07:20:34 -0700611 {"nativeGetFromSurfaceControl", "(J)J",
612 (void*)nativeGetFromSurfaceControl },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000613 {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
Jeff Brown64a55af2012-08-26 02:47:39 -0700614 (void*)nativeReadFromParcel },
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000615 {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
Jeff Brown64a55af2012-08-26 02:47:39 -0700616 (void*)nativeWriteToParcel },
John Reckb35c9602014-11-13 16:15:08 -0800617 {"nativeGetWidth", "(J)I", (void*)nativeGetWidth },
618 {"nativeGetHeight", "(J)I", (void*)nativeGetHeight },
Rob Carr64e516f2015-10-29 00:20:45 +0000619 {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
Robert Carrcd9a18c2015-12-16 18:16:21 -0800620 {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
Robert Carr387838b2016-09-07 14:12:44 -0700621 {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
Robert Carra35e5de2017-03-03 17:04:54 -0800622 {"nativeAttachAndQueueBuffer", "(JLandroid/graphics/GraphicBuffer;)I", (void*)nativeAttachAndQueueBuffer},
Romain Guy0bbf0b42017-07-20 08:57:07 -0700623 {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
624 {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
John Reckbb2d0cc2014-10-21 10:09:36 -0700625
626 // HWUI context
Peiyong Lind8b68712018-03-06 18:34:21 -0800627 {"nHwuiCreate", "(JJZ)J", (void*) hwui::create },
John Reckbb2d0cc2014-10-21 10:09:36 -0700628 {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
629 {"nHwuiDraw", "(J)V", (void*) hwui::draw },
630 {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631};
632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633int register_android_view_Surface(JNIEnv* env)
634{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800635 int err = RegisterMethodsOrDie(env, "android/view/Surface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 gSurfaceMethods, NELEM(gSurfaceMethods));
Jeff Brown64a55af2012-08-26 02:47:39 -0700637
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800638 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");
Jeff Brown64a55af2012-08-26 02:47:39 -0700645
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800646 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");
Jeff Brown64a55af2012-08-26 02:47:39 -0700651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 return err;
653}
654
655};