Move allocatePixelRef methods to hwui.
This patch also makes tests to use SkBitmap backed by hwui/PixelRef, Test: refactoring cl. bug:27762775 Change-Id: Ib936e81877790849118420f5e565fc8f4466c1be
This commit is contained in:
@@ -548,7 +548,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
|
||||
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
|
||||
GraphicsJNI::defaultColorSpace()));
|
||||
|
||||
PixelRef* nativeBitmap = GraphicsJNI::allocateHeapPixelRef(&bitmap, NULL);
|
||||
sk_sp<PixelRef> nativeBitmap = PixelRef::allocateHeapPixelRef(&bitmap, NULL);
|
||||
if (!nativeBitmap) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -558,8 +558,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
|
||||
0, 0, width, height, bitmap);
|
||||
}
|
||||
|
||||
return createBitmap(env, nativeBitmap,
|
||||
getPremulBitmapCreateFlags(isMutable));
|
||||
return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
|
||||
}
|
||||
|
||||
static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
|
||||
@@ -832,7 +831,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
}
|
||||
|
||||
// Map the bitmap in place from the ashmem region if possible otherwise copy.
|
||||
PixelRef* nativeBitmap;
|
||||
sk_sp<PixelRef> nativeBitmap;
|
||||
if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
|
||||
#if DEBUG_PARCEL
|
||||
ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
|
||||
@@ -853,8 +852,8 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
}
|
||||
|
||||
// Map the pixels in place and take ownership of the ashmem region.
|
||||
nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
|
||||
ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable);
|
||||
nativeBitmap = sk_sp<PixelRef>(GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
|
||||
ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
|
||||
SkSafeUnref(ctable);
|
||||
if (!nativeBitmap) {
|
||||
close(dupFd);
|
||||
@@ -880,7 +879,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
#endif
|
||||
|
||||
// Copy the pixels into a new buffer.
|
||||
nativeBitmap = GraphicsJNI::allocateHeapPixelRef(bitmap.get(), ctable);
|
||||
nativeBitmap = PixelRef::allocateHeapPixelRef(bitmap.get(), ctable);
|
||||
SkSafeUnref(ctable);
|
||||
if (!nativeBitmap) {
|
||||
blob.release();
|
||||
@@ -895,7 +894,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
blob.release();
|
||||
}
|
||||
|
||||
return createBitmap(env, nativeBitmap,
|
||||
return createBitmap(env, nativeBitmap.release(),
|
||||
getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
|
||||
}
|
||||
|
||||
|
||||
@@ -399,160 +399,8 @@ jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JNIEnv* vm2env(JavaVM* vm)
|
||||
{
|
||||
JNIEnv* env = NULL;
|
||||
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env)
|
||||
{
|
||||
SkDebugf("------- [%p] vm->GetEnv() failed\n", vm);
|
||||
sk_throw();
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
|
||||
int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
|
||||
int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
|
||||
if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
|
||||
return false; // allocation will be too large
|
||||
}
|
||||
|
||||
*size = sk_64_asS32(bigSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
android::PixelRef* GraphicsJNI::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
const SkImageInfo& info = bitmap->info();
|
||||
if (info.colorType() == kUnknown_SkColorType) {
|
||||
LOG_ALWAYS_FATAL("unknown bitmap configuration");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
if (!computeAllocationSize(*bitmap, &size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we must respect the rowBytes value already set on the bitmap instead of
|
||||
// attempting to compute our own.
|
||||
const size_t rowBytes = bitmap->rowBytes();
|
||||
|
||||
void* addr = calloc(size, 1);
|
||||
if (!addr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto wrapper = new android::PixelRef(addr, size, info, rowBytes, ctable);
|
||||
wrapper->getSkBitmap(bitmap);
|
||||
// since we're already allocated, we lockPixels right away
|
||||
// HeapAllocator behaves this way too
|
||||
bitmap->lockPixels();
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
struct AndroidPixelRefContext {
|
||||
int32_t stableID;
|
||||
};
|
||||
|
||||
static void allocatePixelsReleaseProc(void* ptr, void* ctx) {
|
||||
AndroidPixelRefContext* context = (AndroidPixelRefContext*)ctx;
|
||||
if (android::uirenderer::Caches::hasInstance()) {
|
||||
android::uirenderer::Caches::getInstance().textureCache.releaseTexture(context->stableID);
|
||||
}
|
||||
|
||||
sk_free(ptr);
|
||||
delete context;
|
||||
}
|
||||
|
||||
bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
const SkImageInfo& info = bitmap->info();
|
||||
if (info.colorType() == kUnknown_SkColorType) {
|
||||
doThrowIAE(env, "unknown bitmap configuration");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
if (!computeAllocationSize(*bitmap, &size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we must respect the rowBytes value already set on the bitmap instead of
|
||||
// attempting to compute our own.
|
||||
const size_t rowBytes = bitmap->rowBytes();
|
||||
|
||||
void* addr = sk_malloc_flags(size, 0);
|
||||
if (NULL == addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AndroidPixelRefContext* context = new AndroidPixelRefContext;
|
||||
SkMallocPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rowBytes, ctable, addr,
|
||||
&allocatePixelsReleaseProc, context);
|
||||
if (!pr) {
|
||||
delete context;
|
||||
return false;
|
||||
}
|
||||
|
||||
// set the stableID in the context so that it can be used later in
|
||||
// allocatePixelsReleaseProc to remove the texture from the cache.
|
||||
context->stableID = pr->getStableID();
|
||||
|
||||
bitmap->setPixelRef(pr)->unref();
|
||||
// since we're already allocated, we can lockPixels right away
|
||||
bitmap->lockPixels();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
android::PixelRef* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
|
||||
SkColorTable* ctable) {
|
||||
int fd;
|
||||
|
||||
const SkImageInfo& info = bitmap->info();
|
||||
if (info.colorType() == kUnknown_SkColorType) {
|
||||
doThrowIAE(env, "unknown bitmap configuration");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
if (!computeAllocationSize(*bitmap, &size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we must respect the rowBytes value already set on the bitmap instead of
|
||||
// attempting to compute our own.
|
||||
const size_t rowBytes = bitmap->rowBytes();
|
||||
|
||||
// Create new ashmem region with read/write priv
|
||||
fd = ashmem_create_region("bitmap", size);
|
||||
if (fd < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ashmem_set_prot_region(fd, PROT_READ) < 0) {
|
||||
munmap(addr, size);
|
||||
close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto wrapper = new android::PixelRef(addr, fd, size, info, rowBytes, ctable);
|
||||
wrapper->getSkBitmap(bitmap);
|
||||
// since we're already allocated, we lockPixels right away
|
||||
// HeapAllocator behaves this way too
|
||||
bitmap->lockPixels();
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
android::PixelRef* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
|
||||
SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly) {
|
||||
const SkImageInfo& info = bitmap->info();
|
||||
@@ -597,7 +445,7 @@ sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
mStorage.reset(GraphicsJNI::allocateHeapPixelRef(bitmap, ctable));
|
||||
mStorage = android::PixelRef::allocateHeapPixelRef(bitmap, ctable);
|
||||
return !!mStorage;
|
||||
}
|
||||
|
||||
@@ -702,8 +550,7 @@ AshmemPixelAllocator::AshmemPixelAllocator(JNIEnv *env) {
|
||||
}
|
||||
|
||||
bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
JNIEnv* env = vm2env(mJavaVM);
|
||||
mStorage.reset(GraphicsJNI::allocateAshmemPixelRef(env, bitmap, ctable));
|
||||
mStorage = android::PixelRef::allocateAshmemPixelRef(bitmap, ctable);
|
||||
return !!mStorage;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,11 +72,6 @@ public:
|
||||
|
||||
static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
|
||||
|
||||
static android::PixelRef* allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
|
||||
|
||||
static android::PixelRef* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
|
||||
SkColorTable* ctable);
|
||||
|
||||
static android::PixelRef* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
|
||||
SkColorTable* ctable, int fd, void* addr, size_t size, bool readOnly);
|
||||
|
||||
|
||||
@@ -446,7 +446,8 @@ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
|
||||
GraphicsJNI::defaultColorSpace());
|
||||
SkBitmap bitmap;
|
||||
bitmap.setInfo(info);
|
||||
if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) {
|
||||
sk_sp<PixelRef> pixelRef = PixelRef::allocateHeapPixelRef(&bitmap, NULL);
|
||||
if (!pixelRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,84 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
static bool computeAllocationSize(const SkBitmap& bitmap, size_t* size) {
|
||||
int32_t rowBytes32 = SkToS32(bitmap.rowBytes());
|
||||
int64_t bigSize = (int64_t)bitmap.height() * rowBytes32;
|
||||
if (rowBytes32 < 0 || !sk_64_isS32(bigSize)) {
|
||||
return false; // allocation will be too large
|
||||
}
|
||||
|
||||
*size = sk_64_asS32(bigSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef sk_sp<PixelRef> (*AllocPixeRef)(size_t allocSize, const SkImageInfo& info, size_t rowBytes,
|
||||
SkColorTable* ctable);
|
||||
|
||||
static sk_sp<PixelRef> allocatePixelRef(SkBitmap* bitmap, SkColorTable* ctable, AllocPixeRef alloc) {
|
||||
const SkImageInfo& info = bitmap->info();
|
||||
if (info.colorType() == kUnknown_SkColorType) {
|
||||
LOG_ALWAYS_FATAL("unknown bitmap configuration");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
if (!computeAllocationSize(*bitmap, &size)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// we must respect the rowBytes value already set on the bitmap instead of
|
||||
// attempting to compute our own.
|
||||
const size_t rowBytes = bitmap->rowBytes();
|
||||
auto wrapper = alloc(size, info, rowBytes, ctable);
|
||||
if (wrapper) {
|
||||
wrapper->getSkBitmap(bitmap);
|
||||
// since we're already allocated, we lockPixels right away
|
||||
// HeapAllocator behaves this way too
|
||||
bitmap->lockPixels();
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
sk_sp<PixelRef> PixelRef::allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
return allocatePixelRef(bitmap, ctable, &PixelRef::allocateHeapPixelRef);
|
||||
}
|
||||
|
||||
sk_sp<PixelRef> PixelRef::allocateAshmemPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
return allocatePixelRef(bitmap, ctable, &PixelRef::allocateAshmemPixelRef);
|
||||
}
|
||||
|
||||
sk_sp<PixelRef> PixelRef::allocateHeapPixelRef(size_t size, const SkImageInfo& info, size_t rowBytes,
|
||||
SkColorTable* ctable) {
|
||||
void* addr = calloc(size, 1);
|
||||
if (!addr) {
|
||||
return nullptr;
|
||||
}
|
||||
return sk_sp<PixelRef>(new PixelRef(addr, size, info, rowBytes, ctable));
|
||||
}
|
||||
|
||||
sk_sp<PixelRef> PixelRef::allocateAshmemPixelRef(size_t size, const SkImageInfo& info,
|
||||
size_t rowBytes, SkColorTable* ctable) {
|
||||
// Create new ashmem region with read/write priv
|
||||
int fd = ashmem_create_region("bitmap", size);
|
||||
if (fd < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ashmem_set_prot_region(fd, PROT_READ) < 0) {
|
||||
munmap(addr, size);
|
||||
close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
return sk_sp<PixelRef>(new PixelRef(addr, fd, size, info, rowBytes, ctable));
|
||||
}
|
||||
|
||||
void PixelRef::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
|
||||
if (kIndex_8_SkColorType != newInfo.colorType()) {
|
||||
ctable = nullptr;
|
||||
|
||||
@@ -33,6 +33,14 @@ typedef void (*FreeFunc)(void* addr, void* context);
|
||||
|
||||
class ANDROID_API PixelRef : public SkPixelRef {
|
||||
public:
|
||||
static sk_sp<PixelRef> allocateHeapPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
|
||||
static sk_sp<PixelRef> allocateHeapPixelRef(size_t allocSize, const SkImageInfo& info,
|
||||
size_t rowBytes, SkColorTable* ctable);
|
||||
|
||||
static sk_sp<PixelRef> allocateAshmemPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
|
||||
static sk_sp<PixelRef> allocateAshmemPixelRef(size_t allocSize, const SkImageInfo& info,
|
||||
size_t rowBytes, SkColorTable* ctable);
|
||||
|
||||
PixelRef(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
|
||||
SkColorTable* ctable);
|
||||
PixelRef(void* address, void* context, FreeFunc freeFunc,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <Matrix.h>
|
||||
#include <Rect.h>
|
||||
#include <RenderNode.h>
|
||||
#include <hwui/PixelRef.h>
|
||||
#include <renderstate/RenderState.h>
|
||||
#include <renderthread/RenderThread.h>
|
||||
#include <Snapshot.h>
|
||||
@@ -128,7 +129,7 @@ public:
|
||||
SkImageInfo info = SkImageInfo::Make(width, height,
|
||||
colorType, kPremul_SkAlphaType, colorSpace);
|
||||
bitmap.setInfo(info);
|
||||
bitmap.allocPixels(info);
|
||||
PixelRef::allocateHeapPixelRef(&bitmap, nullptr);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,12 +25,20 @@
|
||||
using namespace android;
|
||||
using namespace android::uirenderer;
|
||||
|
||||
SkBitmap createSkBitmap(int width, int height) {
|
||||
SkBitmap bitmap;
|
||||
SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
|
||||
bitmap.setInfo(info);
|
||||
bitmap.allocPixels(info);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1x1 bitmaps must not be optimized into solid color shaders, since HWUI can't
|
||||
* compose/render color shaders
|
||||
*/
|
||||
TEST(SkiaBehavior, CreateBitmapShader1x1) {
|
||||
SkBitmap origBitmap = TestUtils::createSkBitmap(1, 1);
|
||||
SkBitmap origBitmap = createSkBitmap(1, 1);
|
||||
sk_sp<SkShader> s = SkMakeBitmapShader(
|
||||
origBitmap,
|
||||
SkShader::kClamp_TileMode,
|
||||
@@ -49,7 +57,7 @@ TEST(SkiaBehavior, CreateBitmapShader1x1) {
|
||||
}
|
||||
|
||||
TEST(SkiaBehavior, genIds) {
|
||||
SkBitmap bitmap = TestUtils::createSkBitmap(100, 100);
|
||||
SkBitmap bitmap = createSkBitmap(100, 100);
|
||||
uint32_t genId = bitmap.getGenerationID();
|
||||
bitmap.notifyPixelsChanged();
|
||||
EXPECT_NE(genId, bitmap.getGenerationID());
|
||||
|
||||
Reference in New Issue
Block a user