I've been given a unfinished printer driver to try to fix, unfortunately I've
never worked on a driver, GDI, or windows before. In a call to DrvBitBlt, the
Dest surface is my device managed surface, the source surface contains the
correct image (in this case a piece of text from a pdf that is been sent as
an image because we don't have the correct font), and Rop4=0x8888. The code
for handling BitBlt currently doesn't support Rops that use the destination
so we punt back to GDI(EngBitBlt). the output from copybits is a black image.

If I replace the Rop value with 0xCCCC, and then call EngBitBlt, I get the
correct output. I was wondering: What exactly causes the problem.

Various things I have read on the net mention that you must use a Engine
Managed Surface when you call the Eng functions, is this true? Because if I
replace the Rop4 value I get the correct result.

My idea to fix it involves creating a engine managed surface alongside my
device surface in DrvEnableSurface, store it in my driver, and then use the
eng surface when I call EngBitBlt. the problem is that DrvCopyBits is then
never called,

The code for creating the surface is

HSURF PDevObj::doCreateSurface()
{
SIZEL SurfSize;
HSURF surf;
//HBITMAP bitmap;
FLONG hooks= HOOK_BITBLT |
HOOK_COPYBITS |
HOOK_FILLPATH |
HOOK_LINETO |
HOOK_STRETCHBLT |
HOOK_STRETCHBLTROP |
HOOK_STROKEANDFILLPATH |
HOOK_STROKEPATH |
HOOK_TEXTOUT;
GDI_MESSAGE("doCreateSurface\n");

SurfSize.cx = (LONG)ourGDIInfo.ulHorzRes;
SurfSize.cy = (LONG)ourGDIInfo.ulVertRes;

ourSurf = (HSURF)EngCreateDeviceSurface((DHSURF)ownerPDev, SurfSize,
BMF_24BPP);
//Create Engine Managed Surface for punting
engSurf = EngCreateBitmap(SurfSize, 3 * SurfSize.cy, BMF_24BPP,
BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
GDI_ASSERT((ourSurf != NULL));

if (ourSurf == NULL)
return NULL;

if (!EngAssociateSurface((HSURF)engSurf, (HDEV)engPDev, hooks))
{
surf = (HSURF)engSurf;
doDeleteSurface();
EngDeleteSurface(surf);

GDI_MESSAGE("doCreateSurface - EngAssociateSurface failed for Eng
Managed Surface\n");

return NULL;
}
/* HOOK_xxx values must match those in the DrvFuncTable */
if (!EngAssociateSurface(ourSurf, (HDEV)engPDev, hooks))
{
surf = ourSurf;
doDeleteSurface();
EngDeleteSurface(surf);

GDI_MESSAGE("doCreateSurface - EngAssociateSurface failed\n");

return NULL;
}

return ourSurf;
}

This is the version of DrvBitBlt I am using
BOOL
DrvBitBlt(
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
PRECTL prclDst,
PPOINTL pptlSrc,
PPOINTL pptlMask,
BRUSHOBJ *pbo,
PPOINTL pptlBrushOrg,
ROP4 Rop4
)
{
bool ret;
IPDevObj *pPDevObj = GDISurface_getPDevObj(psoDst);
SURFOBJ *pso;

if (psoDst->iType == STYPE_BITMAP)
return FALSE;

pPDevObj = GDISurface_getPDevObj(psoDst);

if (pPDevObj == NULL)
return FALSE;

GDI_MESSAGE_LOGGER(pPDevObj->getLogger(), "DrvBitBlt\n");

if (pPDevObj->bitBlt(psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc,
pptlMask, pbo, pptlBrushOrg, Rop4))
return TRUE;

/* Couldn't do it so punt */
pso = EngLockSurface((HSURF)pPDevObj->engSurf);
ret = EngBitBlt(pso, psoSrc, psoMask, pco, pxlo, prclDst, pptlSrc,
pptlMask, pbo, pptlBrushOrg, Rop4);
EngUnlockSurface(pso);
return ret;
}
I added the EngLockSurface and EngUnlockSurface lines, and modified the
EngBitBlt to use the locked surface instead of psoDst.
In this case pDevObj->bitBlt will return false.

Any help will be appreciated (if in Sydney, Australia I will buy you a beer).
If I have posted this in the wrong place, could you tell me where I should
have posted?

Re: problem punting in GDI by Tim

Tim
Tue Apr 01 00:09:37 CDT 2008

hwilcox <hwilcox@discussions.microsoft.com> wrote:
>
>I've been given a unfinished printer driver to try to fix, unfortunately I've
>never worked on a driver, GDI, or windows before. In a call to DrvBitBlt, the
>Dest surface is my device managed surface, the source surface contains the
>correct image (in this case a piece of text from a pdf that is been sent as
>an image because we don't have the correct font), and Rop4=0x8888. The code
>for handling BitBlt currently doesn't support Rops that use the destination
>so we punt back to GDI(EngBitBlt). the output from copybits is a black image.

Didn't your DrvCopyBits get called twice? Once to read the current
surface, one to put the drawn bits back? ROP=88 is DSa, which means
destination = destination AND source. If you deliver zero bits when GDI
reads the old destination, then of course the result is always going to be
zero.

Aren't you keeping your own copy of the final surface to send to your
printer? What format is that surface?

>If I replace the Rop value with 0xCCCC, and then call EngBitBlt, I get the
>correct output. I was wondering: What exactly causes the problem.

My guess is that you aren't delivering the real surface bits when GDI asks
for them. I suppose you could call EngBitBlt with 0xCC and then AND the
bits into your surface.

>My idea to fix it involves creating a engine managed surface alongside my
>device surface in DrvEnableSurface, store it in my driver, and then use the
>eng surface when I call EngBitBlt. the problem is that DrvCopyBits is then
>never called,

Of course, because EngBitBlt can put the correct bits into the destination
surface without your help.
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.