📄 ddi_if.cpp
字号:
// Drawing functions
BOOL APIENTRY DrvFillPath(
SURFOBJ *pso,
PATHOBJ *ppo,
CLIPOBJ *pco,
BRUSHOBJ *pbo,
POINTL *pptlBrushOrg,
MIX mix,
FLONG flOptions) // Simply winding mode - we ignore for now.
{
#ifdef DEBUG
if( (GPE_ZONE_POLY) && !(GPE_ZONE_BLT_HI) )
{
ulong oldSettings = dpCurSettings.ulZoneMask;
dpCurSettings.ulZoneMask |= 0x0034; // enter, exit & blt hi and lo
BOOL v = DrvFillPath(pso,ppo,pco,pbo,pptlBrushOrg,mix,flOptions);
dpCurSettings.ulZoneMask = oldSettings;
return v;
}
#endif
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Entering DrvFillPath\r\n")));
BOOL bFailed=false;
EdgeList edgeList( ppo->cCurves );
int bMore;
int moreClipLists;
PATHDATA pd;
ULONG cptfx;
SCODE sc1=0;
SCODE sc2;
RECTL *prclCurr;
GPEBltParms parms;
int i;
// FIX xFirst, yFirst, xLast, yLast;
POINTFIX firstPoint, lastPoint;
// Set up Blt parameters for GPEPolygon::Fill to use
TmpGPESurf pDst(pso);
GPE *pGPE = SurfobjToGPE(pso);
parms.pDst = pDst;
parms.pSrc = (GPESurf *)NULL;
parms.pMask = (GPESurf *)NULL;
parms.prclDst = (RECTL *)NULL;
parms.prclMask = (RECTL *)NULL;
parms.prclClip = (RECTL *)NULL; // while we prepare blt function
parms.xPositive = parms.yPositive = 1; // we don't support overlapped brush & dst
parms.pptlBrush = pptlBrushOrg;
parms.bltFlags = 0;
parms.rop4 = (((ROP4)gaMix[(mix>>8)&0x0f])<<8) | gaMix[mix&0x0f]; // mix -> rop4
// parms.rop4 = 0; // TEMPORARY BLACKNESS
parms.pBrush = (GPESurf *)NULL;
parms.pLookup = (unsigned long *)NULL;
parms.pConvert = NULL;
parms.solidColor = pbo->iSolidColor;
if( pbo )
{
if( pbo->iSolidColor == 0xffffffff )
{
if( pbo->pvRbrush == NULL )
parms.pBrush = (GPESurf *)( BRUSHOBJ_pvGetRbrush( pbo ) );
else
parms.pBrush = (GPESurf *)( pbo->pvRbrush );
}
}
if( FAILED( pGPE->BltPrepare( &parms ) ) )
{
DEBUGMSG(GPE_ZONE_ERROR,(TEXT("Failed to prepare blt for fillpoly operations\r\n")));
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvFillPath\r\n")));
return FALSE;
}
// Create GPEPolygon(s) for the path
PATHOBJ_vEnumStart(ppo);
do
{
bMore = PATHOBJ_bEnum( ppo, &pd );
cptfx = pd.count;
if( !cptfx ){
break;
}
if( pd.flags & PD_BEGINSUBPATH ){
// Start a new subpath - just remember the first point
firstPoint = pd.pptfx[0];
} else {
// Continue old subpath
if FAILED(edgeList.AddEdge( lastPoint.x, lastPoint.y, pd.pptfx[0].x, pd.pptfx[0].y )){
bMore=false;
bFailed=true;
}
}
for( i=0; i<((int)cptfx)-1; i++ ){
if FAILED(edgeList.AddEdge( pd.pptfx[i].x, pd.pptfx[i].y, pd.pptfx[i+1].x, pd.pptfx[i+1].y )){
bMore=false; //The reason we don't return an error immediately is that
bFailed=true; //we used to draw a partial path. For BC we will continue to.
}
}
if( pd.flags & PD_ENDSUBPATH ){
// close the subpath
if FAILED(edgeList.AddEdge( pd.pptfx[i].x, pd.pptfx[i].y, firstPoint.x, firstPoint.y )){
bMore=false;
bFailed=true;
}
}else{
// continue this subpath with next enumeration
lastPoint = pd.pptfx[i];
}
} while(bMore);
// Now, loop through the cliprect(s), calling GPEPolygon::Fill (via GPEPolygonList)
if( ( pco == NULL ) || ( pco->iDComplexity == DC_TRIVIAL ) )
{
DEBUGMSG(GPE_ZONE_POLY,(TEXT("Calling PolygonList::Fill() with no clipping\r\n")));
sc1 = edgeList.Fill( &parms, (RECTL *)NULL, pGPE);
}
else if( pco->iDComplexity == DC_RECT )
{
DEBUGMSG(GPE_ZONE_POLY,(TEXT("Calling PolygonList::Fill() with single cliprect\r\n")));
sc1 = edgeList.Fill( &parms, &pco->rclBounds, pGPE );
}
else
{
DEBUGMSG(GPE_ZONE_POLY,(TEXT("Iterating through complex clipping for fillpoly\r\n")));
CLIPENUM ce;
for( ce.c = 0, moreClipLists=1; ce.c || moreClipLists; ) // <- Note , & ;
{
if( ce.c == 0 )
{
// Get next list of cliprects from clipobj
DEBUGMSG(GPE_ZONE_POLY,(TEXT("Calling CLIPOBJ_bEnum\r\n")));
moreClipLists = CLIPOBJ_bEnum( pco, sizeof(ce), (ULONG *)&ce );
prclCurr = ce.arcl;
if( !ce.c ) // empty list !?
continue;
}
ce.c--;
DEBUGMSG(GPE_ZONE_POLY,(TEXT("Calling PolygonList::Fill() with complex cliprect\r\n")));
if( FAILED(sc1 = edgeList.Fill( &parms, prclCurr++, pGPE ) ) )
break;
}
}
sc2 = pGPE->BltComplete( &parms );
return ((!FAILED(sc1)) && (!FAILED(sc2)) && (!bFailed));
}
BOOL APIENTRY DrvRealizeBrush(
BRUSHOBJ *pbo,
SURFOBJ *psoTarget,
SURFOBJ *psoPattern,
SURFOBJ *psoMask,
XLATEOBJ *pxlo,
ULONG iHatch)
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Entering DrvRealizeBrush\r\n")));
TmpGPESurf tpSrc(psoPattern);
TmpGPESurf tpTrg(psoTarget,psoPattern,&tpSrc);
GPESurf *pSrc = tpSrc;
GPESurf *pTrg = tpTrg;
GPESurf *pDst;
void *pBits;
unsigned long stride;
EGPEFormat patFormat = (pTrg->Format() == gpe24Bpp) ? gpe32Bpp : pTrg->Format();
int temporaryPattern = (( pSrc->Format() != patFormat ) || (pxlo->flXlate != XO_TRIVIAL ) );
// If the Target is 24Bpp, we convert the brush to 32Bpp because the EmulatedBlt routine
// doesn't handle 24Bpp patterns (they cross 32-bit boundaries and this requires
// extra code)
// If the pattern and target have different formats, we need to create a GPESurf to
// contain the pattern but since GDI destroys the brush without notifying the driver,
// the bits associated with the pattern surface must be in the same memory allocation
// to avoid memory leaks.
int memoryRequired = sizeof(GPESurf);
if( temporaryPattern )
{
stride = ((( pSrc->Width() * EGPEFormatToBpp[patFormat] + 7 ) / 8 + 3 )
& 0xfffffffc );
memoryRequired += stride * pSrc->Height();
}
else
stride = pSrc->Stride();
pDst = (GPESurf *)BRUSHOBJ_pvAllocRbrush( pbo, memoryRequired );
if( !pDst )
return FALSE; // memory allocation failed
if( temporaryPattern )
pBits = (void *)((unsigned long)(((unsigned char *)pDst)+sizeof(GPESurf)+3)&0xfffffffc);
else
pBits = pSrc->Buffer();
pDst->Init( pSrc->Width(), pSrc->Height(), pBits, stride, patFormat );
if( temporaryPattern )
{
GPEBltParms parms;
// Create a color converter to handle depth changes
ColorConverter::InitConverter(
pxlo,
&parms.pColorConverter,
&parms.pConvert,
&parms.pLookup );
// Blt the bits to the temporary pattern buffer
RECTL rcl;
rcl.top = 0;
rcl.bottom = pSrc->Height();
rcl.left = 0;
rcl.right = pSrc->Width();
parms.pDst = pDst;
parms.pSrc = pSrc;
parms.pMask = (GPESurf *)NULL;
parms.pBrush = (GPESurf *)NULL;
parms.prclDst = &rcl;
parms.prclSrc = &rcl;
parms.prclClip = (RECTL *)NULL;
parms.solidColor = 0xffffffff;
parms.bltFlags = 0;
parms.rop4 = 0xCCCC; // SRCCOPY
parms.prclMask = (RECTL *)NULL;
parms.pptlBrush = (POINTL *)NULL;
parms.xPositive = parms.yPositive = 1;
SurfobjToGPE(psoTarget)->EmulatedBlt( &parms );
}
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvRealizeBrush\r\n")));
return TRUE;
}
typedef struct _DRVDEVMODEW
{
DEVMODEW devmodew; // DDI definition of mode
GPEMode gpeMode; // GPE definition of mode
} DRVDEVMODEW;
ULONG APIENTRY DrvGetModes(
HANDLE hDriver,
ULONG cjSize,
DEVMODEW *pdm)
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Entering DrvGetModes\r\n")));
GPE *pGPE = GetGPE();
int numModes = pGPE->NumModes();
ULONG bytesReqd = numModes * sizeof(DRVDEVMODEW);
DRVDEVMODEW *pMode = (DRVDEVMODEW *)pdm;
GPEMode *pGPEMode;
int modeNo;
if( !pdm )
{
// GDI is asking how much memory is required for the entire mode list
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvGetModes\r\n")));
return bytesReqd;
}
if( cjSize != bytesReqd )
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvGetModes\r\n")));
return 0; // In this DDI, we insist that GDI gives 0 or sizeof(modelist)
}
memset( pMode, 0, cjSize );
for( modeNo = 0; modeNo < numModes; modeNo++, pMode++ )
{
pGPEMode = &(pMode->gpeMode);
pGPE->GetModeInfo( pGPEMode, modeNo );
memcpy( &(pMode->devmodew.dmDeviceName), TEXT("GPE"), 8 );
pMode->devmodew.dmSize = sizeof(DEVMODEW);
pMode->devmodew.dmDriverExtra = sizeof(GPEMode);
pMode->devmodew.dmFields = ( DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
DM_DISPLAYFREQUENCY | DM_DISPLAYFLAGS );
pMode->devmodew.dmBitsPerPel = pGPEMode->Bpp;
pMode->devmodew.dmPelsWidth = pGPEMode->width;
pMode->devmodew.dmPelsHeight = pGPEMode->height;
pMode->devmodew.dmDisplayFrequency = pGPEMode->frequency;
}
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvGetModes\r\n")));
return cjSize;
}
DHPDEV APIENTRY DrvEnablePDEV(
DEVMODEW *pdm,
LPWSTR pwszLogAddress,
ULONG cPat,
HSURF *phsurfPatterns,
ULONG cjCaps,
ULONG *pdevcaps,
ULONG cjDevInfo,
DEVINFO *pdi,
HDEV hdev,
LPWSTR pwszDeviceName,
HANDLE hDriver)
{
// Make pGPE static to allow this func to be called more than once
static GPE *pGPE;
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Entering DrvEnablePDEV\r\n")));
// Only initialize display driver once. This may be called again by
// printer drivers that leave most of the rendering to GPE.
if( pGPE == NULL )
{
if( ( pGPE = GetGPE() ) == NULL )
{
DEBUGMSG(GPE_ZONE_ERROR,(TEXT("ERROR: Failed to instantiate GPE object\r\n")));
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvEnablePDEV\r\n")));
return (DHPDEV)NULL;
}
if( !AllocConverters() )
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Failed Allocate color converters! Leaving DrvEnablePDEV\r\n")));
return (DHPDEV)NULL;
}
if( FAILED( pGPE->SetMode( ((DRVDEVMODEW *)pdm)->gpeMode.modeId,
&(pdi->hpalDefault) ) ) )
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Failed to set mode! Leaving DrvEnablePDEV\r\n")));
return (DHPDEV)NULL;
}
}
GDIINFO *pgdiinfo = (GDIINFO *)pdevcaps;
pgdiinfo->ulVersion = DDI_DRIVER_VERSION;
pgdiinfo->ulTechnology = DT_RASDISPLAY;
pgdiinfo->ulHorzSize = 64;
pgdiinfo->ulVertSize = 60;
pgdiinfo->ulHorzRes = pdm->dmPelsWidth;
pgdiinfo->ulVertRes = pdm->dmPelsHeight;
pgdiinfo->ulLogPixelsX = 96;
pgdiinfo->ulLogPixelsY = 96;
pgdiinfo->cBitsPixel = pdm->dmBitsPerPel;
pgdiinfo->cPlanes = 1;
pgdiinfo->ulNumColors = 1 << pdm->dmBitsPerPel;
pgdiinfo->ulAspectX = 1;
pgdiinfo->ulAspectY = 1;
pgdiinfo->ulAspectXY = 1;
pgdiinfo->flRaster = RC_BITBLT
| RC_STRETCHBLT
| ((pGPE->IsPaletteSettable())?RC_PALETTE:0);
// DEVINFO Graphics capabilities beyond normal uDDI caps; eg, grayscale text output
pdi->flGraphicsCaps = pGPE->GetGraphicsCaps();
DEBUGMSG(1,(TEXT("Bits-per-pixel: %d\r\n"), pgdiinfo->cBitsPixel ));
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvEnablePDEV\r\n")));
return (DHPDEV)pGPE;
}
// BLT Functions
// All exposed Drv Blt functions are translated into a call to
// AnyBlt directly or indirectly:
BOOL APIENTRY AnyBlt(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclTrg,
RECTL *prclSrc,
POINTL *pptlMask,
BRUSHOBJ *pbo,
POINTL *pptlBrush,
ROP4 rop4,
unsigned long bltFlags);
BOOL APIENTRY DrvPaint(
SURFOBJ* pso,
CLIPOBJ* pco,
BRUSHOBJ* pbo,
POINTL* pptlBrush,
MIX mix)
{
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Entering DrvPaint\r\n")));
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("DrvPaint (mix=0x%04x)\r\n"), mix));
BOOL rc;
ROP4 rop4;
rop4 = (((ROP4)gaMix[(mix >> 8)&0xf]) << 8) | gaMix[mix & 0xf];
// Since our DrvFillPath routine handles almost all fills, DrvPaint
// won't get called all that much (mainly via PaintRgn, FillRgn, or
// complex clipped polygons). As such, we save some code and simply
// allow DrvBitBlt to handle it:
rc = DrvBitBlt(pso, NULL, NULL, pco, NULL, &pco->rclBounds, NULL,
NULL, pbo, pptlBrush, rop4 );
DEBUGMSG(GPE_ZONE_ENTER,(TEXT("Leaving DrvPaint\r\n")));
return rc;
}
BOOL APIENTRY DrvCopyBits(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -