diff options
author | Derek Sollenberger <djsollen@google.com> | 2019-08-14 15:50:59 -0400 |
---|---|---|
committer | Derek Sollenberger <djsollen@google.com> | 2019-09-10 14:50:02 -0400 |
commit | 9ca5bbe39f54547dbe585c39459208719a9728b4 (patch) | |
tree | 945a0e0a7e58c128d31619e5034a9e104ca06766 | |
parent | 00f6e5d22db205765eeadbe6500f3f5500fb3d6a (diff) |
Create C API for accessing android.graphics.Bitmap in native code.
Restrict access to SkBitmap for libandroid_runtime.so to be only within
the boundaries of the graphics module.
Test: CtsUiRenderingTestCases
Bug: 137655431
Change-Id: I4d0ea227e91d22068966513c4e3a55021b9e924f
23 files changed, 646 insertions, 227 deletions
diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 7779f55518f0..d6448da13c39 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -58,6 +58,8 @@ cc_library_shared { whole_static_libs: ["libandroid_graphics"], + export_static_lib_headers: ["libandroid_graphics"], + shared_libs: [ "libbase", "libcutils", @@ -340,7 +342,9 @@ cc_library_static { cppflags: ["-Wno-conversion-null"], srcs: [ + "android/graphics/apex/android_bitmap.cpp", "android/graphics/apex/android_region.cpp", + "android/graphics/apex/android_paint.cpp", "android_graphics_Canvas.cpp", "android_graphics_ColorSpace.cpp", @@ -393,7 +397,6 @@ cc_library_static { ], export_include_dirs: [ - ".", "android/graphics/apex/include", ], diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h index 06e31a1518ca..59adbb207a0c 100644 --- a/core/jni/android/graphics/Bitmap.h +++ b/core/jni/android/graphics/Bitmap.h @@ -39,8 +39,6 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap, jobject ninePatchInsets = nullptr, int density = -1); -void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap); - Bitmap& toBitmap(JNIEnv* env, jobject bitmap); Bitmap& toBitmap(jlong bitmapHandle); diff --git a/core/jni/android/graphics/apex/TypeCast.h b/core/jni/android/graphics/apex/TypeCast.h new file mode 100644 index 000000000000..96721d007951 --- /dev/null +++ b/core/jni/android/graphics/apex/TypeCast.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_GRAPHICS_TYPECAST_H +#define ANDROID_GRAPHICS_TYPECAST_H + +struct ABitmap; +struct ACanvas; +struct APaint; + +namespace android { + + class Bitmap; + class Canvas; + class Paint; + + class TypeCast { + public: + static inline Bitmap& toBitmapRef(const ABitmap* bitmap) { + return const_cast<Bitmap&>(reinterpret_cast<const Bitmap&>(*bitmap)); + } + + static inline Bitmap* toBitmap(ABitmap* bitmap) { + return reinterpret_cast<Bitmap*>(bitmap); + } + + static inline ABitmap* toABitmap(Bitmap* bitmap) { + return reinterpret_cast<ABitmap*>(bitmap); + } + + static inline Canvas* toCanvas(ACanvas* canvas) { + return reinterpret_cast<Canvas*>(canvas); + } + + static inline ACanvas* toACanvas(Canvas* canvas) { + return reinterpret_cast<ACanvas *>(canvas); + } + + static inline const Paint& toPaintRef(const APaint* paint) { + return reinterpret_cast<const Paint&>(*paint); + } + + static inline const Paint* toPaint(const APaint* paint) { + return reinterpret_cast<const Paint*>(paint); + } + + static inline Paint* toPaint(APaint* paint) { + return reinterpret_cast<Paint*>(paint); + } + + static inline APaint* toAPaint(Paint* paint) { + return reinterpret_cast<APaint*>(paint); + } + }; +}; // namespace android + +#endif // ANDROID_GRAPHICS_TYPECAST_H diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp new file mode 100644 index 000000000000..96cc5db8a5a4 --- /dev/null +++ b/core/jni/android/graphics/apex/android_bitmap.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android/graphics/bitmap.h" +#include "Bitmap.h" +#include "TypeCast.h" + +#include <hwui/Bitmap.h> + +using namespace android; + +ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj) { + Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapObj); + bitmap.ref(); + return TypeCast::toABitmap(&bitmap); +} + +void ABitmap_acquireRef(ABitmap* bitmap) { + SkSafeRef(TypeCast::toBitmap(bitmap)); +} + +void ABitmap_releaseRef(ABitmap* bitmap) { + SkSafeUnref(TypeCast::toBitmap(bitmap)); +} + +static AndroidBitmapFormat getFormat(Bitmap* bitmap) { + switch (bitmap->colorType()) { + case kN32_SkColorType: + return ANDROID_BITMAP_FORMAT_RGBA_8888; + case kRGB_565_SkColorType: + return ANDROID_BITMAP_FORMAT_RGB_565; + case kARGB_4444_SkColorType: + return ANDROID_BITMAP_FORMAT_RGBA_4444; + case kAlpha_8_SkColorType: + return ANDROID_BITMAP_FORMAT_A_8; + case kRGBA_F16_SkColorType: + return ANDROID_BITMAP_FORMAT_RGBA_F16; + default: + return ANDROID_BITMAP_FORMAT_NONE; + } +} + +static SkColorType getColorType(AndroidBitmapFormat format) { + switch (format) { + case ANDROID_BITMAP_FORMAT_RGBA_8888: + return kN32_SkColorType; + case ANDROID_BITMAP_FORMAT_RGB_565: + return kRGB_565_SkColorType; + case ANDROID_BITMAP_FORMAT_RGBA_4444: + return kARGB_4444_SkColorType; + case ANDROID_BITMAP_FORMAT_A_8: + return kAlpha_8_SkColorType; + case ANDROID_BITMAP_FORMAT_RGBA_F16: + return kRGBA_F16_SkColorType; + default: + return kUnknown_SkColorType; + } +} + +ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) { + SkColorType dstColorType = getColorType(dstFormat); + if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) { + SkBitmap srcBitmap; + TypeCast::toBitmap(srcBitmapHandle)->getSkBitmap(&srcBitmap); + + sk_sp<Bitmap> dstBitmap = + Bitmap::allocateHeapBitmap(srcBitmap.info().makeColorType(dstColorType)); + if (dstBitmap && srcBitmap.readPixels(dstBitmap->info(), dstBitmap->pixels(), + dstBitmap->rowBytes(), 0, 0)) { + return TypeCast::toABitmap(dstBitmap.release()); + } + } + return nullptr; +} + +AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) { + Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); + + AndroidBitmapInfo info; + info.width = bitmap->width(); + info.height = bitmap->height(); + info.stride = bitmap->rowBytes(); + info.format = getFormat(bitmap); + return info; +} + +void* ABitmap_getPixels(ABitmap* bitmapHandle) { + Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); + if (bitmap->isHardware()) { + return nullptr; + } + return bitmap->pixels(); +} diff --git a/core/jni/android/graphics/apex/android_canvas.cpp b/core/jni/android/graphics/apex/android_canvas.cpp index 7a4495f4f259..527a745426e3 100644 --- a/core/jni/android/graphics/apex/android_canvas.cpp +++ b/core/jni/android/graphics/apex/android_canvas.cpp @@ -16,6 +16,7 @@ #include "android/graphics/canvas.h" +#include "TypeCast.h" #include "GraphicsJNI.h" #include <hwui/Canvas.h> @@ -25,14 +26,6 @@ using namespace android; -static inline Canvas* toCanvas(ACanvas* aCanvas) { - return reinterpret_cast<Canvas*>(aCanvas); -} - -static inline ACanvas* toACanvas(Canvas* canvas) { - return reinterpret_cast<ACanvas*>(canvas); -} - bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) { ANativeWindow_Buffer buffer { 0, 0, 0, bufferFormat, nullptr, {0} }; const SkColorType colorType = uirenderer::ANativeWindowToImageInfo(buffer, nullptr).colorType(); @@ -40,11 +33,11 @@ bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) { } ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvasObj) { - return toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj)); + return TypeCast::toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj)); } -void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, - int32_t /*android_dataspace_t*/ dataspace) { +static SkBitmap convert(const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace) { SkBitmap bitmap; if (buffer != nullptr && buffer->width > 0 && buffer->height > 0) { sk_sp<SkColorSpace> cs(uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace)); @@ -53,18 +46,44 @@ void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, bitmap.setInfo(imageInfo, rowBytes); bitmap.setPixels(buffer->bits); } + return bitmap; +} - toCanvas(canvas)->setBitmap(bitmap); +ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace) { + return TypeCast::toACanvas(Canvas::create_canvas(convert(buffer, dataspace))); } -void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) { +void ACanvas_destroyCanvas(ACanvas* canvas) { + delete TypeCast::toCanvas(canvas); +} + +void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace) { + + + TypeCast::toCanvas(canvas)->setBitmap(convert(buffer, dataspace)); +} + +void ACanvas_clipRect(ACanvas* canvas, const ARect* clipRect, bool /*doAA*/) { //TODO update Canvas to take antialias param - toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, - SkClipOp::kIntersect); + TypeCast::toCanvas(canvas)->clipRect(clipRect->left, clipRect->top, clipRect->right, + clipRect->bottom, SkClipOp::kIntersect); } -void ACanvas_clipOutRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) { +void ACanvas_clipOutRect(ACanvas* canvas, const ARect* clipRect, bool /*doAA*/) { //TODO update Canvas to take antialias param - toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom, - SkClipOp::kDifference); + TypeCast::toCanvas(canvas)->clipRect(clipRect->left, clipRect->top, clipRect->right, + clipRect->bottom, SkClipOp::kDifference); +} + +void ACanvas_drawRect(ACanvas* canvas, const ARect* rect, const APaint* paint) { + TypeCast::toCanvas(canvas)->drawRect(rect->left, rect->top, rect->right, rect->bottom, + TypeCast::toPaintRef(paint)); +} + +void ACanvas_drawBitmap(ACanvas* canvas, const ABitmap* bitmap, float left, float top, + const APaint* paint) { + TypeCast::toCanvas(canvas)->drawBitmap(TypeCast::toBitmapRef(bitmap), left, top, + TypeCast::toPaint(paint)); } diff --git a/core/jni/android/graphics/apex/android_paint.cpp b/core/jni/android/graphics/apex/android_paint.cpp new file mode 100644 index 000000000000..70bd085343ce --- /dev/null +++ b/core/jni/android/graphics/apex/android_paint.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "android/graphics/paint.h" + +#include "TypeCast.h" + +#include <hwui/Paint.h> + +using namespace android; + + +APaint* APaint_createPaint() { + return TypeCast::toAPaint(new Paint()); +} + +void APaint_destroyPaint(APaint* paint) { + delete TypeCast::toPaint(paint); +} + +static SkBlendMode convertBlendMode(ABlendMode blendMode) { + switch (blendMode) { + case ABLEND_MODE_CLEAR: + return SkBlendMode::kClear; + case ABLEND_MODE_SRC_OVER: + return SkBlendMode::kSrcOver; + case ABLEND_MODE_SRC: + return SkBlendMode::kSrc; + } +} + +void APaint_setBlendMode(APaint* paint, ABlendMode blendMode) { + TypeCast::toPaint(paint)->setBlendMode(convertBlendMode(blendMode)); +} diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h new file mode 100644 index 000000000000..bfa4c8df407f --- /dev/null +++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_GRAPHICS_BITMAP_H +#define ANDROID_GRAPHICS_BITMAP_H + +#include <android/bitmap.h> +#include <jni.h> +#include <sys/cdefs.h> + +__BEGIN_DECLS + +/** + * Opaque handle for a native graphics bitmap. + */ +typedef struct ABitmap ABitmap; + +ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj); + +ABitmap* ABitmap_copy(ABitmap* srcBitmap, AndroidBitmapFormat dstFormat); + +void ABitmap_acquireRef(ABitmap* bitmap); +void ABitmap_releaseRef(ABitmap* bitmap); + +AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap); + +void* ABitmap_getPixels(ABitmap* bitmap); + +__END_DECLS + +#ifdef __cplusplus +namespace android { +namespace graphics { + class Bitmap { + public: + Bitmap() : mBitmap(nullptr) {} + Bitmap(JNIEnv* env, jobject bitmapObj) : + mBitmap(ABitmap_acquireBitmapFromJava(env, bitmapObj)) {} + Bitmap(const Bitmap& src) : mBitmap(src.mBitmap) { ABitmap_acquireRef(src.mBitmap); } + ~Bitmap() { ABitmap_releaseRef(mBitmap); } + + // copy operator + Bitmap& operator=(const Bitmap& other) { + if (&other != this) { + ABitmap_releaseRef(mBitmap); + mBitmap = other.mBitmap; + ABitmap_acquireRef(mBitmap); + } + return *this; + } + + // move operator + Bitmap& operator=(Bitmap&& other) { + if (&other != this) { + ABitmap_releaseRef(mBitmap); + mBitmap = other.mBitmap; + other.mBitmap = nullptr; + } + return *this; + } + + Bitmap copy(AndroidBitmapFormat dstFormat) const { + return Bitmap(ABitmap_copy(mBitmap, dstFormat)); + } + + bool isValid() const { return mBitmap != nullptr; } + bool isEmpty() const { + AndroidBitmapInfo info = getInfo(); + return info.width <= 0 || info.height <= 0; + } + void reset() { + ABitmap_releaseRef(mBitmap); + mBitmap = nullptr; + } + + const ABitmap* get() const { return mBitmap; } + + AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); } + void* getPixels() const { return ABitmap_getPixels(mBitmap); } + private: + // takes ownership of the provided ABitmap + Bitmap(ABitmap* bitmap) : mBitmap(bitmap) {} + + ABitmap* mBitmap; + }; +}; // namespace graphics +}; // namespace android +#endif // __cplusplus + +#endif // ANDROID_GRAPHICS_BITMAP_H
\ No newline at end of file diff --git a/core/jni/android/graphics/apex/include/android/graphics/canvas.h b/core/jni/android/graphics/apex/include/android/graphics/canvas.h index c35a7d69b836..190aba4565f8 100644 --- a/core/jni/android/graphics/apex/include/android/graphics/canvas.h +++ b/core/jni/android/graphics/apex/include/android/graphics/canvas.h @@ -16,6 +16,8 @@ #ifndef ANDROID_GRAPHICS_CANVAS_H #define ANDROID_GRAPHICS_CANVAS_H +#include <android/graphics/bitmap.h> +#include <android/graphics/paint.h> #include <android/native_window.h> #include <android/rect.h> #include <jni.h> @@ -23,8 +25,8 @@ __BEGIN_DECLS /** -* Opaque handle for a native graphics canvas. -*/ + * Opaque handle for a native graphics canvas. + */ typedef struct ACanvas ACanvas; // One of AHardwareBuffer_Format. @@ -33,34 +35,104 @@ bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat); /** * Returns a native handle to a Java android.graphics.Canvas * - * @param env - * @param canvas * @return ACanvas* that is only valid for the life of the jobject. */ ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvas); /** + * Creates a canvas that wraps the buffer + * + * @param buffer required + */ +ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace); + +void ACanvas_destroyCanvas(ACanvas* canvas); + +/** * Updates the canvas to render into the pixels in the provided buffer * - * @param canvas * @param buffer The buffer that will provide the backing store for this canvas. The buffer must * remain valid until the this method is called again with either another active * buffer or nullptr. If nullptr is given the canvas will release the previous buffer * and set an empty backing store. - * @param dataspace */ void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer, int32_t /*android_dataspace_t*/ dataspace); /** * Clips operations on the canvas to the intersection of the current clip and the provided clipRect. + * + * @param clipRect required */ -void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool doAntiAlias = false); +void ACanvas_clipRect(ACanvas* canvas, const ARect* clipRect, bool doAntiAlias = false); /** * Clips operations on the canvas to the difference of the current clip and the provided clipRect. + * + * @param clipRect required + */ +void ACanvas_clipOutRect(ACanvas* canvas, const ARect* clipRect, bool doAntiAlias = false); + +/** + * + * @param rect required + * @param paint required + */ +void ACanvas_drawRect(ACanvas* canvas, const ARect* rect, const APaint* paint); + +/** + * + * @param bitmap required + * @param left + * @param top + * @param paint */ -void ACanvas_clipOutRect(ACanvas* canvas, const ARect& clipRect, bool doAntiAlias = false); +void ACanvas_drawBitmap(ACanvas* canvas, const ABitmap* bitmap, float left, float top, + const APaint* paint); __END_DECLS + +#ifdef __cplusplus +namespace android { +namespace graphics { + class Canvas { + public: + Canvas(JNIEnv* env, jobject canvasObj) : + mCanvas(ACanvas_getNativeHandleFromJava(env, canvasObj)), + mOwnedPtr(false) {} + Canvas(const ANativeWindow_Buffer& buffer, int32_t /*android_dataspace_t*/ dataspace) : + mCanvas(ACanvas_createCanvas(&buffer, dataspace)), + mOwnedPtr(true) {} + ~Canvas() { + if (mOwnedPtr) { + ACanvas_destroyCanvas(mCanvas); + } + } + + void setBuffer(const ANativeWindow_Buffer* buffer, + int32_t /*android_dataspace_t*/ dataspace) { + ACanvas_setBuffer(mCanvas, buffer, dataspace); + } + + void clipRect(const ARect& clipRect, bool doAntiAlias = false) { + ACanvas_clipRect(mCanvas, &clipRect, doAntiAlias); + } + + void drawRect(const ARect& rect, const Paint& paint) { + ACanvas_drawRect(mCanvas, &rect, &paint.get()); + } + void drawBitmap(const Bitmap& bitmap, float left, float top, const Paint* paint) { + const APaint* aPaint = (paint) ? &paint->get() : nullptr; + ACanvas_drawBitmap(mCanvas, bitmap.get(), left, top, aPaint); + } + + private: + ACanvas* mCanvas; + const bool mOwnedPtr; + }; +}; // namespace graphics +}; // namespace android +#endif // __cplusplus + #endif // ANDROID_GRAPHICS_CANVAS_H
\ No newline at end of file diff --git a/core/jni/android/graphics/apex/include/android/graphics/paint.h b/core/jni/android/graphics/apex/include/android/graphics/paint.h new file mode 100644 index 000000000000..5895e006bf93 --- /dev/null +++ b/core/jni/android/graphics/apex/include/android/graphics/paint.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_GRAPHICS_PAINT_H +#define ANDROID_GRAPHICS_PAINT_H + +#include <sys/cdefs.h> + +__BEGIN_DECLS + +/** + * Opaque handle for a native graphics canvas. + */ +typedef struct APaint APaint; + +/** Bitmap pixel format. */ +enum ABlendMode { + /** replaces destination with zero: fully transparent */ + ABLEND_MODE_CLEAR = 0, + /** source over destination */ + ABLEND_MODE_SRC_OVER = 1, + /** replaces destination **/ + ABLEND_MODE_SRC = 2, +}; + +APaint* APaint_createPaint(); + +void APaint_destroyPaint(APaint* paint); + +void APaint_setBlendMode(APaint* paint, ABlendMode blendMode); + +__END_DECLS + +#ifdef __cplusplus +namespace android { +namespace graphics { + class Paint { + public: + Paint() : mPaint(APaint_createPaint()) {} + ~Paint() { APaint_destroyPaint(mPaint); } + + void setBlendMode(ABlendMode blendMode) { APaint_setBlendMode(mPaint, blendMode); } + + const APaint& get() const { return *mPaint; } + + private: + APaint* mPaint; + }; +}; // namespace graphics +}; // namespace android +#endif // __cplusplus + + +#endif // ANDROID_GRAPHICS_PAINT_H
\ No newline at end of file diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp index 58c5871aba28..82601baee914 100644 --- a/core/jni/android/opengl/util.cpp +++ b/core/jni/android/opengl/util.cpp @@ -24,15 +24,13 @@ #include <assert.h> #include <dlfcn.h> +#include <android/graphics/bitmap.h> #include <GLES2/gl2.h> #include <GLES2/gl2ext.h> #include <GLES3/gl3.h> #include <ETC1/etc1.h> -#include <SkBitmap.h> - #include "core_jni_helpers.h" -#include "android/graphics/Bitmap.h" #undef LOG_TAG #define LOG_TAG "OpenGLUtil" @@ -628,31 +626,27 @@ void util_multiplyMV(JNIEnv *env, jclass clazz, // The internal format is no longer the same as pixel format, per Table 2 in // https://www.khronos.org/registry/OpenGL-Refpages/es3.1/html/glTexImage2D.xhtml -static int checkInternalFormat(SkColorType colorType, int internalformat, - int type) +static bool checkInternalFormat(int32_t bitmapFormat, int internalformat, int type) { - switch(colorType) { - case kN32_SkColorType: - return (type == GL_UNSIGNED_BYTE && - internalformat == GL_RGBA) || - (type == GL_UNSIGNED_BYTE && - internalformat == GL_SRGB8_ALPHA8) ? 0 : -1; - case kAlpha_8_SkColorType: - return (type == GL_UNSIGNED_BYTE && - internalformat == GL_ALPHA) ? 0 : -1; - case kARGB_4444_SkColorType: - return (type == GL_UNSIGNED_SHORT_4_4_4_4 && - internalformat == GL_RGBA) ? 0 : -1; - case kRGB_565_SkColorType: - return (type == GL_UNSIGNED_SHORT_5_6_5 && - internalformat == GL_RGB) ? 0 : -1; - case kRGBA_F16_SkColorType: - return (type == GL_HALF_FLOAT && - internalformat == GL_RGBA16F) ? 0 : -1; + if (internalformat == GL_PALETTE8_RGBA8_OES) { + return false; + } + switch(bitmapFormat) { + case ANDROID_BITMAP_FORMAT_RGBA_8888: + return (type == GL_UNSIGNED_BYTE && internalformat == GL_RGBA) || + (type == GL_UNSIGNED_BYTE && internalformat == GL_SRGB8_ALPHA8); + case ANDROID_BITMAP_FORMAT_A_8: + return (type == GL_UNSIGNED_BYTE && internalformat == GL_ALPHA); + case ANDROID_BITMAP_FORMAT_RGBA_4444: + return (type == GL_UNSIGNED_SHORT_4_4_4_4 && internalformat == GL_RGBA); + case ANDROID_BITMAP_FORMAT_RGB_565: + return (type == GL_UNSIGNED_SHORT_5_6_5 && internalformat == GL_RGB); + case ANDROID_BITMAP_FORMAT_RGBA_F16: + return (type == GL_HALF_FLOAT && internalformat == GL_RGBA16F); default: break; } - return -1; + return false; } // The internal format is no longer the same as pixel format, per Table 2 in @@ -670,107 +664,92 @@ static int getPixelFormatFromInternalFormat(uint32_t internalFormat) { } } -static int getInternalFormat(SkColorType colorType) -{ - switch(colorType) { - case kAlpha_8_SkColorType: +static int getInternalFormat(int32_t bitmapFormat) { + switch(bitmapFormat) { + case ANDROID_BITMAP_FORMAT_A_8: return GL_ALPHA; - case kARGB_4444_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_4444: return GL_RGBA; - case kN32_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_8888: return GL_RGBA; - case kRGB_565_SkColorType: + case ANDROID_BITMAP_FORMAT_RGB_565: return GL_RGB; - case kRGBA_F16_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_F16: return GL_RGBA16F; default: return -1; } } -static int getType(SkColorType colorType) -{ - switch(colorType) { - case kAlpha_8_SkColorType: +static int getType(int32_t bitmapFormat) { + switch(bitmapFormat) { + case ANDROID_BITMAP_FORMAT_A_8: return GL_UNSIGNED_BYTE; - case kARGB_4444_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_4444: return GL_UNSIGNED_SHORT_4_4_4_4; - case kN32_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_8888: return GL_UNSIGNED_BYTE; - case kRGB_565_SkColorType: + case ANDROID_BITMAP_FORMAT_RGB_565: return GL_UNSIGNED_SHORT_5_6_5; - case kRGBA_F16_SkColorType: + case ANDROID_BITMAP_FORMAT_RGBA_F16: return GL_HALF_FLOAT; default: return -1; } } -static jint util_getInternalFormat(JNIEnv *env, jclass clazz, - jlong bitmapPtr) +static jint util_getInternalFormat(JNIEnv *env, jclass clazz, jobject bitmapObj) { - SkBitmap nativeBitmap; - bitmap::toSkBitmap(bitmapPtr, &nativeBitmap); - return getInternalFormat(nativeBitmap.colorType()); + graphics::Bitmap bitmap(env, bitmapObj); + return getInternalFormat(bitmap.getInfo().format); } -static jint util_getType(JNIEnv *env, jclass clazz, - jlong bitmapPtr) +static jint util_getType(JNIEnv *env, jclass clazz, jobject bitmapObj) { - SkBitmap nativeBitmap; - bitmap::toSkBitmap(bitmapPtr, &nativeBitmap); - return getType(nativeBitmap.colorType()); + graphics::Bitmap bitmap(env, bitmapObj); + return getType(bitmap.getInfo().format); } -static jint util_texImage2D(JNIEnv *env, jclass clazz, - jint target, jint level, jint internalformat, - jlong bitmapPtr, jint type, jint border) +static jint util_texImage2D(JNIEnv *env, jclass clazz, jint target, jint level, + jint internalformat, jobject bitmapObj, jint type, jint border) { - SkBitmap bitmap; - bitmap::toSkBitmap(bitmapPtr, &bitmap); - SkColorType colorType = bitmap.colorType(); + graphics::Bitmap bitmap(env, bitmapObj); + AndroidBitmapInfo bitmapInfo = bitmap.getInfo(); + if (internalformat < 0) { - internalformat = getInternalFormat(colorType); + internalformat = getInternalFormat(bitmapInfo.format); } if (type < 0) { - type = getType(colorType); - } - int err = checkInternalFormat(colorType, internalformat, type); - if (err) - return err; - const int w = bitmap.width(); - const int h = bitmap.height(); - const void* p = bitmap.getPixels(); - if (internalformat == GL_PALETTE8_RGBA8_OES) { - err = -1; - } else { - glTexImage2D(target, level, internalformat, w, h, border, - getPixelFormatFromInternalFormat(internalformat), type, p); + type = getType(bitmapInfo.format); } - return err; + + if (checkInternalFormat(bitmapInfo.format, internalformat, type)) { + glTexImage2D(target, level, internalformat, bitmapInfo.width, bitmapInfo.height, border, + getPixelFormatFromInternalFormat(internalformat), type, bitmap.getPixels()); + return 0; + } + return -1; } -static jint util_texSubImage2D(JNIEnv *env, jclass clazz, - jint target, jint level, jint xoffset, jint yoffset, - jlong bitmapPtr, jint format, jint type) +static jint util_texSubImage2D(JNIEnv *env, jclass clazz, jint target, jint level, + jint xoffset, jint yoffset, jobject bitmapObj, jint format, jint type) { - SkBitmap bitmap; - bitmap::toSkBitmap(bitmapPtr, &bitmap); - SkColorType colorType = bitmap.colorType(); - int internalFormat = getInternalFormat(colorType); + graphics::Bitmap bitmap(env, bitmapObj); + AndroidBitmapInfo bitmapInfo = bitmap.getInfo(); + + int internalFormat = getInternalFormat(bitmapInfo.format); if (format < 0) { format = getPixelFormatFromInternalFormat(internalFormat); if (format == GL_PALETTE8_RGBA8_OES) return -1; // glCompressedTexSubImage2D() not supported } - int err = checkInternalFormat(colorType, internalFormat, type); - if (err) - return err; - const int w = bitmap.width(); - const int h = bitmap.height(); - const void* p = bitmap.getPixels(); - glTexSubImage2D(target, level, xoffset, yoffset, w, h, format, type, p); - return 0; + + if (checkInternalFormat(bitmapInfo.format, internalFormat, type)) { + glTexSubImage2D(target, level, xoffset, yoffset, bitmapInfo.width, bitmapInfo.height, + format, type, bitmap.getPixels()); + return 0; + } + return -1; } /* @@ -1036,10 +1015,10 @@ static const JNINativeMethod gVisibilityMethods[] = { }; static const JNINativeMethod gUtilsMethods[] = { - { "native_getInternalFormat", "(J)I", (void*) util_getInternalFormat }, - { "native_getType", "(J)I", (void*) util_getType }, - { "native_texImage2D", "(IIIJII)I", (void*)util_texImage2D }, - { "native_texSubImage2D", "(IIIIJII)I", (void*)util_texSubImage2D }, + { "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat }, + { "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType }, + { "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D }, + { "native_texSubImage2D", "(IIIILandroid/graphics/Bitmap;II)I", (void*)util_texSubImage2D }, }; static const JNINativeMethod gEtc1Methods[] = { diff --git a/core/jni/android_graphics_GraphicBuffer.cpp b/core/jni/android_graphics_GraphicBuffer.cpp index 43d22eb7df0e..b6d50898a057 100644 --- a/core/jni/android_graphics_GraphicBuffer.cpp +++ b/core/jni/android_graphics_GraphicBuffer.cpp @@ -178,9 +178,9 @@ static jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject, nativeBuffer.format = AHardwareBuffer_convertFromPixelFormat(buffer->getPixelFormat()); nativeBuffer.bits = bits; - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, &nativeBuffer, ADATASPACE_UNKNOWN); - ACanvas_clipRect(canvas, {rect.left, rect.top, rect.right, rect.bottom}); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(&nativeBuffer, ADATASPACE_UNKNOWN); + canvas.clipRect({rect.left, rect.top, rect.right, rect.bottom}); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, @@ -193,8 +193,8 @@ static jboolean android_graphics_GraphicBuffer_lockCanvas(JNIEnv* env, jobject, static jboolean android_graphics_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobject, jlong wrapperHandle, jobject canvasObj) { // release the buffer from the canvas - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, nullptr, ADATASPACE_UNKNOWN); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(nullptr, ADATASPACE_UNKNOWN); GraphicBufferWrapper* wrapper = reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle); diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp index 4f79790dec51..ed2ce506ab23 100644 --- a/core/jni/android_view_PointerIcon.cpp +++ b/core/jni/android_view_PointerIcon.cpp @@ -23,7 +23,7 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> #include <utils/Log.h> -#include <android/graphics/GraphicsJNI.h> +#include <android/graphics/bitmap.h> #include <nativehelper/ScopedLocalRef.h> #include "core_jni_helpers.h" @@ -88,7 +88,7 @@ status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIcon ScopedLocalRef<jobject> bitmapObj( env, env->GetObjectField(pointerIconObj, gPointerIconClassInfo.mBitmap)); if (bitmapObj.get()) { - GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmap)); + outPointerIcon->bitmap = graphics::Bitmap(env, bitmapObj.get()); } ScopedLocalRef<jobjectArray> bitmapFramesObj(env, reinterpret_cast<jobjectArray>( @@ -100,7 +100,7 @@ status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIcon outPointerIcon->bitmapFrames.resize(size); for (jsize i = 0; i < size; ++i) { ScopedLocalRef<jobject> bitmapObj(env, env->GetObjectArrayElement(bitmapFramesObj.get(), i)); - GraphicsJNI::getSkBitmap(env, bitmapObj.get(), &(outPointerIcon->bitmapFrames[i])); + outPointerIcon->bitmapFrames[i] = graphics::Bitmap(env, bitmapObj.get()); } } diff --git a/core/jni/android_view_PointerIcon.h b/core/jni/android_view_PointerIcon.h index 00bdfb4bf04e..908948ea2aa4 100644 --- a/core/jni/android_view_PointerIcon.h +++ b/core/jni/android_view_PointerIcon.h @@ -21,8 +21,8 @@ #include <vector> +#include <android/graphics/bitmap.h> #include <utils/Errors.h> -#include <SkBitmap.h> namespace android { @@ -68,10 +68,10 @@ struct PointerIcon { } int32_t style; - SkBitmap bitmap; + graphics::Bitmap bitmap; float hotSpotX; float hotSpotY; - std::vector<SkBitmap> bitmapFrames; + std::vector<graphics::Bitmap> bitmapFrames; int32_t durationPerFrame; inline bool isNullIcon() { diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index 4c2e91f986d0..058a4c8ee2f9 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -237,12 +237,11 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz, return 0; } - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, &buffer, static_cast<int32_t>(surface->getBuffersDataSpace())); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(&buffer, static_cast<int32_t>(surface->getBuffersDataSpace())); if (dirtyRectPtr) { - ACanvas_clipRect(canvas, {dirtyRect.left, dirtyRect.top, - dirtyRect.right, dirtyRect.bottom}); + canvas.clipRect({dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom}); } if (dirtyRectObj) { @@ -268,8 +267,8 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz, } // detach the canvas from the surface - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, nullptr, ADATASPACE_UNKNOWN); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(nullptr, ADATASPACE_UNKNOWN); // unlock surface status_t err = surface->unlockAndPost(); diff --git a/core/jni/android_view_TextureLayer.cpp b/core/jni/android_view_TextureLayer.cpp index 1ccb6a8f610c..8a3f54039d05 100644 --- a/core/jni/android_view_TextureLayer.cpp +++ b/core/jni/android_view_TextureLayer.cpp @@ -26,10 +26,7 @@ #include <gui/GLConsumer.h> #include <hwui/Paint.h> -#include <SkBitmap.h> -#include <SkCanvas.h> #include <SkMatrix.h> -#include <SkBlendMode.h> #include <DeferredLayerUpdater.h> #include <Rect.h> diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp index 1f69c8bbbe5d..391f515af115 100644 --- a/core/jni/android_view_TextureView.cpp +++ b/core/jni/android_view_TextureView.cpp @@ -124,9 +124,9 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject, int32_t status = native_window_lock(window.get(), &outBuffer, &rect); if (status) return JNI_FALSE; - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, &outBuffer, ANativeWindow_getBuffersDataSpace(window.get())); - ACanvas_clipRect(canvas, {rect.left, rect.top, rect.right, rect.bottom}); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(&outBuffer, ANativeWindow_getBuffersDataSpace(window.get())); + canvas.clipRect({rect.left, rect.top, rect.right, rect.bottom}); if (dirtyRect) { INVOKEV(dirtyRect, gRectClassInfo.set, @@ -140,8 +140,8 @@ static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject, jlong nativeWindow, jobject canvasObj) { // release the buffer from the canvas - ACanvas* canvas = ACanvas_getNativeHandleFromJava(env, canvasObj); - ACanvas_setBuffer(canvas, nullptr, ADATASPACE_UNKNOWN); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(nullptr, ADATASPACE_UNKNOWN); if (nativeWindow) { sp<ANativeWindow> window((ANativeWindow*) nativeWindow); diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 16f2917f8df8..6bb896fd7b29 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -20,11 +20,11 @@ cc_library_shared { ], shared_libs: [ + "libandroid_runtime", "libbinder", "libcutils", "liblog", "libutils", - "libhwui", "libgui", "libui", "libinput", diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index abf083789c23..e4348f2a9b21 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -24,12 +24,6 @@ #include <log/log.h> -#include <SkBitmap.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> -#include <SkBlendMode.h> - namespace android { // --- WeakLooperCallback --- diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index fd386e9f7a8a..804644c230b9 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -23,11 +23,9 @@ #include <utils/String8.h> #include <gui/Surface.h> -#include <SkBitmap.h> -#include <SkCanvas.h> -#include <SkColor.h> -#include <SkPaint.h> - +#include <android/graphics/bitmap.h> +#include <android/graphics/canvas.h> +#include <android/graphics/paint.h> #include <android/native_window.h> namespace android { @@ -132,8 +130,8 @@ void SpriteController::doUpdateSprites() { SpriteUpdate& update = updates.editItemAt(i); if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) { - update.state.surfaceWidth = update.state.icon.bitmap.width(); - update.state.surfaceHeight = update.state.icon.bitmap.height(); + update.state.surfaceWidth = update.state.icon.bitmap.getInfo().width; + update.state.surfaceHeight = update.state.icon.bitmap.getInfo().height; update.state.surfaceDrawn = false; update.state.surfaceVisible = false; update.state.surfaceControl = obtainSurface( @@ -154,8 +152,8 @@ void SpriteController::doUpdateSprites() { } if (update.state.wantSurfaceVisible()) { - int32_t desiredWidth = update.state.icon.bitmap.width(); - int32_t desiredHeight = update.state.icon.bitmap.height(); + int32_t desiredWidth = update.state.icon.bitmap.getInfo().width; + int32_t desiredHeight = update.state.icon.bitmap.getInfo().height; if (update.state.surfaceWidth < desiredWidth || update.state.surfaceHeight < desiredHeight) { needApplyTransaction = true; @@ -201,26 +199,22 @@ void SpriteController::doUpdateSprites() { if (status) { ALOGE("Error %d locking sprite surface before drawing.", status); } else { - SkBitmap surfaceBitmap; - ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format); - surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, outBuffer.height), - outBuffer.bits, bpr); + graphics::Paint paint; + paint.setBlendMode(ABLEND_MODE_SRC); - SkCanvas surfaceCanvas(surfaceBitmap); + graphics::Canvas canvas(outBuffer, (int32_t) surface->getBuffersDataSpace()); + canvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint); - SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); - surfaceCanvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint); + const int iconWidth = update.state.icon.bitmap.getInfo().width; + const int iconHeight = update.state.icon.bitmap.getInfo().height; - if (outBuffer.width > update.state.icon.bitmap.width()) { - paint.setColor(0); // transparent fill color - surfaceCanvas.drawRect(SkRect::MakeLTRB(update.state.icon.bitmap.width(), 0, - outBuffer.width, update.state.icon.bitmap.height()), paint); + if (outBuffer.width > iconWidth) { + paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent + canvas.drawRect({iconWidth, 0, outBuffer.width, iconHeight}, paint); } - if (outBuffer.height > update.state.icon.bitmap.height()) { - paint.setColor(0); // transparent fill color - surfaceCanvas.drawRect(SkRect::MakeLTRB(0, update.state.icon.bitmap.height(), - outBuffer.width, outBuffer.height), paint); + if (outBuffer.height > iconHeight) { + paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent + canvas.drawRect({0, iconHeight, outBuffer.width, outBuffer.height}, paint); } status = surface->unlockAndPost(); @@ -398,12 +392,7 @@ void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) { uint32_t dirty; if (icon.isValid()) { - SkBitmap* bitmapCopy = &mLocked.state.icon.bitmap; - if (bitmapCopy->tryAllocPixels(icon.bitmap.info().makeColorType(kN32_SkColorType))) { - icon.bitmap.readPixels(bitmapCopy->info(), bitmapCopy->getPixels(), - bitmapCopy->rowBytes(), 0, 0); - } - + mLocked.state.icon.bitmap = icon.bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888); if (!mLocked.state.icon.isValid() || mLocked.state.icon.hotSpotX != icon.hotSpotX || mLocked.state.icon.hotSpotY != icon.hotSpotY) { diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h index 79a904f5fe65..2513544d4bdf 100644 --- a/libs/input/SpriteController.h +++ b/libs/input/SpriteController.h @@ -20,10 +20,9 @@ #include <utils/RefBase.h> #include <utils/Looper.h> +#include <android/graphics/bitmap.h> #include <gui/SurfaceComposerClient.h> -#include <SkBitmap.h> - namespace android { /* @@ -56,21 +55,16 @@ struct SpriteTransformationMatrix { */ struct SpriteIcon { inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { } - inline SpriteIcon(const SkBitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) : + inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) : bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } - SkBitmap bitmap; + graphics::Bitmap bitmap; int32_t style; float hotSpotX; float hotSpotY; inline SpriteIcon copy() const { - SkBitmap bitmapCopy; - if (bitmapCopy.tryAllocPixels(bitmap.info().makeColorType(kN32_SkColorType))) { - bitmap.readPixels(bitmapCopy.info(), bitmapCopy.getPixels(), bitmapCopy.rowBytes(), - 0, 0); - } - return SpriteIcon(bitmapCopy, style, hotSpotX, hotSpotY); + return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY); } inline void reset() { @@ -81,7 +75,7 @@ struct SpriteIcon { } inline bool isValid() const { - return !bitmap.isNull() && !bitmap.empty(); + return bitmap.isValid() && !bitmap.isEmpty(); } }; @@ -183,7 +177,7 @@ private: * This structure is designed so that it can be copied during updates so that * surfaces can be resized and redrawn without blocking the client by holding a lock * on the sprites for a long time. - * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */ + * Note that the SpriteIcon holds a reference to a shared (and immutable) bitmap. */ struct SpriteState { inline SpriteState() : dirty(0), visible(false), diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index e83b2a78d180..b1e3d6fe845a 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -18,9 +18,9 @@ cc_test { "PointerController_test.cpp", ], shared_libs: [ + "libandroid_runtime", "libinputservice", "libgui", - "libhwui", "libutils", ], static_libs: [ diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java index ca8d5ac52021..cc46514ae96e 100644 --- a/opengl/java/android/opengl/GLUtils.java +++ b/opengl/java/android/opengl/GLUtils.java @@ -44,7 +44,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - int result = native_getInternalFormat(bitmap.getNativeInstance()); + int result = native_getInternalFormat(bitmap); if (result < 0) { throw new IllegalArgumentException("Unknown internalformat"); } @@ -66,7 +66,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - int result = native_getType(bitmap.getNativeInstance()); + int result = native_getType(bitmap); if (result < 0) { throw new IllegalArgumentException("Unknown type"); } @@ -103,8 +103,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, internalformat, bitmap.getNativeInstance(), -1, - border) != 0) { + if (native_texImage2D(target, level, internalformat, bitmap, -1, border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -130,8 +129,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, internalformat, bitmap.getNativeInstance(), type, - border) != 0) { + if (native_texImage2D(target, level, internalformat, bitmap, type, border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -153,7 +151,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texImage2D(target, level, -1, bitmap.getNativeInstance(), -1, border) != 0) { + if (native_texImage2D(target, level, -1, bitmap, -1, border) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -189,8 +187,7 @@ public final class GLUtils { throw new IllegalArgumentException("bitmap is recycled"); } int type = getType(bitmap); - if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap.getNativeInstance(), -1, - type) != 0) { + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, -1, type) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -214,8 +211,7 @@ public final class GLUtils { if (bitmap.isRecycled()) { throw new IllegalArgumentException("bitmap is recycled"); } - if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap.getNativeInstance(), - format, type) != 0) { + if (native_texSubImage2D(target, level, xoffset, yoffset, bitmap, format, type) != 0) { throw new IllegalArgumentException("invalid Bitmap format"); } } @@ -265,10 +261,10 @@ public final class GLUtils { } } - native private static int native_getInternalFormat(long bitmapHandle); - native private static int native_getType(long bitmapHandle); - native private static int native_texImage2D(int target, int level, int internalformat, - long bitmapHandle, int type, int border); - native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset, - long bitmapHandle, int format, int type); + private static native int native_getInternalFormat(Bitmap bitmap); + private static native int native_getType(Bitmap bitmap); + private static native int native_texImage2D(int target, int level, int internalformat, + Bitmap bitmap, int type, int border); + private static native int native_texSubImage2D(int target, int level, int xoffset, int yoffset, + Bitmap bitmap, int format, int type); } diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 03f475582a5a..0e9da83d4d1f 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -159,12 +159,7 @@ static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextOb status_t status = android_view_PointerIcon_loadSystemIcon(env, contextObj, style, outPointerIcon); if (!status) { - SkBitmap* bitmapCopy = &outSpriteIcon->bitmap; - SkImageInfo bitmapCopyInfo = outPointerIcon->bitmap.info().makeColorType(kN32_SkColorType); - if (bitmapCopy->tryAllocPixels(bitmapCopyInfo)) { - outPointerIcon->bitmap.readPixels(bitmapCopy->info(), bitmapCopy->getPixels(), - bitmapCopy->rowBytes(), 0, 0); - } + outSpriteIcon->bitmap = outPointerIcon->bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888); outSpriteIcon->style = outPointerIcon->style; outSpriteIcon->hotSpotX = outPointerIcon->hotSpotX; outSpriteIcon->hotSpotY = outPointerIcon->hotSpotY; @@ -1709,15 +1704,8 @@ static void nativeSetCustomPointerIcon(JNIEnv* env, jclass /* clazz */, return; } - SpriteIcon spriteIcon; - SkImageInfo spriteInfo = pointerIcon.bitmap.info().makeColorType(kN32_SkColorType); - if (spriteIcon.bitmap.tryAllocPixels(spriteInfo)) { - pointerIcon.bitmap.readPixels(spriteInfo, spriteIcon.bitmap.getPixels(), - spriteIcon.bitmap.rowBytes(), 0, 0); - } - spriteIcon.style = pointerIcon.style; - spriteIcon.hotSpotX = pointerIcon.hotSpotX; - spriteIcon.hotSpotY = pointerIcon.hotSpotY; + SpriteIcon spriteIcon(pointerIcon.bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), + pointerIcon.style, pointerIcon.hotSpotX, pointerIcon.hotSpotY); im->setCustomPointerIcon(spriteIcon); } |