Merge "Create C API for accessing android.graphics.Bitmap in native code."

This commit is contained in:
Derek Sollenberger
2019-09-27 12:49:34 +00:00
committed by Android (Google) Code Review
23 changed files with 646 additions and 227 deletions

View File

@@ -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",
],

View File

@@ -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);

View 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

View 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();
}

View File

@@ -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));
}

View 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));
}

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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[] = {

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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>

View File

@@ -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);

View File

@@ -20,11 +20,11 @@ cc_library_shared {
],
shared_libs: [
"libandroid_runtime",
"libbinder",
"libcutils",
"liblog",
"libutils",
"libhwui",
"libgui",
"libui",
"libinput",

View File

@@ -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 ---

View File

@@ -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) {

View File

@@ -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),

View File

@@ -18,9 +18,9 @@ cc_test {
"PointerController_test.cpp",
],
shared_libs: [
"libandroid_runtime",
"libinputservice",
"libgui",
"libhwui",
"libutils",
],
static_libs: [

View File

@@ -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);
}

View File

@@ -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);
}