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