Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8a11b3c
mbedTLS fix for cURL 8.8.0
Lpsd May 24, 2024
181bf0f
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd May 24, 2024
6728cbe
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd May 25, 2024
0b989ac
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd May 26, 2024
9c19509
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jun 2, 2024
75c36ed
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jun 19, 2024
96dd1ee
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 2, 2024
f9eaf3f
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 8, 2024
54bd11b
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 10, 2024
ddee2d0
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 19, 2024
288b8db
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 21, 2024
b30a4a2
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Oct 22, 2024
27b9eae
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Dec 17, 2024
3731d81
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jan 14, 2025
b50a68c
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jan 22, 2025
58ae23f
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Feb 19, 2025
f3645b8
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Mar 4, 2025
e62d9f4
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Mar 14, 2025
3346e9c
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Mar 16, 2025
95dfc97
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Sep 6, 2025
3307dc6
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Sep 14, 2025
f091a85
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Sep 24, 2025
c66e5de
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Nov 7, 2025
c132ae1
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Nov 9, 2025
5739ef0
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jan 7, 2026
4e8d1c0
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jan 7, 2026
27d7fd7
Merge branch 'master' of https://github.com/multitheftauto/mtasa-blue
Lpsd Jan 13, 2026
ee4475e
External begin frame scheduling
Lpsd Jan 13, 2026
d728302
Optimize dirty rect handling
Lpsd Jan 13, 2026
a84d11c
Use D3DPOOL_DEFAULT with D3DUSAGE_DYNAMIC
Lpsd Jan 13, 2026
ab0bcbf
Browser lazy loading
Lpsd Jan 13, 2026
7d5c788
Video decode acceleration & gpu compositing
Lpsd Jan 14, 2026
0ff9e41
Mouse input throttling & dirty rect optimizations
Lpsd Jan 14, 2026
eefc173
Lazy loading fixes
Lpsd Jan 14, 2026
701b0a9
Remove outdated wine comment
Lpsd Jan 14, 2026
3388945
Revert OnPaint dirty rect optimization from 0ff9e41d5
Lpsd Jan 14, 2026
2090d12
Improve CWebView::UpdateTexture edge cases
Lpsd Jan 14, 2026
624f063
Remove dirty rect processing & improve restore
Lpsd Jan 14, 2026
cbcd8cf
Merge branch 'master' into cef-performance
Lpsd Mar 6, 2026
352ab57
Merge remote-tracking branch 'upstream/master' into cef-performance
Lpsd Apr 15, 2026
3b95b6a
Run clang-format
Lpsd Apr 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions Client/cefweb/CWebApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ namespace
// Prevent Chromium from dropping privileges; required for elevated launches (see chromium/3960)
commandLine->AppendSwitch("do-not-de-elevate");

// Must apply essential CEF switches regardless of WebCore availability
commandLine->AppendSwitch("disable-gpu-compositing");
// Enable external begin frame scheduling for MTA-controlled rendering
commandLine->AppendSwitch("enable-begin-frame-scheduling");
// Explicitly block account sign-in to avoid crashes when Google API keys are registered on the system
commandLine->AppendSwitchWithValue("allow-browser-signin", "false");
Expand All @@ -71,6 +70,7 @@ namespace
}

bool disableGpu = false;
bool enableVideoAccel = true;
if (g_pCore && IsReadablePointer(g_pCore, sizeof(void*)))
{
auto* cvars = g_pCore->GetCVars();
Expand All @@ -79,6 +79,8 @@ namespace
bool gpuEnabled = true;
cvars->Get("browser_enable_gpu", gpuEnabled);
disableGpu = !gpuEnabled;

cvars->Get("browser_enable_video_acceleration", enableVideoAccel);
}
}

Expand All @@ -92,13 +94,22 @@ namespace
else
{
// In Wine, we generally want to try GPU (DXVK handles it well)
// But disable-gpu-compositing is already set above which is key
// If user hasn't explicitly disabled GPU in cvars, let it run
}
}

if (disableGpu)
{
commandLine->AppendSwitch("disable-gpu");
// Also disable GPU compositing when GPU is disabled
commandLine->AppendSwitch("disable-gpu-compositing");
}

// Hardware video decoding - enable when GPU is enabled and video acceleration is requested
if (!disableGpu && enableVideoAccel)
{
commandLine->AppendSwitch("enable-accelerated-video-decode");
}
}
} // namespace

