summaryrefslogtreecommitdiff
path: root/libs/hwui/jni/GraphicsJNI.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui/jni/GraphicsJNI.h')
-rw-r--r--libs/hwui/jni/GraphicsJNI.h335
1 files changed, 335 insertions, 0 deletions
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
new file mode 100644
index 000000000000..b58a740a4c27
--- /dev/null
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -0,0 +1,335 @@
+#ifndef _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
+#define _ANDROID_GRAPHICS_GRAPHICS_JNI_H_
+
+#include <cutils/compiler.h>
+
+#include "Bitmap.h"
+#include "SkBitmap.h"
+#include "SkBRDAllocator.h"
+#include "SkCodec.h"
+#include "SkPixelRef.h"
+#include "SkMallocPixelRef.h"
+#include "SkPoint.h"
+#include "SkRect.h"
+#include "SkColorSpace.h"
+#include <hwui/Canvas.h>
+#include <hwui/Bitmap.h>
+
+#include "graphics_jni_helpers.h"
+
+class SkBitmapRegionDecoder;
+class SkCanvas;
+
+namespace android {
+class Paint;
+struct Typeface;
+}
+
+class GraphicsJNI {
+public:
+ // This enum must keep these int values, to match the int values
+ // in the java Bitmap.Config enum.
+ enum LegacyBitmapConfig {
+ kNo_LegacyBitmapConfig = 0,
+ kA8_LegacyBitmapConfig = 1,
+ kIndex8_LegacyBitmapConfig = 2,
+ kRGB_565_LegacyBitmapConfig = 3,
+ kARGB_4444_LegacyBitmapConfig = 4,
+ kARGB_8888_LegacyBitmapConfig = 5,
+ kRGBA_16F_LegacyBitmapConfig = 6,
+ kHardware_LegacyBitmapConfig = 7,
+
+ kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
+ };
+
+ static void setJavaVM(JavaVM* javaVM);
+
+ /** returns a pointer to the JavaVM provided when we initialized the module */
+ static JavaVM* getJavaVM() { return mJavaVM; }
+
+ /** return a pointer to the JNIEnv for this thread */
+ static JNIEnv* getJNIEnv();
+
+ /** create a JNIEnv* for this thread or assert if one already exists */
+ static JNIEnv* attachJNIEnv(const char* envName);
+
+ /** detach the current thread from the JavaVM */
+ static void detachJNIEnv();
+
+ // returns true if an exception is set (and dumps it out to the Log)
+ static bool hasException(JNIEnv*);
+
+ static void get_jrect(JNIEnv*, jobject jrect, int* L, int* T, int* R, int* B);
+ static void set_jrect(JNIEnv*, jobject jrect, int L, int T, int R, int B);
+
+ static SkIRect* jrect_to_irect(JNIEnv*, jobject jrect, SkIRect*);
+ static void irect_to_jrect(const SkIRect&, JNIEnv*, jobject jrect);
+
+ static SkRect* jrectf_to_rect(JNIEnv*, jobject jrectf, SkRect*);
+ static SkRect* jrect_to_rect(JNIEnv*, jobject jrect, SkRect*);
+ static void rect_to_jrectf(const SkRect&, JNIEnv*, jobject jrectf);
+
+ static void set_jpoint(JNIEnv*, jobject jrect, int x, int y);
+
+ static SkIPoint* jpoint_to_ipoint(JNIEnv*, jobject jpoint, SkIPoint* point);
+ static void ipoint_to_jpoint(const SkIPoint& point, JNIEnv*, jobject jpoint);
+
+ static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
+ static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
+
+ ANDROID_API static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
+ static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
+ static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes,
+ bool* isHardware);
+ static SkRegion* getNativeRegion(JNIEnv*, jobject region);
+
+ /*
+ * LegacyBitmapConfig is the old enum in Skia that matched the enum int values
+ * in Bitmap.Config. Skia no longer supports this config, but has replaced it
+ * with SkColorType. These routines convert between the two.
+ */
+ static SkColorType legacyBitmapConfigToColorType(jint legacyConfig);
+ static jint colorTypeToLegacyBitmapConfig(SkColorType colorType);
+
+ /** Return the corresponding native colorType from the java Config enum,
+ or kUnknown_SkColorType if the java object is null.
+ */
+ static SkColorType getNativeBitmapColorType(JNIEnv*, jobject jconfig);
+ static AndroidBitmapFormat getFormatFromConfig(JNIEnv* env, jobject jconfig);
+ static jobject getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
+
+ static bool isHardwareConfig(JNIEnv* env, jobject jconfig);
+ static jint hardwareLegacyBitmapConfig();
+
+ static jobject createRegion(JNIEnv* env, SkRegion* region);
+
+ static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
+
+ /**
+ * Given a bitmap we natively allocate a memory block to store the contents
+ * of that bitmap. The memory is then attached to the bitmap via an
+ * SkPixelRef, which ensures that upon deletion the appropriate caches
+ * are notified.
+ */
+ static bool allocatePixels(JNIEnv* env, SkBitmap* bitmap);
+
+ /** Copy the colors in colors[] to the bitmap, convert to the correct
+ format along the way.
+ Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
+ */
+ static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
+ int srcStride, int x, int y, int width, int height,
+ SkBitmap* dstBitmap);
+
+ /**
+ * Convert the native SkColorSpace retrieved from ColorSpace.Rgb.getNativeInstance().
+ *
+ * This will never throw an Exception. If the ColorSpace is one that Skia cannot
+ * use, ColorSpace.Rgb.getNativeInstance() would have thrown an Exception. It may,
+ * however, be nullptr, which may be acceptable.
+ */
+ static sk_sp<SkColorSpace> getNativeColorSpace(jlong colorSpaceHandle);
+
+ /**
+ * Return the android.graphics.ColorSpace Java object that corresponds to decodeColorSpace
+ * and decodeColorType.
+ *
+ * This may create a new object if none of the Named ColorSpaces match.
+ */
+ static jobject getColorSpace(JNIEnv* env, SkColorSpace* decodeColorSpace,
+ SkColorType decodeColorType);
+
+ /**
+ * Convert from a Java @ColorLong to an SkColor4f that Skia can use directly.
+ *
+ * This ignores the encoded ColorSpace, besides checking to see if it is sRGB,
+ * which is encoded differently. The color space should be passed down separately
+ * via ColorSpace#getNativeInstance(), and converted with getNativeColorSpace(),
+ * above.
+ */
+ static SkColor4f convertColorLong(jlong color);
+
+private:
+ /* JNI JavaVM pointer */
+ static JavaVM* mJavaVM;
+};
+
+class HeapAllocator : public SkBRDAllocator {
+public:
+ HeapAllocator() { };
+ ~HeapAllocator() { };
+
+ virtual bool allocPixelRef(SkBitmap* bitmap) override;
+
+ /**
+ * Fetches the backing allocation object. Must be called!
+ */
+ android::Bitmap* getStorageObjAndReset() {
+ return mStorage.release();
+ };
+
+ SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kYes_ZeroInitialized; }
+private:
+ sk_sp<android::Bitmap> mStorage;
+};
+
+/**
+ * Allocator to handle reusing bitmaps for BitmapRegionDecoder.
+ *
+ * The BitmapRegionDecoder documentation states that, if it is
+ * provided, the recycled bitmap will always be reused, clipping
+ * the decoded output to fit in the recycled bitmap if necessary.
+ * This allocator implements that behavior.
+ *
+ * Skia's SkBitmapRegionDecoder expects the memory that
+ * is allocated to be large enough to decode the entire region
+ * that is requested. It will decode directly into the memory
+ * that is provided.
+ *
+ * FIXME: BUG:25465958
+ * If the recycled bitmap is not large enough for the decode
+ * requested, meaning that a clip is required, we will allocate
+ * enough memory for Skia to perform the decode, and then copy
+ * from the decoded output into the recycled bitmap.
+ *
+ * If the recycled bitmap is large enough for the decode requested,
+ * we will provide that memory for Skia to decode directly into.
+ *
+ * This allocator should only be used for a single allocation.
+ * After we reuse the recycledBitmap once, it is dangerous to
+ * reuse it again, given that it still may be in use from our
+ * first allocation.
+ */
+class RecyclingClippingPixelAllocator : public SkBRDAllocator {
+public:
+
+ RecyclingClippingPixelAllocator(android::Bitmap* recycledBitmap,
+ size_t recycledBytes);
+
+ ~RecyclingClippingPixelAllocator();
+
+ virtual bool allocPixelRef(SkBitmap* bitmap) override;
+
+ /**
+ * Must be called!
+ *
+ * In the event that the recycled bitmap is not large enough for
+ * the allocation requested, we will allocate memory on the heap
+ * instead. As a final step, once we are done using this memory,
+ * we will copy the contents of the heap memory into the recycled
+ * bitmap's memory, clipping as necessary.
+ */
+ void copyIfNecessary();
+
+ /**
+ * Indicates that this allocator does not allocate zero initialized
+ * memory.
+ */
+ SkCodec::ZeroInitialized zeroInit() const override { return SkCodec::kNo_ZeroInitialized; }
+
+private:
+ android::Bitmap* mRecycledBitmap;
+ const size_t mRecycledBytes;
+ SkBitmap* mSkiaBitmap;
+ bool mNeedsCopy;
+};
+
+class AshmemPixelAllocator : public SkBitmap::Allocator {
+public:
+ explicit AshmemPixelAllocator(JNIEnv* env);
+ ~AshmemPixelAllocator() { };
+ virtual bool allocPixelRef(SkBitmap* bitmap);
+ android::Bitmap* getStorageObjAndReset() {
+ return mStorage.release();
+ };
+
+private:
+ JavaVM* mJavaVM;
+ sk_sp<android::Bitmap> mStorage;
+};
+
+
+enum JNIAccess {
+ kRO_JNIAccess,
+ kRW_JNIAccess
+};
+
+class AutoJavaFloatArray {
+public:
+ AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
+ int minLength = 0, JNIAccess = kRW_JNIAccess);
+ ~AutoJavaFloatArray();
+
+ float* ptr() const { return fPtr; }
+ int length() const { return fLen; }
+
+private:
+ JNIEnv* fEnv;
+ jfloatArray fArray;
+ float* fPtr;
+ int fLen;
+ int fReleaseMode;
+};
+
+class AutoJavaIntArray {
+public:
+ AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
+ ~AutoJavaIntArray();
+
+ jint* ptr() const { return fPtr; }
+ int length() const { return fLen; }
+
+private:
+ JNIEnv* fEnv;
+ jintArray fArray;
+ jint* fPtr;
+ int fLen;
+};
+
+class AutoJavaShortArray {
+public:
+ AutoJavaShortArray(JNIEnv* env, jshortArray array,
+ int minLength = 0, JNIAccess = kRW_JNIAccess);
+ ~AutoJavaShortArray();
+
+ jshort* ptr() const { return fPtr; }
+ int length() const { return fLen; }
+
+private:
+ JNIEnv* fEnv;
+ jshortArray fArray;
+ jshort* fPtr;
+ int fLen;
+ int fReleaseMode;
+};
+
+class AutoJavaByteArray {
+public:
+ AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
+ ~AutoJavaByteArray();
+
+ jbyte* ptr() const { return fPtr; }
+ int length() const { return fLen; }
+
+private:
+ JNIEnv* fEnv;
+ jbyteArray fArray;
+ jbyte* fPtr;
+ int fLen;
+};
+
+void doThrowNPE(JNIEnv* env);
+void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
+void doThrowIAE(JNIEnv* env, const char* msg = NULL); // Illegal Argument
+void doThrowRE(JNIEnv* env, const char* msg = NULL); // Runtime
+void doThrowISE(JNIEnv* env, const char* msg = NULL); // Illegal State
+void doThrowOOME(JNIEnv* env, const char* msg = NULL); // Out of memory
+void doThrowIOE(JNIEnv* env, const char* msg = NULL); // IO Exception
+
+#define NPE_CHECK_RETURN_ZERO(env, object) \
+ do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0)
+
+#define NPE_CHECK_RETURN_VOID(env, object) \
+ do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
+
+#endif // _ANDROID_GRAPHICS_GRAPHICS_JNI_H_