Merge pull request #182 from alexey-pelykh/newNdkBranch
Fix of stride vs rowBytes, added direct rendering where supported
This commit is contained in:
commit
3981dec18f
5 changed files with 139 additions and 35 deletions
|
@ -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
|
|
@ -53,6 +53,6 @@ else
|
|||
LOCAL_STATIC_LIBRARIES := proto_neon skia_neon
|
||||
endif
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
LOCAL_LDLIBS := -llog -ljnigraphics
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue