Home | History | Annotate | Download | only in graphics
      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      */
    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      */
    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      */
    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);
    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 
    244     float* ptr() const { return fPtr; }
    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 
    260     jint* ptr() const { return fPtr; }
    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 
    276     jshort* ptr() const { return fPtr; }
    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 
    292     jbyte* ptr() const { return fPtr; }
    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