1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-14 00:14:18 +00:00
Commit graph

41 commits

Author SHA1 Message Date
reuk
336dcfc08c Direct2DImage: Update interface to accept a Device instead of a DeviceContext 2024-12-13 14:43:06 +00:00
reuk
90f37e27ea Windows: Fix DLL build
There were a few "ambiguous operator new/delete" errors that were due to
inheriting from a private base class that used the leak detector. These
errors are resolved by adding the leak detector to the derived classes.

JUCE_API was missing from a few useful types, notably the ARA hosting
types.
2024-10-22 13:24:46 +01:00
reuk
7f52509c78
Direct2D: Simplify SwapChain buffer creation 2024-10-16 10:36:53 +01:00
reuk
f5cc7902b1 Direct2D: Avoid using dirty rects when painting full frame
This fixes an issue where Direct2D will emit an error when using dirty
rects on the first full frame after resizing.

The issue isn't present on all hardware/drivers, but was observed on a
Windows 11 computer with a 890M iGPU.
2024-10-14 11:13:26 +01:00
reuk
362a1cc070
Direct2D: Convert unnecessary multi-threaded factory to single-threaded 2024-10-10 11:47:18 +01:00
reuk
fa0ab06d41 Direct2D: Fix performance issue caused by the entire window painting unnecessarily 2024-10-09 18:13:46 +01:00
reuk
d22d287c6f Direct2D: Avoid presenting incomplete buffers after startFrame fails 2024-10-09 13:15:45 +01:00
reuk
c57041e5bc
Direct2D: Simplify threading of swapchain presentation
Previously, IDXGISwapChain::Present was called on a background thread,
which made it difficult to avoid race conditions. e.g. during a
live-resize of a window, we would occasionally draw old incomplete
frames instead of new frames at the correct size.

The new approach moves the Present call to the main thread via
AsyncUpdater. We attempt to present whenever the swap event wakes, and
whenever a frame is drawn. Only a single Present call may be made after
the swap event wakes. Subsequent Present calls will be ignored until the
next time the swap event wakes.
2024-10-08 16:10:07 +01:00
reuk
c7f7a7c1bb
Direct2D: Remove setResizing and getResizing members from renderer
We instead query from the renderer whether the current render size has
changed since the last frame, and repaint the entire window if so.
2024-10-07 11:50:26 +01:00
reuk
1a1dc90a24
Direct2D: Remove frameSize member from Direct2DHwndContext pimpl 2024-10-02 11:35:38 +01:00
reuk
9b36effbf4
Direct2D: Make checkPaintReady check more robust
This additionally ensures that we'll paint when the swap chain has just
been resized
2024-10-02 11:35:38 +01:00
reuk
d64e963b14
Direct2D: Tidy up rect/point creation 2024-10-02 11:35:38 +01:00
reuk
c1c2e1d8d2
Direct2D: Invalidate deviceContext when adapters change, to avoid referencing missing devices 2024-09-18 15:44:04 +01:00
reuk
8a9fea51e5
Direct2D: Avoid rare crashes due to nullptr deref of swapChainThread 2024-09-18 15:44:04 +01:00
reuk
589d9940ed
Direct2D: Add support for bitmaps spanning multiple texture pages 2024-09-18 15:44:04 +01:00
reuk
25e2fa44ff
Direct2D: Correctly recreate ID2D1DeviceContext when moving transparent windows between devices 2024-09-05 12:16:02 +01:00
reuk
9a93fb03a4 Direct2D: Add null check in PresentationQueue 2024-08-23 13:51:40 +01:00
reuk
6cd018a679
Direct2D: Fix implementation of Direct2DPixelData::fromDirect2DBitmap
Previously, this function didn't store/copy the provided bitmap, so the
resulting image was blank. This also broke createSnapshot(), which would
always return a blank image.
2024-08-22 18:18:17 +01:00
reuk
348d638581
Direct2D: Temporarily disable window transparency for D2D windows 2024-08-22 18:18:17 +01:00
reuk
8a1bf07f14
Direct2D: Adjust return type of getPaintAreas in Direct2DHwndContext 2024-08-22 18:18:15 +01:00
reuk
570fd4b65c
Direct2D: Track UpdateRegions in D2DContext rather than the Direct2DHwndContext 2024-08-22 18:18:15 +01:00
reuk
c94b8e1712
Direct2D: Refactor paintAreas handling in graphics contexts 2024-08-22 18:18:15 +01:00
reuk
e2b9dd9a05
Direct2D: Remove redundant adapter member from Direct2DGraphicsContext 2024-08-22 18:18:15 +01:00
reuk
68441e0726
Direct2D: Refactor DeviceResources helper 2024-08-22 18:18:15 +01:00
reuk
58c267106f
Direct2D: Move UpdateRegion helper to shared DirectX header 2024-08-22 18:18:14 +01:00
reuk
8bbcfe4d6b
Direct2D: Move DeviceContext helpers to shared DirectX header 2024-08-22 18:18:14 +01:00
reuk
bb53174196
Direct2D: Add null check before reading from D2D texture 2024-08-22 18:18:14 +01:00
reuk
025a05d210
Windows: Remove clearWindowRedirectionBitmap() 2024-08-22 18:18:14 +01:00
reuk
1b69ba3997
Direct2DResources: Refactor CompositionTree 2024-08-22 18:18:13 +01:00
reuk
e67e78803c
Direct2D: Tidy up implementation of createBitmap and remove lineStride parameter
The lineStride parameter is only required to be set when the 'data'
pointer is also set.
2024-07-04 13:03:34 +01:00
reuk
815da2ec6d Direct2D: Tidy up clearWindowRedirectionBitmap 2024-06-26 14:33:26 +01:00
reuk
9ae52f3d7a Direct2D: Update backbuffer implementation
Problem description
===================