Expand Down
15 changes: 14 additions & 1 deletion Client/cefweb/CWebCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,20 @@ void CWebCore::DoEventQueuePulse()
event.callback();
}

// Invoke paint method if necessary on the main thread
// Request new frames from CEF using external begin frame scheduling
// This synchronizes CEF rendering with MTA's render loop, eliminating
// the previous 250ms blocking wait in OnPaint
for (auto& view : m_WebViews)
{
if (view->IsBeingDestroyed() || view->GetRenderingPaused())
continue;

auto browser = view->GetCefBrowser();
if (browser)
browser->GetHost()->SendExternalBeginFrame();
}

// Copy rendered data to D3D textures on the main thread
for (auto& view : m_WebViews)
{
view->UpdateTexture();
Expand Down
365 changes: 144 additions & 221 deletions Client/cefweb/CWebView.cpp

Large diffs are not rendered by default.

58 changes: 30 additions & 28 deletions Client/cefweb/CWebView.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
#include <cef3/cef/include/cef_values.h>
#include <SString.h>
#include <audiopolicy.h>
#include <condition_variable>
#include <functional>
#include <memory>
#include <mmdeviceapi.h>
#include <mutex>
#include <cstdint>
#include <chrono>
#define GetNextSibling(hwnd) GetWindow(hwnd, GW_HWNDNEXT) // Re-define the conflicting macro
#define GetFirstChild(hwnd) GetTopWindow(hwnd)

Expand All @@ -43,12 +43,6 @@ namespace WebViewAuth
bool HandleInputFocus(CWebView*, CefRefPtr<CefListValue>, const bool);
}

enum class ECefThreadState
{
Running = 0, // CEF thread is currently running
Wait // CEF thread is waiting for the main thread
};

class CWebView : public CWebViewInterface,
private CefClient,
private CefRenderHandler,
Expand All @@ -71,6 +65,7 @@ class CWebView : public CWebViewInterface,
void SetWebBrowserEvents(CWebBrowserEventsInterface* pInterface);
void ClearWebBrowserEvents(CWebBrowserEventsInterface* pInterface);
void CloseBrowser();
bool EnsureBrowserCreated(); // Lazy creation: creates browser on first use
CefRefPtr<CefBrowser> GetCefBrowser() { return m_pWebView; };

bool IsBeingDestroyed() { return m_bBeingDestroyed; }
Expand Down Expand Up @@ -211,7 +206,6 @@ class CWebView : public CWebViewInterface,
CefRefPtr<CefMenuModel> model) override;

private:
void ResumeCefThread();
void QueueBrowserEvent(const char* name, std::function<void(CWebBrowserEventsInterface*)>&& fn);

struct FEventTarget
Expand Down Expand Up @@ -270,29 +264,37 @@ class CWebView : public CWebViewInterface,
CefRefPtr<CefBrowser> m_pWebView;
CWebBrowserItem* m_pWebBrowserRenderItem;

std::atomic_bool m_bBeingDestroyed;
bool m_bIsLocal;
bool m_bIsRenderingPaused;
bool m_bIsTransparent;
POINT m_vecMousePosition;
bool m_mouseButtonStates[3];
SString m_CurrentTitle;
float m_fVolume;
std::map<SString, SString> m_Properties;
bool m_bHasInputFocus;
std::set<std::string> m_AjaxHandlers;
std::shared_ptr<FEventTarget> m_pEventTarget;
std::atomic_bool m_bBeingDestroyed;
bool m_bIsLocal;
bool m_bIsRenderingPaused;
bool m_bIsTransparent;
bool m_bBrowserCreated = false; // Lazy creation: tracks if CEF browser has been created
SString m_strPendingURL; // Lazy creation: URL to load when browser is ready
bool m_bPendingURLFilterEnabled = true;
SString m_strPendingPostData;
bool m_bPendingURLEncoded = true;
POINT m_vecMousePosition;
POINT m_vecPendingMousePosition; // Pending position for throttled mouse move
bool m_bHasPendingMouseMove = false; // Whether there's a pending throttled mouse move
std::chrono::steady_clock::time_point m_lastMouseMoveTime; // For mouse move throttling
bool m_mouseButtonStates[3];
SString m_CurrentTitle;
float m_fVolume;
std::map<SString, SString> m_Properties;
bool m_bHasInputFocus;
std::set<std::string> m_AjaxHandlers;
std::shared_ptr<FEventTarget> m_pEventTarget;

