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