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