diff --git a/c++/palanteer.h b/c++/palanteer.h index 174389f..a14d67b 100644 --- a/c++/palanteer.h +++ b/c++/palanteer.h @@ -1297,8 +1297,8 @@ class plCliIo { #if USE_PL==1 || PL_EXPORT==1 // Library version -#define PALANTEER_VERSION "0.3" -#define PALANTEER_VERSION_NUM 300 // Monotonic number. 100 per version component. Official release are multiples of 100 +#define PALANTEER_VERSION "0.4.dev1" +#define PALANTEER_VERSION_NUM 301 // Monotonic number. 100 per version component. Official releases are multiple of 100 // Client-Server protocol version #define PALANTEER_CLIENT_PROTOCOL_VERSION 1 diff --git a/c++/test/test_instru_configuration.py b/c++/test/test_instru_configuration.py index c6d2487..3539490 100644 --- a/c++/test/test_instru_configuration.py +++ b/c++/test/test_instru_configuration.py @@ -64,7 +64,7 @@ def test_usepl1_nocontrol(): """Config PL_NOCONTROL=1""" build_target("testprogram", "USE_PL=1 PL_NOCONTROL=1") - data_configure_events(CRASH_SPEC+[spec_add_fruit]) + data_configure_events(CRASH_SPEC + [spec_add_fruit]) try: launch_testprogram() CHECK(True, "Connection established") @@ -88,7 +88,7 @@ def test_usepl1_noevent(): """Config PL_NOEVENT=1""" build_target("testprogram", "USE_PL=1 PL_NOEVENT=1") - data_configure_events(CRASH_SPEC+[spec_add_fruit]) + data_configure_events(CRASH_SPEC + [spec_add_fruit]) try: launch_testprogram() CHECK(True, "Connection established") @@ -111,7 +111,7 @@ def test_usepl1_noassert(): """Config PL_NOASSERT=1""" build_target("testprogram", "USE_PL=1 PL_NOASSERT=1") - data_configure_events(CRASH_SPEC+[spec_add_fruit]) + data_configure_events(CRASH_SPEC + [spec_add_fruit]) try: launch_testprogram( pass_first_freeze_point=True diff --git a/docs/more.md.html b/docs/more.md.html index d618791..4cecc34 100644 --- a/docs/more.md.html +++ b/docs/more.md.html @@ -379,10 +379,14 @@

@@ More

- **Use asserts** - They greatly speed up the bug investigation by crashing "nicely" close to the inconsistency. - Their impact on performance is usually low because data is already in the cache/registers so a test is ~1 CPU cycle. - - Also, if `Palanteer` is used, groups of asserts can be enabled on demand at compile-time, which can greatly speed-up investigations + - Also, if `Palanteer` is used, groups of asserts can be enabled on demand at compile-time - Keep the condition as a simple check, never perform actions inside an assertion as it may be disabled at compile time. - Never assert on external inputs, as they are not under control. +- **For time related constant/variable, always include the unit in the name (exemple: `timeout_msec`)** + - Such bugs due to confusion on units are so frequent and so easy to avoid... + - Mistake on time units are the more representative, but this hint is applicable to all units as soon as there may be some ambiguity + - **Use address sanitizers (ASAN)** whenever possible - It is built-in in `gcc` and `clang`, enabled with a few compilation/linking flags - The reported issues (uninitialized memory read, leaks...) would be very hard to track without such class of tool. diff --git a/server/base/bsOs.h b/server/base/bsOs.h index 39d101c..a3e1c38 100644 --- a/server/base/bsOs.h +++ b/server/base/bsOs.h @@ -71,7 +71,7 @@ void osCreateWindow(const char* windowTitle, const char* configName, bool overrideWindowManager=false); void osDestroyWindow(void); void osSetWindowTitle(const bsString& title); -void osGetWindowSize(int& width, int& height); +void osGetWindowSize(int& width, int& height, int& dpiWidth, int& dpiHeight); void osProcessInputs(bsOsHandler* osHandler); void osHideWindow(void); void osShowWindow(void); diff --git a/server/base/bsOsLinux.cpp b/server/base/bsOsLinux.cpp index ca64c2a..3190d33 100644 --- a/server/base/bsOsLinux.cpp +++ b/server/base/bsOsLinux.cpp @@ -67,8 +67,10 @@ static struct { Cursor noCursor = None; Cursor defaultCursor = None; Cursor currentCursor = None; - int wWidth = -1; - int wHeight = -1; + int wWidth = -1; + int wHeight = -1; + int dpiWidth = -1; + int dpiHeight = -1; // Character inputs XIM xInputMethod = 0; // Input method linked to the X display XIC xInputContext = 0; // Input context used to gete unicode input in our window @@ -167,13 +169,22 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, attr.override_redirect = gGlob.isDirectOverride; attr.event_mask = StructureNotifyMask | EnterWindowMask | LeaveWindowMask | ExposureMask | ButtonPressMask | PointerMotionMask | ButtonReleaseMask | OwnerGrabButtonMask | FocusChangeMask | KeyPressMask | KeyReleaseMask; - int attr_mask = CWBackPixmap | CWColormap | CWBorderPixel| CWEventMask | CWOverrideRedirect ; - int dWidth = DisplayWidth (gGlob.xDisplay, DefaultScreen(gGlob.xDisplay)); - int dHeight = DisplayHeight(gGlob.xDisplay, DefaultScreen(gGlob.xDisplay)); + int attr_mask = CWBackPixmap | CWColormap | CWBorderPixel| CWEventMask | CWOverrideRedirect; + int defaultScreenId = DefaultScreen(gGlob.xDisplay); + int dWidth = DisplayWidth (gGlob.xDisplay, defaultScreenId); // In pixel + int dHeight = DisplayHeight (gGlob.xDisplay, defaultScreenId); + + // Compute DPI +#define COMPUTE_DPI(pix, mm) (int)(9.6*((int)(((double)pix)/((double)mm)*(254./96.)+0.5))) /* Quantize the DPI each 5%, to clean approximated values */ + int dWidthMm = DisplayWidthMM (gGlob.xDisplay, defaultScreenId); // In millimeter + int dHeightMm = DisplayHeightMM(gGlob.xDisplay, defaultScreenId); + gGlob.dpiWidth = COMPUTE_DPI(dWidth, dWidthMm); + gGlob.dpiHeight = COMPUTE_DPI(dHeight, dHeightMm); + int x = (int)(ratioLeft *(float)dWidth); int y = (int)(ratioTop *(float)dHeight); - gGlob.wWidth = (int)((ratioRight-ratioLeft)*(float)dWidth); - gGlob.wHeight = (int)((ratioBottom-ratioTop)*(float)dHeight); + gGlob.wWidth = (int)((ratioRight-ratioLeft)*(float)dWidth); + gGlob.wHeight = (int)((ratioBottom-ratioTop)*(float)dHeight); gGlob.windowHandle = XCreateWindow(gGlob.xDisplay, Xroot, x, y, gGlob.wWidth, gGlob.wHeight, 0, visual->depth, InputOutput, visual->visual, attr_mask, &attr); gGlob.glXWindowHandle = gGlob.windowHandle; @@ -209,7 +220,7 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, gGlob.xInputMethod = XOpenIM(gGlob.xDisplay, NULL, NULL, NULL); if(gGlob.xInputMethod) { gGlob.xInputContext = XCreateIC(gGlob.xInputMethod, XNClientWindow, gGlob.glXWindowHandle, XNFocusWindow, gGlob.glXWindowHandle, - XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); } // Create the OpenGL 3.0 context @@ -272,10 +283,12 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, // =============== void -osGetWindowSize(int& width, int& height) +osGetWindowSize(int& width, int& height, int& dpiWidth, int& dpiHeight) { - width = gGlob.wWidth; - height = gGlob.wHeight; + width = gGlob.wWidth; + height = gGlob.wHeight; + dpiWidth = gGlob.dpiWidth; + dpiHeight = gGlob.dpiHeight; } diff --git a/server/base/bsOsWindows.cpp b/server/base/bsOsWindows.cpp index 6e29686..08c7829 100644 --- a/server/base/bsOsWindows.cpp +++ b/server/base/bsOsWindows.cpp @@ -67,6 +67,8 @@ static struct { int windowWidth = -1; int windowHeight = -1; + int dpiWidth = 96; + int dpiHeight = 96; HINSTANCE hInstance = 0; int nCmdShow = -1; LPTSTR windowClass; // Window Class @@ -101,6 +103,16 @@ showMessage(LPCWSTR message) // Forward declaration static LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); +// DPI awareness and getters from Dear Imgui, file backends/imgui_impl_win32.cpp +#ifndef DPI_ENUMS_DECLARED +typedef enum { MDT_EFFECTIVE_DPI = 0, MDT_ANGULAR_DPI = 1, MDT_RAW_DPI = 2, MDT_DEFAULT = MDT_EFFECTIVE_DPI } MONITOR_DPI_TYPE; +#endif +#ifndef _DPI_AWARENESS_CONTEXTS_ +DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE (DPI_AWARENESS_CONTEXT)-3 +#endif +typedef HRESULT(WINAPI* PFN_GetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); // Shcore.lib + dll, Windows 8.1+ + void osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, float ratioTop, float ratioRight, float ratioBottom, bool overrideWindowManager) @@ -112,6 +124,9 @@ osCreateWindow(const char* windowTitle, const char* configName, float ratioLeft, plAssert(ratioLeftgetConfig().getFontSize(); + ImGui::GetStyle().ScaleAllSizes(_dpiScale); // @#TODO: set window size & pos from config. And show the window only after that @@ -465,16 +469,15 @@ vwPlatform::installFont(const void* fontData, int fontDataSize, int fontSize) bool vwPlatform::redraw(void) { - // Filter out some redraw based on the dirtyness of the state. - // Due to imgui which requires several frames to handle user events properly, we batch the display. - // Also we do a "bounce" after a delay, which is needed for some tooltip to appear, even if no user event occurs. + // Filter out some redraw based on the dirtiness of the display state. + // Dear Imgui requires several frames to handle user events properly, so we display per batch. + // Also a "bounce" is required after a delay for some tooltip to appear, even if no user event occurs. bsUs_t currentTimeUs = bsGetClockUs(); - u64 tmp = _dirtyRedrawCount.load(); + u64 tmp = _dirtyRedrawCount.load(); int dirtyRedrawCount = (int)(tmp&0xFFFFFFFF); int bounceCount = (int)((tmp>>32)&0xFFFFFFFF); - if(dirtyRedrawCount<=0 && // Not a dirty display or... - !(bounceCount==1 && currentTimeUs-_lastRenderingTimeUs>=BOUNCE_RENDER_GAP_US)) { // not (we need a bounce and waited enough) - return false; // Nothing to display + if(dirtyRedrawCount<=0 && !(bounceCount==1 && currentTimeUs-_lastRenderingTimeUs>=BOUNCE_RENDER_GAP_US)) { + return false; // Display is not dirty and it is not a bounce time: nothing to display } #define WRITE_DIRTY_COUNT(drc,bc) _dirtyRedrawCount.store((((u64)bc)<<32) | ((u32)(drc&0xFFFFFFFF))) if(dirtyRedrawCount>=0) { @@ -492,7 +495,8 @@ vwPlatform::redraw(void) // Change font, if needed if(_newFontSizeToInstall>0) { - installFont(vwGetFontDataRobotoMedium(), vwGetFontDataSizeRobotoMedium(), _newFontSizeToInstall); + installFont(vwGetFontDataRobotoMedium(), vwGetFontDataSizeRobotoMedium(), + bsRound(_dpiScale*_newFontSizeToInstall)); _newFontSizeToInstall = -1; } diff --git a/server/viewer/vwPlatform.h b/server/viewer/vwPlatform.h index 9ae3ea6..d3a7b60 100644 --- a/server/viewer/vwPlatform.h +++ b/server/viewer/vwPlatform.h @@ -87,6 +87,7 @@ class vwPlatform : public bsOsHandler { // ImGui & OpenGL int _displayWidth = -1; int _displayHeight = -1; + float _dpiScale = 1.; bsUs_t _lastUpdateDurationUs = 1; // Update only bsUs_t _lastRenderingDurationUs = 1; // Update and OpenGL rendering bsUs_t _lastRenderingTimeUs = 0; diff --git a/tools/testframework.py b/tools/testframework.py index 8a90392..9b6aec6 100755 --- a/tools/testframework.py +++ b/tools/testframework.py @@ -222,7 +222,10 @@ class _TestFailedError(Exception): # Public CRASH_SPEC -CRASH_SPEC = [palanteer_scripting.EvtSpec("CRASH Stacktrace"), palanteer_scripting.EvtSpec(parent="CRASH Stacktrace", events=["*"])] +CRASH_SPEC = [ + palanteer_scripting.EvtSpec("CRASH Stacktrace"), + palanteer_scripting.EvtSpec(parent="CRASH Stacktrace", events=["*"]), +] # Used server port (better if different from the viewer's one) SERVER_PORT = 59060