📄 bltfuncs.cpp
字号:
/***************************************************************************
* Name : bltfuncs.cpp
* Title : MBX WinCE driver GPE class
* Author(s) : Imagination Technologies
* Created : 29th January 2003
*
* Copyright : 2003 by Imagination Technologies. All rights reserved.
* : No part of this software, either material or conceptual
* : may be copied or distributed, transmitted, transcribed,
* : stored in a retrieval system or translated into any
* : human or computer language in any form by any means,
* : electronic, mechanical, manual or other-wise, or
* : disclosed to third parties without the express written
* : permission of Imagination Technologies Limited, Unit 8,
* : HomePark Industrial Estate, King's Langley, Hertfordshire,
* : WD4 8LZ, U.K.
*
* Description : MBX WinCE driver mode related components of GPE class.
*
* Platform : WinCE
*
* Modifications:-
* $Log: bltfuncs.cpp $
*
****************************************************************************/
#include "precomp.h"
#ifdef SUPPORT_CLEARTYPE
#include <ctblt.h>
#endif /* SUPPORT_CLEARTYPE */
#include <aablt.h>
extern "C"
{
#include "bltfuncs.h"
#include "hwfix.h"
#define DISPPERF_DECLARE
#include "dispperf.h"
}
// Gradfill iDComplexity fix
BOOL (*pfnMSDrvGradientFill)(SURFOBJ *, CLIPOBJ *, XLATEOBJ *, TRIVERTEX *, ULONG, PVOID, ULONG, RECTL *, POINTL *, ULONG)=0;
#ifdef ENABLE_2D_PROFILE
PROFILE_NODE gProfile[NODE_MAX];
LONGLONG g_i64EntryTime = 0;
BOOL g_bTimingOfBltActive = FALSE;
#endif
#define CAPTURE_SYSMEM_BLT 0
#define ENABLE_TRACE 0
#if CAPTURE_SYSMEM_BLT
static BOOL CreateBmp(LPCTSTR pwszFileName,
PVOID pvData,
ULONG ulX,
ULONG ulY,
ULONG ulStride,
ULONG ulBPP,
EGPEFormat eDstFmt,
PULONG pulPalette,
ULONG ulRotationDegrees);
DWORD gdwCaptureSysmemBlt=0;
#endif
#if ENABLE_TRACE
DWORD gdwTrace=0;
DWORD gdwTraceCounter=0;
static int SurfRotate(GPESurfRotate *pSurf)
{
switch (pSurf->Rotate())
{
case DMDO_90:
return 90;
case DMDO_180:
return 180;
case DMDO_270:
return 270;
}
return 0;
}
static LPWSTR FormatStr(EGPEFormat format)
{
switch(format)
{
case gpe1Bpp: return (L"gpe1Bpp");
case gpe2Bpp: return (L"gpe2Bpp");
case gpe4Bpp: return (L"gpe4Bpp");
case gpe8Bpp: return (L"gpe8Bpp");
case gpe16Bpp: return (L"gpe16Bpp");
case gpe24Bpp: return (L"gpe24Bpp");
case gpe32Bpp: return (L"gpe32Bpp");
default: return (L"?format?");
}
}
static LPWSTR GetBltInfo(GPEBltParms *psBlitParameters)
{
static WORD temp[255];
LPWSTR lpWstr = (LPWSTR) &temp[0];
temp[0] = 0;
if (psBlitParameters->bltFlags & BLT_TRANSPARENT)
{
wcscat(lpWstr, L"BLT_TRANSPARENT ");
}
if (psBlitParameters->bltFlags & BLT_STRETCH)
{
wcscat(lpWstr, L"BLT_STRETCH");
}
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
if (psBlitParameters->bltFlags & BLT_ALPHABLEND)
{
wcscat(lpWstr, L"BLT_ALPHABLEND");
}
#endif
if ((psBlitParameters->rop4 & 0xffff) == 0xaaf0)
{
switch (psBlitParameters->pMask->Format())
{
case gpe4Bpp:
{
wcscat(lpWstr, L"AAtext");
break;
}
case gpe8Bpp:
{
wcscat(lpWstr, L"ClearType");
break;
}
case gpe1Bpp:
{
wcscat(lpWstr, L"Text");
break;
}
default:
{
wcscat(lpWstr, L"Unknown text format");
break;
}
}
}
return lpWstr;
}
#endif//#if ENABLE_TRACE
/***********************************************************************************
Function Name : BltPrepare
Inputs : psBlitParameters
Outputs : psBlitParameters
Returns : Error code
Globals Used : None
Description : Driver entry point. (see WinCE documentation)
************************************************************************************/
SCODE MBX::BltPrepare(GPEBltParms *psBlitParameters)
{
#ifdef USE_SW_CURSOR
RECTL sRectl;
#endif
DPFX(PVR_ZONE_BLT, (L"MBX::BltPrepare"));
RECTL *prclDst = psBlitParameters->prclDst;
PVRSRV_SYNC_INFO *psPrimarySyncInfo = ((MBXSurf*)m_pPrimarySurface)->GetMemInfo()->psSyncInfo;
#ifdef LOCAL_MEMORY_SELF_REFRESH
SysLocalMemoryEnable(m_sDevData.psDevInfoKM);
#endif // LOCAL_MEMORY_SELF_REFRESH
/* Perform coarse grain synchronisation if any external activity is touching the primary */
if(psBlitParameters->pDst == m_pPrimarySurface &&
psPrimarySyncInfo->ui32LastWriteOpVal != psPrimarySyncInfo->ui32NextWriteOp - 1)
{
PVRSRV_DEV_INFO *psDevInfo = m_sDevData.psDevInfoKM;
IMG_BOOL bTimeout = IMG_TRUE;
IMG_BOOL bStart = IMG_FALSE;
IMG_UINT32 uiStart = 0;
/* Lock the surface */
psPrimarySyncInfo->ui32NextWriteOp++;
do
{
if (psPrimarySyncInfo->ui32ReadOpsComplete ==
psPrimarySyncInfo->ui32ReadOpsPending &&
psPrimarySyncInfo->ui32LastWriteOpVal ==
psPrimarySyncInfo->ui32NextWriteOp - 2)
{
bTimeout = IMG_FALSE;
break;
}
if(bStart == IMG_FALSE)
{
bStart = IMG_TRUE;
uiStart = HostClockus();
}
HostWaitus(MAX_HW_TIME_US/(WAIT_TRY_COUNT));
SysKickCmdProc(psDevInfo->pui32KickerAddrKM);
} while ((HostClockus() - uiStart) < MAX_HW_TIME_US);
if(bTimeout == IMG_TRUE)
{
/*
manually update write ops - It will look wrong but we can't wait here for ever
*/
psPrimarySyncInfo->ui32LastWriteOpVal++;
m_bPrimaryLocked = FALSE;
}
else
{
/* Flag that we've locked the primary */
m_bPrimaryLocked = TRUE;
m_bHardwareUsed = TRUE;
}
}
DispPerfStart (psBlitParameters->rop4);
#ifdef ENABLE_2D_PROFILE
profile_start(m_sActiveNode, NODE_DEFAULT);
#endif
#if defined ROTATE_ENABLE && (_WINCEOSVER < 500)
/* Detect and fix GPE bug :
The test kit generates out-of-order rectangles, and this causes the Microsoft GPE code to set the BLT_STRETCH
flag even though the source and destination rectangles are exactly the same size. This is because microsoft test
the width before unscambling the coordinates, and the width goes negative.
It then runs through the GPE stretch blt code, and because the source and destination are both on the same surface
(the primary) it allocates some extra video memory and copies the source bitmap into it so it can seperate the
source and destination before the stretch blt. The GPE code calls our AllocSurface and we give it a correctly
allocated MBXSurf which is rotated by the same amount as the primary.
The problem is that after the AllocSurface, GPE contructs it's own internal dummy GPESurf structure instead of using
the one that AllocSurface gives it (this is not allowed but they do it anyway). There are then two surfaces with the
same bitmap address, the dummy and the real one. The dummy surface is not constructed correctly, for example the
flags indicate that it is in system memory but it is really in video memory, also the rotation is changed to 0 but
the surface has not been properly unrotated and so the stride is wrong. GPE uses the dummy surface as the source,
and so it fails.
To fix this, the driver now remembers the address of the last allocated surface, and it then detects the dummy
surface and switches back to the real one. We have to assume that the linear address of the first pixel of a bitmap
can be used to identify the surface. This fixes the 219 failure caused by the dummy surface.
*/
if ( (!psBlitParameters->pDst->InVideoMemory()) && (psBlitParameters->pDst->Buffer() == m_pvMostRecentAllocSurfaceAddr) )
{
psBlitParameters->pDst = m_psMostRecentMBXSurf;
}
#endif /* ROTATE_ENABLE && _WINCEOSVER < 500 */
/*
* Don't unscramble the dest rect if BLT_STRETCH is set because it might be a mirrored blt.
*
* The WinCE testkit test 212 generates rectangles with randon co-ordinates thus producing
* badly ordered dst rectangles
*/
if (prclDst && !(psBlitParameters->bltFlags & BLT_STRETCH) )
{
/* rclDst is not necessarily well ordered for us!! */
if (prclDst->left > prclDst->right)
{
LONG tmp = prclDst->left;
prclDst->left = prclDst->right;
prclDst->right = tmp;
}
if (prclDst->top > prclDst->bottom)
{
LONG tmp = prclDst->top;
prclDst->top = prclDst->bottom;
prclDst->bottom = tmp;
}
}
#if ENABLE_TRACE
if (gdwTrace)
{
gdwTraceCounter++;
DPFINFO ((L"Rop4=%04X %s #%d", psBlitParameters->rop4, GetBltInfo(psBlitParameters), gdwTraceCounter ));
DPFINFO ((L"Dst surf %dx%d %d @%.8lx rect %d,%d to %d,%d %s %s",
psBlitParameters->pDst->Width(),
psBlitParameters->pDst->Height(),
SurfRotate((GPESurfRotate *)psBlitParameters->pDst),
psBlitParameters->pDst->Buffer(),
(psBlitParameters->prclDst) ? psBlitParameters->prclDst->left : 0,
(psBlitParameters->prclDst) ? psBlitParameters->prclDst->top : 0,
(psBlitParameters->prclDst) ? psBlitParameters->prclDst->right : 0,
(psBlitParameters->prclDst) ? psBlitParameters->prclDst->bottom : 0,
FormatStr(psBlitParameters->pDst->Format()),
(psBlitParameters->pDst->InVideoMemory()) ? "Y" : "N"
));
if (psBlitParameters->pSrc)
{
DPFINFO ((L"Src surf %dx%d %d @%.8lx rect %d,%d to %d,%d %s %s",
psBlitParameters->pSrc->Width(),
psBlitParameters->pSrc->Height(),
SurfRotate((GPESurfRotate *)psBlitParameters->pSrc),
psBlitParameters->pSrc->Buffer(),
(psBlitParameters->prclSrc) ? psBlitParameters->prclSrc->left : 0,
(psBlitParameters->prclSrc) ? psBlitParameters->prclSrc->top : 0,
(psBlitParameters->prclSrc) ? psBlitParameters->prclSrc->right : 0,
(psBlitParameters->prclSrc) ? psBlitParameters->prclSrc->bottom : 0,
FormatStr(psBlitParameters->pSrc->Format()),
(psBlitParameters->pSrc->InVideoMemory()) ? "Y" : "N"
));
}
if (psBlitParameters->pMask)
{
DPFINFO ((L"Mask surf %dx%d %d @%.8lx rect %d,%d to %d,%d %s %s",
psBlitParameters->pMask->Width(),
psBlitParameters->pMask->Height(),
SurfRotate((GPESurfRotate *)psBlitParameters->pMask),
psBlitParameters->pMask->Buffer(),
(psBlitParameters->prclMask) ? psBlitParameters->prclMask->left : 0,
(psBlitParameters->prclMask) ? psBlitParameters->prclMask->top : 0,
(psBlitParameters->prclMask) ? psBlitParameters->prclMask->right : 0,
(psBlitParameters->prclMask) ? psBlitParameters->prclMask->bottom : 0,
FormatStr(psBlitParameters->pMask->Format()),
(psBlitParameters->pMask->InVideoMemory()) ? "Y" : "N"
));
}
if (psBlitParameters->pBrush)
{
DPFINFO ((L"Brush surf %dx%d %d @%.8lx size %d,%d %s %s",
psBlitParameters->pBrush->Width(),
psBlitParameters->pBrush->Height(),
SurfRotate((GPESurfRotate *)psBlitParameters->pBrush),
psBlitParameters->pBrush->Buffer(),
(psBlitParameters->pptlBrush) ? psBlitParameters->pptlBrush->x : 0,
(psBlitParameters->pptlBrush) ? psBlitParameters->pptlBrush->y : 0,
FormatStr(psBlitParameters->pBrush->Format()),
(psBlitParameters->pBrush->InVideoMemory()) ? "Y" : "N"
));
}
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
if ( psBlitParameters->bltFlags & BLT_ALPHABLEND)
{
DPFINFO ((L"Blend Info Op:0x%.2X Flags:0x%.2X SrcAlpha:0x%.2X Format:0x%.2X",
psBlitParameters->blendFunction.BlendOp,
psBlitParameters->blendFunction.BlendFlags,
psBlitParameters->blendFunction.SourceConstantAlpha,
psBlitParameters->blendFunction.AlphaFormat
));
}
#endif
}
#endif//#if ENABLE_TRACE
#ifdef DEBUG
#ifdef LOCAL_MEMORY_SELF_REFRESH
// default to base EmulatedBlt routine
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))WrappedEmulatedBlt;
#else
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))EmulatedBlt;
#endif
#else
// for release builds go via exception handled stub
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))TryEmulatedBlt;
#endif
/* init state to idle */
m_eHWBltState = BLT_Idle;
#ifdef USE_SW_CURSOR
if (m_bCursorVisible && !m_bCursorDisabled)
{
// check for destination overlap with cursor and turn off cursor if overlaps
if (psBlitParameters->pDst == m_pPrimarySurface) // only care if dest is main display surface
{
{
if (psBlitParameters->prclDst != NULL) // make sure there is a valid prclDst
{
sRectl = *psBlitParameters->prclDst; // if so, use it
}
else
{
sRectl = m_sCursorRect; // if not, use the Cursor rect - this forces the cursor to be turned off in this case
}
if (m_sCursorRect.top < sRectl.bottom && m_sCursorRect.bottom > sRectl.top &&
m_sCursorRect.left < sRectl.right && m_sCursorRect.right > sRectl.left)
{
CursorOff();
m_bCursorForcedOff = TRUE;
}
}
// check for source overlap with cursor and turn off cursor if overlaps
if (psBlitParameters->pSrc == m_pPrimarySurface) // only care if source is main display surface
{
if (psBlitParameters->prclSrc != NULL) // make sure there is a valid prclSrc
{
sRectl = *psBlitParameters->prclSrc; // if so, use it
}
else
{
sRectl = m_sCursorRect; // if not, use the CUrsor rect - this forces the cursor to be turned off in this case
}
if (m_sCursorRect.top < sRectl.bottom && m_sCursorRect.bottom > sRectl.top &&
m_sCursorRect.left < sRectl.right && m_sCursorRect.right > sRectl.left)
{
CursorOff();
m_bCursorForcedOff = TRUE;
}
}
}
#endif /* USE_SW_CURSOR */
#ifdef ROTATE_ENABLE
/*
* only the primary surface is rotated, all offscreen bitmaps are unrotated
*/
if (m_iRotate && (psBlitParameters->pSrc == m_pPrimarySurface) || (psBlitParameters->pDst == m_pPrimarySurface))
{
#ifdef DEBUG
#ifdef LOCAL_MEMORY_SELF_REFRESH
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))WrappedEmulatedBltRotate;
#else
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))EmulatedBlt;
#endif
#else
// for release builds go via exception handled stub
psBlitParameters->pBlt = (SCODE (GPE::*)(GPEBltParms *))TryEmulatedBltRotate;
#endif
}
#endif /* ROTATE_ENABLE */
#if defined (_WINCEOSVER) && (_WINCEOSVER >= 500)
/* AlphaBlend test */
if ( psBlitParameters->bltFlags & BLT_ALPHABLEND)
{
/*
* Punt all as MBX acceleration does not support this type of blending.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -