Merge pull request #182 from alexey-pelykh/newNdkBranch

Fix of stride vs rowBytes, added direct rendering where supported
This commit is contained in:
vshcherb 2012-03-01 07:48:01 -08:00
commit 3981dec18f
5 changed files with 139 additions and 35 deletions

View file

@ -1,6 +1,5 @@
# This is built only for ARMv5
ifneq ($(TARGET_ARCH_ABI),armeabi-v7a)
ifneq ($(LOCAL_ARM_NEON),true)
# Do not build for NEON
ifneq ($(OSMAND_NEON),true)
LOCAL_PATH := $(call my-dir)
@ -19,4 +18,3 @@ include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)
endif
endif

View file

@ -53,6 +53,6 @@ else
LOCAL_STATIC_LIBRARIES := proto_neon skia_neon
endif
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS := -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)

View file

@ -4,6 +4,7 @@
#include <jni.h>
#include <math.h>
#include <android/log.h>
#include <android/bitmap.h>
#include <stdio.h>
#include <vector>
#include <set>
@ -697,10 +698,118 @@ void loadJNIRendering(){
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_generateRendering_1Direct( JNIEnv* ienv, jobject obj,
jobject renderingContext, jint searchResult,
jobject targetBitmap,
jboolean useEnglishNames, jobject renderingRuleSearchRequest, jint defaultColor) {
setGlobalEnv(ienv);
// Gain information about bitmap
AndroidBitmapInfo bitmapInfo;
if(AndroidBitmap_getInfo(ienv, targetBitmap, &bitmapInfo) != ANDROID_BITMAP_RESUT_SUCCESS) {
__android_log_print(ANDROID_LOG_ERROR, "net.osmand", "Failed to execute AndroidBitmap_getInfo");
}
sprintf(debugMessage, "Creating SkBitmap in native w:%d h:%d s:%d f:%d!", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride, bitmapInfo.format);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
SkBitmap* bitmap = new SkBitmap();
if(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
int rowBytes = bitmapInfo.stride;
sprintf(debugMessage, "Row bytes for RGBA_8888 is %d", rowBytes);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
bitmap->setConfig(SkBitmap::kARGB_8888_Config, bitmapInfo.width, bitmapInfo.height, rowBytes);
} else if(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565) {
int rowBytes = bitmapInfo.stride;
sprintf(debugMessage, "Row bytes for RGB_565 is %d", rowBytes);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
bitmap->setConfig(SkBitmap::kRGB_565_Config, bitmapInfo.width, bitmapInfo.height, rowBytes);
} else {
__android_log_print(ANDROID_LOG_ERROR, "net.osmand", "Unknown target bitmap format");
}
void* lockedBitmapData = NULL;
if(AndroidBitmap_lockPixels(ienv, targetBitmap, &lockedBitmapData) != ANDROID_BITMAP_RESUT_SUCCESS || !lockedBitmapData) {
__android_log_print(ANDROID_LOG_ERROR, "net.osmand", "Failed to execute AndroidBitmap_lockPixels");
}
sprintf(debugMessage, "Locked %d bytes at %p", bitmap->getSize(), lockedBitmapData);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
bitmap->setPixels(lockedBitmapData);
SkCanvas* canvas = new SkCanvas(*bitmap);
canvas->drawColor(defaultColor);
SkPaint* paint = new SkPaint;
paint->setAntiAlias(true);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Initializing rendering");
watcher initObjects;
initObjects.start();
RenderingRuleSearchRequest* req = initSearchRequest(renderingRuleSearchRequest);
RenderingContext rc;
copyRenderingContext(renderingContext, &rc);
rc.useEnglishNames = useEnglishNames;
SearchResult* result = ((SearchResult*) searchResult);
// std::vector <BaseMapDataObject* > mapDataObjects = marshalObjects(binaryMapDataObjects);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "Rendering image");
initObjects.pause();
// Main part do rendering
rc.nativeOperations.start();
if(result != NULL) {
doRendering(result->result, canvas, paint, req, &rc);
}
rc.nativeOperations.pause();
mergeRenderingContext(renderingContext, &rc);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", "End Rendering image");
if(AndroidBitmap_unlockPixels(ienv, targetBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) {
__android_log_print(ANDROID_LOG_ERROR, "net.osmand", "Failed to execute AndroidBitmap_unlockPixels");
}
// delete variables
delete paint;
delete canvas;
delete req;
delete bitmap;
// deleteObjects(mapDataObjects);
jclass resultClass = ienv->FindClass("net/osmand/plus/render/NativeOsmandLibrary$RenderingGenerationResult");
if(!resultClass)
resultClass = ienv->FindClass("net/osmand/render/NativeOsmandLibrary$RenderingGenerationResult");
sprintf(debugMessage, "Result class = %p", resultClass);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
jmethodID resultClassCtorId = ienv->GetMethodID(resultClass, "<init>", "(Ljava/nio/ByteBuffer;Ljava/lang/String;)V");
sprintf(debugMessage, "Result class ctor = %p", resultClassCtorId);
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
#ifdef DEBUG_NAT_OPERATIONS
sprintf(debugMessage, "Native ok (init %d, native op %d) ", initObjects.getElapsedTime(), rc.nativeOperations.getElapsedTime());
#else
sprintf(debugMessage, "Native ok (init %d, rendering %d) ", initObjects.getElapsedTime(), rc.nativeOperations.getElapsedTime());
#endif
__android_log_print(ANDROID_LOG_WARN, "net.osmand", debugMessage);
// Allocate ctor paramters
jstring message = globalEnv()->NewStringUTF(debugMessage);
/* Construct a result object */
jobject resultObject = ienv->NewObject(resultClass, resultClassCtorId, NULL, message);
return resultObject;
}
void* bitmapData = NULL;
size_t bitmapDataSize = 0;
JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_generateRendering( JNIEnv* ienv, jobject obj,
jobject renderingContext, jint searchResult, jint requestedBitmapWidth, jint requestedBitmapHeight, jboolean isTransparent,
JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_generateRendering_1Indirect( JNIEnv* ienv, jobject obj,
jobject renderingContext, jint searchResult,
jint requestedBitmapWidth, jint requestedBitmapHeight, jint rowBytes, jboolean isTransparent,
jboolean useEnglishNames, jobject renderingRuleSearchRequest, jint defaultColor) {
setGlobalEnv(ienv);
@ -709,11 +818,10 @@ JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_genera
SkBitmap* bitmap = new SkBitmap();
if(isTransparent == JNI_TRUE)
bitmap->setConfig(SkBitmap::kARGB_8888_Config, requestedBitmapWidth, requestedBitmapHeight);
bitmap->setConfig(SkBitmap::kARGB_8888_Config, requestedBitmapWidth, requestedBitmapHeight, rowBytes);
else
bitmap->setConfig(SkBitmap::kRGB_565_Config, requestedBitmapWidth, requestedBitmapHeight);
bitmap->setConfig(SkBitmap::kRGB_565_Config, requestedBitmapWidth, requestedBitmapHeight, rowBytes);
// re]allocate buffer only if size changed in greated direction?
if(bitmapData != NULL && bitmapDataSize != bitmap->getSize()) {
free(bitmapData);
bitmapData = NULL;
@ -794,23 +902,6 @@ JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_genera
return resultObject;
}
JNIEXPORT jobject JNICALL Java_net_osmand_plus_render_NativeOsmandLibrary_releaseRenderingGenerationResults( JNIEnv* ienv, jobject obj,
jobject results) {
setGlobalEnv(ienv);
// Not needed
/*
jclass resultClass = ienv->FindClass("net/osmand/plus/render/NativeOsmandLibrary$RenderingGenerationResult");
if(!resultClass)
resultClass = ienv->FindClass("net/osmand/render/NativeOsmandLibrary$RenderingGenerationResult");
jfieldID resultClass_bitmapBuffer = globalEnv()->GetFieldID(resultClass, "bitmapBuffer", "Ljava/nio/ByteBuffer;");
jobject bitmapBuffer = globalEnv()->GetObjectField(results, resultClass_bitmapBuffer);
void *buffer = ienv->GetDirectBufferAddress(bitmapBuffer);
free(buffer);
*/
}
#ifdef __cplusplus
}
#endif

View file

@ -26,6 +26,10 @@ public class NativeOsmandLibrary {
System.loadLibrary("stlport_shared");
log.debug("Loading native cpufeatures_proxy..."); //$NON-NLS-1$
System.loadLibrary("cpufeatures_proxy");
if(android.os.Build.VERSION.SDK_INT >= 8) {
log.debug("Loading jnigraphics, since Android >= 2.2 ..."); //$NON-NLS-1$
System.loadLibrary("jnigraphics");
}
if(!cpuHasNeonSupport()) {
log.debug("Loading native osmand..."); //$NON-NLS-1$
System.loadLibrary("osmand");
@ -66,12 +70,16 @@ public class NativeOsmandLibrary {
}
public RenderingGenerationResult generateRendering(RenderingContext rc, NativeSearchResult searchResultHandler,
int requestedBitmapWidth, int requestedBitmapHeight, boolean isTransparent,
Bitmap bitmap, int requestedBitmapWidth, int requestedBitmapHeight, int rowBytes, boolean isTransparent,
boolean useEnglishNames, RenderingRuleSearchRequest render, int defaultColor) {
if (searchResultHandler == null) {
return new RenderingGenerationResult(null, "Error searchresult = null");
}
return generateRendering(rc, searchResultHandler.nativeHandler, requestedBitmapWidth, requestedBitmapHeight, isTransparent, useEnglishNames, render, defaultColor);
if(android.os.Build.VERSION.SDK_INT >= 8) // Android 2.2+
return generateRendering_Direct(rc, searchResultHandler.nativeHandler, bitmap, useEnglishNames, render, defaultColor);
else
return generateRendering_Indirect(rc, searchResultHandler.nativeHandler, requestedBitmapWidth, requestedBitmapHeight, rowBytes, isTransparent, useEnglishNames, render, defaultColor);
}
/**
@ -139,10 +147,12 @@ public class NativeOsmandLibrary {
private static native void initRenderingRulesStorage(RenderingRulesStorage storage);
private static native RenderingGenerationResult generateRendering(RenderingContext rc, int searchResultHandler,
int requestedBitmapWidth, int requestedBitmapHeight, boolean isTransparent, boolean useEnglishNames,
private static native RenderingGenerationResult generateRendering_Indirect(RenderingContext rc, int searchResultHandler,
int requestedBitmapWidth, int requestedBitmapHeight, int rowBytes, boolean isTransparent, boolean useEnglishNames,
RenderingRuleSearchRequest render, int defaultColor);
private static native RenderingGenerationResult generateRendering_Direct(RenderingContext rc, int searchResultHandler,
Bitmap bitmap, boolean useEnglishNames,
RenderingRuleSearchRequest render, int defaultColor);
public static native void releaseRenderingGenerationResults(RenderingGenerationResult results);
private static native int searchObjectsForRendering(int sleft, int sright, int stop, int sbottom, int zoom, String mapnaem,
RenderingRuleSearchRequest request, boolean skipDuplicates, int searchResultHandler, Object objectWithInterruptedField);

View file

@ -214,8 +214,13 @@ public class OsmandRenderer {
final Handler h = new Handler(Looper.getMainLooper());
notifyListenersWithDelay(rc, notifyList, h);
}
final NativeOsmandLibrary.RenderingGenerationResult res = library.generateRendering(rc, searchResultHandler,
bmp.getWidth(), bmp.getHeight(), bmp.hasAlpha(),
// Native library will decide on it's own best way of rendering
// If res.bitmapBuffer is null, it indicates that rendering was done directly to
// memory of passed bitmap, but this is supported only on Android >= 2.2
final NativeOsmandLibrary.RenderingGenerationResult res = library.generateRendering(
rc, searchResultHandler,
bmp, bmp.getWidth(), bmp.getHeight(), bmp.getRowBytes(), bmp.hasAlpha(),
useEnglishNames, render, defaultColor);
rc.ended = true;
notifyListeners(notifyList);
@ -224,9 +229,9 @@ public class OsmandRenderer {
+ "(%s points, %s points inside, %s of %s objects visible)\n" + res.debugMessage,//$NON-NLS-1$
time, rc.textRenderingTime, rc.pointCount, rc.pointInsideCount, rc.visible, rc.allObjects);
// See upper note
if(res.bitmapBuffer != null) {
bmp.copyPixelsFromBuffer(res.bitmapBuffer);
NativeOsmandLibrary.releaseRenderingGenerationResults(res);
}
} catch (Exception e) {
e.printStackTrace();