feat(screenshot): Add threaded JPEG/PNG screenshots without game stalls#1785
feat(screenshot): Add threaded JPEG/PNG screenshots without game stalls#1785bobtista wants to merge 5 commits into
Conversation
20a3df1 to
37bd840
Compare
|
Some initial thoughts:
|
|
Agree with Stubbjax. JPG 90 is big file. Better make it default 80. Replace BMP screenshot with PNG screenshot. PNG is lossless compressed and always better than BMP. Make F12 take JPG 80 screenshot. Make CTRL+F12 take PNG screenshot. Make JPG Quality adjustable. Remove the old BMP code(s) and only use the new code for screenshot. |
|
Regarding Github formatting: When you write
Then it will not close this report when this is merged. Please read up on it here: |
RE moving logic to core, I moved what I could to core - but there are a lot more files that need to be moved to core before this can be moved there eg WWVegas/WW3D2/* |
3535e1e to
efc773f
Compare
977a6dc to
f8162f3
Compare
d7e8a8d to
d197bdd
Compare
d197bdd to
9669966
Compare
|
Needs rebase. |
9669966 to
4897b0b
Compare
Done |
9c99306 to
de35e57
Compare
|
This needs rebasing before review. |
7d40c12 to
93bd190
Compare
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp | New file implementing threaded JPEG/PNG capture; all previously flagged issues are resolved (DESTROY_MESSAGE, memory cleanup on thread failure, success message gated on thread creation, quality fallback to m_jpegQuality). |
| GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DScreenshot.cpp | Mirror of Generals W3DScreenshot.cpp for Zero Hour; identical logic, only header comment differs. All issues resolved in both copies. |
| cmake/stb.cmake | Adds STB via FetchContent when vcpkg doesn't provide it; add_library(stb INTERFACE) is unconditional so the target is always defined, and Stb_INCLUDE_DIR is populated in both paths. |
| Core/GameEngineDevice/Source/W3DDevice/GameClient/stb_image_write_impl.cpp | Single-purpose translation unit that defines STB_IMAGE_WRITE_IMPLEMENTATION; compiled into both game targets via the corei_gameenginedevice_private INTERFACE. |
| Core/GameEngine/Source/Common/OptionPreferences.cpp | Adds getJPEGQuality() reading JPEGQuality key from Options.ini; clamps result to [1, 100] with default 80 when key is absent. |
| Generals/Code/GameEngine/Source/Common/GlobalData.cpp | Initializes m_jpegQuality to 80 in constructor and loads it from OptionPreferences in parseGameDataDefinition; mirrors correctly in GeneralsMD. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp | Registers F12 for JPEG screenshot and Ctrl+F12 for PNG; both bindings use the guarded if(map->m_key == MK_NONE) pattern. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp | Both MSG_META_TAKE_SCREENSHOT and MSG_META_TAKE_SCREENSHOT_PNG cases correctly set disp = DESTROY_MESSAGE before break. |
| Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScreenshot.h | Minimal shared header declaring W3D_TakeCompressedScreenshot with default quality=0, ensuring the m_jpegQuality fallback triggers when called from W3DDisplay::takeScreenShot. |
Sequence Diagram
sequenceDiagram
participant User
participant MetaMap
participant CommandXlat
participant W3DDisplay
participant W3DScreenshot
participant BGThread
User->>MetaMap: Press F12 (or Ctrl+F12)
MetaMap->>CommandXlat: MSG_META_TAKE_SCREENSHOT(_PNG)
CommandXlat->>W3DDisplay: "takeScreenShot(JPEG|PNG)"
W3DDisplay->>W3DScreenshot: W3D_TakeCompressedScreenshot(format)
W3DScreenshot->>W3DScreenshot: Get back buffer surface copy
W3DScreenshot->>W3DScreenshot: Lock surface, swizzle BGR to RGB pixels
W3DScreenshot->>W3DScreenshot: Unlock and release surface
W3DScreenshot->>BGThread: CreateThread(screenshotThreadFunc, data)
W3DScreenshot->>User: "TheInGameUI->message(GUI:ScreenCapture)"
BGThread->>BGThread: stbi_write_jpg / stbi_write_png
BGThread->>BGThread: delete imageData, delete threadData
Reviews (14): Last reviewed commit: "fix(stb): Create stb target on both vcpk..." | Re-trigger Greptile
93bd190 to
516acb2
Compare
c4673ea to
45c0339
Compare
Additional Comments (1)
The old Prompt To Fix With AIThis is a comment left during a code review.
Path: Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp
Line: 2807:2880
Comment:
**Dead `CreateBMPFile` function left behind**
The old `takeScreenShot` method (which was the only caller of `CreateBMPFile`) has been removed, leaving this ~75-line static function as dead code. It will produce a compiler warning for unused static function. Consider removing it since BMP screenshot functionality is fully replaced by the new JPEG/PNG implementation. The same applies to the GeneralsMD mirror file.
How can I resolve this? If you propose a fix, please make it concise. |
65867f4 to
7704e08
Compare
8779ab1 to
b709c32
Compare
35ba6d6 to
2e284e0
Compare
|
Any more changes requested? Or is this good to merge? |
|
LGTM, frametime analysis shows zero stutter. Nitpick 1: The screenshot naming logic seems to be incrementing per file extension (or filling the lowest available index) rather than using a global counter. This could break 'Sort by Name' in the destination folder because a newer PNG might get a lower index than an older JPG. Nitpick 2: The shortcut for uncompressed images has been changed from F12 to Ctrl+F12. This took me a whole few seconds to get used to. But for users this might be preferred. Neither of these are blockers for me personally. |
Maybe the filename should contain the date and time (incl milliseconds) instead as a sequencer |
2e284e0 to
fa826df
Compare
I'm happy to add this now or as a follow on PR, would be good to get this merged though. Edit: Done, went with Skyaero's suggestion. |
Summary
Replaces the old BMP screenshot with compressed JPEG screenshots that don't stall the game, and adds PNG support.
Closes #1555
Closes #106 ... sort of
Adds a new screenshot function using the stb_image_write library with background threading:
Notes
Testing