|
15 | 15 | bool g_bInGTAScene = false; |
16 | 16 | CProxyDirect3DDevice9* g_pProxyDevice = NULL; |
17 | 17 | CProxyDirect3DDevice9::SD3DDeviceState* g_pDeviceState = NULL; |
| 18 | +SGammaState g_GammaState; |
18 | 19 |
|
19 | 20 | // Proxy constructor and destructor. |
20 | 21 | CProxyDirect3DDevice9::CProxyDirect3DDevice9(IDirect3DDevice9* pDevice) |
@@ -123,6 +124,22 @@ CProxyDirect3DDevice9::~CProxyDirect3DDevice9() |
123 | 124 | { |
124 | 125 | WriteDebugEvent(SString("CProxyDirect3DDevice9::~CProxyDirect3DDevice9 %08x", this)); |
125 | 126 |
|
| 127 | + // Reset gamma state when device is destroyed |
| 128 | + if (g_pProxyDevice == this) |
| 129 | + { |
| 130 | + // Restore original gamma if we had stored it |
| 131 | + if (g_GammaState.bOriginalGammaStored && m_pDevice) |
| 132 | + { |
| 133 | + m_pDevice->SetGammaRamp(g_GammaState.lastSwapChain, 0, &g_GammaState.originalGammaRamp); |
| 134 | + WriteDebugEvent("Restored original gamma ramp on device destruction"); |
| 135 | + } |
| 136 | + |
| 137 | + // Reset gamma state |
| 138 | + g_GammaState.bOriginalGammaStored = false; |
| 139 | + g_GammaState.bLastWasBorderless = false; |
| 140 | + ZeroMemory(&g_GammaState.originalGammaRamp, sizeof(g_GammaState.originalGammaRamp)); |
| 141 | + } |
| 142 | + |
126 | 143 | // Release our reference to the wrapped device |
127 | 144 | // Note: We don't check m_ulRefCount here because destructor is only called |
128 | 145 | // when Release() determined the count reached 0 |
@@ -374,6 +391,12 @@ HRESULT CProxyDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParamet |
374 | 391 | return D3DERR_INVALIDCALL; |
375 | 392 | } |
376 | 393 |
|
| 394 | + // Reset gamma state since display mode might change |
| 395 | + g_GammaState.bOriginalGammaStored = false; |
| 396 | + g_GammaState.bLastWasBorderless = false; |
| 397 | + ZeroMemory(&g_GammaState.originalGammaRamp, sizeof(g_GammaState.originalGammaRamp)); |
| 398 | + WriteDebugEvent("Reset gamma state due to device reset"); |
| 399 | + |
377 | 400 | // Check cooperative level before attempting reset |
378 | 401 | HRESULT hCoopLevel = m_pDevice->TestCooperativeLevel(); |
379 | 402 | if (hCoopLevel == D3DERR_DEVICELOST) |
@@ -473,6 +496,7 @@ HRESULT CProxyDirect3DDevice9::Reset(D3DPRESENT_PARAMETERS* pPresentationParamet |
473 | 496 | return hResult; |
474 | 497 | } |
475 | 498 |
|
| 499 | + |
476 | 500 | HRESULT CProxyDirect3DDevice9::Present(CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) |
477 | 501 | { |
478 | 502 | CDirect3DEvents9::OnPresent(m_pDevice); |
@@ -508,12 +532,99 @@ HRESULT CProxyDirect3DDevice9::SetDialogBoxMode(BOOL bEnableDialogs) |
508 | 532 |
|
509 | 533 | VOID CProxyDirect3DDevice9::SetGammaRamp(UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) |
510 | 534 | { |
511 | | - m_pDevice->SetGammaRamp(iSwapChain, Flags, pRamp); |
| 535 | + // Validate inputs first |
| 536 | + if (!pRamp) |
| 537 | + { |
| 538 | + WriteDebugEvent("CProxyDirect3DDevice9::SetGammaRamp - Invalid gamma ramp pointer"); |
| 539 | + return; |
| 540 | + } |
| 541 | + |
| 542 | + // Validate swap chain index |
| 543 | + if (iSwapChain >= GetNumberOfSwapChains()) |
| 544 | + { |
| 545 | + WriteDebugEvent(SString("CProxyDirect3DDevice9::SetGammaRamp - Invalid swap chain index: %d", iSwapChain)); |
| 546 | + return; |
| 547 | + } |
| 548 | + |
| 549 | + // Get current display mode state - use a timeout to avoid race conditions during mode transitions |
| 550 | + CVideoModeManagerInterface* pVideoModeManager = GetVideoModeManager(); |
| 551 | + if (!pVideoModeManager) |
| 552 | + { |
| 553 | + // Fallback to original behavior if video mode manager is unavailable |
| 554 | + m_pDevice->SetGammaRamp(iSwapChain, Flags, pRamp); |
| 555 | + return; |
| 556 | + } |
| 557 | + |
| 558 | + bool bIsBorderlessMode = pVideoModeManager->IsDisplayModeWindowed() || pVideoModeManager->IsDisplayModeFullScreenWindow(); |
| 559 | + |
| 560 | + // Store original gamma ramp on first call or mode change |
| 561 | + if (!g_GammaState.bOriginalGammaStored || g_GammaState.lastSwapChain != iSwapChain || g_GammaState.bLastWasBorderless != bIsBorderlessMode) |
| 562 | + { |
| 563 | + if (!bIsBorderlessMode || !g_GammaState.bOriginalGammaStored) |
| 564 | + { |
| 565 | + // In fullscreen mode or first time - this is likely the original gamma |
| 566 | + g_GammaState.originalGammaRamp = *pRamp; |
| 567 | + g_GammaState.bOriginalGammaStored = true; |
| 568 | + g_GammaState.lastSwapChain = iSwapChain; |
| 569 | + } |
| 570 | + g_GammaState.bLastWasBorderless = bIsBorderlessMode; |
| 571 | + } |
| 572 | + |
| 573 | + if (bIsBorderlessMode) |
| 574 | + { |
| 575 | + // Apply brightness and contrast adjustment to match fullscreen mode |
| 576 | + D3DGAMMARAMP adjustedRamp = *pRamp; |
| 577 | + |
| 578 | + // Use lighter gamma correction to prevent darkening effect |
| 579 | + // and optimize brightness boost for better visibility |
| 580 | + const float fGammaCorrection = 1.0f / 1.3f; |
| 581 | + const float fBrightnessBoost = 1.4f; |
| 582 | + |
| 583 | + for (int i = 0; i < 256; i++) |
| 584 | + { |
| 585 | + // Convert to normalized float (0.0 - 1.0) |
| 586 | + float fRed = static_cast<float>(pRamp->red[i]) / 65535.0f; |
| 587 | + float fGreen = static_cast<float>(pRamp->green[i]) / 65535.0f; |
| 588 | + float fBlue = static_cast<float>(pRamp->blue[i]) / 65535.0f; |
| 589 | + |
| 590 | + // Clamp input values to valid range |
| 591 | + fRed = std::max(0.0f, std::min(1.0f, fRed)); |
| 592 | + fGreen = std::max(0.0f, std::min(1.0f, fGreen)); |
| 593 | + fBlue = std::max(0.0f, std::min(1.0f, fBlue)); |
| 594 | + |
| 595 | + // Apply gentler gamma correction first |
| 596 | + fRed = powf(fRed, fGammaCorrection); |
| 597 | + fGreen = powf(fGreen, fGammaCorrection); |
| 598 | + fBlue = powf(fBlue, fGammaCorrection); |
| 599 | + |
| 600 | + // Then apply balanced brightness boost |
| 601 | + fRed = std::min(1.0f, fRed * fBrightnessBoost); |
| 602 | + fGreen = std::min(1.0f, fGreen * fBrightnessBoost); |
| 603 | + fBlue = std::min(1.0f, fBlue * fBrightnessBoost); |
| 604 | + |
| 605 | + // Convert back to WORD values with proper rounding |
| 606 | + adjustedRamp.red[i] = static_cast<WORD>(fRed * 65535.0f + 0.5f); |
| 607 | + adjustedRamp.green[i] = static_cast<WORD>(fGreen * 65535.0f + 0.5f); |
| 608 | + adjustedRamp.blue[i] = static_cast<WORD>(fBlue * 65535.0f + 0.5f); |
| 609 | + } |
| 610 | + |
| 611 | + // Set the adjusted gamma ramp |
| 612 | + m_pDevice->SetGammaRamp(iSwapChain, Flags, &adjustedRamp); |
| 613 | + |
| 614 | + WriteDebugEvent("Applied gamma adjustment for borderless windowed mode"); |
| 615 | + } |
| 616 | + else |
| 617 | + { |
| 618 | + // In exclusive fullscreen mode, use the original gamma ramp |
| 619 | + m_pDevice->SetGammaRamp(iSwapChain, Flags, pRamp); |
| 620 | + |
| 621 | + WriteDebugEvent("Applied original gamma ramp for fullscreen mode"); |
| 622 | + } |
512 | 623 | } |
513 | 624 |
|
514 | 625 | VOID CProxyDirect3DDevice9::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) |
515 | 626 | { |
516 | | - m_pDevice->GetGammaRamp(iSwapChain, pRamp); |
| 627 | + return m_pDevice->GetGammaRamp(iSwapChain, pRamp); |
517 | 628 | } |
518 | 629 |
|
519 | 630 | HRESULT CProxyDirect3DDevice9::CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, |
|
0 commit comments