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