• 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 "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             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);
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:
HeapAllocator()127    HeapAllocator() { };
~HeapAllocator()128     ~HeapAllocator() { };
129 
130     virtual bool allocPixelRef(SkBitmap* bitmap) override;
131 
132     /**
133      * Fetches the backing allocation object. Must be called!
134      */
getStorageObjAndReset()135     android::Bitmap* getStorageObjAndReset() {
136         return mStorage.release();
137     };
138 
zeroInit()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) 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      */
zeroInit()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);
~AshmemPixelAllocator()208     ~AshmemPixelAllocator() { };
209     virtual bool allocPixelRef(SkBitmap* bitmap);
getStorageObjAndReset()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 
ptr()231     float* ptr() const { return fPtr; }
length()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 
ptr()247     jint* ptr() const { return fPtr; }
length()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 
ptr()263     jshort* ptr() const { return fPtr; }
length()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 
ptr()279     jbyte* ptr() const { return fPtr; }
length()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