struct
{
bool changed = false;
std::mutex dataMutex;
ECefThreadState cefThreadState = ECefThreadState::Running;
std::condition_variable cefThreadCv;

const void* buffer;
int width, height;
CefRenderHandler::RectList dirtyRects;
bool changed = false;
std::mutex dataMutex;

// Main frame buffer - we now own this buffer (copied in OnPaint)
std::unique_ptr<byte[]> buffer;
size_t bufferSize = 0;
int width = 0;
int height = 0;

CefRect popupRect;
bool popupShown = false;
Expand Down
1 change: 1 addition & 0 deletions Client/core/CClientVariables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ void CClientVariables::LoadDefaults()
DEFAULT("discord_rpc_share_data", false); // Consistent Rich Presence data sharing
DEFAULT("discord_rpc_share_data_firsttime", false); // Display the user data sharing consent dialog box - for the first time
DEFAULT("browser_enable_gpu", true); // Enable GPU in CEF? (allows stuff like WebGL to function)
DEFAULT("browser_enable_video_acceleration", true); // Enable hardware video decoding in CEF?
DEFAULT("process_cpu_affinity", true); // Set CPU 0 affinity to improve game performance and fix the known issue in single-threaded games
DEFAULT("ask_before_disconnect", true); // Ask before disconnecting from a server
DEFAULT("allow_steam_client", false); // Allow connecting with the local Steam client (to set GTA:SA ingame status)
Expand Down
17 changes: 16 additions & 1 deletion Client/core/CSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ void CSettings::ResetGuiPointers()
m_pGridBrowserWhitelist = NULL;
m_pButtonBrowserWhitelistRemove = NULL;
m_pCheckBoxBrowserGPUEnabled = NULL;
m_pCheckBoxBrowserVideoAccelEnabled = NULL;
}

CSettings::CSettings()
Expand Down Expand Up @@ -1555,6 +1556,10 @@ void CSettings::CreateGUI()
m_pCheckBoxBrowserGPUEnabled->SetPosition(CVector2D(browserRightColumnX, vecTemp.fY - 25.0f));
m_pCheckBoxBrowserGPUEnabled->AutoSize(NULL, 20.0f);

m_pCheckBoxBrowserVideoAccelEnabled = reinterpret_cast<CGUICheckBox*>(pManager->CreateCheckBox(m_pTabBrowser, _("Enable video acceleration"), true));
m_pCheckBoxBrowserVideoAccelEnabled->SetPosition(CVector2D(browserRightColumnX, vecTemp.fY));
m_pCheckBoxBrowserVideoAccelEnabled->AutoSize(NULL, 20.0f);

m_pLabelBrowserCustomBlacklist = reinterpret_cast<CGUILabel*>(pManager->CreateLabel(m_pTabBrowser, _("Custom blacklist")));
m_pLabelBrowserCustomBlacklist->SetPosition(CVector2D(vecTemp.fX, vecTemp.fY + 30.0f));
m_pLabelBrowserCustomBlacklist->GetPosition(vecTemp);
Expand Down Expand Up @@ -4218,6 +4223,8 @@ void CSettings::LoadData()
m_pCheckBoxRemoteJavascript->SetSelected(bVar);
CVARS_GET("browser_enable_gpu", bVar);
m_pCheckBoxBrowserGPUEnabled->SetSelected(bVar);
CVARS_GET("browser_enable_video_acceleration", bVar);
m_pCheckBoxBrowserVideoAccelEnabled->SetSelected(bVar);

ReloadBrowserLists();
}
Expand Down Expand Up @@ -4723,6 +4730,13 @@ void CSettings::SaveData()
bool bBrowserGPUSettingChanged = (bBrowserGPUSetting != bBrowserGPUEnabled);
CVARS_SET("browser_enable_gpu", bBrowserGPUSetting);

bool bBrowserVideoAccelEnabled = false;
CVARS_GET("browser_enable_video_acceleration", bBrowserVideoAccelEnabled);

bool bBrowserVideoAccelSetting = m_pCheckBoxBrowserVideoAccelEnabled->GetSelected();
bool bBrowserVideoAccelSettingChanged = (bBrowserVideoAccelSetting != bBrowserVideoAccelEnabled);
CVARS_SET("browser_enable_video_acceleration", bBrowserVideoAccelSetting);

