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