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