• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
2 #define _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
3 
4 #include <cutils/compiler.h>
5 
6 #include "Bitmap.h"
7 #include "BRDAllocator.h"
8 #include "SkBitmap.h"
9 #include "SkCodec.h"
10 #include "SkPixelRef.h"
11 #include "SkMallocPixelRef.h"
12 #include "SkPoint.h"
13 #include "SkRect.h"
14 #include "SkColorSpace.h"
15 #include <hwui/Canvas.h>
16 #include <hwui/Bitmap.h>
17 
18 #include "graphics_jni_helpers.h"
19 
20 class SkCanvas;
21 struct SkFontMetrics;
22 
23 namespace android {
24 namespace skia {
25     class BitmapRegionDecoder;
26 }
27 class Canvas;
28 class Paint;
29 struct Typeface;
30 }
31 
32 class GraphicsJNI {
33 public:
34     // This enum must keep these int values, to match the int values
35     // in the java Bitmap.Config enum.
36     enum LegacyBitmapConfig {
37         kNo_LegacyBitmapConfig          = 0,
38         kA8_LegacyBitmapConfig          = 1,
39         kIndex8_LegacyBitmapConfig      = 2,
40         kRGB_565_LegacyBitmapConfig     = 3,
41         kARGB_4444_LegacyBitmapConfig   = 4,
42         kARGB_8888_LegacyBitmapConfig   = 5,
43         kRGBA_16F_LegacyBitmapConfig    = 6,
44         kHardware_LegacyBitmapConfig    = 7,
45 
46         kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
47     };
48 
49     static void setJavaVM(JavaVM* javaVM);
50 
51     /** returns a pointer to the JavaVM provided when we initialized the module */
getJavaVM()52     static JavaVM* getJavaVM() { return mJavaVM; }
53 
54     /** return a pointer to the JNIEnv for this thread */
55     static JNIEnv* getJNIEnv();
56 
57     /** create a JNIEnv* for this thread or assert if one already exists */
58     static JNIEnv* attachJNIEnv(const char* envName);
59 
60     /** detach the current thread from the JavaVM */
61     static void detachJNIEnv();
62 
63     // returns true if an exception is set (and dumps it out to the Log)
64     static bool hasException(JNIEnv*);
65 
66     static void get_jrect(JNIEnv*, jobject jrect, int* L, int* T, int* R, int* B);
67     static void set_jrect(JNIEnv*, jobject jrect, int L, int T, int R, int B);
68 
69     static SkIRect* jrect_to_irect(JNIEnv*, jobject jrect, SkIRect*);
70     static void irect_to_jrect(const SkIRect&, JNIEnv*, jobject jrect);
71 
72     static SkRect* jrectf_to_rect(JNIEnv*, jobject jrectf, SkRect*);
73     static SkRect* jrect_to_rect(JNIEnv*, jobject jrect, SkRect*);
74     static void rect_to_jrectf(const SkRect&, JNIEnv*, jobject jrectf);
75 
76     static void set_jpoint(JNIEnv*, jobject jrect, int x, int y);
77 
78     static SkIPoint* jpoint_to_ipoint(JNIEnv*, jobject jpoint, SkIPoint* point);
79     static void ipoint_to_jpoint(const SkIPoint& point, JNIEnv*, jobject jpoint);
80 
81     static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
82     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
83 
84     ANDROID_API static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
85     static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
86     static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes,
87                                      bool* isHardware);
88     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
89 
90     /**
91      * Set SkFontMetrics to Java Paint.FontMetrics.
92      * Do nothing if metrics is nullptr.
93      */
94     static void set_metrics(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
95     /**
96      * Set SkFontMetrics to Java Paint.FontMetricsInt and return recommended interline space.
97      * Do nothing if metrics is nullptr.
98      */
99     static int set_metrics_int(JNIEnv*, jobject metrics, const SkFontMetrics& skmetrics);
100 
101     /*
102      *  LegacyBitmapConfig is the old enum in Skia that matched the enum int values
103      *  in Bitmap.Config. Skia no longer supports this config, but has replaced it
104      *  with SkColorType. These routines convert between the two.
105      */
106     static SkColorType legacyBitmapConfigToColorType(jint legacyConfig);
107     static jint colorTypeToLegacyBitmapConfig(SkColorType colorType);
108 
109     /** Return the corresponding native colorType from the java Config enum,
110         or kUnknown_SkColorType if the java object is null.
111     */
112     static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
113     static AndroidBitmapFormat getFormatFromConfig(JNIEnv* env, jobject jconfig);
114     static jobject getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
115 
116     static bool isHardwareConfig(JNIEnv* env, jobject jconfig);
117     static jint hardwareLegacyBitmapConfig();
118 
119     static jobject createRegion(JNIEnv* env, SkRegion* region);
120 
121     static jobject createBitmapRegionDecoder(JNIEnv* env,
122                                              android::skia::BitmapRegionDecoder* bitmap);
123 
124     /**
125      * Given a bitmap we natively allocate a memory block to store the contents
126      * of that bitmap.  The memory is then attached to the bitmap via an
127      * SkPixelRef, which ensures that upon deletion the appropriate caches
128      * are notified.
129      */
130     static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap);
131 
132     /** Copy the colors in colors[] to the bitmap, convert to the correct
133         format along the way.
134         Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
135     */
136     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
137             int srcStride, int x, int y, int width, int height,
138             SkBitmap* dstBitmap);
139 
140     /**
141      * Convert the native SkColorSpace retrieved from ColorSpace.Rgb.getNativeInstance().
142      *
143      * This will never throw an Exception. If the ColorSpace is one that Skia cannot
144      * use, ColorSpace.Rgb.getNativeInstance() would have thrown an Exception. It may,
145      * however, be nullptr, which may be acceptable.
146      */
147     static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle);
148 
149     /**
150      * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace
151      * and decodeColorType.
152      *
153      * This may create a new object if none of the Named ColorSpaces match.
154      */
155     static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
156             SkColorType decodeColorType);
157 
158     /**
159      * Convert from a Java @ColorLong to an SkColor4f that Skia can use directly.
160      *
161      * This ignores the encoded ColorSpace, besides checking to see if it is sRGB,
162      * which is encoded differently. The color space should be passed down separately
163      * via ColorSpace#getNativeInstance(), and converted with getNativeColorSpace(),
164      * above.
165      */
166     static SkColor4f convertColorLong(jlong color);
167 
168 private:
169     /* JNI JavaVM pointer */
170     static JavaVM* mJavaVM;
171 };
172 
173 class HeapAllocator : public android::skia::BRDAllocator {
174 public:
HeapAllocator()175    HeapAllocator() { };
~HeapAllocator()176     ~HeapAllocator() { };
177 
178     virtual bool allocPixelRef(SkBitmap* bitmap) override;
179 
180     /**
181      * Fetches the backing allocation object. Must be called!
182      */
getStorageObjAndReset()183     android::Bitmap* getStorageObjAndReset() {
184         return mStorage.release();
185     };
186 
zeroInit()187     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
188 private:
189     sk_sp<android::Bitmap> mStorage;
190 };
191 
192 /**
193  *  Allocator to handle reusing bitmaps for BitmapRegionDecoder.
194  *
195  *  The BitmapRegionDecoder documentation states that, if it is
196  *  provided, the recycled bitmap will always be reused, clipping
197  *  the decoded output to fit in the recycled bitmap if necessary.
198  *  This allocator implements that behavior.
199  *
200  *  Skia's BitmapRegionDecoder expects the memory that
201  *  is allocated to be large enough to decode the entire region
202  *  that is requested.  It will decode directly into the memory
203  *  that is provided.
204  *
205  *  FIXME: BUG:25465958
206  *  If the recycled bitmap is not large enough for the decode
207  *  requested, meaning that a clip is required, we will allocate
208  *  enough memory for Skia to perform the decode, and then copy
209  *  from the decoded output into the recycled bitmap.
210  *
211  *  If the recycled bitmap is large enough for the decode requested,
212  *  we will provide that memory for Skia to decode directly into.
213  *
214  *  This allocator should only be used for a single allocation.
215  *  After we reuse the recycledBitmap once, it is dangerous to
216  *  reuse it again, given that it still may be in use from our
217  *  first allocation.
218  */
219 class RecyclingClippingPixelAllocator : public android::skia::BRDAllocator {
220 public:
221 
222     RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
223             size_t recycledBytes);
224 
225     ~RecyclingClippingPixelAllocator();
226 
227     virtual bool allocPixelRef(SkBitmap* bitmap) override;
228 
229     /**
230      *  Must be called!
231      *
232      *  In the event that the recycled bitmap is not large enough for
233      *  the allocation requested, we will allocate memory on the heap
234      *  instead.  As a final step, once we are done using this memory,
235      *  we will copy the contents of the heap memory into the recycled
236      *  bitmap's memory, clipping as necessary.
237      */
238     void copyIfNecessary();
239 
240     /**
241      *  Indicates that this allocator does not allocate zero initialized
242      *  memory.
243      */
zeroInit()244     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
245 
246 private:
247     android::Bitmap* mRecycledBitmap;
248     const size_t     mRecycledBytes;
249     SkBitmap*        mSkiaBitmap;
250     bool             mNeedsCopy;
251 };
252 
253 class AshmemPixelAllocator : public SkBitmap::Allocator {
254 public:
255     explicit AshmemPixelAllocator(JNIEnv* env);
~AshmemPixelAllocator()256     ~AshmemPixelAllocator() { };
257     virtual bool allocPixelRef(SkBitmap* bitmap);
getStorageObjAndReset()258     android::Bitmap* getStorageObjAndReset() {
259         return mStorage.release();
260     };
261 
262 private:
263     JavaVM* mJavaVM;
264     sk_sp<android::Bitmap> mStorage;
265 };
266 
267 
268 enum JNIAccess {
269     kRO_JNIAccess,
270     kRW_JNIAccess
271 };
272 
273 class AutoJavaFloatArray {
274 public:
275     AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
276                        int minLength = 0, JNIAccess = kRW_JNIAccess);
277     ~AutoJavaFloatArray();
278 
ptr()279     float* ptr() const { return fPtr; }
length()280     int    length() const { return fLen; }
281 
282 private:
283     JNIEnv*     fEnv;
284     jfloatArray fArray;
285     float*      fPtr;
286     int         fLen;
287     int         fReleaseMode;
288 };
289 
290 class AutoJavaIntArray {
291 public:
292     AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
293     ~AutoJavaIntArray();
294 
ptr()295     jint* ptr() const { return fPtr; }
length()296     int    length() const { return fLen; }
297 
298 private:
299     JNIEnv*     fEnv;
300     jintArray fArray;
301     jint*      fPtr;
302     int         fLen;
303 };
304 
305 class AutoJavaShortArray {
306 public:
307     AutoJavaShortArray(JNIEnv* env, jshortArray array,
308                        int minLength = 0, JNIAccess = kRW_JNIAccess);
309     ~AutoJavaShortArray();
310 
ptr()311     jshort* ptr() const { return fPtr; }
length()312     int    length() const { return fLen; }
313 
314 private:
315     JNIEnv*     fEnv;
316     jshortArray fArray;
317     jshort*      fPtr;
318     int         fLen;
319     int         fReleaseMode;
320 };
321 
322 class AutoJavaByteArray {
323 public:
324     AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
325     ~AutoJavaByteArray();
326 
ptr()327     jbyte* ptr() const { return fPtr; }
length()328     int    length() const { return fLen; }
329 
330 private:
331     JNIEnv*     fEnv;
332     jbyteArray fArray;
333     jbyte*      fPtr;
334     int         fLen;
335 };
336 
337 void doThrowNPE(JNIEnv* env);
338 void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
339 void doThrowIAE(JNIEnv* env, const char* msg = NULL);   // Illegal Argument
340 void doThrowRE(JNIEnv* env, const char* msg = NULL);   // Runtime
341 void doThrowISE(JNIEnv* env, const char* msg = NULL);   // Illegal State
342 void doThrowOOME(JNIEnv* env, const char* msg = NULL);   // Out of memory
343 void doThrowIOE(JNIEnv* env, const char* msg = NULL);   // IO Exception
344 
345 #define NPE_CHECK_RETURN_ZERO(env, object)    \
346     do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0)
347 
348 #define NPE_CHECK_RETURN_VOID(env, object)    \
349     do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
350 
351 #endif  // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
352