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 "SkMatrix44.h"
     14 #include <jni.h>
     15 #include <hwui/Canvas.h>
     16 #include <hwui/Bitmap.h>
     17 
     18 class SkBitmapRegionDecoder;
     19 class SkCanvas;
     20 
     21 namespace android {
     22 class Paint;
     23 struct Typeface;
     24 }
     25 
     26 class GraphicsJNI {
     27 public:
     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     /*
     70      *  LegacyBitmapConfig is the old enum in Skia that matched the enum int values
     71      *  in Bitmap.Config. Skia no longer supports this config, but has replaced it
     72      *  with SkColorType. These routines convert between the two.
     73      */
     74     static SkColorType legacyBitmapConfigToColorType(jint legacyConfig);
     75     static jint colorTypeToLegacyBitmapConfig(SkColorType colorType);
     76 
     77     /** Return the corresponding native colorType from the java Config enum,
     78         or kUnknown_SkColorType if the java object is null.
     79     */
     80     static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
     81 
     82     static bool isHardwareConfig(JNIEnv* env, jobject jconfig);
     83     static jint hardwareLegacyBitmapConfig();
     84 
     85     static jobject createRegion(JNIEnv* env, SkRegion* region);
     86 
     87     static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
     88 
     89     static android::Bitmap* mapAshmemBitmap(JNIEnv* env, SkBitmap* bitmap,
     90             int fd, void* addr, size_t size, bool readOnly);
     91 
     92     /**
     93      * Given a bitmap we natively allocate a memory block to store the contents
     94      * of that bitmap.  The memory is then attached to the bitmap via an
     95      * SkPixelRef, which ensures that upon deletion the appropriate caches
     96      * are notified.
     97      */
     98     static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap);
     99 
    100     /** Copy the colors in colors[] to the bitmap, convert to the correct
    101         format along the way.
    102         Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
    103     */
    104     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
    105             int srcStride, int x, int y, int width, int height,
    106             const SkBitmap& dstBitmap);
    107 
    108     static sk_sp<SkColorSpace> defaultColorSpace();
    109     static sk_sp<SkColorSpace> linearColorSpace();
    110     static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
    111     static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
    112 
    113     static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
    114     static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
    115     static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace);
    116 
    117     static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
    118             SkColorType decodeColorType);
    119 };
    120 
    121 class HeapAllocator : public SkBRDAllocator {
    122 public:
    123    HeapAllocator() { };
    124     ~HeapAllocator() { };
    125 
    126     virtual bool allocPixelRef(SkBitmap* bitmap) override;
    127 
    128     /**
    129      * Fetches the backing allocation object. Must be called!
    130      */
    131     android::Bitmap* getStorageObjAndReset() {
    132         return mStorage.release();
    133     };
    134 
    135     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
    136 private:
    137     sk_sp<android::Bitmap> mStorage;
    138 };
    139 
    140 /**
    141  *  Allocator to handle reusing bitmaps for BitmapRegionDecoder.
    142  *
    143  *  The BitmapRegionDecoder documentation states that, if it is
    144  *  provided, the recycled bitmap will always be reused, clipping
    145  *  the decoded output to fit in the recycled bitmap if necessary.
    146  *  This allocator implements that behavior.
    147  *
    148  *  Skia's SkBitmapRegionDecoder expects the memory that
    149  *  is allocated to be large enough to decode the entire region
    150  *  that is requested.  It will decode directly into the memory
    151  *  that is provided.
    152  *
    153  *  FIXME: BUG:25465958
    154  *  If the recycled bitmap is not large enough for the decode
    155  *  requested, meaning that a clip is required, we will allocate
    156  *  enough memory for Skia to perform the decode, and then copy
    157  *  from the decoded output into the recycled bitmap.
    158  *
    159  *  If the recycled bitmap is large enough for the decode requested,
    160  *  we will provide that memory for Skia to decode directly into.
    161  *
    162  *  This allocator should only be used for a single allocation.
    163  *  After we reuse the recycledBitmap once, it is dangerous to
    164  *  reuse it again, given that it still may be in use from our
    165  *  first allocation.
    166  */
    167 class RecyclingClippingPixelAllocator : public SkBRDAllocator {
    168 public:
    169 
    170     RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
    171             size_t recycledBytes);
    172 
    173     ~RecyclingClippingPixelAllocator();
    174 
    175     virtual bool allocPixelRef(SkBitmap* bitmap) override;
    176 
    177     /**
    178      *  Must be called!
    179      *
    180      *  In the event that the recycled bitmap is not large enough for
    181      *  the allocation requested, we will allocate memory on the heap
    182      *  instead.  As a final step, once we are done using this memory,
    183      *  we will copy the contents of the heap memory into the recycled
    184      *  bitmap's memory, clipping as necessary.
    185      */
    186     void copyIfNecessary();
    187 
    188     /**
    189      *  Indicates that this allocator does not allocate zero initialized
    190      *  memory.
    191      */
    192     SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
    193 
    194 private:
    195     android::Bitmap* mRecycledBitmap;
    196     const size_t     mRecycledBytes;
    197     SkBitmap*        mSkiaBitmap;
    198     bool             mNeedsCopy;
    199 };
    200 
    201 class AshmemPixelAllocator : public SkBitmap::Allocator {
    202 public:
    203     explicit AshmemPixelAllocator(JNIEnv* env);
    204     ~AshmemPixelAllocator() { };
    205     virtual bool allocPixelRef(SkBitmap* bitmap);
    206     android::Bitmap* getStorageObjAndReset() {
    207         return mStorage.release();
    208     };
    209 
    210 private:
    211     JavaVM* mJavaVM;
    212     sk_sp<android::Bitmap> mStorage;
    213 };
    214 
    215 
    216 enum JNIAccess {
    217     kRO_JNIAccess,
    218     kRW_JNIAccess
    219 };
    220 
    221 class AutoJavaFloatArray {
    222 public:
    223     AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
    224                        int minLength = 0, JNIAccess = kRW_JNIAccess);
    225     ~AutoJavaFloatArray();
    226 
    227     float* ptr() const { return fPtr; }
    228     int    length() const { return fLen; }
    229 
    230 private:
    231     JNIEnv*     fEnv;
    232     jfloatArray fArray;
    233     float*      fPtr;
    234     int         fLen;
    235     int         fReleaseMode;
    236 };
    237 
    238 class AutoJavaIntArray {
    239 public:
    240     AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
    241     ~AutoJavaIntArray();
    242 
    243     jint* ptr() const { return fPtr; }
    244     int    length() const { return fLen; }
    245 
    246 private:
    247     JNIEnv*     fEnv;
    248     jintArray fArray;
    249     jint*      fPtr;
    250     int         fLen;
    251 };
    252 
    253 class AutoJavaShortArray {
    254 public:
    255     AutoJavaShortArray(JNIEnv* env, jshortArray array,
    256                        int minLength = 0, JNIAccess = kRW_JNIAccess);
    257     ~AutoJavaShortArray();
    258 
    259     jshort* ptr() const { return fPtr; }
    260     int    length() const { return fLen; }
    261 
    262 private:
    263     JNIEnv*     fEnv;
    264     jshortArray fArray;
    265     jshort*      fPtr;
    266     int         fLen;
    267     int         fReleaseMode;
    268 };
    269 
    270 class AutoJavaByteArray {
    271 public:
    272     AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
    273     ~AutoJavaByteArray();
    274 
    275     jbyte* ptr() const { return fPtr; }
    276     int    length() const { return fLen; }
    277 
    278 private:
    279     JNIEnv*     fEnv;
    280     jbyteArray fArray;
    281     jbyte*      fPtr;
    282     int         fLen;
    283 };
    284 
    285 void doThrowNPE(JNIEnv* env);
    286 void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
    287 void doThrowIAE(JNIEnv* env, const char* msg = NULL);   // Illegal Argument
    288 void doThrowRE(JNIEnv* env, const char* msg = NULL);   // Runtime
    289 void doThrowISE(JNIEnv* env, const char* msg = NULL);   // Illegal State
    290 void doThrowOOME(JNIEnv* env, const char* msg = NULL);   // Out of memory
    291 void doThrowIOE(JNIEnv* env, const char* msg = NULL);   // IO Exception
    292 
    293 #define NPE_CHECK_RETURN_ZERO(env, object)    \
    294     do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0)
    295 
    296 #define NPE_CHECK_RETURN_VOID(env, object)    \
    297     do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
    298 
    299 #endif  // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
    300