diff options
author | Robin Watts <robin.watts@artifex.com> | 2018-03-26 17:27:43 +0100 |
---|---|---|
committer | Sebastian Rasmussen <sebras@gmail.com> | 2018-04-03 22:27:39 +0800 |
commit | 73867ca96bbd6f45ffafde234c22cbcf0489ea57 (patch) | |
tree | cba2fed0d7e94fcf6a069170b205c1c0dcd22282 | |
parent | b8dd674459a15ccffe49eff0c2b89dd0e22ac393 (diff) | |
download | mupdf-73867ca96bbd6f45ffafde234c22cbcf0489ea57.tar.xz |
Android: Scavenge on Bitmap.lockPixels() failure.
If Bitmap.lockPixels fails with an allocation error, scavenge in
the store.
-rw-r--r-- | include/mupdf/fitz/store.h | 12 | ||||
-rw-r--r-- | platform/java/mupdf_native.c | 27 | ||||
-rw-r--r-- | source/fitz/store.c | 11 |
3 files changed, 48 insertions, 2 deletions
diff --git a/include/mupdf/fitz/store.h b/include/mupdf/fitz/store.h index 5b048ed0..7dff6c30 100644 --- a/include/mupdf/fitz/store.h +++ b/include/mupdf/fitz/store.h @@ -243,6 +243,18 @@ void fz_empty_store(fz_context *ctx); int fz_store_scavenge(fz_context *ctx, size_t size, int *phase); /* + fz_store_scavenge_external: External function for callers to use + to scavenge while trying allocations. + + size: The number of bytes we are trying to have free. + + phase: What phase of the scavenge we are in. Updated on exit. + + Returns non zero if we managed to free any memory. +*/ +int fz_store_scavenge_external(fz_context *ctx, size_t size, int *phase); + +/* fz_shrink_store: Evict items from the store until the total size of the objects in the store is reduced to a given percentage of its current size. diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c index 29c427b7..8af0b8a4 100644 --- a/platform/java/mupdf_native.c +++ b/platform/java/mupdf_native.c @@ -2556,6 +2556,7 @@ struct NativeDeviceInfo int xOffset; int yOffset; int width; + int height; }; static NativeDeviceInfo *lockNativeDevice(JNIEnv *env, jobject self, int *err) @@ -3268,6 +3269,7 @@ newNativeAndroidDrawDevice(JNIEnv *env, jobject self, fz_context *ctx, jobject o ninfo->xOffset = patchX0; ninfo->yOffset = patchY0; ninfo->width = width; + ninfo->height = height; ninfo->object = obj; (*env)->SetLongField(env, self, fid_NativeDevice_nativeInfo, jlong_cast(ninfo)); (*env)->SetObjectField(env, self, fid_NativeDevice_nativeResource, obj); @@ -3301,11 +3303,22 @@ newNativeAndroidDrawDevice(JNIEnv *env, jobject self, fz_context *ctx, jobject o static int androidDrawDevice_lock(JNIEnv *env, NativeDeviceInfo *info) { uint8_t *pixels; + int ret; + int phase = 0; + fz_context *ctx = get_context(env); + size_t size = info->width * info->height * 4; assert(info); assert(info->object); - if (AndroidBitmap_lockPixels(env, info->object, (void **)&pixels) != ANDROID_BITMAP_RESULT_SUCCESS) + while (1) { + ret = AndroidBitmap_lockPixels(env, info->object, (void **)&pixels); + if (ret == ANDROID_BITMAP_RESULT_SUCCESS) + break; + if (!fz_store_scavenge_external(ctx, size, &phase)) + break; /* Failed to free any */ + } + if (ret != ANDROID_BITMAP_RESULT_SUCCESS) { info->pixmap->samples = NULL; jni_throw(env, FZ_ERROR_GENERIC, "bitmap lock failed in DrawDevice call"); @@ -3386,8 +3399,18 @@ FUN(AndroidImage_newImageFromBitmap)(JNIEnv *env, jobject self, jobject jbitmap, fz_try(ctx) { + int ret; + int phase = 0; + size_t size = info.width * info.height * 4; pixmap = fz_new_pixmap(ctx, fz_device_rgb(ctx), info.width, info.height, NULL, 1); - if (AndroidBitmap_lockPixels(env, jbitmap, &pixels) != ANDROID_BITMAP_RESULT_SUCCESS) + while (1) { + ret = AndroidBitmap_lockPixels(env, jbitmap, (void **)&pixels); + if (ret == ANDROID_BITMAP_RESULT_SUCCESS) + break; + if (!fz_store_scavenge_external(ctx, size, &phase)) + break; /* Failed to free any */ + } + if (ret != ANDROID_BITMAP_RESULT_SUCCESS) fz_throw(ctx, FZ_ERROR_GENERIC, "bitmap lock failed in new Image"); memcpy(pixmap->samples, pixels, info.width * info.height * 4); if (AndroidBitmap_unlockPixels(env, jbitmap) != ANDROID_BITMAP_RESULT_SUCCESS) diff --git a/source/fitz/store.c b/source/fitz/store.c index f94a8aa2..f0d7c795 100644 --- a/source/fitz/store.c +++ b/source/fitz/store.c @@ -776,6 +776,17 @@ scavenge(fz_context *ctx, size_t tofree) return count != 0; } +int fz_store_scavenge_external(fz_context *ctx, size_t size, int *phase) +{ + int ret; + + fz_lock(ctx, FZ_LOCK_ALLOC); + ret = fz_store_scavenge(ctx, size, phase); + fz_unlock(ctx, FZ_LOCK_ALLOC); + + return ret; +} + int fz_store_scavenge(fz_context *ctx, size_t size, int *phase) { fz_store *store; |