From 48767a40c2461405dfce14e8d9eafbbab21d203e Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 13 Jan 2012 16:13:40 +0100 Subject: NEWT/OSX Performance Fix: Cache CGDisplayScreenSize() result, since it's ridiculous slow Each call to CGDisplayScreenSize() took around 6ms (5ms .. 20ms, avrg 6ms) which added up to ~2s for ~400 Screen modes. --- make/build-newt.xml | 1 + .../jogamp/newt/driver/macosx/MacScreen.java | 26 +++++++-- src/newt/native/MacWindow.m | 62 ++++++++++++++++++++-- 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/make/build-newt.xml b/make/build-newt.xml index ac220c7b4..c812d98f3 100644 --- a/make/build-newt.xml +++ b/make/build-newt.xml @@ -531,6 +531,7 @@ + diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java index 3204982be..b9c725fd4 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java @@ -38,16 +38,24 @@ import java.util.List; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Point; import jogamp.newt.ScreenImpl; +import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.newt.ScreenMode; import com.jogamp.newt.util.ScreenModeUtil; public class MacScreen extends ScreenImpl { + + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + private static IntObjectHashMap/**/ scrnIdx2Dimension; + static { MacDisplay.initSingleton(); + scrnIdx2Dimension = new IntObjectHashMap(); + scrnIdx2Dimension.setKeyNotFoundValue(null); } public MacScreen() { @@ -63,7 +71,18 @@ public class MacScreen extends ScreenImpl { private static native int getHeightImpl0(int scrn_idx); private int[] getScreenModeIdx(int idx) { - int[] modeProps = getScreenMode0(screen_idx, idx); + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx); + if(null == dim) { + int[] res = getScreenSizeMM0(screen_idx); + if(null == res || 0 == res.length) { + return null; + } + dim = new Dimension(res[0], res[1]); + scrnIdx2Dimension.put(screen_idx, dim); + } + + int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight()); if (null == modeProps || 0 == modeProps.length) { return null; } @@ -117,7 +136,8 @@ public class MacScreen extends ScreenImpl { virtualSize.setWidth(getWidthImpl0(screen_idx)); virtualSize.setHeight(getHeightImpl0(screen_idx)); } - - private native int[] getScreenMode0(int screen_index, int mode_index); + + private native int[] getScreenSizeMM0(int screen_idx); + private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM); private native boolean setScreenMode0(int screen_index, int mode_idx); } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index ddd59f0a1..c528ebb64 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -44,6 +44,10 @@ #import +#ifdef DBG_PERF + #include "timespec.h" +#endif + static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point"; static const char * const ClazzAnyCstrName = ""; static const char * const ClazzNamePointCstrSignature = "(II)V"; @@ -313,13 +317,62 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) // For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270] #define ROTMODES_PER_REALMODE 4 +/* + * Class: jogamp_newt_driver_macosx_MacScreen + * Method: getScreenSizeMM0 + * Signature: (I)[I + */ +JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSizeMM0 + (JNIEnv *env, jobject obj, jint scrn_idx) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + +#ifdef DBG_PERF + struct timespec t0, t1, td; + long td_ms; + timespec_now(&t0); +#endif + + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL); +#endif + + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL); +#endif + + CGSize screenDim = CGDisplayScreenSize(display); +#ifdef DBG_PERF + timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td); + fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL); +#endif + + jint prop[ 2 ]; + prop[0] = (jint) screenDim.width; + prop[1] = (jint) screenDim.height; + + jintArray properties = (*env)->NewIntArray(env, 2); + if (properties == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2"); + } + (*env)->SetIntArrayRegion(env, properties, 0, 2, prop); + + [pool release]; + + return properties; +} + /* * Class: jogamp_newt_driver_macosx_MacScreen * Method: getScreenMode0 - * Signature: (II)[I + * Signature: (IIII)[I */ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0 - (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx) + (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; @@ -360,7 +413,6 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo } // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef - CGSize screenDim = CGDisplayScreenSize(display); int mWidth = CGDDGetModeWidth(mode); int mHeight = CGDDGetModeHeight(mode); @@ -383,8 +435,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo prop[propIndex++] = mWidth; prop[propIndex++] = mHeight; prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); - prop[propIndex++] = (jint) screenDim.width; - prop[propIndex++] = (jint) screenDim.height; + prop[propIndex++] = widthMM; + prop[propIndex++] = heightMM; prop[propIndex++] = CGDDGetModeRefreshRate(mode); prop[propIndex++] = ccwRot; prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL -- cgit v1.2.3