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
18class SkBitmapRegionDecoder;
19class SkCanvas;
20
21namespace android {
22class Paint;
23struct Typeface;
24}
25
26class GraphicsJNI {
27public:
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            SkColorTable* ctable, 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, SkColorTable* ctable);
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
125class HeapAllocator : public SkBRDAllocator {
126public:
127   HeapAllocator() { };
128    ~HeapAllocator() { };
129
130    virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) override;
131
132    /**
133     * Fetches the backing allocation object. Must be called!
134     */
135    android::Bitmap* getStorageObjAndReset() {
136        return mStorage.release();
137    };
138
139    SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
140private:
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 */
171class RecyclingClippingPixelAllocator : public SkBRDAllocator {
172public:
173
174    RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
175            size_t recycledBytes);
176
177    ~RecyclingClippingPixelAllocator();
178
179    virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) 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     */
196    SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
197
198private:
199    android::Bitmap* mRecycledBitmap;
200    const size_t     mRecycledBytes;
201    SkBitmap*        mSkiaBitmap;
202    bool             mNeedsCopy;
203};
204
205class AshmemPixelAllocator : public SkBitmap::Allocator {
206public:
207    explicit AshmemPixelAllocator(JNIEnv* env);
208    ~AshmemPixelAllocator() { };
209    virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
210    android::Bitmap* getStorageObjAndReset() {
211        return mStorage.release();
212    };
213
214private:
215    JavaVM* mJavaVM;
216    sk_sp<android::Bitmap> mStorage;
217};
218
219
220enum JNIAccess {
221    kRO_JNIAccess,
222    kRW_JNIAccess
223};
224
225class AutoJavaFloatArray {
226public:
227    AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
228                       int minLength = 0, JNIAccess = kRW_JNIAccess);
229    ~AutoJavaFloatArray();
230
231    float* ptr() const { return fPtr; }
232    int    length() const { return fLen; }
233
234private:
235    JNIEnv*     fEnv;
236    jfloatArray fArray;
237    float*      fPtr;
238    int         fLen;
239    int         fReleaseMode;
240};
241
242class AutoJavaIntArray {
243public:
244    AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
245    ~AutoJavaIntArray();
246
247    jint* ptr() const { return fPtr; }
248    int    length() const { return fLen; }
249
250private:
251    JNIEnv*     fEnv;
252    jintArray fArray;
253    jint*      fPtr;
254    int         fLen;
255};
256
257class AutoJavaShortArray {
258public:
259    AutoJavaShortArray(JNIEnv* env, jshortArray array,
260                       int minLength = 0, JNIAccess = kRW_JNIAccess);
261    ~AutoJavaShortArray();
262
263    jshort* ptr() const { return fPtr; }
264    int    length() const { return fLen; }
265
266private:
267    JNIEnv*     fEnv;
268    jshortArray fArray;
269    jshort*      fPtr;
270    int         fLen;
271    int         fReleaseMode;
272};
273
274class AutoJavaByteArray {
275public:
276    AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
277    ~AutoJavaByteArray();
278
279    jbyte* ptr() const { return fPtr; }
280    int    length() const { return fLen; }
281
282private:
283    JNIEnv*     fEnv;
284    jbyteArray fArray;
285    jbyte*      fPtr;
286    int         fLen;
287};
288
289void doThrowNPE(JNIEnv* env);
290void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
291void doThrowIAE(JNIEnv* env, const char* msg = NULL);   // Illegal Argument
292void doThrowRE(JNIEnv* env, const char* msg = NULL);   // Runtime
293void doThrowISE(JNIEnv* env, const char* msg = NULL);   // Illegal State
294void doThrowOOME(JNIEnv* env, const char* msg = NULL);   // Out of memory
295void 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