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