This re-uses the game capture code for checking whether the original
window still exists or not. If it doesn't or the name changed, it'll
insert the value at the top of the list so it doesn't automatically
select another when the user opens properties.
Basically, this fixes an issue where opening properties could sometimes
cause it to instantly capture whatever window was at the top of the
list, which is undesirable.
Closesobsproject/obs-studio#2421
Adds an "Automatic" method to the capture method property of window
capture. This allows the ability for window capture to automatically
determine the best capture method to use. Primarily, it prefers BitBlt
in most cases, but will use WGC when it detects the window is a browser,
microsoft office, or a UWP program.
This was implemented because the new capture method has a number of
undesired effects associated with it -- the issue of the capture border
that we can do nothing about, the fact that we can't control the capture
of the cursor, and the fact that Microsoft designed it to switch the
cursor away from hardware cursor mode when the capture is active (there
was absolutely no reason to do this because even OBS can capture the
hardware cursor with no issue). Until we get a new version of this API
that doesn't absolutely blow, we're stuck preferring BitBlt instead.
But hey, at least people will be able to capture browser windows now.
Users will now have the option of legacy window capture via BitBlt, or
Windows Graphics Capture, which is new to Windows 10.
There are two annoyances with the new capture method though. One is that
there is a bright, yellow border added to the original window (but not
the OBS view of it). The other is that the mouse cursor is always
captured, and we won't be able to capture without cursor until a later
version of Windows 10 is released.
It should also be noted that DPI scaling is now applied, which may
result in blurrier images caused by Windows rescaling.
Before this change, after a game capture source would send a signal to
init or restart a graphics hook, it would respond to any and all hook
ready signals.
With multiple game capture sources in the same scene, a source could
receive the signal intended for another source, and show the wrong
texture.
This change adds the window handle to the name for shared data with the
hook, resulting in hooks for other sources being ignored.
When changing the target for display or window capture, force a
refresh of the source by setting the timer to fire immediately. This
removes 1-3 seconds of "lag" before the new display or window is
visible and makes the UI feel more responsive.
Closes https://github.com/obsproject/obs-studio/issues/2322
**Commit message modified and clarified by Jim**
When hooking a program that has both DirectX and OpenGL contexts in use,
it is possible to cause a crash on shutdown due to capture_active()
returning true when an OpenGL context is deleted. Normally, when
capturing an OpenGL program, this would not happen because the 'active'
variable would not be set due to OpenGL capture not being initialized,
but if DirectX is captured while an OpenGL context is available, and
OpenGL could not load these required functions, then GL can crash due to
trying to use unavailable functions.
This case is extremely rare and doesn't happen under normal
circumstances; only if a program is using both DirectX and OpenGL within
the same program simultaneously, and *only* if OpenGL could not load the
required functions. This likely almost never happens under normal
programs, games, and hardware. This was apparently produced by hooking
a GL Qt program that used QWebEngine, which used multiple contexts at
once.
Make duplicator_capture_tick the sole creater, and reference adder of
IDXGIOutputDuplication objects. This prevents a situation where
duplicator_capture::showing cause be false while
duplicator_capture::duplicator was not null at startup on background
scenes, preventing IDXGIOutputDuplication from being recreated when
DXGI_ERROR_ACCESS_LOST.
Code submissions have continually suffered from formatting
inconsistencies that constantly have to be addressed. Using
clang-format simplifies this by making code formatting more consistent,
and allows automation of the code formatting so that maintainers can
focus more on the code itself instead of code formatting.
When window capture is not capturing a window, don't try to find the
window every frame. Instead, just check once per frame. The process of
finding a window has a lot of checks and requires a surprising amount of
processing.
Operating systems don't report monitors from 0, so OBS shouldn't
either. This avoids user confusion when display capture doesn't work.
This does not change monitor count internally.
The GDI+ based Text Source actually uses Premultiplied Alpha. The edges
of the fonts are therefore incorrectly blended, causing ugly artifacts
especially if bright text above a bright background is used. Here's an
image comparing the new text blending (left) to before (right):
![https://i.imgur.com/VhhkQcZ.png](https://i.imgur.com/VhhkQcZ.png)
Additionally, the game capture has the same problem, so premultiplied
alpha is used there as well now.
Makes Visual C runtime libraries consistent across
Debug/MinSizeRel/Release/RelWithDebInfo, rather than just changing those
flags for RelWithDebInfo. Also adds /Zl for statically linked
libraries.
Closesobsproject/obs-studio#1421
Occasionally users accidentally select the following applications built
into Windows 10 using game capture, which cannot be captured.
This PR simply hides them from the game capture list.
The latter takes up 6 entries in the dropdown.
LockApp.exe - the lock screen which doesn't run in user space
WindowsInternal.ComposableShell.Experiences.TextInput.InputApp
Re-fetch texture when cursor's either width or height changed.
When the cursor icon changed and the new one has the same width or height,
it may not recreate the texture and thus cause memory access violation.
When drawing cursor to window capture area - use actual resource width
and height instead of system metric values for icons. Fixes an issue
where under rare circumstances, certain cursors would not draw at the
correct size.
Closesobsproject/obs-studio#1284
Fixes an issue where align_pos could be smaller than
sizeof(struct shmem_data), potentially overwriting memory of the header.
References jp9000/obs-studio#1202
Makes it a bit more clear this option shouldn't be used unless you're on
SLI/crossfire.
In the future, something should be put in to the program that detects
laptops and warns on how to set up their adapter for efficient capture.
Closesjp9000/obs-studio#1138
If the target process re-creates its D3D context, the game capture tick
can trigger before the capture is setup, in which case OBS gets a
CAPTURE_RETRY message. However with the memory capture method, it
continues to try and copy from the shared memory pointer which is no
longer valid, resulting in a crash. The fix uses the old texture until
the next tick at which point the new capture should be ready for use.
Windows SDK 10.0.16299.0 defines these structures as part of winternl.h
but using different types and names. Unfortunately there's no macro to
detect the SDK version, so to avoid conflicting with newer / older SDKs
the OBS structs have been renamed.
"Life is Feudal: Your Own" will use Direct3D to render the game, then
OpenGL to render its in-game menus, which causes a conflict with itself.
This specifically blacklists the game from capturing OpenGL to prevent
that from happening.
When hooking DXGI-based graphics programs in the hook, the first hook
point is IDXGISwapChain::Present. To be able to initiate a capture, a
pointer to the device context that created the swap chain is required,
which can be retrieved via IDXGISwapChain::GetDevice. Determining
whether the device context was D3D10 or D3D11 has always been somewhat
of an issue due to D3D10 and D3D11 being nearly identical, as well as
their interoperability/interchangeability. The GetDevice function would
first be called with the UUID of ID3D10Device, then if that failed,
the UUID of ID3D11Device.
However, with certain specific D3D11 games, GetDevice would for some
unknown reason succeed with the UUID of ID3D10Device, which would cause
capture to fail. (Conversely, attempting to call GetDevice with the
UUID of ID3D11Device on a device that's actually ID3D10Device would
always succeed, so reversing the order of the test was not an option).
There were originally three known D3D11 games that would erroneously
succeed when querying a D3D10 device interface: Call of Duty: Ghosts,
Just Cause 3, and theHunter: Call of the Wild. All other known D3D11
games would work correctly. Because it was only these three games, a
hack was originally implemented in the form of an executable exception
list that would force them to capture D3D11.
Unfortunately, Oculus games are now failing under the same circumstance
as well, so a simple hack will no longer work. To fix this, a more
reliable method of detecting which context it is had to be discovered:
simply check the feature level using ID3D11Device::GetFeatureLevel. If
the feature level is D3D_FEATURE_LEVEL_11_0 or D3D_FEATURE_LEVEL_11_1,
the device is definitely a D3D11 device. Otherwise, continue the tests
as they were before. Successfully tested with many D3D10 games, many
D3D11 games, and especially those three D3D11 games that previously were
detected as D3D10 erroneously.
Changes "class" prioritization to attempt to find the window either with
the same title, or the next window of the same window class (window
type), changes "title" prioritization to only find the window based
upon its title, and changes "executable" prioritization to attempt to
find the window with the same title, or the next window of the same
executable.
Additionally changes the text associated with these selections to
clarify that functionality to users.
When kaspersky is installed on windows 7, FindWindowEx will fail to find
any windows due to apparently being blocked by kaspersky, so detect when
that happens, and fall back to GetWindow instead if it does.
Using and creating a window can use issues in game capture if multiple
game captures are active, so revert back to using a mutex, and just
ignore the keepalive check failure if injected inside a UWP program
(only check to see if GetLastError reports that it's not found -- if it
returns access denied or any other error, assume it's in a UWP program,
and ignore the keepalive check).
If the backbuffer count is larger than 3, it could still try to assign
backbuffers to pointers beyond the variable's array size when calling
swap->GetBuffer.
Due to using FindWindowEx to search for certain windows, certain windows
will show up that aren't usable/capturable. Prevent these windows from
showing up in the window lists.