Merge "Create C API for accessing android.graphics.Bitmap in native code."
This commit is contained in:
committed by
Android (Google) Code Review
commit
84d5b1947f
@@ -54,6 +54,8 @@ cc_library_shared {
|
||||
|
||||
whole_static_libs: ["libandroid_graphics"],
|
||||
|
||||
export_static_lib_headers: ["libandroid_graphics"],
|
||||
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libcutils",
|
||||
@@ -337,7 +339,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",
|
||||
@@ -390,7 +394,6 @@ cc_library_static {
|
||||
],
|
||||
|
||||
export_include_dirs: [
|
||||
".",
|
||||
"android/graphics/apex/include",
|
||||
],
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
70
core/jni/android/graphics/apex/TypeCast.h
Normal file
70
core/jni/android/graphics/apex/TypeCast.h
Normal file
@@ -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
|
||||
106
core/jni/android/graphics/apex/android_bitmap.cpp
Normal file
106
core/jni/android/graphics/apex/android_bitmap.cpp
Normal file
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
toCanvas(canvas)->setBitmap(bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) {
|
||||
ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer,
|
||||
int32_t /*android_dataspace_t*/ dataspace) {
|
||||
return TypeCast::toACanvas(Canvas::create_canvas(convert(buffer, dataspace)));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
47
core/jni/android/graphics/apex/android_paint.cpp
Normal file
47
core/jni/android/graphics/apex/android_paint.cpp
Normal file
@@ -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));
|
||||
}
|
||||
102
core/jni/android/graphics/apex/include/android/graphics/bitmap.h
Normal file
102
core/jni/android/graphics/apex/include/android/graphics/bitmap.h
Normal file
@@ -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
|
||||
@@ -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);
|
||||
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_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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
type = getType(bitmapInfo.format);
|
||||
}
|
||||
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);
|
||||
|
||||
if (checkInternalFormat(bitmapInfo.format, internalformat, type)) {
|
||||
glTexImage2D(target, level, internalformat, bitmapInfo.width, bitmapInfo.height, border,
|
||||
getPixelFormatFromInternalFormat(internalformat), type, bitmap.getPixels());
|
||||
return 0;
|
||||
}
|
||||
return err;
|
||||
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[] = {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -20,11 +20,11 @@ cc_library_shared {
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libandroid_runtime",
|
||||
"libbinder",
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libhwui",
|
||||
"libgui",
|
||||
"libui",
|
||||
"libinput",
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -18,9 +18,9 @@ cc_test {
|
||||
"PointerController_test.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libandroid_runtime",
|
||||
"libinputservice",
|
||||
"libgui",
|
||||
"libhwui",
|
||||
"libutils",
|
||||
],
|
||||
static_libs: [
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user