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