It's because usually your FB app doesn't opt-in to do its own scaling, so when you/fbgfx creates the 800x600 window, Windows scales it up to keep the effective 800x600 resolution. In full screen mode, the resolution really is 800x600 but Windows still scales the window hence it looks wrong despite the output being exactly the same, its just cropped to the top left 800x600 corner of the window.
Opting in to DPI scaling before the Screen/ScreenRes will create an 800x600 window, with no scaling so fullscreen looks great. You're then on the hook for scaling up things in windowed mode to keep your effective 800x600 resolution. If not, at 150% scaling you'll have an equivalent window size of 533x400 and it'll only get smaller from there.
A solution where you opt-in and leave it all to fbgfx will have the same results as now whichever way it works. If it scales up, it will look a bit blurry as the 800x600 canvas will have to be blown up to keep the effective resolution or if it leaves it alone, the window will get smaller and smaller as the scaling factor increases.
You can opt in by saving this as <your-exe-name>.manifest
So if your exe is superfile.exe, you'd save it in the same directory as superfile.exe.manifest
Code: Select all
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Here's a slightly modified version of the OP that displays the dpi status
Code: Select all
' Windows 10 bug 3D cube and orb test
#include "fbgfx.bi"
#include "windows.bi"
#include "crt/stdio.bi"
#define GPA(x, dll) x = cast(TypeOf(x), GetProcAddress(dll, #x))
Dim GetProcessDpiAwareness as Function stdcall (ByVal h as Any Ptr, ByVal awareness as Long Ptr) as Long
Dim GetThreadDpiAwarenessContext as Function stdcall() As Any Ptr
Dim GetDpiForWindow as Function stdcall (ByVal h as Any Ptr) as ULong
Dim GetSystemDpiForProcess as Function stdcall(ByVal h As Any Ptr) As ULong
Dim GetDpiForSystem As Function stdcall() As ULong
Dim AreDpiAwarenessContextsEqual as Function stdcall(ByVal a as Any Ptr, ByVal b as Any Ptr) As Long
Dim as HMODULE hShCore = LoadLibrary("shcore.dll")
Dim as HMODULE hUser32 = GetModuleHandle("user32.dll")
GPA(GetProcessDpiAwareness, hShCore)
GPA(GetThreadDpiAwarenessContext, hUser32)
GPA(GetDpiForWindow, hUser32)
GPA(GetDpiForSystem, hUser32)
GPA(GetSystemDpiForProcess, hUser32)
GPA(AreDpiAwarenessContextsEqual, hUser32)
enum DpiAwareness
DA_None = 0,
DA_SystemAware = 1,
DA_PerMonitorAware = 2
End Enum
const DAC_Unaware = -1
const DAC_System_Aware = -2
const DAC_Per_Monitor_Aware = -3
const DAC_Per_Monitor_V2_Aware = -4
const DAC_Unaware_GDIScaled = -5
''Screenres 800,600,32 ' This works
'Screen 19,32 ' This works
Screenres 800,600,32,1,1 ' FullScreen This squashes cube and orb
'Screen 19,32,1,1 ' FullScreen This squashes cube and orb
cls
Dim msg as ZString * 250
Dim as integer pwnd
ScreenControl fb.GET_WINDOW_HANDLE, pwnd
If (GetThreadDpiAwarenessContext) AndAlso (AreDpiAwarenessContextsEqual) Then
dim as Any Ptr threadCtx = GetThreadDpiAwarenessContext()
Dim as Any Ptr pmv2Ctx = cast(Any Ptr, DAC_Per_Monitor_V2_Aware)
Dim as Long isPMV2 = AreDpiAwarenessContextsEqual(threadCtx, pmV2Ctx)
snprintf(msg, 250, "Thread Awareness Context: %s/%#x", IIf(isPMV2 <> 0, "PMv2", "Not PMv2"), threadCtx)
Draw String (0, 0), msg
End If
dim as Any Ptr curProc = GetCurrentProcess()
Dim as DpiAwareness procAwareness = DA_None
If(GetProcessDpiAwareness) Then
GetProcessDpiAwareness(curProc, @procAwareness)
snprintf(msg, 250, "Proc Awareness: %#x", procAwareness)
Draw String (0, 30), msg
End If
If GetSystemDpiForProcess Then
Dim as ULong sysAwareness = GetSystemDpiForProcess(curProc)
snprintf(msg, 250, "Sys Proc Dpi: %lu", sysAwareness)
Draw String (250, 30), msg
End If
If GetDpiForWindow Then
Dim as ULong winDpi = GetDpiForWindow(cast(any Ptr, pwnd))
snprintf(msg, 250, "Window DPI: %lu", winDpi)
Draw String (0, 45), msg
End If
If GetDpiForSystem Then
Dim as ULong sysDpi = GetDpiForSystem()
snprintf(msg, 250, "System DPI: %lu", sysDpi)
Draw String (250, 45), msg
End If
Dim As Single x,y
Dim As Ubyte Alpha,i,r, Red, Green, Blue
Line (100,100)-(100,300)
Line (100,100)-(300,100)
Line (300,100)-(300,300)
Line (300,300)-(100,300)
Line (200,200)-(200,400)
Line (200,200)-(400,200)
Line (400,200)-(400,400)
Line (400,400)-(200,400)
Line (100,100)-(200,200)
Line (100,300)-(200,400)
Line (300,100)-(400,200)
Line (300,300)-(400,400)
x = 250: y = 250
Alpha = 255:Red = 255:Green = 255
r = 31: blue = 0
FOR i = 1 TO r
CIRCLE (x, y ),i, RGBA(Red, Green, Blue, Alpha)
CIRCLE (x, y + 1), i, RGBA(Red, Green, Blue, Alpha)
red -= 6:green -= 6
next
FreeLibrary(hShCore)
sleep
Without the manifest all the numbers should be 96, with it, they should be different (unless you're still at 100% scaling) and the window will look smaller.