From 67e479a4e8a66057f4ebe6f03727cebc480716ec Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Mon, 5 Aug 2019 16:47:40 -0700 Subject: Add cursor type and hotspot to surface metadata. Also bootstrap unit tests for PointerController. Need to mark 3 functions of SpriteController virtual so their behaviors can be overridden. Bug: 130822623 Test: SurfaceFlinger can get cursor type and hotspot. Change-Id: I739cd03214364144bb4e22a166ecc7abfd3492fe --- libs/input/SpriteController.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'libs/input/SpriteController.cpp') diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index c1868d3a94d6..fd386e9f7a8a 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -245,7 +245,8 @@ void SpriteController::doUpdateSprites() { if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER - | DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID))))) { + | DIRTY_VISIBILITY | DIRTY_HOTSPOT | DIRTY_DISPLAY_ID + | DIRTY_ICON_STYLE))))) { needApplyTransaction = true; if (wantSurfaceVisibleAndDrawn @@ -274,6 +275,21 @@ void SpriteController::doUpdateSprites() { update.state.transformationMatrix.dtdy); } + if (wantSurfaceVisibleAndDrawn + && (becomingVisible + || (update.state.dirty & (DIRTY_HOTSPOT | DIRTY_ICON_STYLE)))) { + Parcel p; + p.writeInt32(update.state.icon.style); + p.writeFloat(update.state.icon.hotSpotX); + p.writeFloat(update.state.icon.hotSpotY); + + // Pass cursor metadata in the sprite surface so that when Android is running as a + // client OS (e.g. ARC++) the host OS can get the requested cursor metadata and + // update mouse cursor in the host OS. + t.setMetadata( + update.state.surfaceControl, METADATA_MOUSE_CURSOR, p); + } + int32_t surfaceLayer = mOverlayLayer + update.state.layer; if (wantSurfaceVisibleAndDrawn && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) { @@ -397,9 +413,14 @@ void SpriteController::SpriteImpl::setIcon(const SpriteIcon& icon) { } else { dirty = DIRTY_BITMAP; } + + if (mLocked.state.icon.style != icon.style) { + mLocked.state.icon.style = icon.style; + dirty |= DIRTY_ICON_STYLE; + } } else if (mLocked.state.icon.isValid()) { mLocked.state.icon.bitmap.reset(); - dirty = DIRTY_BITMAP | DIRTY_HOTSPOT; + dirty = DIRTY_BITMAP | DIRTY_HOTSPOT | DIRTY_ICON_STYLE; } else { return; // setting to invalid icon and already invalid so nothing to do } -- cgit v1.2.3-59-g8ed1b From 9ca5bbe39f54547dbe585c39459208719a9728b4 Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Wed, 14 Aug 2019 15:50:59 -0400 Subject: 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 --- core/jni/Android.bp | 5 +- core/jni/android/graphics/Bitmap.h | 2 - core/jni/android/graphics/apex/TypeCast.h | 70 +++++++++ core/jni/android/graphics/apex/android_bitmap.cpp | 106 ++++++++++++++ core/jni/android/graphics/apex/android_canvas.cpp | 55 ++++--- core/jni/android/graphics/apex/android_paint.cpp | 47 ++++++ .../apex/include/android/graphics/bitmap.h | 102 +++++++++++++ .../apex/include/android/graphics/canvas.h | 88 ++++++++++-- .../graphics/apex/include/android/graphics/paint.h | 66 +++++++++ core/jni/android/opengl/util.cpp | 159 +++++++++------------ core/jni/android_graphics_GraphicBuffer.cpp | 10 +- core/jni/android_view_PointerIcon.cpp | 6 +- core/jni/android_view_PointerIcon.h | 6 +- core/jni/android_view_Surface.cpp | 11 +- core/jni/android_view_TextureLayer.cpp | 3 - core/jni/android_view_TextureView.cpp | 10 +- libs/input/Android.bp | 2 +- libs/input/PointerController.cpp | 6 - libs/input/SpriteController.cpp | 51 +++---- libs/input/SpriteController.h | 18 +-- libs/input/tests/Android.bp | 2 +- opengl/java/android/opengl/GLUtils.java | 30 ++-- ...om_android_server_input_InputManagerService.cpp | 18 +-- 23 files changed, 646 insertions(+), 227 deletions(-) create mode 100644 core/jni/android/graphics/apex/TypeCast.h create mode 100644 core/jni/android/graphics/apex/android_bitmap.cpp create mode 100644 core/jni/android/graphics/apex/android_paint.cpp create mode 100644 core/jni/android/graphics/apex/include/android/graphics/bitmap.h create mode 100644 core/jni/android/graphics/apex/include/android/graphics/paint.h (limited to 'libs/input/SpriteController.cpp') 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(reinterpret_cast(*bitmap)); + } + + static inline Bitmap* toBitmap(ABitmap* bitmap) { + return reinterpret_cast(bitmap); + } + + static inline ABitmap* toABitmap(Bitmap* bitmap) { + return reinterpret_cast(bitmap); + } + + static inline Canvas* toCanvas(ACanvas* canvas) { + return reinterpret_cast(canvas); + } + + static inline ACanvas* toACanvas(Canvas* canvas) { + return reinterpret_cast(canvas); + } + + static inline const Paint& toPaintRef(const APaint* paint) { + return reinterpret_cast(*paint); + } + + static inline const Paint* toPaint(const APaint* paint) { + return reinterpret_cast(paint); + } + + static inline Paint* toPaint(APaint* paint) { + return reinterpret_cast(paint); + } + + static inline APaint* toAPaint(Paint* paint) { + return reinterpret_cast(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 + +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 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 @@ -25,14 +26,6 @@ using namespace android; -static inline Canvas* toCanvas(ACanvas* aCanvas) { - return reinterpret_cast(aCanvas); -} - -static inline ACanvas* toACanvas(Canvas* canvas) { - return reinterpret_cast(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 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 + +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 +#include +#include + +__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 +#include #include #include #include @@ -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 + +__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 #include +#include #include #include #include #include -#include - #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(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 #include #include -#include +#include #include #include "core_jni_helpers.h" @@ -88,7 +88,7 @@ status_t android_view_PointerIcon_getLoadedIcon(JNIEnv* env, jobject pointerIcon ScopedLocalRef 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 bitmapFramesObj(env, reinterpret_cast( @@ -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 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 +#include #include -#include namespace android { @@ -68,10 +68,10 @@ struct PointerIcon { } int32_t style; - SkBitmap bitmap; + graphics::Bitmap bitmap; float hotSpotX; float hotSpotY; - std::vector bitmapFrames; + std::vector 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(surface->getBuffersDataSpace())); + graphics::Canvas canvas(env, canvasObj); + canvas.setBuffer(&buffer, static_cast(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 #include -#include -#include #include -#include #include #include 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 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 -#include -#include -#include -#include -#include - 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 #include -#include -#include -#include -#include - +#include +#include +#include #include 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 #include +#include #include -#include - 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); } -- cgit v1.2.3-59-g8ed1b From 19a44bc5bc1b243d9f2e2cf7c769b10626157a94 Mon Sep 17 00:00:00 2001 From: Garfield Tan Date: Thu, 28 May 2020 14:31:29 -0700 Subject: Isolate SpriteIcon into its own file. This is to isolate differences between internal master and AOSP so that the open source intern can work on a relatively new project. It also isolates a divergent piece of code into SpriteIcon.cpp. Bug: None Test: Pointer icons in ApiDemos still work. Change-Id: I1bf8f23411ad7170de2497d6fee0f70b015e9b5f Merged-In: I1bf8f23411ad7170de2497d6fee0f70b015e9b5f (cherry picked from commit 7e3457e593f417eb7a5a55d301b3d5f5dd1debdf) --- libs/input/Android.bp | 1 + libs/input/SpriteController.cpp | 46 +++++-------------------------- libs/input/SpriteController.h | 32 ++------------------- libs/input/SpriteIcon.cpp | 60 ++++++++++++++++++++++++++++++++++++++++ libs/input/SpriteIcon.h | 61 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 69 deletions(-) create mode 100644 libs/input/SpriteIcon.cpp create mode 100644 libs/input/SpriteIcon.h (limited to 'libs/input/SpriteController.cpp') diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 88d6033ed9fb..5252cd041199 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -17,6 +17,7 @@ cc_library_shared { srcs: [ "PointerController.cpp", "SpriteController.cpp", + "SpriteIcon.cpp", ], shared_libs: [ diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp index 804644c230b9..acd8bced0612 100644 --- a/libs/input/SpriteController.cpp +++ b/libs/input/SpriteController.cpp @@ -23,11 +23,6 @@ #include #include -#include -#include -#include -#include - namespace android { // --- SpriteController --- @@ -130,8 +125,8 @@ void SpriteController::doUpdateSprites() { SpriteUpdate& update = updates.editItemAt(i); if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) { - update.state.surfaceWidth = update.state.icon.bitmap.getInfo().width; - update.state.surfaceHeight = update.state.icon.bitmap.getInfo().height; + update.state.surfaceWidth = update.state.icon.width(); + update.state.surfaceHeight = update.state.icon.height(); update.state.surfaceDrawn = false; update.state.surfaceVisible = false; update.state.surfaceControl = obtainSurface( @@ -152,8 +147,8 @@ void SpriteController::doUpdateSprites() { } if (update.state.wantSurfaceVisible()) { - int32_t desiredWidth = update.state.icon.bitmap.getInfo().width; - int32_t desiredHeight = update.state.icon.bitmap.getInfo().height; + int32_t desiredWidth = update.state.icon.width(); + int32_t desiredHeight = update.state.icon.height(); if (update.state.surfaceWidth < desiredWidth || update.state.surfaceHeight < desiredHeight) { needApplyTransaction = true; @@ -194,36 +189,9 @@ void SpriteController::doUpdateSprites() { if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn && update.state.wantSurfaceVisible()) { sp surface = update.state.surfaceControl->getSurface(); - ANativeWindow_Buffer outBuffer; - status_t status = surface->lock(&outBuffer, NULL); - if (status) { - ALOGE("Error %d locking sprite surface before drawing.", status); - } else { - graphics::Paint paint; - paint.setBlendMode(ABLEND_MODE_SRC); - - graphics::Canvas canvas(outBuffer, (int32_t) surface->getBuffersDataSpace()); - canvas.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 > iconWidth) { - paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent - canvas.drawRect({iconWidth, 0, outBuffer.width, iconHeight}, 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(); - if (status) { - ALOGE("Error %d unlocking and posting sprite surface after drawing.", status); - } else { - update.state.surfaceDrawn = true; - update.surfaceChanged = surfaceChanged = true; - } + if (update.state.icon.draw(surface)) { + update.state.surfaceDrawn = true; + update.surfaceChanged = surfaceChanged = true; } } } diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h index 2513544d4bdf..137b5646feae 100644 --- a/libs/input/SpriteController.h +++ b/libs/input/SpriteController.h @@ -20,9 +20,10 @@ #include #include -#include #include +#include "SpriteIcon.h" + namespace android { /* @@ -50,35 +51,6 @@ struct SpriteTransformationMatrix { } }; -/* - * Icon that a sprite displays, including its hotspot. - */ -struct SpriteIcon { - inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { } - inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) : - bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { } - - graphics::Bitmap bitmap; - int32_t style; - float hotSpotX; - float hotSpotY; - - inline SpriteIcon copy() const { - return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY); - } - - inline void reset() { - bitmap.reset(); - style = 0; - hotSpotX = 0; - hotSpotY = 0; - } - - inline bool isValid() const { - return bitmap.isValid() && !bitmap.isEmpty(); - } -}; - /* * A sprite is a simple graphical object that is displayed on-screen above other layers. * The basic sprite class is an interface. diff --git a/libs/input/SpriteIcon.cpp b/libs/input/SpriteIcon.cpp new file mode 100644 index 000000000000..b7e51e22a214 --- /dev/null +++ b/libs/input/SpriteIcon.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2020 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 "SpriteIcon.h" + +#include +#include +#include +#include +#include + +namespace android { + +bool SpriteIcon::draw(sp surface) const { + ANativeWindow_Buffer outBuffer; + status_t status = surface->lock(&outBuffer, NULL); + if (status) { + ALOGE("Error %d locking sprite surface before drawing.", status); + return false; + } + + graphics::Paint paint; + paint.setBlendMode(ABLEND_MODE_SRC); + + graphics::Canvas canvas(outBuffer, (int32_t)surface->getBuffersDataSpace()); + canvas.drawBitmap(bitmap, 0, 0, &paint); + + const int iconWidth = width(); + const int iconHeight = height(); + + if (outBuffer.width > iconWidth) { + paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent + canvas.drawRect({iconWidth, 0, outBuffer.width, iconHeight}, 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(); + if (status) { + ALOGE("Error %d unlocking and posting sprite surface after drawing.", status); + } + return !status; +} + +} // namespace android diff --git a/libs/input/SpriteIcon.h b/libs/input/SpriteIcon.h new file mode 100644 index 000000000000..a257d7e89ebc --- /dev/null +++ b/libs/input/SpriteIcon.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 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 _UI_SPRITE_ICON_H +#define _UI_SPRITE_ICON_H + +#include +#include + +namespace android { + +/* + * Icon that a sprite displays, including its hotspot. + */ +struct SpriteIcon { + inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) {} + inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) + : bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) {} + + graphics::Bitmap bitmap; + int32_t style; + float hotSpotX; + float hotSpotY; + + inline SpriteIcon copy() const { + return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY); + } + + inline void reset() { + bitmap.reset(); + style = 0; + hotSpotX = 0; + hotSpotY = 0; + } + + inline bool isValid() const { return bitmap.isValid() && !bitmap.isEmpty(); } + + inline int32_t width() const { return bitmap.getInfo().width; } + inline int32_t height() const { return bitmap.getInfo().height; } + + // Draw the bitmap onto the given surface. Returns true if it's successful, or false otherwise. + // Note it doesn't set any metadata to the surface. + bool draw(const sp surface) const; +}; + +} // namespace android + +#endif // _UI_SPRITE_ICON_H -- cgit v1.2.3-59-g8ed1b