summaryrefslogtreecommitdiff
path: root/alf/alfcompat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alfcompat.cpp')
-rw-r--r--alf/alfcompat.cpp175
1 files changed, 169 insertions, 6 deletions
diff --git a/alf/alfcompat.cpp b/alf/alfcompat.cpp
index 6321a44..df7f27d 100644
--- a/alf/alfcompat.cpp
+++ b/alf/alfcompat.cpp
@@ -4,6 +4,20 @@
DWORD _alf_compatBits = 0;
+typedef struct {
+ LONG lock;
+ SIZE currentBitmapSize;
+ SIZE maxBitmapSize;
+ HDC hdcBuffer;
+ HBITMAP hbmBuffer;
+ HBITMAP hbmOld;
+
+ HDC hdcTarget;
+ RECT rcTarget;
+} ALFCompatBufferedPaintPriv;
+
+ALFCompatBufferedPaintPriv *_alf_compatBufferedPaintPriv = NULL;
+
static
DWORD ALF_DllGetVersion(const char *dll)
{
@@ -290,6 +304,73 @@ ALF_Compat_fallbackBufferedPaintUnInit(void)
return E_NOTIMPL;
}
+static ALF_Compat_HPAINTBUFFER WINAPI
+ALF_Compat_fallbackBeginBufferedPaint(HDC hdc, const RECT *prcTarget, DWORD dwFormat,
+ ALF_Compat_BP_PAINTPARAMS *pPaintParams,
+ HDC *phdcTarget)
+{
+ if (dwFormat != 0 || pPaintParams != 0
+ || !_alf_compatBufferedPaintPriv
+ || prcTarget->right - prcTarget->left > _alf_compatBufferedPaintPriv->maxBitmapSize.cx
+ || prcTarget->bottom - prcTarget->top > _alf_compatBufferedPaintPriv->maxBitmapSize.cy
+ || InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 1)) {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return NULL;
+ }
+
+ // we have locked the buffer! now allocate the bitmap if necessary
+ if (!_alf_compatBufferedPaintPriv->hdcBuffer) {
+ _alf_compatBufferedPaintPriv->hdcBuffer = CreateCompatibleDC(NULL);
+ if (!_alf_compatBufferedPaintPriv->hdcBuffer) {
+ InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0);
+ return NULL;
+ }
+ }
+
+
+ if (!_alf_compatBufferedPaintPriv->hbmBuffer
+ || prcTarget->right - prcTarget->left > _alf_compatBufferedPaintPriv->currentBitmapSize.cx
+ || prcTarget->bottom - prcTarget->top > _alf_compatBufferedPaintPriv->currentBitmapSize.cy) {
+
+ DeleteBitmap(_alf_compatBufferedPaintPriv->hbmBuffer);
+
+ int neww = _alf_compatBufferedPaintPriv->currentBitmapSize.cx;
+ int newh = _alf_compatBufferedPaintPriv->currentBitmapSize.cy;
+
+ if (neww < 1)
+ neww = 32;
+ if (newh < 1)
+ newh = 16;
+
+ while (neww < prcTarget->right - prcTarget->left) {
+ neww *= 2;
+ }
+ while (newh < prcTarget->bottom - prcTarget->top) {
+ newh *= 2;
+ }
+
+ HDC hdcScreen = GetDC(NULL);
+ _alf_compatBufferedPaintPriv->hbmBuffer = CreateCompatibleBitmap(hdcScreen, neww, newh);
+ ReleaseDC(NULL, hdcScreen);
+
+ if (!_alf_compatBufferedPaintPriv->hbmBuffer) {
+ InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0);
+ return NULL;
+ }
+
+ _alf_compatBufferedPaintPriv->currentBitmapSize.cx = neww;
+ _alf_compatBufferedPaintPriv->currentBitmapSize.cy = newh;
+ }
+
+ _alf_compatBufferedPaintPriv->hbmOld = SelectBitmap(_alf_compatBufferedPaintPriv->hdcBuffer, _alf_compatBufferedPaintPriv->hbmBuffer);
+
+ _alf_compatBufferedPaintPriv->hdcTarget = hdc;
+ _alf_compatBufferedPaintPriv->rcTarget = *prcTarget;
+ *phdcTarget = _alf_compatBufferedPaintPriv->hdcBuffer;
+
+ return _alf_compatBufferedPaintPriv;
+}
+
static ALF_Compat_HANIMATIONBUFFER WINAPI
ALF_Compat_fallbackBeginBufferedAnimation(HWND hwnd, HDC hdcTarget,
const RECT *prcTarget, DWORD dwFormat,
@@ -297,18 +378,41 @@ ALF_Compat_fallbackBeginBufferedAnimation(HWND hwnd, HDC hdcTarget,
ALF_Compat_BP_ANIMATIONPARAMS *pAnimationParams,
HDC *phdcFrom, HDC *phdcTo)
{
- (void)hwnd; (void)hdcTarget; (void)prcTarget; (void)dwFormat;
- (void)pPaintParams; (void)pAnimationParams; (void)phdcFrom; (void)phdcTo;
+ (void)hwnd;
+ if (pAnimationParams != NULL && pAnimationParams->dwDuration == 0) {
+ *phdcFrom = NULL;
+ return ALF_Compat_fallbackBeginBufferedPaint(hdcTarget, prcTarget, dwFormat, pPaintParams, phdcTo);
+ } else {
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return NULL;
+ }
+}
- return NULL;
+extern HRESULT WINAPI
+ALF_Compat_fallbackEndBufferedPaint(ALF_Compat_HPAINTBUFFER hpbBuffer, BOOL fUpdateTarget)
+{
+ if (hpbBuffer != _alf_compatBufferedPaintPriv)
+ return E_INVALIDARG;
+
+ if (fUpdateTarget)
+ BitBlt(_alf_compatBufferedPaintPriv->hdcTarget,
+ _alf_compatBufferedPaintPriv->rcTarget.left,
+ _alf_compatBufferedPaintPriv->rcTarget.top,
+ _alf_compatBufferedPaintPriv->rcTarget.right - _alf_compatBufferedPaintPriv->rcTarget.left,
+ _alf_compatBufferedPaintPriv->rcTarget.bottom - _alf_compatBufferedPaintPriv->rcTarget.top,
+ _alf_compatBufferedPaintPriv->hdcBuffer,
+ 0, 0, SRCCOPY);
+
+ SelectBitmap(_alf_compatBufferedPaintPriv->hdcBuffer, _alf_compatBufferedPaintPriv->hbmOld);
+ _alf_compatBufferedPaintPriv->hdcTarget = NULL;
+ InterlockedExchange(&_alf_compatBufferedPaintPriv->lock, 0);
+ return S_OK;
}
static HRESULT WINAPI
ALF_Compat_fallbackEndBufferedAnimation(ALF_Compat_HANIMATIONBUFFER hbpAnimation, BOOL fUpdateTarget)
{
- (void)hbpAnimation; (void)fUpdateTarget;
-
- return E_NOTIMPL;
+ return ALF_Compat_fallbackEndBufferedPaint(hbpAnimation, fUpdateTarget);
}
static BOOL WINAPI
@@ -499,7 +603,9 @@ void ALF_LoadCompatFunctions(void)
LOAD_FUNC(uxtheme, BufferedPaintInit);
LOAD_FUNC(uxtheme, BufferedPaintUnInit);
LOAD_FUNC(uxtheme, BeginBufferedAnimation);
+ LOAD_FUNC(uxtheme, BeginBufferedPaint);
LOAD_FUNC(uxtheme, EndBufferedAnimation);
+ LOAD_FUNC(uxtheme, EndBufferedPaint);
LOAD_FUNC(uxtheme, BufferedPaintRenderAnimation);
LOAD_FUNC(uxtheme, GetThemeTransitionDuration);
LOAD_FUNC(uxtheme, GetThemePartSize);
@@ -516,10 +622,63 @@ void ALF_LoadCompatFunctions(void)
} else {
ALF_Compat_DrawDisabledText = ALF_Compat_DrawDisabledText31;
}
+
+ // initialize double buffering wrapper
+ if (ALF_Compat_BufferedPaintInit == ALF_Compat_fallbackBufferedPaintInit) {
+ // set max size based on available RAM, so that at most 1‰ of it is spent on us
+ int maxx = 0;
+ int maxy = 0;
+
+ MEMORYSTATUS ms;
+ ZeroMemory(&ms, sizeof(ms));
+ GlobalMemoryStatus(&ms);
+
+ if (ms.dwTotalPhys >= 16777216u) {
+ maxx = 128;
+ maxy = 32;
+ }
+ if (ms.dwTotalPhys >= 33554432u) {
+ maxy = 64;
+ }
+ if (ms.dwTotalPhys >= 67108864u) {
+ maxx = 256;
+ }
+ if (ms.dwTotalPhys >= 134217728u) {
+ maxy = 128;
+ }
+ if (ms.dwTotalPhys >= 268435456u) {
+ maxx = 512;
+ }
+ if (ms.dwTotalPhys >= 536870912u) {
+ maxx = 1024;
+ }
+ if (ms.dwTotalPhys >= 1073741824u) {
+ maxy = 256;
+ }
+ if (ms.dwTotalPhys >= 2147483648u) {
+ maxy = 512;
+ }
+ if (ms.dwTotalPhys == (SIZE_T)-1) {
+ maxy = 1024;
+ }
+
+ if (maxx > 0 && maxy > 0) {
+ _alf_compatBufferedPaintPriv = ALF_New(ALFCompatBufferedPaintPriv, 1);
+ _alf_compatBufferedPaintPriv->maxBitmapSize.cx = maxx;
+ _alf_compatBufferedPaintPriv->maxBitmapSize.cy = maxy;
+ }
+ }
}
void ALF_UnloadCompatFunctions(void)
{
+ if (_alf_compatBufferedPaintPriv) {
+ DeleteDC(_alf_compatBufferedPaintPriv->hdcBuffer);
+ DeleteBitmap(_alf_compatBufferedPaintPriv->hbmBuffer);
+ ALF_Free(_alf_compatBufferedPaintPriv);
+ _alf_compatBufferedPaintPriv = NULL;
+ }
+
UNLOAD_FUNC(IsAppThemed);
UNLOAD_FUNC(GetDpiForWindow);
UNLOAD_FUNC(AdjustWindowRectExForDpi);
@@ -537,7 +696,9 @@ void ALF_UnloadCompatFunctions(void)
UNLOAD_FUNC(BufferedPaintInit);
UNLOAD_FUNC(BufferedPaintUnInit);
UNLOAD_FUNC(BeginBufferedAnimation);
+ UNLOAD_FUNC(BeginBufferedPaint);
UNLOAD_FUNC(EndBufferedAnimation);
+ UNLOAD_FUNC(EndBufferedPaint);
UNLOAD_FUNC(BufferedPaintRenderAnimation);
UNLOAD_FUNC(GetThemeTransitionDuration);
UNLOAD_FUNC(GetThemePartSize);
@@ -573,7 +734,9 @@ HRESULT (WINAPI *ALF_Compat_GetThemePartSize)(HTHEME,HDC,int,int,RECT *,THEMESIZ
HRESULT (WINAPI *ALF_Compat_BufferedPaintInit)(void) = NULL;
HRESULT (WINAPI *ALF_Compat_BufferedPaintUnInit)(void) = NULL;
ALF_Compat_HANIMATIONBUFFER (WINAPI *ALF_Compat_BeginBufferedAnimation)(HWND,HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,ALF_Compat_BP_ANIMATIONPARAMS *,HDC *,HDC *) = NULL;
+ALF_Compat_HPAINTBUFFER (WINAPI *ALF_Compat_BeginBufferedPaint)(HDC,const RECT *,DWORD,ALF_Compat_BP_PAINTPARAMS *,HDC *) = NULL;
HRESULT (WINAPI *ALF_Compat_EndBufferedAnimation)(ALF_Compat_HANIMATIONBUFFER,BOOL) = NULL;
+HRESULT (WINAPI *ALF_Compat_EndBufferedPaint)(ALF_Compat_HPAINTBUFFER,BOOL) = NULL;
BOOL (WINAPI *ALF_Compat_BufferedPaintRenderAnimation)(HWND,HDC) = NULL;
HRESULT (WINAPI *ALF_Compat_GetThemeTransitionDuration)(HTHEME,int,int,int,int,DWORD*) = NULL;
HRESULT (WINAPI *ALF_Compat_GetThemeColor)(HTHEME,int,int,int,COLORREF*) = NULL;