blob: 24f9e82b5340f0319493f3bc51557b3eb8c47c3a [file] [log] [blame]
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001#ifndef _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
2#define _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003
Derek Sollenberger2173ea22020-02-19 15:37:29 -05004#include <cutils/compiler.h>
Nader Jawada3521852023-01-30 20:23:46 -08005#include <hwui/Bitmap.h>
6#include <hwui/Canvas.h>
Derek Sollenberger2173ea22020-02-19 15:37:29 -05007
John Reckcca989f2023-01-30 20:46:20 +00008#include "BRDAllocator.h"
Nader Jawada3521852023-01-30 20:23:46 -08009#include "Bitmap.h"
Patrick Dubroye4ac2d62010-12-01 11:23:13 -080010#include "SkBitmap.h"
Matt Sarett1f979632015-10-27 10:33:20 -040011#include "SkCodec.h"
Nader Jawada3521852023-01-30 20:23:46 -080012#include "SkColorSpace.h"
John Reckcca989f2023-01-30 20:46:20 +000013#include "SkMallocPixelRef.h"
Nader Jawada3521852023-01-30 20:23:46 -080014#include "SkPixelRef.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015#include "SkPoint.h"
16#include "SkRect.h"
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040017#include "graphics_jni_helpers.h"
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019class SkCanvas;
Seigo Nonaka1ed4f642020-09-10 17:19:34 -070020struct SkFontMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021
Raph Levien3d528c402014-06-26 09:04:54 -070022namespace android {
Fyodor Kyslovb0da4a52023-01-26 18:39:33 +000023class BitmapRegionDecoderWrapper;
John Reckbe671952021-01-13 22:39:32 -050024class Canvas;
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -040025class Paint;
sergeyvbad99182016-03-17 11:24:22 -070026struct Typeface;
Raph Levien3d528c402014-06-26 09:04:54 -070027}
28
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029class GraphicsJNI {
30public:
Romain Guye8d2ebb2017-02-09 18:38:47 -080031 // This enum must keep these int values, to match the int values
32 // in the java Bitmap.Config enum.
33 enum LegacyBitmapConfig {
Alec Mouri1efd0a52022-01-20 13:58:23 -080034 kNo_LegacyBitmapConfig = 0,
35 kA8_LegacyBitmapConfig = 1,
36 kIndex8_LegacyBitmapConfig = 2,
37 kRGB_565_LegacyBitmapConfig = 3,
38 kARGB_4444_LegacyBitmapConfig = 4,
39 kARGB_8888_LegacyBitmapConfig = 5,
40 kRGBA_16F_LegacyBitmapConfig = 6,
41 kHardware_LegacyBitmapConfig = 7,
42 kRGBA_1010102_LegacyBitmapConfig = 8,
Romain Guye8d2ebb2017-02-09 18:38:47 -080043
Alec Mouri1efd0a52022-01-20 13:58:23 -080044 kLastEnum_LegacyBitmapConfig = kRGBA_1010102_LegacyBitmapConfig
Romain Guye8d2ebb2017-02-09 18:38:47 -080045 };
46
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040047 static void setJavaVM(JavaVM* javaVM);
48
John Recka6b177b2023-02-24 17:25:18 -050049 /**
50 * returns a pointer to the JavaVM provided when we initialized the module
51 * DEPRECATED: Objects should know the JavaVM that created them
52 */
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040053 static JavaVM* getJavaVM() { return mJavaVM; }
54
John Recka6b177b2023-02-24 17:25:18 -050055 /**
56 * return a pointer to the JNIEnv for this thread
57 * DEPRECATED: Objects should know the JavaVM that created them
58 */
Derek Sollenbergerc5882c42019-10-25 11:11:32 -040059 static JNIEnv* getJNIEnv();
60
61 /** create a JNIEnv* for this thread or assert if one already exists */
62 static JNIEnv* attachJNIEnv(const char* envName);
63
64 /** detach the current thread from the JavaVM */
65 static void detachJNIEnv();
66
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 // returns true if an exception is set (and dumps it out to the Log)
68 static bool hasException(JNIEnv*);
69
70 static void get_jrect(JNIEnv*, jobject jrect, int* L, int* T, int* R, int* B);
71 static void set_jrect(JNIEnv*, jobject jrect, int L, int T, int R, int B);
72
73 static SkIRect* jrect_to_irect(JNIEnv*, jobject jrect, SkIRect*);
74 static void irect_to_jrect(const SkIRect&, JNIEnv*, jobject jrect);
75
76 static SkRect* jrectf_to_rect(JNIEnv*, jobject jrectf, SkRect*);
77 static SkRect* jrect_to_rect(JNIEnv*, jobject jrect, SkRect*);
78 static void rect_to_jrectf(const SkRect&, JNIEnv*, jobject jrectf);
Elliott Hughes8451b252011-04-07 19:17:57 -070079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 static void set_jpoint(JNIEnv*, jobject jrect, int x, int y);
Elliott Hughes8451b252011-04-07 19:17:57 -070081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 static SkIPoint* jpoint_to_ipoint(JNIEnv*, jobject jpoint, SkIPoint* point);
83 static void ipoint_to_jpoint(const SkIPoint& point, JNIEnv*, jobject jpoint);
Elliott Hughes8451b252011-04-07 19:17:57 -070084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
86 static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
Elliott Hughes8451b252011-04-07 19:17:57 -070087
Derek Sollenberger2173ea22020-02-19 15:37:29 -050088 ANDROID_API static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
Derek Sollenberger6c41ab12019-11-08 08:50:58 -050089 static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
Leon Scroggins III84a2afc2020-01-19 19:27:16 -050090 static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes,
91 bool* isHardware);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 static SkRegion* getNativeRegion(JNIEnv*, jobject region);
Elliott Hughes8451b252011-04-07 19:17:57 -070093
Seigo Nonaka1ed4f642020-09-10 17:19:34 -070094 /**
95 * Set SkFontMetrics to Java Paint.FontMetrics.
96 * Do nothing if metrics is nullptr.
97 */
98 static void set_metrics(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
99 /**
100 * Set SkFontMetrics to Java Paint.FontMetricsInt and return recommended interline space.
101 * Do nothing if metrics is nullptr.
102 */
103 static int set_metrics_int(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
104
Mike Reed1103b322014-07-08 12:36:44 -0400105 /*
106 * LegacyBitmapConfig is the old enum in Skia that matched the enum int values
107 * in Bitmap.Config. Skia no longer supports this config, but has replaced it
108 * with SkColorType. These routines convert between the two.
109 */
110 static SkColorType legacyBitmapConfigToColorType(jint legacyConfig);
111 static jint colorTypeToLegacyBitmapConfig(SkColorType colorType);
112
Mike Reed42a1d082014-07-07 18:06:18 -0400113 /** Return the corresponding native colorType from the java Config enum,
114 or kUnknown_SkColorType if the java object is null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 */
Mike Reed42a1d082014-07-07 18:06:18 -0400116 static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
Derek Sollenberger213daca2019-10-25 14:17:32 -0400117 static AndroidBitmapFormat getFormatFromConfig(JNIEnv* env, jobject jconfig);
118 static jobject getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
Elliott Hughes8451b252011-04-07 19:17:57 -0700119
sergeyvda6c8ffc2016-11-22 18:28:54 -0800120 static bool isHardwareConfig(JNIEnv* env, jobject jconfig);
sergeyv19b4b012016-12-13 16:06:00 -0800121 static jint hardwareLegacyBitmapConfig();
sergeyvda6c8ffc2016-11-22 18:28:54 -0800122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 static jobject createRegion(JNIEnv* env, SkRegion* region);
124
Leon Scroggins III23ac0362020-05-04 15:38:58 -0400125 static jobject createBitmapRegionDecoder(JNIEnv* env,
Fyodor Kyslovb0da4a52023-01-26 18:39:33 +0000126 android::BitmapRegionDecoderWrapper* bitmap);
Joseph Wenf1f48bc2010-07-19 16:59:51 +0800127
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500128 /**
129 * Given a bitmap we natively allocate a memory block to store the contents
130 * of that bitmap. The memory is then attached to the bitmap via an
131 * SkPixelRef, which ensures that upon deletion the appropriate caches
132 * are notified.
133 */
Mike Reed81397c42017-07-18 17:04:16 -0400134 static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap);
Derek Sollenberger3d4eed72014-12-04 15:20:29 -0500135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 /** Copy the colors in colors[] to the bitmap, convert to the correct
137 format along the way.
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400138 Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 */
140 static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
Chris Craik1abf5d62013-08-16 12:47:03 -0700141 int srcStride, int x, int y, int width, int height,
Brian Osman91c9c282018-08-17 16:57:15 -0400142 SkBitmap* dstBitmap);
Romain Guy253f2c22016-09-28 17:34:42 -0700143
Leon Scroggins III0e443d12018-12-19 11:38:35 -0500144 /**
145 * Convert the native SkColorSpace retrieved from ColorSpace.Rgb.getNativeInstance().
146 *
147 * This will never throw an Exception. If the ColorSpace is one that Skia cannot
148 * use, ColorSpace.Rgb.getNativeInstance() would have thrown an Exception. It may,
149 * however, be nullptr, which may be acceptable.
150 */
151 static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle);
Romain Guy95648b82017-04-13 18:43:42 -0700152
Derek Sollenbergerbf3e4642019-01-30 11:28:27 -0500153 /**
154 * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace
155 * and decodeColorType.
156 *
157 * This may create a new object if none of the Named ColorSpaces match.
158 */
159 static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
Romain Guy95648b82017-04-13 18:43:42 -0700160 SkColorType decodeColorType);
Leon Scroggins III94ba1002019-01-17 13:34:51 -0500161
162 /**
163 * Convert from a Java @ColorLong to an SkColor4f that Skia can use directly.
164 *
165 * This ignores the encoded ColorSpace, besides checking to see if it is sRGB,
166 * which is encoded differently. The color space should be passed down separately
167 * via ColorSpace#getNativeInstance(), and converted with getNativeColorSpace(),
168 * above.
169 */
170 static SkColor4f convertColorLong(jlong color);
Derek Sollenbergerc5882c42019-10-25 11:11:32 -0400171
172private:
173 /* JNI JavaVM pointer */
174 static JavaVM* mJavaVM;
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800175};
176
Leon Scroggins III23ac0362020-05-04 15:38:58 -0400177class HeapAllocator : public android::skia::BRDAllocator {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178public:
sergeyvc69853c2016-10-07 14:14:09 -0700179 HeapAllocator() { };
180 ~HeapAllocator() { };
Elliott Hughes8451b252011-04-07 19:17:57 -0700181
Mike Reed81397c42017-07-18 17:04:16 -0400182 virtual bool allocPixelRef(SkBitmap* bitmap) override;
Patrick Dubroyafde46e2010-12-15 11:52:01 -0800183
John Reckf29ed282015-04-07 07:32:03 -0700184 /**
185 * Fetches the backing allocation object. Must be called!
Patrick Dubroyafde46e2010-12-15 11:52:01 -0800186 */
sergeyvc1c54062016-10-19 18:47:26 -0700187 android::Bitmap* getStorageObjAndReset() {
sergeyvc69853c2016-10-07 14:14:09 -0700188 return mStorage.release();
Patrick Dubroyafde46e2010-12-15 11:52:01 -0800189 };
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800190
Matt Sarett1f979632015-10-27 10:33:20 -0400191 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192private:
sergeyvc1c54062016-10-19 18:47:26 -0700193 sk_sp<android::Bitmap> mStorage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194};
195
Matt Sarett1f979632015-10-27 10:33:20 -0400196/**
197 * Allocator to handle reusing bitmaps for BitmapRegionDecoder.
198 *
199 * The BitmapRegionDecoder documentation states that, if it is
200 * provided, the recycled bitmap will always be reused, clipping
201 * the decoded output to fit in the recycled bitmap if necessary.
202 * This allocator implements that behavior.
203 *
Leon Scroggins III23ac0362020-05-04 15:38:58 -0400204 * Skia's BitmapRegionDecoder expects the memory that
Matt Sarett1f979632015-10-27 10:33:20 -0400205 * is allocated to be large enough to decode the entire region
206 * that is requested. It will decode directly into the memory
207 * that is provided.
208 *
209 * FIXME: BUG:25465958
210 * If the recycled bitmap is not large enough for the decode
211 * requested, meaning that a clip is required, we will allocate
212 * enough memory for Skia to perform the decode, and then copy
213 * from the decoded output into the recycled bitmap.
214 *
215 * If the recycled bitmap is large enough for the decode requested,
216 * we will provide that memory for Skia to decode directly into.
217 *
218 * This allocator should only be used for a single allocation.
219 * After we reuse the recycledBitmap once, it is dangerous to
220 * reuse it again, given that it still may be in use from our
221 * first allocation.
222 */
Leon Scroggins III23ac0362020-05-04 15:38:58 -0400223class RecyclingClippingPixelAllocator : public android::skia::BRDAllocator {
Matt Sarett1f979632015-10-27 10:33:20 -0400224public:
225
sergeyvc1c54062016-10-19 18:47:26 -0700226 RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
Matt Sarett1f979632015-10-27 10:33:20 -0400227 size_t recycledBytes);
228
229 ~RecyclingClippingPixelAllocator();
230
Mike Reed81397c42017-07-18 17:04:16 -0400231 virtual bool allocPixelRef(SkBitmap* bitmap) override;
Matt Sarett1f979632015-10-27 10:33:20 -0400232
233 /**
234 * Must be called!
235 *
236 * In the event that the recycled bitmap is not large enough for
237 * the allocation requested, we will allocate memory on the heap
238 * instead. As a final step, once we are done using this memory,
239 * we will copy the contents of the heap memory into the recycled
240 * bitmap's memory, clipping as necessary.
241 */
242 void copyIfNecessary();
243
244 /**
245 * Indicates that this allocator does not allocate zero initialized
246 * memory.
247 */
248 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
249
250private:
sergeyvc1c54062016-10-19 18:47:26 -0700251 android::Bitmap* mRecycledBitmap;
Matt Sarett1f979632015-10-27 10:33:20 -0400252 const size_t mRecycledBytes;
253 SkBitmap* mSkiaBitmap;
254 bool mNeedsCopy;
255};
256
Riley Andrews721ae5f2015-05-11 16:08:22 -0700257class AshmemPixelAllocator : public SkBitmap::Allocator {
258public:
Chih-Hung Hsieha6543282016-08-29 14:46:35 -0700259 explicit AshmemPixelAllocator(JNIEnv* env);
sergeyvc69853c2016-10-07 14:14:09 -0700260 ~AshmemPixelAllocator() { };
Mike Reed81397c42017-07-18 17:04:16 -0400261 virtual bool allocPixelRef(SkBitmap* bitmap);
sergeyvc1c54062016-10-19 18:47:26 -0700262 android::Bitmap* getStorageObjAndReset() {
sergeyvc69853c2016-10-07 14:14:09 -0700263 return mStorage.release();
Riley Andrews721ae5f2015-05-11 16:08:22 -0700264 };
265
266private:
267 JavaVM* mJavaVM;
sergeyvc1c54062016-10-19 18:47:26 -0700268 sk_sp<android::Bitmap> mStorage;
Riley Andrews721ae5f2015-05-11 16:08:22 -0700269};
270
271
Mike Reedc04851f2009-10-28 15:09:45 -0400272enum JNIAccess {
273 kRO_JNIAccess,
274 kRW_JNIAccess
275};
276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277class AutoJavaFloatArray {
278public:
Mike Reedc04851f2009-10-28 15:09:45 -0400279 AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
280 int minLength = 0, JNIAccess = kRW_JNIAccess);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 ~AutoJavaFloatArray();
Elliott Hughes8451b252011-04-07 19:17:57 -0700282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 float* ptr() const { return fPtr; }
284 int length() const { return fLen; }
Elliott Hughes8451b252011-04-07 19:17:57 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286private:
287 JNIEnv* fEnv;
288 jfloatArray fArray;
289 float* fPtr;
290 int fLen;
Mike Reedc04851f2009-10-28 15:09:45 -0400291 int fReleaseMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292};
293
294class AutoJavaIntArray {
295public:
296 AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
297 ~AutoJavaIntArray();
Elliott Hughes8451b252011-04-07 19:17:57 -0700298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 jint* ptr() const { return fPtr; }
300 int length() const { return fLen; }
Elliott Hughes8451b252011-04-07 19:17:57 -0700301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302private:
303 JNIEnv* fEnv;
304 jintArray fArray;
305 jint* fPtr;
306 int fLen;
307};
308
309class AutoJavaShortArray {
310public:
Mike Reedc04851f2009-10-28 15:09:45 -0400311 AutoJavaShortArray(JNIEnv* env, jshortArray array,
312 int minLength = 0, JNIAccess = kRW_JNIAccess);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 ~AutoJavaShortArray();
Elliott Hughes8451b252011-04-07 19:17:57 -0700314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 jshort* ptr() const { return fPtr; }
316 int length() const { return fLen; }
Elliott Hughes8451b252011-04-07 19:17:57 -0700317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318private:
319 JNIEnv* fEnv;
320 jshortArray fArray;
321 jshort* fPtr;
322 int fLen;
Mike Reedc04851f2009-10-28 15:09:45 -0400323 int fReleaseMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324};
325
326class AutoJavaByteArray {
327public:
328 AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
329 ~AutoJavaByteArray();
Elliott Hughes8451b252011-04-07 19:17:57 -0700330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 jbyte* ptr() const { return fPtr; }
332 int length() const { return fLen; }
Elliott Hughes8451b252011-04-07 19:17:57 -0700333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334private:
335 JNIEnv* fEnv;
336 jbyteArray fArray;
337 jbyte* fPtr;
338 int fLen;
339};
340
Nader Jawada3521852023-01-30 20:23:46 -0800341class JGlobalRefHolder {
342public:
343 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
344
345 virtual ~JGlobalRefHolder() {
John Recka6b177b2023-02-24 17:25:18 -0500346 env()->DeleteGlobalRef(mObject);
Nader Jawada3521852023-01-30 20:23:46 -0800347 mObject = nullptr;
348 }
349
350 jobject object() { return mObject; }
351 JavaVM* vm() { return mVm; }
352
John Recka6b177b2023-02-24 17:25:18 -0500353 JNIEnv* env() {
354 JNIEnv* env;
355 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
356 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
357 }
358 return env;
359 }
360
Nader Jawada3521852023-01-30 20:23:46 -0800361private:
362 JGlobalRefHolder(const JGlobalRefHolder&) = delete;
363 void operator=(const JGlobalRefHolder&) = delete;
364
365 JavaVM* mVm;
366 jobject mObject;
367};
368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369void doThrowNPE(JNIEnv* env);
370void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
371void doThrowIAE(JNIEnv* env, const char* msg = NULL); // Illegal Argument
372void doThrowRE(JNIEnv* env, const char* msg = NULL); // Runtime
373void doThrowISE(JNIEnv* env, const char* msg = NULL); // Illegal State
374void doThrowOOME(JNIEnv* env, const char* msg = NULL); // Out of memory
Joseph Wenf1f48bc2010-07-19 16:59:51 +0800375void doThrowIOE(JNIEnv* env, const char* msg = NULL); // IO Exception
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376
377#define NPE_CHECK_RETURN_ZERO(env, object) \
378 do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0)
379
380#define NPE_CHECK_RETURN_VOID(env, object) \
381 do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
382
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800383#endif // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_