• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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