app.dhover×386 error×23all
// macOS/AppKit F04 demo — vsync / frame pacing (../../../features/f04-frame-pacing.md).
// Redraw of a trivially cheap frame (solid color flip) is paced by the platform
// frame clock: a CADisplayLink obtained from the view via
// displayLinkWithTarget:selector: (macOS 14+; the older CVDisplayLink C API is
// deprecated since macOS 15) and added to the main run loop in
// NSRunLoopCommonModes. Every fire logs
//     frame_callback t=<link.timestamp> target=<link.targetTimestamp> path=displaylink
// until 600 frames are paced; at exit the demo prints min/median/p99/max
// inter-frame delta and a coarse jitter histogram.
//
// Fallback chain (so the demo always completes headless / screen-locked, where
// the WindowServer may never drive the link):
//   1. NSView responds to displayLinkWithTarget:selector:?  no -> NSTimer path.
//   2. CADisplayLink silent for >3 s (watchdog, ignoring the deliberate hidden
//      phase)? -> invalidate it and fall back to a ~16 ms NSTimer; every frame
//      logs path=displaylink|timer so the two are never conflated.
//
// Occlusion probe: ~6 s in (or at frame 300), the window is sent orderOut: for
// ~3 s, then makeKeyAndOrderFront: again — Apple documents the view display link
// as following the view's window/display visibility, so the fires should pause;
// the demo logs vis_change, frames observed while hidden, the resume gap, and
// windowDidChangeOcclusionState:. NSScreen.maximumFramesPerSecond is logged at
// startup as the nominal cadence reference.
// Findings: ../../f04-frame-pacing.md; recipe and build command: ../../scaffold.md.
//
// Always bounded: exits 0 after 600 paced frames + the occlusion probe, or at a
// hard ~30 s deadline, whichever comes first. Headless-safe: prints `SKIP:` and
// exits 0 when there is no window server (CGMainDisplayID() == 0).
module 
(module) app
app
;
import
(package) core
core
.
(module) core.attribute

This module contains UDA's (User Defined Attributes) either used in the runtime or special UDA's recognized by compiler.

Attribute Name, Linkage, Description

gnuAbiTag, C++, Declares an ABI tag on a C++ symbol. mustuse,, Ensures that values of a struct or union type are not discarded. optional, Objective-C, Makes an Objective-C interface method optional. selector, Objective-C, Attaches an Objective-C selector to a method. standalone,, Marks a shared module constructor as not depending on any other module constructor being run first. weak,, Specifies that a global symbol should be emitted with weak linkage.

Source

core/attribute.d

