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 /* 70 * LegacyBitmapConfig is the old enum in Skia that matched the enum int values 71 * in Bitmap.Config. Skia no longer supports this config, but has replaced it 72 * with SkColorType. These routines convert between the two. 73 */ 74 static SkColorType legacyBitmapConfigToColorType(jint legacyConfig); 75 static jint colorTypeToLegacyBitmapConfig(SkColorType colorType); 76 77 /** Return the corresponding native colorType from the java Config enum, 78 or kUnknown_SkColorType if the java object is null. 79 */ 80 static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig); 81 82 static bool isHardwareConfig(JNIEnv* env, jobject jconfig); 83 static jint hardwareLegacyBitmapConfig(); 84 85 static jobject createRegion(JNIEnv* env, SkRegion* region); 86 87 static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap); 88 89 static android::Bitmap* mapAshmemBitmap(JNIEnv* env, SkBitmap* bitmap, 90 int fd, void* addr, size_t size, bool readOnly); 91 92 /** 93 * Given a bitmap we natively allocate a memory block to store the contents 94 * of that bitmap. The memory is then attached to the bitmap via an 95 * SkPixelRef, which ensures that upon deletion the appropriate caches 96 * are notified. 97 */ 98 static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap); 99 100 /** Copy the colors in colors[] to the bitmap, convert to the correct 101 format along the way. 102 Whether to use premultiplied pixels is determined by dstBitmap's alphaType. 103 */ 104 static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset, 105 int srcStride, int x, int y, int width, int height, 106 const SkBitmap& dstBitmap); 107 108 static sk_sp<SkColorSpace> defaultColorSpace(); 109 static sk_sp<SkColorSpace> linearColorSpace(); 110 static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type); 111 static bool isColorSpaceSRGB(SkColorSpace* colorSpace); 112 113 static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams); 114 static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50); 115 static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace); 116 117 static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace, 118 SkColorType decodeColorType); 119 }; 120 121 class HeapAllocator : public SkBRDAllocator { 122 public: HeapAllocator()123 HeapAllocator() { }; ~HeapAllocator()124 ~HeapAllocator() { }; 125 126 virtual bool allocPixelRef(SkBitmap* bitmap) override; 127 128 /** 129 * Fetches the backing allocation object. Must be called! 130 */ getStorageObjAndReset()131 android::Bitmap* getStorageObjAndReset() { 132 return mStorage.release(); 133 }; 134 zeroInit()135 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; } 136 private: 137 sk_sp<android::Bitmap> mStorage; 138 }; 139 140 /** 141 * Allocator to handle reusing bitmaps for BitmapRegionDecoder. 142 * 143 * The BitmapRegionDecoder documentation states that, if it is 144 * provided, the recycled bitmap will always be reused, clipping 145 * the decoded output to fit in the recycled bitmap if necessary. 146 * This allocator implements that behavior. 147 * 148 * Skia's SkBitmapRegionDecoder expects the memory that 149 * is allocated to be large enough to decode the entire region 150 * that is requested. It will decode directly into the memory 151 * that is provided. 152 * 153 * FIXME: BUG:25465958 154 * If the recycled bitmap is not large enough for the decode 155 * requested, meaning that a clip is required, we will allocate 156 * enough memory for Skia to perform the decode, and then copy 157 * from the decoded output into the recycled bitmap. 158 * 159 * If the recycled bitmap is large enough for the decode requested, 160 * we will provide that memory for Skia to decode directly into. 161 * 162 * This allocator should only be used for a single allocation. 163 * After we reuse the recycledBitmap once, it is dangerous to 164 * reuse it again, given that it still may be in use from our 165 * first allocation. 166 */ 167 class RecyclingClippingPixelAllocator : public SkBRDAllocator { 168 public: 169 170 RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap, 171 size_t recycledBytes); 172 173 ~RecyclingClippingPixelAllocator(); 174 175 virtual bool allocPixelRef(SkBitmap* bitmap) override; 176 177 /** 178 * Must be called! 179 * 180 * In the event that the recycled bitmap is not large enough for 181 * the allocation requested, we will allocate memory on the heap 182 * instead. As a final step, once we are done using this memory, 183 * we will copy the contents of the heap memory into the recycled 184 * bitmap's memory, clipping as necessary. 185 */ 186 void copyIfNecessary(); 187 188 /** 189 * Indicates that this allocator does not allocate zero initialized 190 * memory. 191 */ zeroInit()192 SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; } 193 194 private: 195 android::Bitmap* mRecycledBitmap; 196 const size_t mRecycledBytes; 197 SkBitmap* mSkiaBitmap; 198 bool mNeedsCopy; 199 }; 200 201 class AshmemPixelAllocator : public SkBitmap::Allocator { 202 public: 203 explicit AshmemPixelAllocator(JNIEnv* env); ~AshmemPixelAllocator()204 ~AshmemPixelAllocator() { }; 205 virtual bool allocPixelRef(SkBitmap* bitmap); getStorageObjAndReset()206 android::Bitmap* getStorageObjAndReset() { 207 return mStorage.release(); 208 }; 209 210 private: 211 JavaVM* mJavaVM; 212 sk_sp<android::Bitmap> mStorage; 213 }; 214 215 216 enum JNIAccess { 217 kRO_JNIAccess, 218 kRW_JNIAccess 219 }; 220 221 class AutoJavaFloatArray { 222 public: 223 AutoJavaFloatArray(JNIEnv* env, jfloatArray array, 224 int minLength = 0, JNIAccess = kRW_JNIAccess); 225 ~AutoJavaFloatArray(); 226 ptr()227 float* ptr() const { return fPtr; } length()228 int length() const { return fLen; } 229 230 private: 231 JNIEnv* fEnv; 232 jfloatArray fArray; 233 float* fPtr; 234 int fLen; 235 int fReleaseMode; 236 }; 237 238 class AutoJavaIntArray { 239 public: 240 AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0); 241 ~AutoJavaIntArray(); 242 ptr()243 jint* ptr() const { return fPtr; } length()244 int length() const { return fLen; } 245 246 private: 247 JNIEnv* fEnv; 248 jintArray fArray; 249 jint* fPtr; 250 int fLen; 251 }; 252 253 class AutoJavaShortArray { 254 public: 255 AutoJavaShortArray(JNIEnv* env, jshortArray array, 256 int minLength = 0, JNIAccess = kRW_JNIAccess); 257 ~AutoJavaShortArray(); 258 ptr()259 jshort* ptr() const { return fPtr; } length()260 int length() const { return fLen; } 261 262 private: 263 JNIEnv* fEnv; 264 jshortArray fArray; 265 jshort* fPtr; 266 int fLen; 267 int fReleaseMode; 268 }; 269 270 class AutoJavaByteArray { 271 public: 272 AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0); 273 ~AutoJavaByteArray(); 274 ptr()275 jbyte* ptr() const { return fPtr; } length()276 int length() const { return fLen; } 277 278 private: 279 JNIEnv* fEnv; 280 jbyteArray fArray; 281 jbyte* fPtr; 282 int fLen; 283 }; 284 285 void doThrowNPE(JNIEnv* env); 286 void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception 287 void doThrowIAE(JNIEnv* env, const char* msg = NULL); // Illegal Argument 288 void doThrowRE(JNIEnv* env, const char* msg = NULL); // Runtime 289 void doThrowISE(JNIEnv* env, const char* msg = NULL); // Illegal State 290 void doThrowOOME(JNIEnv* env, const char* msg = NULL); // Out of memory 291 void doThrowIOE(JNIEnv* env, const char* msg = NULL); // IO Exception 292 293 #define NPE_CHECK_RETURN_ZERO(env, object) \ 294 do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0) 295 296 #define NPE_CHECK_RETURN_VOID(env, object) \ 297 do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0) 298 299 #endif // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_ 300