1 #ifndef _ANDROID_GRAPHICS_GRAPHICS_JNI_H_ 2 #define _ANDROID_GRAPHICS_GRAPHICS_JNI_H_ 3 4 #include <cutils/compiler.h> 5 #include <hwui/Bitmap.h> 6 #include <hwui/Canvas.h> 7 8 #include "BRDAllocator.h" 9 #include "Bitmap.h" 10 #include "SkBitmap.h" 11 #include "SkCodec.h" 12 #include "SkColorSpace.h" 13 #include "SkMallocPixelRef.h" 14 #include "SkPixelRef.h" 15 #include "SkPoint.h" 16 #include "SkRect.h" 17 #include "graphics_jni_helpers.h" 18 19 class SkCanvas; 20 struct SkFontMetrics; 21 22 namespace android { 23 class BitmapRegionDecoderWrapper; 24 class Canvas; 25 class Paint; 26 struct Typeface; 27 } 28 29 class GraphicsJNI { 30 public: 31 // This enum must keep these int values, to match the int values 32 // in the java Bitmap.Config enum. 33 enum LegacyBitmapConfig { 34 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, 43 44 kLastEnum_LegacyBitmapConfig = kRGBA_1010102_LegacyBitmapConfig 45 }; 46 47 static void setJavaVM(JavaVM* javaVM); 48 49 /** 50 * returns a pointer to the JavaVM provided when we initialized the module 51 * DEPRECATED: Objects should know the JavaVM that created them 52 */ getJavaVM()53 static JavaVM* getJavaVM() { return mJavaVM; } 54 55 /** 56 * return a pointer to the JNIEnv for this thread 57 * DEPRECATED: Objects should know the JavaVM that created them 58 */ 59 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 67 // 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); 79 80 static void set_cluster_count_to_run_info(JNIEnv* env, jobject runInfo, jint clusterCount); 81 82 static void set_jpoint(JNIEnv*, jobject jrect, int x, int y); 83 84 static SkIPoint* jpoint_to_ipoint(JNIEnv*, jobject jpoint, SkIPoint* point); 85 static void ipoint_to_jpoint(const SkIPoint& point, JNIEnv*, jobject jpoint); 86 87 static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point); 88 static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf); 89 90 ANDROID_API static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas); 91 static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap); 92 static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes, 93 bool* isHardware); 94 static SkRegion* getNativeRegion(JNIEnv*, jobject region); 95 96 /** 97 * Set SkFontMetrics to Java Paint.FontMetrics. 98 * Do nothing if metrics is nullptr. 99 */ 100 static void set_metrics(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics); 101 /** 102 * Set SkFontMetrics to Java Paint.FontMetricsInt and return recommended interline space. 103 * Do nothing if metrics is nullptr. 104 */ 105 static int set_metrics_int(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics); 106 107 /* 108 * LegacyBitmapConfig is the old enum in Skia that matched the enum int values 109 * in Bitmap.Config. Skia no longer supports this config, but has replaced it 110 * with SkColorType. These routines convert between the two. 111 */ 112 static SkColorType legacyBitmapConfigToColorType(jint legacyConfig); 113 static jint colorTypeToLegacyBitmapConfig(SkColorType colorType); 114 115 /** Return the corresponding native colorType from the java Config enum, 116 or kUnknown_SkColorType if the java object is null. 117 */ 118 static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig); 119 static AndroidBitmapFormat getFormatFromConfig(JNIEnv* env, jobject jconfig); 120 static jobject getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format); 121 122 static bool isHardwareConfig(JNIEnv* env, jobject jconfig); 123 static jint hardwareLegacyBitmapConfig(); 124 125 static jobject createRegion(JNIEnv* env, SkRegion* region); 126 127 static jobject createBitmapRegionDecoder(JNIEnv* env, 128 android::BitmapRegionDecoderWrapper* bitmap); 129 130 /** Copy the colors in colors[] to the bitmap, convert to the correct 131 format along the way. 132 Whether to use premultiplied pixels is determined by dstBitmap's alphaType. 133 */ 134 static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset, 135 int srcStride, int x, int y, int width, int height, 136 SkBitmap* dstBitmap); 137 138 /** 139 * Convert the native SkColorSpace retrieved from ColorSpace.Rgb.getNativeInstance(). 140 * 141 * This will never throw an Exception. If the ColorSpace is one that Skia cannot 142 * use, ColorSpace.Rgb.getNativeInstance() would have thrown an Exception. It may, 143 * however, be nullptr, which may be acceptable. 144 */ 145 static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle); 146 147 /** 148 * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace 149 * and decodeColorType. 150 * 151 * This may create a new object if none of the Named ColorSpaces match. 152 */ 153 static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace, 154 SkColorType decodeColorType); 155 156 /** 157 * Convert from a Java @ColorLong to an SkColor4f that Skia can use directly. 158 * 159 * This ignores the encoded ColorSpace, besides checking to see if it is sRGB, 160 * which is encoded differently. The color space should be passed down separately 161 * via ColorSpace#getNativeInstance(), and converted with getNativeColorSpace(), 162 * above. 163 */ 164 static SkColor4f convertColorLong(jlong color); 165 166 private: 167 /* JNI JavaVM pointer */ 168 static JavaVM* mJavaVM; 169 }; 170 171 class HeapAllocator : public android::skia::BRDAllocator { 172 public: HeapAllocator()173 HeapAllocator() { }; ~HeapAllocator()174 ~HeapAllocator() { }; 175 176 virtual bool allocPixelRef(SkBitmap* bitmap) override; 177 178 /** 179 * Fetches the backing allocation object. Must be called! 180 */ getStorageObjAndReset()181 android::Bitmap* getStorageObjAndReset() { 182 return mStorage.release(); 183 }; 184 zeroInit()185 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; } 186 private: 187 sk_sp<android::Bitmap> mStorage; 188 }; 189 190 /** 191 * Allocator to handle reusing bitmaps for BitmapRegionDecoder. 192 * 193 * The BitmapRegionDecoder documentation states that, if it is 194 * provided, the recycled bitmap will always be reused, clipping 195 * the decoded output to fit in the recycled bitmap if necessary. 196 * This allocator implements that behavior. 197 * 198 * Skia's BitmapRegionDecoder expects the memory that 199 * is allocated to be large enough to decode the entire region 200 * that is requested. It will decode directly into the memory 201 * that is provided. 202 * 203 * FIXME: BUG:25465958 204 * If the recycled bitmap is not large enough for the decode 205 * requested, meaning that a clip is required, we will allocate 206 * enough memory for Skia to perform the decode, and then copy 207 * from the decoded output into the recycled bitmap. 208 * 209 * If the recycled bitmap is large enough for the decode requested, 210 * we will provide that memory for Skia to decode directly into. 211 * 212 * This allocator should only be used for a single allocation. 213 * After we reuse the recycledBitmap once, it is dangerous to 214 * reuse it again, given that it still may be in use from our 215 * first allocation. 216 */ 217 class RecyclingClippingPixelAllocator : public android::skia::BRDAllocator { 218 public: 219 RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap, 220 bool mustMatchColorType = true); 221 222 ~RecyclingClippingPixelAllocator(); 223 224 virtual bool allocPixelRef(SkBitmap* bitmap) override; 225 226 /** 227 * Must be called! 228 * 229 * In the event that the recycled bitmap is not large enough for 230 * the allocation requested, we will allocate memory on the heap 231 * instead. As a final step, once we are done using this memory, 232 * we will copy the contents of the heap memory into the recycled 233 * bitmap's memory, clipping as necessary. 234 */ 235 void copyIfNecessary(); 236 237 /** 238 * Indicates that this allocator does not allocate zero initialized 239 * memory. 240 */ zeroInit()241 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; } 242 243 private: 244 android::Bitmap* mRecycledBitmap; 245 const size_t mRecycledBytes; 246 SkBitmap* mSkiaBitmap; 247 bool mNeedsCopy; 248 const bool mMustMatchColorType; 249 }; 250 251 class AshmemPixelAllocator : public SkBitmap::Allocator { 252 public: 253 explicit AshmemPixelAllocator(JNIEnv* env); ~AshmemPixelAllocator()254 ~AshmemPixelAllocator() { }; 255 virtual bool allocPixelRef(SkBitmap* bitmap); getStorageObjAndReset()256 android::Bitmap* getStorageObjAndReset() { 257 return mStorage.release(); 258 }; 259 260 private: 261 JavaVM* mJavaVM; 262 sk_sp<android::Bitmap> mStorage; 263 }; 264 265 266 enum JNIAccess { 267 kRO_JNIAccess, 268 kRW_JNIAccess 269 }; 270 271 class AutoJavaFloatArray { 272 public: 273 AutoJavaFloatArray(JNIEnv* env, jfloatArray array, 274 int minLength = 0, JNIAccess = kRW_JNIAccess); 275 ~AutoJavaFloatArray(); 276 ptr()277 float* ptr() const { return fPtr; } length()278 int length() const { return fLen; } 279 280 private: 281 JNIEnv* fEnv; 282 jfloatArray fArray; 283 float* fPtr; 284 int fLen; 285 int fReleaseMode; 286 }; 287 288 class AutoJavaIntArray { 289 public: 290 AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0); 291 ~AutoJavaIntArray(); 292 ptr()293 jint* ptr() const { return fPtr; } length()294 int length() const { return fLen; } 295 296 private: 297 JNIEnv* fEnv; 298 jintArray fArray; 299 jint* fPtr; 300 int fLen; 301 }; 302 303 class AutoJavaShortArray { 304 public: 305 AutoJavaShortArray(JNIEnv* env, jshortArray array, 306 int minLength = 0, JNIAccess = kRW_JNIAccess); 307 ~AutoJavaShortArray(); 308 ptr()309 jshort* ptr() const { return fPtr; } length()310 int length() const { return fLen; } 311 312 private: 313 JNIEnv* fEnv; 314 jshortArray fArray; 315 jshort* fPtr; 316 int fLen; 317 int fReleaseMode; 318 }; 319 320 class AutoJavaByteArray { 321 public: 322 AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0); 323 ~AutoJavaByteArray(); 324 ptr()325 jbyte* ptr() const { return fPtr; } length()326 int length() const { return fLen; } 327 328 private: 329 JNIEnv* fEnv; 330 jbyteArray fArray; 331 jbyte* fPtr; 332 int fLen; 333 }; 334 335 class JGlobalRefHolder { 336 public: JGlobalRefHolder(JavaVM * vm,jobject object)337 JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {} 338 ~JGlobalRefHolder()339 virtual ~JGlobalRefHolder() { 340 env()->DeleteGlobalRef(mObject); 341 mObject = nullptr; 342 } 343 object()344 jobject object() { return mObject; } vm()345 JavaVM* vm() { return mVm; } 346 env()347 JNIEnv* env() { 348 JNIEnv* env; 349 if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 350 LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm); 351 } 352 return env; 353 } 354 355 private: 356 JGlobalRefHolder(const JGlobalRefHolder&) = delete; 357 void operator=(const JGlobalRefHolder&) = delete; 358 359 JavaVM* mVm; 360 jobject mObject; 361 }; 362 363 void doThrowNPE(JNIEnv* env); 364 void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception 365 void doThrowIAE(JNIEnv* env, const char* msg = NULL); // Illegal Argument 366 void doThrowRE(JNIEnv* env, const char* msg = NULL); // Runtime 367 void doThrowISE(JNIEnv* env, const char* msg = NULL); // Illegal State 368 void doThrowOOME(JNIEnv* env, const char* msg = NULL); // Out of memory 369 void doThrowIOE(JNIEnv* env, const char* msg = NULL); // IO Exception 370 371 #define NPE_CHECK_RETURN_ZERO(env, object) \ 372 do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0) 373 374 #define NPE_CHECK_RETURN_VOID(env, object) \ 375 do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0) 376 377 #endif // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_ 378