// Ensure CVARS ranges ok
CClientVariables::GetSingleton().ValidateValues();

Expand All @@ -4732,7 +4746,8 @@ void CSettings::SaveData()
gameSettings->Save();

// Ask to restart?
if (bIsVideoModeChanged || bIsAntiAliasingChanged || bIsCustomizedSAFilesChanged || processsDPIAwareChanged || bBrowserGPUSettingChanged)
if (bIsVideoModeChanged || bIsAntiAliasingChanged || bIsCustomizedSAFilesChanged || processsDPIAwareChanged || bBrowserGPUSettingChanged ||
bBrowserVideoAccelSettingChanged)
ShowRestartQuestion();
else if (CModManager::GetSingleton().IsLoaded() && bBrowserSettingChanged)
ShowDisconnectQuestion();
Expand Down
1 change: 1 addition & 0 deletions Client/core/CSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ class CSettings
CGUIButton* m_pButtonBrowserWhitelistRemove;
CGUIButton* m_pButtonBrowserWhitelistRemoveAll;
CGUICheckBox* m_pCheckBoxBrowserGPUEnabled;
CGUICheckBox* m_pCheckBoxBrowserVideoAccelEnabled;
bool m_bBrowserListsChanged;
bool m_bBrowserListsLoadEnabled;

Expand Down
26 changes: 13 additions & 13 deletions Client/core/Graphics/CRenderItem.WebBrowser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,25 @@ bool CWebBrowserItem::IsValid()
//
// CWebBrowserItem::OnLostDevice
//
// Release device stuff
// Release device stuff - D3DPOOL_DEFAULT textures must be released
//
////////////////////////////////////////////////////////////////
void CWebBrowserItem::OnLostDevice()
{
ReleaseUnderlyingData();
}

////////////////////////////////////////////////////////////////
//
// CWebBrowserItem::OnResetDevice
//
// Recreate device stuff
// Recreate device stuff - D3DPOOL_DEFAULT textures must be recreated
//
////////////////////////////////////////////////////////////////
void CWebBrowserItem::OnResetDevice()
{
CreateUnderlyingData();
m_bTextureWasRecreated = true; // Force full repaint after device reset
}

////////////////////////////////////////////////////////////////
Expand All @@ -87,8 +90,13 @@ void CWebBrowserItem::CreateUnderlyingData()
assert(!m_pD3DRenderTargetSurface);
assert(!m_pD3DTexture);

// Check if texture is actually created. It can be failed in some conditions(e.g. lack of memory).
if (FAILED(D3DXCreateTexture(m_pDevice, m_uiSizeX, m_uiSizeY, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, (IDirect3DTexture9**)&m_pD3DTexture)) ||
// Use D3DPOOL_DEFAULT with D3DUSAGE_DYNAMIC for better performance:
// - Dynamic textures are optimized for frequent Lock/Unlock operations
// - D3DLOCK_DISCARD can be used effectively to avoid stalls
// - No system memory copy (unlike D3DPOOL_MANAGED), reducing memory usage
// Note: Must handle device lost/reset as DEFAULT pool textures don't survive resets
if (FAILED(m_pDevice->CreateTexture(m_uiSizeX, m_uiSizeY, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**)&m_pD3DTexture,
nullptr)) ||
!m_pD3DTexture)
return;

Expand All @@ -99,15 +107,7 @@ void CWebBrowserItem::CreateUnderlyingData()
return;
}

// D3DXCreateTexture sets width and height to 1 if the argument value was 0
// See: https://docs.microsoft.com/en-us/windows/desktop/direct3d9/d3dxcreatetexture
if (m_uiSizeX == 0)
m_uiSizeX = 1;

if (m_uiSizeY == 0)
m_uiSizeY = 1;

// Update surface size, although it probably will be unchanged | Todo: Remove this
// Update surface size - dynamic textures may have different dimensions than requested
D3DSURFACE_DESC desc;
m_pD3DRenderTargetSurface->GetDesc(&desc);
m_uiSurfaceSizeX = desc.Width;
Expand Down
1 change: 1 addition & 0 deletions Client/sdk/core/CRenderItemManagerInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -573,4 +573,5 @@ class CWebBrowserItem : public CTextureItem
virtual void Resize(const CVector2D& size);

IDirect3DSurface9* m_pD3DRenderTargetSurface;
bool m_bTextureWasRecreated = false; // Set after device reset to force full repaint
};
Loading