@copyrightCopyright Jacob Carlborg 2015.@licenseBoost License 1.0@authorsJacob Carlborg
attribute
: selector;
module `core.attribute` import `selector` not found
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) app.malloc = void* core.stdc.stdlib.malloc(ulong size) nothrow @nogc
malloc
,
(alias) app.free = void core.stdc.stdlib.free(void* ptr) nothrow @nogc
free
,
(alias) app.qsort = void core.stdc.stdlib.qsort(void* base, ulong nmemb, ulong size, extern (C) int function(const(void*), const(void*)) compar) nothrow @nogc
qsort
;
import instrument : instr, instrInit, instrNowUs;
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
import objc.autorelease : autoreleasepool_push, autoreleasepool_pop; // objective-d
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
// Objective-C runtime selector lookup (objective-d wraps libobjc; declaring // sel_registerName ourselves would clash with objc.rt's typed declaration). import objc.rt : SEL;
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
// --- C-level declarations ----------------------------------------------------- // CoreGraphics C API — linked transitively via the Cocoa umbrella framework. extern (C) nothrow @nogc { uint
uint app.CGMainDisplayID() nothrow @nogc
CGMainDisplayID
();
void*
void* app.CGColorSpaceCreateDeviceRGB() nothrow @nogc
CGColorSpaceCreateDeviceRGB
();
void
void app.CGColorSpaceRelease(void* space) nothrow @nogc
CGColorSpaceRelease
(void*
(parameter) void* space
space
);
void*
void* app.CGDataProviderCreateWithData(void* info, const(void)* data, ulong size, void* releaseCallback) nothrow @nogc
CGDataProviderCreateWithData
(void*
(parameter) void* info
info
, const(void)*
(parameter) const(void)* data
data
,
(alias) object.size_t = ulong
size_t
(parameter) ulong size
size
,
void*
(parameter) void* releaseCallback
releaseCallback
);
void
void app.CGDataProviderRelease(void* provider) nothrow @nogc
CGDataProviderRelease
(void*
(parameter) void* provider
provider
);
void*
void* app.CGImageCreate(ulong width, ulong height, ulong bitsPerComponent, ulong bitsPerPixel, ulong bytesPerRow, void* colorSpace, uint bitmapInfo, void* provider, const(double)* decode, bool shouldInterpolate, int intent) nothrow @nogc
CGImageCreate
(
(alias) object.size_t = ulong
size_t
(parameter) ulong width
width
,
(alias) object.size_t = ulong
size_t
(parameter) ulong height
height
,
(alias) object.size_t = ulong
size_t
(parameter) ulong bitsPerComponent
bitsPerComponent
,
(alias) object.size_t = ulong
size_t
(parameter) ulong bitsPerPixel
bitsPerPixel
,
(alias) object.size_t = ulong
size_t
(parameter) ulong bytesPerRow
bytesPerRow
, void*
(parameter) void* colorSpace
colorSpace
, uint
(parameter) uint bitmapInfo
bitmapInfo
,
void*
(parameter) void* provider
provider
, const(double)*
(parameter) const(double)* decode
decode
, bool
(parameter) bool shouldInterpolate
shouldInterpolate
, int
(parameter) int intent
intent
);
void
void app.CGImageRelease(void* image) nothrow @nogc
CGImageRelease
(void*
(parameter) void* image
image
);
void
void app.CGContextDrawImage(void* ctx, app.NSRect rect, void* image) nothrow @nogc
CGContextDrawImage
(void*
(parameter) void* ctx
ctx
,
(struct) app.NSRect
NSRect
(parameter) app.NSRect rect
rect
, void*
(parameter) void* image
image
);
} enum uint
(constant) uint app.kCGImageAlphaNoneSkipFirst = 6u
kCGImageAlphaNoneSkipFirst
= 6; // XRGB: alpha byte present, ignored
enum uint
(constant) uint app.kCGBitmapByteOrder32Little = 8192u
kCGBitmapByteOrder32Little
= 2 << 12; // 32-bit little-endian packing
enum int
(constant) int app.kCGRenderingIntentDefault = 0
kCGRenderingIntentDefault
= 0;
// Cocoa geometry (CGFloat == double on 64-bit). Plain C structs, not ObjC objects. extern (C) struct
(struct) app.NSPoint
NSPoint
{ double
(field) double app.NSPoint.x
x
,
(field) double app.NSPoint.y
y
;
} extern (C) struct
(struct) app.NSSize
NSSize
{ double
(field) double app.NSSize.width
width
,
(field) double app.NSSize.height
height
;
} extern (C) struct
(struct) app.NSRect
NSRect
{
(struct) app.NSPoint
NSPoint
(field) app.NSPoint app.NSRect.origin
origin
;
(struct) app.NSSize
NSSize
(field) app.NSSize app.NSRect.size
size
;
} // --- AppKit/QuartzCore class declarations -------------------------------------- extern (Objective-C): extern class
(class) app.NSObject
NSObject
class `app.NSObject` Objective-C classes not supported
{ bool
app.NSObject.respondsToSelector
respondsToSelector
(SEL sel) @selector("respondsToSelector:");
} extern class
(class) app.NSString
NSString
:
(class) app.NSObject
NSObject
class `app.NSString` Objective-C classes not supported
{ static
(class) app.NSString
NSString
app.NSString app.NSString.alloc()
alloc
() @selector("alloc");
(class) app.NSString
NSString
app.NSString app.NSString.initWithUTF8String(const(char)* s)
initWithUTF8String
(const(char)*
(parameter) const(char)* s
s
) @selector("initWithUTF8String:");
} extern class
(class) app.NSResponder
NSResponder
:
(class) app.NSObject
NSObject
class `app.NSResponder` Objective-C classes not supported
{ } extern class
(class) app.NSEvent
NSEvent
:
(class) app.NSObject
NSObject
class `app.NSEvent` Objective-C classes not supported
{ static
(class) app.NSEvent
NSEvent
app.NSEvent app.NSEvent.otherEventWithType(long type, app.NSPoint location, ulong modifierFlags, double timestamp, long windowNumber, app.NSObject context, short subtype, long data1, long data2)
otherEventWithType
(long
(parameter) long type
type
,
(struct) app.NSPoint
NSPoint
(parameter) app.NSPoint location
location
, ulong
(parameter) ulong modifierFlags
modifierFlags
,
double
(parameter) double timestamp
timestamp
, long
(parameter) long windowNumber
windowNumber
,
(class) app.NSObject
NSObject
(parameter) app.NSObject context
context
, short
(parameter) short subtype
subtype
,
long
(parameter) long data1
data1
, long
(parameter) long data2
data2
)
@selector("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"); } extern class
(class) app.NSTimer
NSTimer
:
(class) app.NSObject
NSObject
class `app.NSTimer` Objective-C classes not supported
{ static
(class) app.NSTimer
NSTimer
app.NSTimer.timerWithTimeInterval
timerWithTimeInterval
(double interval,
(class) app.NSObject
NSObject
(parameter) NSObject target
target
,
SEL sel,
(class) app.NSObject
NSObject
userInfo, bool repeats)
@selector("timerWithTimeInterval:target:selector:userInfo:repeats:"); void
void app.NSTimer.invalidate()
invalidate
() @selector("invalidate");
} extern class
(class) app.NSRunLoop
NSRunLoop
:
(class) app.NSObject
NSObject
class `app.NSRunLoop` Objective-C classes not supported
{ static
(class) app.NSRunLoop
NSRunLoop
app.NSRunLoop app.NSRunLoop.currentRunLoop()
currentRunLoop
() @selector("currentRunLoop");
void
void app.NSRunLoop.addTimer(app.NSTimer timer, app.NSString mode)
addTimer
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer timer
timer
,
(class) app.NSString
NSString
(parameter) app.NSString mode
mode
) @selector("addTimer:forMode:");
} // QuartzCore's frame clock (-framework QuartzCore). The macOS 14+ instance comes // from -[NSView displayLinkWithTarget:selector:]; timestamps are CFTimeInterval // seconds on the mach_absolute_time/CACurrentMediaTime timebase. extern class
(class) app.CADisplayLink
CADisplayLink
:
(class) app.NSObject
NSObject
class `app.CADisplayLink` Objective-C classes not supported
{ double
double app.CADisplayLink.timestamp()
timestamp
() @selector("timestamp");
double
double app.CADisplayLink.targetTimestamp()
targetTimestamp
() @selector("targetTimestamp");
double
double app.CADisplayLink.duration()
duration
() @selector("duration");
bool
bool app.CADisplayLink.isPaused()
isPaused
() @selector("isPaused");
void
void app.CADisplayLink.addToRunLoop(app.NSRunLoop runLoop, app.NSString mode)
addToRunLoop
(
(class) app.NSRunLoop
NSRunLoop
(parameter) app.NSRunLoop runLoop
runLoop
,
(class) app.NSString
NSString
(parameter) app.NSString mode
mode
) @selector("addToRunLoop:forMode:");
void
void app.CADisplayLink.invalidate()
invalidate
() @selector("invalidate");
} extern class
(class) app.NSScreen
NSScreen
:
(class) app.NSObject
NSObject
class `app.NSScreen` Objective-C classes not supported
{ static
(class) app.NSScreen
NSScreen
app.NSScreen app.NSScreen.mainScreen()
mainScreen
() @selector("mainScreen");
long
long app.NSScreen.maximumFramesPerSecond()
maximumFramesPerSecond
() @selector("maximumFramesPerSecond");
} extern class
(class) app.NSGraphicsContext
NSGraphicsContext
:
(class) app.NSObject
NSObject
class `app.NSGraphicsContext` Objective-C classes not supported
{ static
(class) app.NSGraphicsContext
NSGraphicsContext
app.NSGraphicsContext app.NSGraphicsContext.currentContext()
currentContext
() @selector("currentContext");
void*
void* app.NSGraphicsContext.CGContext()
CGContext
() @selector("CGContext"); // CGContextRef
} extern class
(class) app.NSApplication
NSApplication
:
(class) app.NSResponder
NSResponder
class `app.NSApplication` Objective-C classes not supported
{ static
(class) app.NSApplication
NSApplication
app.NSApplication app.NSApplication.sharedApplication()
sharedApplication
() @selector("sharedApplication");
void
void app.NSApplication.setActivationPolicy(long policy)
setActivationPolicy
(long
(parameter) long policy
policy
) @selector("setActivationPolicy:");
void
void app.NSApplication.activateIgnoringOtherApps(bool flag)
activateIgnoringOtherApps
(bool
(parameter) bool flag
flag
) @selector("activateIgnoringOtherApps:");
void
void app.NSApplication.run()
run
() @selector("run");
void
void app.NSApplication.stop(app.NSObject sender)
stop
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("stop:");
void
void app.NSApplication.postEvent(app.NSEvent event, bool atStart)
postEvent
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent event
event
, bool
(parameter) bool atStart
atStart
) @selector("postEvent:atStart:");
void
void app.NSApplication.terminate(app.NSObject sender)
terminate
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("terminate:");
} extern class
(class) app.NSView
NSView
:
(class) app.NSResponder
NSResponder
class `app.NSView` Objective-C classes not supported
{ void
void app.NSView.setNeedsDisplay(bool flag)
setNeedsDisplay
(bool
(parameter) bool flag
flag
) @selector("setNeedsDisplay:");
(struct) app.NSRect
NSRect
app.NSRect app.NSView.bounds()
bounds
() @selector("bounds");
// macOS 14.0+ — gated at runtime via respondsToSelector:.
(class) app.CADisplayLink
CADisplayLink
app.NSView.displayLinkWithTarget
displayLinkWithTarget
(
(class) app.NSObject
NSObject
(parameter) NSObject target
target
, SEL sel)
@selector("displayLinkWithTarget:selector:"); } extern class
(class) app.NSWindow
NSWindow
:
(class) app.NSResponder
NSResponder
class `app.NSWindow` Objective-C classes not supported
{ static
(class) app.NSWindow
NSWindow
app.NSWindow app.NSWindow.alloc()
alloc
() @selector("alloc");
(class) app.NSWindow
NSWindow
app.NSWindow app.NSWindow.initWithContentRect(app.NSRect contentRect, ulong styleMask, ulong backing, bool defer)
initWithContentRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect contentRect
contentRect
, ulong
(parameter) ulong styleMask
styleMask
,
ulong
(parameter) ulong backing
backing
, bool
(parameter) bool defer
defer
) @selector("initWithContentRect:styleMask:backing:defer:");
void
void app.NSWindow.setTitle(app.NSString title)
setTitle
(
(class) app.NSString
NSString
(parameter) app.NSString title
title
) @selector("setTitle:");
void
void app.NSWindow.setContentView(app.NSView view)
setContentView
(
(class) app.NSView
NSView
(parameter) app.NSView view
view
) @selector("setContentView:");
void
void app.NSWindow.setDelegate(app.NSObject anObject)
setDelegate
(
(class) app.NSObject
NSObject
(parameter) app.NSObject anObject
anObject
) @selector("setDelegate:");
void
void app.NSWindow.makeKeyAndOrderFront(app.NSObject sender)
makeKeyAndOrderFront
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("makeKeyAndOrderFront:");
void
void app.NSWindow.orderOut(app.NSObject sender)
orderOut
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("orderOut:");
ulong
ulong app.NSWindow.occlusionState()
occlusionState
() @selector("occlusionState");
double
double app.NSWindow.backingScaleFactor()
backingScaleFactor
() @selector("backingScaleFactor");
} // --- The custom NSView subclass, defined in D ---------------------------------- // Scaffold recipe: bodied @selector methods are the implementation; the display // link / timer / delegate callbacks are selector-only (no base declaration). class
(class) app.FlipView
FlipView
:
(class) app.NSView
NSView
class `app.FlipView` Objective-C classes not supported
{ static
(class) app.FlipView
FlipView
app.FlipView app.FlipView.alloc()
alloc
() @selector("alloc");
(class) app.FlipView
FlipView
app.FlipView app.FlipView.initWithFrame(app.NSRect frame)
initWithFrame
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect frame
frame
) @selector("initWithFrame:");
void
void app.FlipView.drawRect(app.NSRect dirtyRect)
drawRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect dirtyRect
dirtyRect
) @selector("drawRect:")
{ onDrawRect(this.
this.bounds
bounds
());
} // CADisplayLink fire — the platform frame clock. void
void app.FlipView.displayTick(app.CADisplayLink link)
displayTick
(
(class) app.CADisplayLink
CADisplayLink
(parameter) app.CADisplayLink link
link
) @selector("displayTick:")
{ onFrame(link.
link.timestamp
timestamp
(), link.
link.targetTimestamp
targetTimestamp
(), Path.
Path.displaylink
displaylink
);
} // Fallback frame clock: a ~16 ms NSTimer in NSRunLoopCommonModes. void
void app.FlipView.timerTick(app.NSTimer timer)
timerTick
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer timer
timer
) @selector("timerTick:")
{ immutable
_error_ t
t
= instrNowUs() / 1e6;
onFrame(t, t + fallbackIntervalMs / 1000.0, Path.
Path.timer
timer
);
} // 100 ms state-machine scheduler (watchdog, occlusion probe, deadline). void
void app.FlipView.schedTick(app.NSTimer timer)
schedTick
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer timer
timer
) @selector("schedTick:")
{ onSchedule(); } // NSWindowDelegate: occlusion-state transitions (orderOut:/orderFront:). void
void app.FlipView.windowDidChangeOcclusionState(app.NSObject notification)
windowDidChangeOcclusionState
(
(class) app.NSObject
NSObject
(parameter) app.NSObject notification
notification
)
@selector("windowDidChangeOcclusionState:") { instr("vis_change", "state=occlusion occlusion_state=%lu visible=%d", g_win.
g_win.occlusionState
occlusionState
(),
(g_win.
g_win.occlusionState
occlusionState
() & NSWindowOcclusionStateVisible) != 0 ? 1 : 0);
} void
void app.FlipView.windowWillClose(app.NSObject notification)
windowWillClose
(
(class) app.NSObject
NSObject
(parameter) app.NSObject notification
notification
) @selector("windowWillClose:")
{ instr("close_requested"); g_app.
g_app.terminate
terminate
(null);
} } extern (D): // back to D linkage for the rest of the module enum
(constant) int app.NSApplicationActivationPolicyRegular = 0
NSApplicationActivationPolicyRegular
= 0;
enum : ulong {
(enum value) app.NSWindowStyleMaskTitled = 1LU
NSWindowStyleMaskTitled
= 1,
(enum value) app.NSWindowStyleMaskClosable = 2LU
NSWindowStyleMaskClosable
= 2,
(enum value) app.NSWindowStyleMaskResizable = 8LU
NSWindowStyleMaskResizable
= 8,
} enum ulong
(constant) ulong app.NSBackingStoreBuffered = 2LU
NSBackingStoreBuffered
= 2;
enum long
(constant) long app.NSEventTypeApplicationDefined = 15L
NSEventTypeApplicationDefined
= 15;
enum ulong
(constant) ulong app.NSWindowOcclusionStateVisible = 2LU
NSWindowOcclusionStateVisible
= 1UL << 1;
// --- Demo state ----------------------------------------------------------------- enum
(enum) app.Path
Path
: int
{
(enum value) app.Path.displaylink = 0
displaylink
= 0,
(enum value) app.Path.timer = 1
timer
= 1,
} immutable
(alias) object.string = string
string
[2]
(immutable global) immutable(string[2]) app.pathNames
pathNames
= ["displaylink", "timer"];
enum
(constant) int app.targetFrames = 600
targetFrames
= 600; // per the F04 spec
enum
(constant) int app.fallbackIntervalMs = 16
fallbackIntervalMs
= 16; // NSTimer fallback cadence
enum
(constant) int app.watchdogSilenceMs = 3000
watchdogSilenceMs
= 3000;
enum
(constant) int app.hideAtMs = 6000
hideAtMs
= 6000; // occlusion probe: orderOut: ...
enum
(constant) int app.hideAtFrame = 300
hideAtFrame
= 300; // ... or at frame 300, whichever first
enum
(constant) int app.hiddenForMs = 3000
hiddenForMs
= 3000;
enum
(constant) int app.deadlineMs = 30000
deadlineMs
= 30_000; // hard stop: the demo always completes
__gshared
(class) app.NSApplication
NSApplication
(__gshared global) app.NSApplication app.g_app
g_app
;
__gshared
(class) app.NSWindow
NSWindow
(__gshared global) app.NSWindow app.g_win
g_win
;
__gshared
(class) app.NSRunLoop
NSRunLoop
(__gshared global) app.NSRunLoop app.g_runLoop
g_runLoop
;
__gshared
(class) app.NSString
NSString
(__gshared global) app.NSString app.g_modeCommon
g_modeCommon
;
__gshared
(class) app.FlipView
FlipView
(__gshared global) app.FlipView app.g_view
g_view
;
__gshared
(class) app.CADisplayLink
CADisplayLink
(__gshared global) app.CADisplayLink app.g_link
g_link
;
__gshared uint*
(__gshared global) uint* app.g_buf
g_buf
;
__gshared
(alias) object.size_t = ulong
size_t
(__gshared global) ulong app.g_bufW
g_bufW
,
(__gshared global) ulong app.g_bufH
g_bufH
;
__gshared
(enum) app.Path
Path
(__gshared global) app.Path app.g_path
g_path
= Path.
Path.displaylink
displaylink
;
__gshared int
(__gshared global) int app.g_frames
g_frames
,
(__gshared global) int app.g_draws
g_draws
;
__gshared int[2]
(__gshared global) int[2] app.g_framesPerPath
g_framesPerPath
;
__gshared double
(__gshared global) double app.g_lastTs
g_lastTs
= 0;
__gshared bool
(__gshared global) bool app.g_skipNextDelta
g_skipNextDelta
; // after path switch / un-hide: gap is not jitter
__gshared double[2048]
(__gshared global) double[2048] app.g_deltas
g_deltas
; // seconds; capped, extra frames only counted
__gshared int
(__gshared global) int app.g_deltaCount
g_deltaCount
;
__gshared bool
(__gshared global) bool app.g_hidden
g_hidden
,
(__gshared global) bool app.g_hideDone
g_hideDone
,
(__gshared global) bool app.g_showDone
g_showDone
,
(__gshared global) bool app.g_fellBack
g_fellBack
,
(__gshared global) bool app.g_finished
g_finished
;
__gshared ulong
(__gshared global) ulong app.g_hideAtUs
g_hideAtUs
,
(__gshared global) ulong app.g_lastFrameUs
g_lastFrameUs
;
__gshared int
(__gshared global) int app.g_framesAtHide
g_framesAtHide
,
(__gshared global) int app.g_hiddenFrames
g_hiddenFrames
;
__gshared double
(__gshared global) double app.g_resumeGapMs
g_resumeGapMs
= -1;
void
void app.onFrame(double ts, double target, app.Path path)
onFrame
(double
(parameter) double ts
ts
, double
(parameter) double target
target
,
(enum) app.Path
Path
(parameter) app.Path path
path
)
{ if (g_finished || path != g_path) return; // ignore stragglers from an invalidated clock ++g_frames; ++g_framesPerPath[path]; g_lastFrameUs = instrNowUs(); if (g_hidden) ++g_hiddenFrames; instr("frame_callback", "t=%.6f target=%.6f path=%.*s", ts, target, cast(int) pathNames[path].length, pathNames[path].ptr); if (g_lastTs > 0) { immutable
_error_ delta
delta
= ts - g_lastTs;
if (g_skipNextDelta) { g_skipNextDelta = false; if (g_showDone && g_resumeGapMs < 0) { g_resumeGapMs = delta * 1000.0; instr("resume_gap", "gap_ms=%.1f", g_resumeGapMs); } } else if (g_deltaCount < cast(int) g_deltas.length) g_deltas[g_deltaCount++] = delta; } g_lastTs = ts; g_view.
g_view.setNeedsDisplay
setNeedsDisplay
(true); // solid color flip — the trivially cheap frame
// Don't finish while the occlusion probe is mid-flight; onSchedule's // deadline covers the pathological cases. if (g_frames >= targetFrames && g_showDone) finish("frames"); } void
void app.onSchedule()
onSchedule
()
{ if (g_finished) return; immutable
_error_ nowMs
nowMs
= instrNowUs() / 1000;
// Watchdog: the display link never fired / went silent (and not because we // hid the window on purpose) -> fall back to the NSTimer frame clock. if (g_path == Path.
Path.displaylink
displaylink
&& !g_fellBack && !g_hidden)
{ immutable
_error_ sinceLast
sinceLast
= g_frames == 0 ? nowMs : (instrNowUs() - g_lastFrameUs) / 1000;
if (sinceLast > watchdogSilenceMs) { g_fellBack = true; instr("watchdog", "displaylink_silent_ms=%llu frames_so_far=%d link_paused=%d occlusion_state=%lu action=fallback_timer", cast(ulong) sinceLast, g_frames, (g_link !is null && g_link.
g_link.isPaused
isPaused
()) ? 1 : 0, g_win.
g_win.occlusionState
occlusionState
());
if (g_link !is null) g_link.
g_link.invalidate
invalidate
();
startTimerPath(); } } // Occlusion probe: hide for ~3 s mid-run, then show again. if (!g_hideDone && (nowMs >= hideAtMs || g_frames >= hideAtFrame)) { g_hideDone = true; g_hidden = true; g_hideAtUs = instrNowUs(); g_framesAtHide = g_frames; instr("vis_change", "state=hidden api=orderOut frames=%d link_paused=%d", g_frames, (g_link !is null && g_path == Path.
Path.displaylink
displaylink
&& g_link.
g_link.isPaused
isPaused
()) ? 1 : 0);
g_win.
g_win.orderOut
orderOut
(null);
} else if (g_hideDone && !g_showDone && instrNowUs() >= g_hideAtUs + hiddenForMs * 1000) { g_showDone = true; g_hidden = false; g_skipNextDelta = true; instr("vis_change", "state=visible api=makeKeyAndOrderFront hidden_frames=%d link_paused=%d", g_hiddenFrames, (g_link !is null && g_path == Path.
Path.displaylink
displaylink
&& g_link.
g_link.isPaused
isPaused
()) ? 1 : 0);
g_win.
g_win.makeKeyAndOrderFront
makeKeyAndOrderFront
(null);
} if (nowMs >= deadlineMs) finish("deadline"); else if (g_frames >= targetFrames && g_showDone) finish("frames"); } void
void app.startTimerPath()
startTimerPath
()
{ g_path = Path.
Path.timer
timer
;
g_lastTs = 0; // timer timestamps are on the demo's own monotonic epoch g_skipNextDelta = true; instr("path_select", "path=timer interval_ms=%d", fallbackIntervalMs);
(unresolved type) NSTimer
NSTimer
_error_ t
t
= NSTimer.
NSTimer.timerWithTimeInterval
timerWithTimeInterval
(fallbackIntervalMs / 1000.0, g_view,
SEL.register("timerTick:"), null, true); g_runLoop.
g_runLoop.addTimer
addTimer
(t, g_modeCommon);
} extern (C) int
int app.cmpDouble(const(void)* a, const(void)* b) nothrow @nogc
cmpDouble
(const(void)*
(parameter) const(void)* a
a
, const(void)*
(parameter) const(void)* b
b
) nothrow @nogc
{ immutable
_error_ x
x
= *cast(const double*) a,
_error_ y
y
= *cast(const double*) b;
return (x > y) - (x < y); } void
void app.finish(const(char)* reason)
finish
(const(char)*
(parameter) const(char)* reason
reason
)
{ if (g_finished) return; g_finished = true; instr("step", "name=finish reason=%s", reason); if (g_deltaCount > 0) { qsort(g_deltas.ptr, g_deltaCount, double.sizeof, &cmpDouble); immutable
_error_ minMs
minMs
= g_deltas[0] * 1000.0;
immutable
_error_ medMs
medMs
= g_deltas[g_deltaCount / 2] * 1000.0;
immutable
_error_ p99Ms
p99Ms
= g_deltas[(g_deltaCount * 99) / 100 >= g_deltaCount
? g_deltaCount - 1 : (g_deltaCount * 99) / 100] * 1000.0; immutable
_error_ maxMs
maxMs
= g_deltas[g_deltaCount - 1] * 1000.0;
instr("stats", "n=%d min_ms=%.3f median_ms=%.3f p99_ms=%.3f max_ms=%.3f", g_deltaCount, minMs, medMs, p99Ms, maxMs); // Coarse jitter histogram (inter-frame delta, ms). static immutable double[9]
double[9] edges
edges
= [2, 4, 6, 9, 13, 18, 25, 40, 100];
int[10]
_error_ buckets
buckets
;
foreach (
(parameter) i
i
; 0 .. g_deltaCount)
{ immutable
_error_ ms
ms
= g_deltas[i] * 1000.0;
(unresolved type) size_t
size_t
_error_ b
b
= edges.length;
foreach (
(parameter) j
j
,
(parameter) e
e
; edges)
if (ms < e) { b = j; break; } ++buckets[b]; } foreach (
(parameter) j
j
,
(parameter) count
count
; buckets)
{ if (count == 0) continue; if (j == 0) instr("histogram", "bucket_ms=<%.0f count=%d", edges[0], count); else if (j == edges.length) instr("histogram", "bucket_ms=>=%.0f count=%d", edges[$ - 1], count); else instr("histogram", "bucket_ms=%.0f-%.0f count=%d", edges[j - 1], edges[j], count); } } else instr("stats", "n=0"); instr("loop_exit", "frames=%d frames_displaylink=%d frames_timer=%d draws=%d hidden_frames=%d fell_back=%d", g_frames, g_framesPerPath[Path.
Path.displaylink
displaylink
], g_framesPerPath[Path.
Path.timer
timer
],
g_draws, g_hiddenFrames, g_fellBack ? 1 : 0); g_app.
g_app.stop
stop
(null);
// stop: is only checked after an event dispatch; post a synthetic event so // [NSApp run] wakes up and exits (scaffold finding).
(unresolved type) NSEvent
NSEvent
_error_ ev
ev
= NSEvent.
NSEvent.otherEventWithType
otherEventWithType
(NSEventTypeApplicationDefined,
NSPoint(0, 0), 0, 0, 0, null, 0, 0, 0); g_app.
g_app.postEvent
postEvent
(ev, true);
} void
void app.onDrawRect(app.NSRect bounds)
onDrawRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect bounds
bounds
)
{ immutable double
_error_ scale
scale
= g_win.
g_win.backingScaleFactor
backingScaleFactor
();
immutable
(unresolved type) size_t
size_t
_error_ pw
pw
= cast(
(unresolved type) size_t
size_t
) (bounds.
bounds.size
size
.
bounds.size.width
width
* scale);
immutable
(unresolved type) size_t
size_t
_error_ ph
ph
= cast(
(unresolved type) size_t
size_t
) (bounds.
bounds.size
size
.
bounds.size.height
height
* scale);
if (pw == 0 || ph == 0) return; if (pw != g_bufW || ph != g_bufH) { free(g_buf); g_buf = cast(uint*) malloc(pw * ph * 4); g_bufW = pw; g_bufH = ph; } // The cheapest possible frame: a solid color flipping per paced frame. immutable uint
_error_ color
color
= (g_frames & 1) ? 0xFFFF_FFFF : 0xFF10_1018;
foreach (
(parameter) i
i
; 0 .. pw * ph)
g_buf[i] = color; void*
_error_ cs
cs
= CGColorSpaceCreateDeviceRGB();
void*
_error_ dp
dp
= CGDataProviderCreateWithData(null, g_buf, pw * ph * 4, null);
void*
_error_ img
img
= CGImageCreate(pw, ph, 8, 32, pw * 4, cs,
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, dp, null, false, kCGRenderingIntentDefault); void*
_error_ ctx
ctx
= NSGraphicsContext.
NSGraphicsContext.currentContext
currentContext
().
NSGraphicsContext.currentContext().CGContext
CGContext
();
CGContextDrawImage(ctx, bounds, img); CGImageRelease(img); CGDataProviderRelease(dp); CGColorSpaceRelease(cs); ++g_draws; } int
int D main()
main
()
{ instrInit("APPKIT_F04"); instr("init_start", "target_frames=%d deadline_ms=%d", targetFrames, deadlineMs); if (CGMainDisplayID() == 0) { printf("SKIP: no macOS window server (CGMainDisplayID == 0)\n"); return 0; } auto
_error_ pool
pool
= autoreleasepool_push();
scope (exit) autoreleasepool_pop(pool); g_app = NSApplication.
NSApplication.sharedApplication
sharedApplication
();
g_app.
g_app.setActivationPolicy
setActivationPolicy
(NSApplicationActivationPolicyRegular);
(unresolved type) NSScreen
NSScreen
_error_ screen
screen
= NSScreen.
NSScreen.mainScreen
mainScreen
();
instr("screen_info", "max_fps=%ld", screen !is null ? screen.
screen.maximumFramesPerSecond
maximumFramesPerSecond
() : -1);
immutable
_error_ contentRect
contentRect
= NSRect(NSPoint(120, 120), NSSize(480, 320));
g_win = NSWindow.
NSWindow.alloc
alloc
().
NSWindow.alloc().initWithContentRect
initWithContentRect
(contentRect,
NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable, NSBackingStoreBuffered, false); g_win.
g_win.setTitle
setTitle
(NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
("wsi-f04-frame-pacing"));
instr("window_created", "scale=%.1f occlusion_state=%lu", g_win.
g_win.backingScaleFactor
backingScaleFactor
(), g_win.
g_win.occlusionState
occlusionState
());
g_view = FlipView.
FlipView.alloc
alloc
().
FlipView.alloc().initWithFrame
initWithFrame
(contentRect);
g_win.
g_win.setContentView
setContentView
(g_view);
g_win.
g_win.setDelegate
setDelegate
(g_view);
g_win.
g_win.makeKeyAndOrderFront
makeKeyAndOrderFront
(null);
g_app.
g_app.activateIgnoringOtherApps
activateIgnoringOtherApps
(true);
g_runLoop = NSRunLoop.
NSRunLoop.currentRunLoop
currentRunLoop
();
g_modeCommon = NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
("kCFRunLoopCommonModes");
// Frame-clock selection: CADisplayLink via the macOS 14+ NSView API, else // the NSTimer fallback. The link is created unscheduled and must be added // to a run loop explicitly; common modes so it survives tracking loops (F03). if (g_view.
g_view.respondsToSelector
respondsToSelector
(SEL.register("displayLinkWithTarget:selector:")))
{ g_link = g_view.
g_view.displayLinkWithTarget
displayLinkWithTarget
(g_view, SEL.register("displayTick:"));
if (g_link !is null) { g_link.
g_link.addToRunLoop
addToRunLoop
(g_runLoop, g_modeCommon);
instr("path_select", "path=displaylink api=NSView_displayLinkWithTarget paused=%d", g_link.
g_link.isPaused
isPaused
() ? 1 : 0);
} } if (g_link is null) { instr("path_select", "path=timer reason=no_displaylink_api"); startTimerPath(); } // The 100 ms scheduler (watchdog / occlusion probe / deadline), common modes.
(unresolved type) NSTimer
NSTimer
_error_ sched
sched
= NSTimer.
NSTimer.timerWithTimeInterval
timerWithTimeInterval
(0.1, g_view,
SEL.register("schedTick:"), null, true); g_runLoop.
g_runLoop.addTimer
addTimer
(sched, g_modeCommon);
instr("step", "name=NSApp_run"); g_app.
g_app.run
run
();
free(g_buf); return g_finished ? 0 : 1; }