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