mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-21 18:58:13 +00:00
os2: add port files for SDL2-2.0.4 from Andrey Vasilkin
only geniconv/iconv.h (was from LGPL libiconv) is replaced with a generic minimal iconv.h based on public knowledge.
This commit is contained in:
512
src/video/os2/SDL_os2vman.c
Normal file
512
src/video/os2/SDL_os2vman.c
Normal file
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSMODULEMGR
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#define INCL_GPIBITMAPS // GPI bit map functions
|
||||
#include <os2.h>
|
||||
#define INCL_GRE_DEVICE
|
||||
#define INCL_GRE_DEVMISC
|
||||
#include <pmddi.h>
|
||||
#include "SDL_os2output.h"
|
||||
#include "gradd.h"
|
||||
#include "SDL_os2video.h"
|
||||
|
||||
typedef struct _VODATA {
|
||||
PVOID pBuffer;
|
||||
HRGN hrgnVisible;
|
||||
ULONG ulBPP;
|
||||
ULONG ulScanLineSize;
|
||||
ULONG ulWidth;
|
||||
ULONG ulHeight;
|
||||
ULONG ulScreenHeight;
|
||||
ULONG ulScreenBytesPerLine;
|
||||
RECTL rectlWin;
|
||||
|
||||
PRECTL pRectl;
|
||||
ULONG cRectl;
|
||||
PBLTRECT pBltRect;
|
||||
ULONG cBltRect;
|
||||
} VODATA;
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo);
|
||||
static PVODATA voOpen();
|
||||
static VOID voClose(PVODATA pVOData);
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible);
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize);
|
||||
static VOID voVideoBufFree(PVODATA pVOData);
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects);
|
||||
|
||||
OS2VIDEOOUTPUT voVMan = {
|
||||
voQueryInfo,
|
||||
voOpen,
|
||||
voClose,
|
||||
voSetVisibleRegion,
|
||||
voVideoBufAlloc,
|
||||
voVideoBufFree,
|
||||
voUpdate
|
||||
};
|
||||
|
||||
|
||||
static HMODULE hmodVMan = NULLHANDLE;
|
||||
static FNVMIENTRY *pfnVMIEntry = NULL;
|
||||
static ULONG ulVRAMAddress = 0;
|
||||
|
||||
VOID APIENTRY ExitVMan(VOID)
|
||||
{
|
||||
if ( ( ulVRAMAddress != 0 ) && ( hmodVMan != NULLHANDLE ) )
|
||||
{
|
||||
pfnVMIEntry( 0, VMI_CMD_TERMPROC, NULL, NULL );
|
||||
DosFreeModule( hmodVMan );
|
||||
}
|
||||
|
||||
DosExitList( EXLST_EXIT, (PFNEXITLIST)NULL );
|
||||
}
|
||||
|
||||
static BOOL _vmanInit()
|
||||
{
|
||||
ULONG ulRC;
|
||||
CHAR acBuf[255];
|
||||
INITPROCOUT stInitProcOut;
|
||||
|
||||
if ( hmodVMan != NULLHANDLE )
|
||||
// Already was initialized.
|
||||
return TRUE;
|
||||
|
||||
// Load vman.dll
|
||||
ulRC = DosLoadModule( &acBuf, sizeof(acBuf), "VMAN", &hmodVMan );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Could not load VMAN.DLL, rc = %u : %s", ulRC, &acBuf );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get VMIEntry.
|
||||
ulRC = DosQueryProcAddr( hmodVMan, 0L, "VMIEntry", (PFN *)&pfnVMIEntry );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Could not query address of pfnVMIEntry func. of VMAN.DLL, "
|
||||
"rc = %u", ulRC );
|
||||
DosFreeModule( hmodVMan );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// VMAN initialization.
|
||||
stInitProcOut.ulLength = sizeof(stInitProcOut);
|
||||
ulRC = pfnVMIEntry( 0, VMI_CMD_INITPROC, NULL, &stInitProcOut );
|
||||
if ( ulRC != RC_SUCCESS )
|
||||
{
|
||||
debug( "Could not initialize VMAN for this process" );
|
||||
pfnVMIEntry = NULL;
|
||||
DosFreeModule( hmodVMan );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Store video memory virtual address.
|
||||
ulVRAMAddress = stInitProcOut.ulVRAMVirt;
|
||||
// We use exit list for VMI_CMD_TERMPROC.
|
||||
if ( DosExitList( EXLST_ADD | 0x00001000, (PFNEXITLIST)ExitVMan )
|
||||
!= NO_ERROR )
|
||||
debug( "DosExitList() failed" );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PRECTL _getRectlArray(PVODATA pVOData, ULONG cRects)
|
||||
{
|
||||
PRECTL pRectl;
|
||||
|
||||
if ( pVOData->cRectl >= cRects )
|
||||
return pVOData->pRectl;
|
||||
|
||||
pRectl = SDL_realloc( pVOData->pRectl, cRects * sizeof(RECTL) );
|
||||
if ( pRectl == NULL )
|
||||
return NULL;
|
||||
|
||||
pVOData->pRectl = pRectl;
|
||||
pVOData->cRectl = cRects;
|
||||
return pRectl;
|
||||
}
|
||||
|
||||
static PBLTRECT _getBltRectArray(PVODATA pVOData, ULONG cRects)
|
||||
{
|
||||
PBLTRECT pBltRect;
|
||||
|
||||
if ( pVOData->cBltRect >= cRects )
|
||||
return pVOData->pBltRect;
|
||||
|
||||
pBltRect = SDL_realloc( pVOData->pBltRect, cRects * sizeof(BLTRECT) );
|
||||
if ( pBltRect == NULL )
|
||||
return NULL;
|
||||
|
||||
pVOData->pBltRect = pBltRect;
|
||||
pVOData->cBltRect = cRects;
|
||||
return pBltRect;
|
||||
}
|
||||
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo)
|
||||
{
|
||||
ULONG ulRC;
|
||||
GDDMODEINFO sCurModeInfo;
|
||||
|
||||
if ( !_vmanInit() )
|
||||
return FALSE;
|
||||
|
||||
// Query current (desktop) mode.
|
||||
ulRC = pfnVMIEntry( 0, VMI_CMD_QUERYCURRENTMODE, NULL, &sCurModeInfo );
|
||||
if ( ulRC != RC_SUCCESS )
|
||||
{
|
||||
debug( "Could not query desktop video mode." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pInfo->ulBPP = sCurModeInfo.ulBpp;
|
||||
pInfo->ulHorizResolution = sCurModeInfo.ulHorizResolution;
|
||||
pInfo->ulVertResolution = sCurModeInfo.ulVertResolution;
|
||||
pInfo->ulScanLineSize = sCurModeInfo.ulScanLineSize;
|
||||
pInfo->fccColorEncoding = sCurModeInfo.fccColorEncoding;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PVODATA voOpen()
|
||||
{
|
||||
PVODATA pVOData;
|
||||
|
||||
if ( !_vmanInit() )
|
||||
return NULL;
|
||||
|
||||
pVOData = SDL_calloc( 1, sizeof(VODATA) );
|
||||
if ( pVOData == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pVOData;
|
||||
}
|
||||
|
||||
static VOID voClose(PVODATA pVOData)
|
||||
{
|
||||
if ( pVOData->pRectl != NULL )
|
||||
SDL_free( pVOData->pRectl );
|
||||
|
||||
if ( pVOData->pBltRect != NULL )
|
||||
SDL_free( pVOData->pBltRect );
|
||||
|
||||
voVideoBufFree( pVOData );
|
||||
}
|
||||
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible)
|
||||
{
|
||||
HPS hps;
|
||||
BOOL fSuccess = FALSE;
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
|
||||
if ( pVOData->hrgnVisible != NULLHANDLE )
|
||||
{
|
||||
GpiDestroyRegion( hps, pVOData->hrgnVisible );
|
||||
pVOData->hrgnVisible = NULLHANDLE;
|
||||
}
|
||||
|
||||
if ( fVisible )
|
||||
{
|
||||
// Query visible rectangles
|
||||
|
||||
pVOData->hrgnVisible = GpiCreateRegion( hps, 0, NULL );
|
||||
if ( pVOData->hrgnVisible == NULLHANDLE )
|
||||
{
|
||||
SDL_SetError( "GpiCreateRegion() failed" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( WinQueryVisibleRegion( hwnd, pVOData->hrgnVisible ) == RGN_ERROR )
|
||||
{
|
||||
GpiDestroyRegion( hps, pVOData->hrgnVisible );
|
||||
pVOData->hrgnVisible = NULLHANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( hrgnShape != NULLHANDLE )
|
||||
GpiCombineRegion( hps, pVOData->hrgnVisible, pVOData->hrgnVisible,
|
||||
hrgnShape, CRGN_AND );
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
WinQueryWindowRect( hwnd, &pVOData->rectlWin );
|
||||
WinMapWindowPoints( hwnd, HWND_DESKTOP, (PPOINTL)&pVOData->rectlWin, 2 );
|
||||
|
||||
if ( pSDLDisplayMode != NULL )
|
||||
{
|
||||
pVOData->ulScreenHeight = pSDLDisplayMode->h;
|
||||
pVOData->ulScreenBytesPerLine =
|
||||
((PMODEDATA)pSDLDisplayMode->driverdata)->ulScanLineBytes;
|
||||
}
|
||||
}
|
||||
|
||||
WinReleasePS( hps );
|
||||
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize)
|
||||
{
|
||||
ULONG ulRC;
|
||||
ULONG ulScanLineSize = ulWidth * (ulBPP >> 3);
|
||||
|
||||
// Destroy previous buffer.
|
||||
voVideoBufFree( pVOData );
|
||||
|
||||
if ( ( ulWidth == 0 ) || ( ulHeight == 0 ) || ( ulBPP == 0 ) )
|
||||
return NULL;
|
||||
|
||||
// Bytes per line.
|
||||
ulScanLineSize = ( ulScanLineSize + 3 ) & ~3; /* 4-byte aligning */
|
||||
*pulScanLineSize = ulScanLineSize;
|
||||
|
||||
ulRC = DosAllocMem( &pVOData->pBuffer,
|
||||
(ulHeight * ulScanLineSize) + sizeof(ULONG),
|
||||
PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosAllocMem(), rc = %u", ulRC );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pVOData->ulBPP = ulBPP;
|
||||
pVOData->ulScanLineSize = ulScanLineSize;
|
||||
pVOData->ulWidth = ulWidth;
|
||||
pVOData->ulHeight = ulHeight;
|
||||
|
||||
return pVOData->pBuffer;
|
||||
}
|
||||
|
||||
static VOID voVideoBufFree(PVODATA pVOData)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( pVOData->pBuffer == NULL )
|
||||
return;
|
||||
|
||||
ulRC = DosFreeMem( pVOData->pBuffer );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosFreeMem(), rc = %u", ulRC );
|
||||
else
|
||||
pVOData->pBuffer = NULL;
|
||||
}
|
||||
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects)
|
||||
{
|
||||
PRECTL prectlDst, prectlScan;
|
||||
HPS hps;
|
||||
HRGN hrgnUpdate;
|
||||
RGNRECT rgnCtl;
|
||||
SDL_Rect stSDLRectDef;
|
||||
BMAPINFO bmiSrc;
|
||||
BMAPINFO bmiDst;
|
||||
PPOINTL pptlSrcOrg;
|
||||
PBLTRECT pbrDst;
|
||||
HWREQIN sHWReqIn;
|
||||
BITBLTINFO sBitbltInfo = { 0 };
|
||||
ULONG ulIdx;
|
||||
// RECTL rectlScreenUpdate;
|
||||
|
||||
if ( pVOData->pBuffer == NULL )
|
||||
return FALSE;
|
||||
|
||||
if ( pVOData->hrgnVisible == NULLHANDLE )
|
||||
return TRUE;
|
||||
|
||||
bmiSrc.ulLength = sizeof(BMAPINFO);
|
||||
bmiSrc.ulType = BMAP_MEMORY;
|
||||
bmiSrc.ulWidth = pVOData->ulWidth;
|
||||
bmiSrc.ulHeight = pVOData->ulHeight;
|
||||
bmiSrc.ulBpp = pVOData->ulBPP;
|
||||
bmiSrc.ulBytesPerLine = pVOData->ulScanLineSize;
|
||||
bmiSrc.pBits = (PBYTE)pVOData->pBuffer;
|
||||
|
||||
bmiDst.ulLength = sizeof(BMAPINFO);
|
||||
bmiDst.ulType = BMAP_VRAM;
|
||||
bmiDst.pBits = (PBYTE)ulVRAMAddress;
|
||||
bmiDst.ulWidth = bmiSrc.ulWidth;
|
||||
bmiDst.ulHeight = bmiSrc.ulHeight;
|
||||
bmiDst.ulBpp = bmiSrc.ulBpp;
|
||||
bmiDst.ulBytesPerLine = pVOData->ulScreenBytesPerLine;
|
||||
|
||||
// List of update rectangles. This is the intersection of requested
|
||||
// rectangles and visible rectangles.
|
||||
|
||||
if ( cSDLRects == 0 )
|
||||
{
|
||||
// Full update requested.
|
||||
stSDLRectDef.x = 0;
|
||||
stSDLRectDef.y = 0;
|
||||
stSDLRectDef.w = bmiSrc.ulWidth;
|
||||
stSDLRectDef.h = bmiSrc.ulHeight;
|
||||
pSDLRects = &stSDLRectDef;
|
||||
cSDLRects = 1;
|
||||
}
|
||||
|
||||
// Make list of destionation rectangles (prectlDst) list from the source
|
||||
// list (prectl).
|
||||
prectlDst = _getRectlArray( pVOData, cSDLRects );
|
||||
if ( prectlDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
return FALSE;
|
||||
}
|
||||
prectlScan = prectlDst;
|
||||
for( ulIdx = 0; ulIdx < cSDLRects; ulIdx++, pSDLRects++, prectlScan++ )
|
||||
{
|
||||
prectlScan->xLeft = pSDLRects->x;
|
||||
prectlScan->yTop = pVOData->ulHeight - pSDLRects->y;
|
||||
prectlScan->xRight = prectlScan->xLeft + pSDLRects->w;
|
||||
prectlScan->yBottom = prectlScan->yTop - pSDLRects->h;
|
||||
}
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
if ( hps == NULLHANDLE )
|
||||
return FALSE;
|
||||
|
||||
// Make destination region to update.
|
||||
hrgnUpdate = GpiCreateRegion( hps, cSDLRects, prectlDst );
|
||||
// "AND" on visible and destination regions, result is region to update.
|
||||
GpiCombineRegion( hps, hrgnUpdate, hrgnUpdate, pVOData->hrgnVisible,
|
||||
CRGN_AND );
|
||||
|
||||
// Get rectangles of the region to update.
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = 0;
|
||||
rgnCtl.ulDirection = 1;
|
||||
rgnCtl.crcReturned = 0;
|
||||
GpiQueryRegionRects( hps, hrgnUpdate, NULL, &rgnCtl, NULL );
|
||||
if ( rgnCtl.crcReturned == 0 )
|
||||
{
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
return TRUE;
|
||||
}
|
||||
// We don't need prectlDst, use it again to store update regions.
|
||||
prectlDst = _getRectlArray( pVOData, rgnCtl.crcReturned );
|
||||
if ( prectlDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
return FALSE;
|
||||
}
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = rgnCtl.crcReturned;
|
||||
rgnCtl.ulDirection = 1;
|
||||
GpiQueryRegionRects( hps, hrgnUpdate, NULL, &rgnCtl, prectlDst );
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
cSDLRects = rgnCtl.crcReturned;
|
||||
// Now cRect/prectlDst is a list of regions in window (update && visible).
|
||||
|
||||
// Make lists for blitting from update regions.
|
||||
|
||||
pbrDst = _getBltRectArray( pVOData, cSDLRects );
|
||||
if ( pbrDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
prectlScan = prectlDst;
|
||||
pptlSrcOrg = (PPOINTL)prectlDst; // Yes, this memory block will be used again.
|
||||
for( ulIdx = 0; ulIdx < cSDLRects; ulIdx++, prectlScan++, pptlSrcOrg++ )
|
||||
{
|
||||
pbrDst[ulIdx].ulXOrg = pVOData->rectlWin.xLeft + prectlScan->xLeft;
|
||||
pbrDst[ulIdx].ulYOrg = pVOData->ulScreenHeight -
|
||||
( pVOData->rectlWin.yBottom + prectlScan->yTop );
|
||||
pbrDst[ulIdx].ulXExt = prectlScan->xRight - prectlScan->xLeft;
|
||||
pbrDst[ulIdx].ulYExt = prectlScan->yTop - prectlScan->yBottom;
|
||||
pptlSrcOrg->x = prectlScan->xLeft;
|
||||
pptlSrcOrg->y = bmiSrc.ulHeight - prectlScan->yTop;
|
||||
}
|
||||
pptlSrcOrg = (PPOINTL)prectlDst;
|
||||
|
||||
// Request HW
|
||||
sHWReqIn.ulLength = sizeof(HWREQIN);
|
||||
sHWReqIn.ulFlags = REQUEST_HW;
|
||||
sHWReqIn.cScrChangeRects = 1;
|
||||
sHWReqIn.arectlScreen = &pVOData->rectlWin;
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_REQUESTHW, &sHWReqIn, NULL ) != RC_SUCCESS )
|
||||
{
|
||||
debug( "pfnVMIEntry(,VMI_CMD_REQUESTHW,,) failed" );
|
||||
sHWReqIn.cScrChangeRects = 0; // for fail signal only.
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTL rclSrcBounds;
|
||||
|
||||
rclSrcBounds.xLeft = 0;
|
||||
rclSrcBounds.yBottom = 0;
|
||||
rclSrcBounds.xRight = bmiSrc.ulWidth;
|
||||
rclSrcBounds.yTop = bmiSrc.ulHeight;
|
||||
|
||||
sBitbltInfo.ulLength = sizeof(BITBLTINFO);
|
||||
sBitbltInfo.ulBltFlags = BF_DEFAULT_STATE | BF_ROP_INCL_SRC | BF_PAT_HOLLOW;
|
||||
sBitbltInfo.cBlits = cSDLRects;
|
||||
sBitbltInfo.ulROP = ROP_SRCCOPY;
|
||||
sBitbltInfo.pSrcBmapInfo = &bmiSrc;
|
||||
sBitbltInfo.pDstBmapInfo = &bmiDst;
|
||||
sBitbltInfo.prclSrcBounds = &rclSrcBounds;
|
||||
sBitbltInfo.prclDstBounds = &pVOData->rectlWin;
|
||||
sBitbltInfo.aptlSrcOrg = pptlSrcOrg;
|
||||
sBitbltInfo.abrDst = pbrDst;
|
||||
|
||||
// Screen update.
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_BITBLT, &sBitbltInfo, NULL ) != RC_SUCCESS )
|
||||
{
|
||||
debug( "pfnVMIEntry(,VMI_CMD_BITBLT,,) failed" );
|
||||
sHWReqIn.cScrChangeRects = 0; // for fail signal only.
|
||||
}
|
||||
|
||||
// Release HW.
|
||||
sHWReqIn.ulFlags = 0;
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_REQUESTHW, &sHWReqIn, NULL ) != RC_SUCCESS )
|
||||
debug( "pfnVMIEntry(,VMI_CMD_REQUESTHW,,) failed" );
|
||||
}
|
||||
|
||||
return sHWReqIn.cScrChangeRects != 0;
|
||||
}
|
Reference in New Issue
Block a user