Loading core/jni/android/graphics/Bitmap.cpp +109 −35 Original line number Original line Diff line number Diff line #define LOG_TAG "Bitmap" #define LOG_TAG "Bitmap" #include "Bitmap.h" #include "Bitmap.h" #include "Paint.h" #include "Paint.h" Loading @@ -23,6 +22,10 @@ #include "core_jni_helpers.h" #include "core_jni_helpers.h" #include <jni.h> #include <jni.h> #include <memory> #include <string> #include <sys/mman.h> #include <cutils/ashmem.h> namespace android { namespace android { Loading Loading @@ -135,6 +138,17 @@ Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc, mPixelRef->unref(); mPixelRef->unref(); } } Bitmap::Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) : mPixelStorageType(PixelStorageType::Ashmem) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; mPixelStorage.ashmem.size = ashmem_get_size_region(fd); mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable)); // Note: this will trigger a call to onStrongRefDestroyed(), but // we want the pixel ref to have a ref count of 0 at this point mPixelRef->unref(); } Bitmap::~Bitmap() { Bitmap::~Bitmap() { doFreePixels(); doFreePixels(); } } Loading @@ -156,6 +170,10 @@ void Bitmap::doFreePixels() { mPixelStorage.external.freeFunc(mPixelStorage.external.address, mPixelStorage.external.freeFunc(mPixelStorage.external.address, mPixelStorage.external.context); mPixelStorage.external.context); break; break; case PixelStorageType::Ashmem: munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size); close(mPixelStorage.ashmem.fd); break; case PixelStorageType::Java: case PixelStorageType::Java: JNIEnv* env = jniEnv(); JNIEnv* env = jniEnv(); LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef, LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef, Loading @@ -179,6 +197,15 @@ void Bitmap::setHasHardwareMipMap(bool hasMipMap) { mPixelRef->setHasHardwareMipMap(hasMipMap); mPixelRef->setHasHardwareMipMap(hasMipMap); } } int Bitmap::getAshmemFd() const { switch (mPixelStorageType) { case PixelStorageType::Ashmem: return mPixelStorage.ashmem.fd; default: return -1; } } const SkImageInfo& Bitmap::info() const { const SkImageInfo& Bitmap::info() const { assertValid(); assertValid(); return mPixelRef->info(); return mPixelRef->info(); Loading Loading @@ -274,6 +301,7 @@ void Bitmap::pinPixelsLocked() { LOG_ALWAYS_FATAL("Cannot pin invalid pixels!"); LOG_ALWAYS_FATAL("Cannot pin invalid pixels!"); break; break; case PixelStorageType::External: case PixelStorageType::External: case PixelStorageType::Ashmem: // Nothing to do // Nothing to do break; break; case PixelStorageType::Java: { case PixelStorageType::Java: { Loading @@ -296,6 +324,7 @@ void Bitmap::unpinPixelsLocked() { LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!"); LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!"); break; break; case PixelStorageType::External: case PixelStorageType::External: case PixelStorageType::Ashmem: // Don't need to do anything // Don't need to do anything break; break; case PixelStorageType::Java: { case PixelStorageType::Java: { Loading Loading @@ -898,34 +927,76 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { } } } } android::Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, bitmap.get(), ctable); int fd = p->readFileDescriptor(); if (!nativeBitmap) { int dupFd = dup(fd); if (dupFd < 0) { SkSafeUnref(ctable); SkSafeUnref(ctable); doThrowRE(env, "Could not dup parcel fd."); return NULL; return NULL; } } bool readOnlyMapping = !isMutable; Bitmap* nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(), ctable, dupFd, readOnlyMapping); SkSafeUnref(ctable); SkSafeUnref(ctable); if (!nativeBitmap) { size_t size = bitmap->getSize(); close(dupFd); doThrowRE(env, "Could not allocate ashmem pixel ref."); android::Parcel::ReadableBlob blob; android::status_t status = p->readBlob(size, &blob); if (status) { nativeBitmap->detachFromJava(); doThrowRE(env, "Could not read bitmap from parcel blob."); return NULL; return NULL; } } bitmap->pixelRef()->setImmutable(); bitmap->lockPixels(); memcpy(bitmap->getPixels(), blob.data(), size); bitmap->unlockPixels(); blob.release(); return GraphicsJNI::createBitmap(env, nativeBitmap, return GraphicsJNI::createBitmap(env, nativeBitmap, getPremulBitmapCreateFlags(isMutable), NULL, NULL, density); getPremulBitmapCreateFlags(isMutable), NULL, NULL, density); } } class Ashmem { public: Ashmem(size_t sz, bool removeWritePerm) : mSize(sz) { int fd = -1; void *addr = nullptr; // Create new ashmem region with read/write priv fd = ashmem_create_region("bitmap", sz); if (fd < 0) { goto error; } addr = mmap(nullptr, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { goto error; } // If requested, remove the ability to make additional writeable to // this memory. if (removeWritePerm) { if (ashmem_set_prot_region(fd, PROT_READ) < 0) { goto error; } } mFd = fd; mPtr = addr; return; error: if (fd >= 0) { close(fd); } if (addr) { munmap(addr, sz); } } ~Ashmem() { if (mPtr) { close(mFd); munmap(mPtr, mSize); } } void *getPtr() const { return mPtr; } int getFd() const { return mFd; } private: int mFd = -1; int mSize; void* mPtr = nullptr; }; static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jlong bitmapHandle, jboolean isMutable, jint density, jboolean isMutable, jint density, Loading @@ -937,7 +1008,9 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, android::Parcel* p = android::parcelForJavaObject(env, parcel); android::Parcel* p = android::parcelForJavaObject(env, parcel); SkBitmap bitmap; SkBitmap bitmap; reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap); android::Bitmap* androidBitmap = reinterpret_cast<Bitmap*>(bitmapHandle); androidBitmap->getSkBitmap(&bitmap); p->writeInt32(isMutable); p->writeInt32(isMutable); p->writeInt32(bitmap.colorType()); p->writeInt32(bitmap.colorType()); Loading @@ -959,25 +1032,26 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, } } } } size_t size = bitmap.getSize(); bool ashmemSrc = androidBitmap->getAshmemFd() >= 0; if (ashmemSrc && !isMutable) { android::Parcel::WritableBlob blob; p->writeDupFileDescriptor(androidBitmap->getAshmemFd()); android::status_t status = p->writeBlob(size, &blob); } else { if (status) { Ashmem dstAshmem(bitmap.getSize(), !isMutable); doThrowRE(env, "Could not write bitmap to parcel blob."); if (!dstAshmem.getPtr()) { doThrowRE(env, "Could not allocate ashmem for new bitmap."); return JNI_FALSE; return JNI_FALSE; } } bitmap.lockPixels(); bitmap.lockPixels(); const void* pSrc = bitmap.getPixels(); const void* pSrc = bitmap.getPixels(); if (pSrc == NULL) { if (pSrc == NULL) { memset(blob.data(), 0, size); memset(dstAshmem.getPtr(), 0, bitmap.getSize()); } else { } else { memcpy(blob.data(), pSrc, size); memcpy(dstAshmem.getPtr(), pSrc, bitmap.getSize()); } } bitmap.unlockPixels(); bitmap.unlockPixels(); p->writeDupFileDescriptor(dstAshmem.getFd()); blob.release(); } return JNI_TRUE; return JNI_TRUE; } } Loading core/jni/android/graphics/Bitmap.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ enum class PixelStorageType { Invalid, Invalid, External, External, Java, Java, Ashmem, }; }; class WrappedPixelRef; class WrappedPixelRef; Loading @@ -50,6 +51,8 @@ public: const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, void* context, FreeFunc freeFunc, Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info() const; const SkImageInfo& info() const; Loading @@ -76,6 +79,7 @@ public: bool hasHardwareMipMap(); bool hasHardwareMipMap(); void setHasHardwareMipMap(bool hasMipMap); void setHasHardwareMipMap(bool hasMipMap); int getAshmemFd() const; private: private: friend class WrappedPixelRef; friend class WrappedPixelRef; Loading Loading @@ -103,6 +107,11 @@ private: void* context; void* context; FreeFunc freeFunc; FreeFunc freeFunc; } external; } external; struct { void* address; int fd; size_t size; } ashmem; struct { struct { JavaVM* jvm; JavaVM* jvm; jweak jweakRef; jweak jweakRef; Loading core/jni/android/graphics/Graphics.cpp +80 −0 Original line number Original line Diff line number Diff line #define LOG_TAG "GraphicsJNI" #define LOG_TAG "GraphicsJNI" #include <unistd.h> #include <sys/mman.h> #include "jni.h" #include "jni.h" #include "JNIHelp.h" #include "JNIHelp.h" #include "GraphicsJNI.h" #include "GraphicsJNI.h" Loading @@ -10,6 +13,7 @@ #include "SkMath.h" #include "SkMath.h" #include "SkRegion.h" #include "SkRegion.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h> #include <cutils/ashmem.h> #include <Caches.h> #include <Caches.h> #include <TextureCache.h> #include <TextureCache.h> Loading Loading @@ -572,6 +576,82 @@ bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ct return true; return true; } } android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) { int fd; const SkImageInfo& info = bitmap->info(); if (info.fColorType == 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; } android::Bitmap* wrapper = new android::Bitmap(addr, fd, 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::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable, int fd, bool readOnly) { int flags; const SkImageInfo& info = bitmap->info(); if (info.fColorType == kUnknown_SkColorType) { doThrowIAE(env, "unknown bitmap configuration"); return nullptr; } // Create new ashmem region with read/write priv flags = readOnly ? (PROT_READ) : (PROT_READ | PROT_WRITE); void* addr = mmap(NULL, ashmem_get_size_region(fd), flags, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { 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(); android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too bitmap->lockPixels(); return wrapper; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) { JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) { Loading core/jni/android/graphics/GraphicsJNI.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -95,6 +95,12 @@ public: static android::Bitmap* allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, static android::Bitmap* allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable); SkColorTable* ctable); static android::Bitmap* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable); static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable, int fd, bool readOnly); /** /** * Given a bitmap we natively allocate a memory block to store the contents * Given a bitmap we natively allocate a memory block to store the contents * of that bitmap. The memory is then attached to the bitmap via an * of that bitmap. The memory is then attached to the bitmap via an Loading Loading
core/jni/android/graphics/Bitmap.cpp +109 −35 Original line number Original line Diff line number Diff line #define LOG_TAG "Bitmap" #define LOG_TAG "Bitmap" #include "Bitmap.h" #include "Bitmap.h" #include "Paint.h" #include "Paint.h" Loading @@ -23,6 +22,10 @@ #include "core_jni_helpers.h" #include "core_jni_helpers.h" #include <jni.h> #include <jni.h> #include <memory> #include <string> #include <sys/mman.h> #include <cutils/ashmem.h> namespace android { namespace android { Loading Loading @@ -135,6 +138,17 @@ Bitmap::Bitmap(void* address, void* context, FreeFunc freeFunc, mPixelRef->unref(); mPixelRef->unref(); } } Bitmap::Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable) : mPixelStorageType(PixelStorageType::Ashmem) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; mPixelStorage.ashmem.size = ashmem_get_size_region(fd); mPixelRef.reset(new WrappedPixelRef(this, address, info, rowBytes, ctable)); // Note: this will trigger a call to onStrongRefDestroyed(), but // we want the pixel ref to have a ref count of 0 at this point mPixelRef->unref(); } Bitmap::~Bitmap() { Bitmap::~Bitmap() { doFreePixels(); doFreePixels(); } } Loading @@ -156,6 +170,10 @@ void Bitmap::doFreePixels() { mPixelStorage.external.freeFunc(mPixelStorage.external.address, mPixelStorage.external.freeFunc(mPixelStorage.external.address, mPixelStorage.external.context); mPixelStorage.external.context); break; break; case PixelStorageType::Ashmem: munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size); close(mPixelStorage.ashmem.fd); break; case PixelStorageType::Java: case PixelStorageType::Java: JNIEnv* env = jniEnv(); JNIEnv* env = jniEnv(); LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef, LOG_ALWAYS_FATAL_IF(mPixelStorage.java.jstrongRef, Loading @@ -179,6 +197,15 @@ void Bitmap::setHasHardwareMipMap(bool hasMipMap) { mPixelRef->setHasHardwareMipMap(hasMipMap); mPixelRef->setHasHardwareMipMap(hasMipMap); } } int Bitmap::getAshmemFd() const { switch (mPixelStorageType) { case PixelStorageType::Ashmem: return mPixelStorage.ashmem.fd; default: return -1; } } const SkImageInfo& Bitmap::info() const { const SkImageInfo& Bitmap::info() const { assertValid(); assertValid(); return mPixelRef->info(); return mPixelRef->info(); Loading Loading @@ -274,6 +301,7 @@ void Bitmap::pinPixelsLocked() { LOG_ALWAYS_FATAL("Cannot pin invalid pixels!"); LOG_ALWAYS_FATAL("Cannot pin invalid pixels!"); break; break; case PixelStorageType::External: case PixelStorageType::External: case PixelStorageType::Ashmem: // Nothing to do // Nothing to do break; break; case PixelStorageType::Java: { case PixelStorageType::Java: { Loading @@ -296,6 +324,7 @@ void Bitmap::unpinPixelsLocked() { LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!"); LOG_ALWAYS_FATAL("Cannot unpin invalid pixels!"); break; break; case PixelStorageType::External: case PixelStorageType::External: case PixelStorageType::Ashmem: // Don't need to do anything // Don't need to do anything break; break; case PixelStorageType::Java: { case PixelStorageType::Java: { Loading Loading @@ -898,34 +927,76 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { } } } } android::Bitmap* nativeBitmap = GraphicsJNI::allocateJavaPixelRef(env, bitmap.get(), ctable); int fd = p->readFileDescriptor(); if (!nativeBitmap) { int dupFd = dup(fd); if (dupFd < 0) { SkSafeUnref(ctable); SkSafeUnref(ctable); doThrowRE(env, "Could not dup parcel fd."); return NULL; return NULL; } } bool readOnlyMapping = !isMutable; Bitmap* nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(), ctable, dupFd, readOnlyMapping); SkSafeUnref(ctable); SkSafeUnref(ctable); if (!nativeBitmap) { size_t size = bitmap->getSize(); close(dupFd); doThrowRE(env, "Could not allocate ashmem pixel ref."); android::Parcel::ReadableBlob blob; android::status_t status = p->readBlob(size, &blob); if (status) { nativeBitmap->detachFromJava(); doThrowRE(env, "Could not read bitmap from parcel blob."); return NULL; return NULL; } } bitmap->pixelRef()->setImmutable(); bitmap->lockPixels(); memcpy(bitmap->getPixels(), blob.data(), size); bitmap->unlockPixels(); blob.release(); return GraphicsJNI::createBitmap(env, nativeBitmap, return GraphicsJNI::createBitmap(env, nativeBitmap, getPremulBitmapCreateFlags(isMutable), NULL, NULL, density); getPremulBitmapCreateFlags(isMutable), NULL, NULL, density); } } class Ashmem { public: Ashmem(size_t sz, bool removeWritePerm) : mSize(sz) { int fd = -1; void *addr = nullptr; // Create new ashmem region with read/write priv fd = ashmem_create_region("bitmap", sz); if (fd < 0) { goto error; } addr = mmap(nullptr, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { goto error; } // If requested, remove the ability to make additional writeable to // this memory. if (removeWritePerm) { if (ashmem_set_prot_region(fd, PROT_READ) < 0) { goto error; } } mFd = fd; mPtr = addr; return; error: if (fd >= 0) { close(fd); } if (addr) { munmap(addr, sz); } } ~Ashmem() { if (mPtr) { close(mFd); munmap(mPtr, mSize); } } void *getPtr() const { return mPtr; } int getFd() const { return mFd; } private: int mFd = -1; int mSize; void* mPtr = nullptr; }; static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jlong bitmapHandle, jboolean isMutable, jint density, jboolean isMutable, jint density, Loading @@ -937,7 +1008,9 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, android::Parcel* p = android::parcelForJavaObject(env, parcel); android::Parcel* p = android::parcelForJavaObject(env, parcel); SkBitmap bitmap; SkBitmap bitmap; reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap); android::Bitmap* androidBitmap = reinterpret_cast<Bitmap*>(bitmapHandle); androidBitmap->getSkBitmap(&bitmap); p->writeInt32(isMutable); p->writeInt32(isMutable); p->writeInt32(bitmap.colorType()); p->writeInt32(bitmap.colorType()); Loading @@ -959,25 +1032,26 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, } } } } size_t size = bitmap.getSize(); bool ashmemSrc = androidBitmap->getAshmemFd() >= 0; if (ashmemSrc && !isMutable) { android::Parcel::WritableBlob blob; p->writeDupFileDescriptor(androidBitmap->getAshmemFd()); android::status_t status = p->writeBlob(size, &blob); } else { if (status) { Ashmem dstAshmem(bitmap.getSize(), !isMutable); doThrowRE(env, "Could not write bitmap to parcel blob."); if (!dstAshmem.getPtr()) { doThrowRE(env, "Could not allocate ashmem for new bitmap."); return JNI_FALSE; return JNI_FALSE; } } bitmap.lockPixels(); bitmap.lockPixels(); const void* pSrc = bitmap.getPixels(); const void* pSrc = bitmap.getPixels(); if (pSrc == NULL) { if (pSrc == NULL) { memset(blob.data(), 0, size); memset(dstAshmem.getPtr(), 0, bitmap.getSize()); } else { } else { memcpy(blob.data(), pSrc, size); memcpy(dstAshmem.getPtr(), pSrc, bitmap.getSize()); } } bitmap.unlockPixels(); bitmap.unlockPixels(); p->writeDupFileDescriptor(dstAshmem.getFd()); blob.release(); } return JNI_TRUE; return JNI_TRUE; } } Loading
core/jni/android/graphics/Bitmap.h +9 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ enum class PixelStorageType { Invalid, Invalid, External, External, Java, Java, Ashmem, }; }; class WrappedPixelRef; class WrappedPixelRef; Loading @@ -50,6 +51,8 @@ public: const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, void* context, FreeFunc freeFunc, Bitmap(void* address, void* context, FreeFunc freeFunc, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); Bitmap(void* address, int fd, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable); const SkImageInfo& info() const; const SkImageInfo& info() const; Loading @@ -76,6 +79,7 @@ public: bool hasHardwareMipMap(); bool hasHardwareMipMap(); void setHasHardwareMipMap(bool hasMipMap); void setHasHardwareMipMap(bool hasMipMap); int getAshmemFd() const; private: private: friend class WrappedPixelRef; friend class WrappedPixelRef; Loading Loading @@ -103,6 +107,11 @@ private: void* context; void* context; FreeFunc freeFunc; FreeFunc freeFunc; } external; } external; struct { void* address; int fd; size_t size; } ashmem; struct { struct { JavaVM* jvm; JavaVM* jvm; jweak jweakRef; jweak jweakRef; Loading
core/jni/android/graphics/Graphics.cpp +80 −0 Original line number Original line Diff line number Diff line #define LOG_TAG "GraphicsJNI" #define LOG_TAG "GraphicsJNI" #include <unistd.h> #include <sys/mman.h> #include "jni.h" #include "jni.h" #include "JNIHelp.h" #include "JNIHelp.h" #include "GraphicsJNI.h" #include "GraphicsJNI.h" Loading @@ -10,6 +13,7 @@ #include "SkMath.h" #include "SkMath.h" #include "SkRegion.h" #include "SkRegion.h" #include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h> #include <cutils/ashmem.h> #include <Caches.h> #include <Caches.h> #include <TextureCache.h> #include <TextureCache.h> Loading Loading @@ -572,6 +576,82 @@ bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ct return true; return true; } } android::Bitmap* GraphicsJNI::allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) { int fd; const SkImageInfo& info = bitmap->info(); if (info.fColorType == 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; } android::Bitmap* wrapper = new android::Bitmap(addr, fd, 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::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable, int fd, bool readOnly) { int flags; const SkImageInfo& info = bitmap->info(); if (info.fColorType == kUnknown_SkColorType) { doThrowIAE(env, "unknown bitmap configuration"); return nullptr; } // Create new ashmem region with read/write priv flags = readOnly ? (PROT_READ) : (PROT_READ | PROT_WRITE); void* addr = mmap(NULL, ashmem_get_size_region(fd), flags, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { 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(); android::Bitmap* wrapper = new android::Bitmap(addr, fd, info, rowBytes, ctable); wrapper->getSkBitmap(bitmap); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too bitmap->lockPixels(); return wrapper; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) { JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) { Loading
core/jni/android/graphics/GraphicsJNI.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -95,6 +95,12 @@ public: static android::Bitmap* allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, static android::Bitmap* allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable); SkColorTable* ctable); static android::Bitmap* allocateAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable); static android::Bitmap* mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable, int fd, bool readOnly); /** /** * Given a bitmap we natively allocate a memory block to store the contents * Given a bitmap we natively allocate a memory block to store the contents * of that bitmap. The memory is then attached to the bitmap via an * of that bitmap. The memory is then attached to the bitmap via an Loading