Firstly, the linked-list of pending presentations acted as a stack
(FILO).  If the swap chain thread and main thread processed frames at
varying rates, then the following sequence of events was possible:

Main thread           Swap chain thread       Queue state
---------------------------------------------------------
Push frame (1)                                [1]
Push frame (2)                                [2, 1]
                      Pop frame (2)           [1]
Push frame (3)                                [3, 1]
                      Pop frame (3)           [1]
                      Pop frame (1)           [] <--  Out of sequence!

Secondly, the swap chain's sequential flip model can only maintain a
valid back-buffer state as long as the list of dirty rects is correct,
and every pixel within the dirty rects is painted incrementally.

In the example above, if the main thread were to produce two frames
before the swap chain thread could present any frame, then presenting
*only* the frame 2 (skipping frame 1) may produce incorrect results when
combined with the existing back buffer. This is because regions updated
in frame 1 may not be updated in frame 2, so regions *only* updated in
frame 1 will be omitted from the back buffer.

Mitigation
==========

This patch removes the old stack of presentations and replaces it with a
slightly more complex mechanism that tracks two different Presentation
objects. At any time, up to one Presentation may be in use by the swap
chain thread (i.e. actively presenting), up to one Presentation may be
accumulating updated/dirty regions (i.e. painting), and up to one region
may be ready, awaiting display.

This scheme resolves the first issue described above by ensuring that
old frame data is not kept around. There is never more than one frame
awaiting display, which means that if the swap chain thread attempts to
display twice in a row (before the main thread produces a new frame),
the second attempt will be a no-op.

The second issue is resolved by accumulating changes into a single
Presentation whenever the main thread produces two or more frames in a
row. If there is already a 'ready' Presentation when the main thread
finishes painting, then all updated regions from the newest Presentation
will be added to the 'ready' Presentation, rather than replacing it.
When the swap chain thread is ready to present, it will therefore see
the result of all the accumulated Presentations produced by the main
thread, instead of just the newest Presentation.
2024-06-26 14:33:25 +01:00
reuk
659de5842f
Direct2D: Fix flickery resizing when using an internal resizer
Resizing using window manager functionality (e.g. clicking and dragging
in the non-client area) will send WM_SIZING to the window, which in turn
will enable continuous repainting in the D2D renderer until the resize
operation ends.

Continuous repainting is required in order for the window to display
correctly during the resize. Without continuous repainting, some frames
may not be completely painted, and may display with black areas,
producing a flickery effect.

When a resize is controlled entirely by the client, e.g. using the
corner resizer in the AudioPluginDemo standalone, WM_SIZING is never
posted. Instead, we assume that if the window has captured the cursor
during a setBounds call then it is probably resizing. We enable
continuous repainting in this case, and stop repainting once the window
releases the mouse.

An alternative appropach would be to add some kind of start/stop resize
API to ComponentPeer. I'm currently reluctant to do that because the
ComponentPeer API is already so large.
2024-05-31 11:43:30 +01:00
reuk
2ca5fdf18d
Direct2D: Avoid continuous repainting when moving but not resizing windows 2024-05-28 11:28:51 +01:00
reuk
793af50964
D2D: Fix typo which caused window to repaint continuously after resize 2024-04-29 16:08:23 +01:00
reuk
c2d86693ff
D2D: Avoid calling setPhysicalPixelScaleFactor 2024-04-29 16:08:23 +01:00
reuk
e005a41d6b
D2D: Remove unnecessary scaling in HwndPimpl::setSize 2024-04-29 16:08:23 +01:00
reuk
238edf6437
D2D: Remove unused function 2024-04-29 16:08:23 +01:00
reuk
122b75909e
D2D: Avoid setting DPI when resizing context, as it is already set per-frame 2024-04-29 16:08:23 +01:00
reuk
06903573d2
D2D: Refactor SwapChainThread and attempt to ensure correct alignment of slist entries 2024-04-29 16:08:22 +01:00
reuk
19061e6d17
Direct2D: Add initial support 2024-04-18 14:16:02 +01:00