DrvCopyBits() & DrvBitBlt()

Hi, everyone

In the display driver, what’s the difference between the DrvCopyBits()
and DrvBitBlt()? Looks like they have the similar functionality.

I am writing a mirror driver and want to make all the surfaces as
engine-managed surfaces. Do I need to provide both of these two
routines? Could anyone tell me that in what cases they will be
invoked?

Thank you.

Lei

Lei Zhang wrote:

Hi, everyone

In the display driver, what’s the difference between the DrvCopyBits()
and DrvBitBlt()? Looks like they have the similar functionality.

DrvCopyBits is a subset of DrvBitBlt, used when there is no mask surface
and no ROP. I am not sure what the motivation was for including
DrvCopyBits; perhaps it was intended as a low-overhead method of
handling the simple calls.

Assuming you have implemented DrvBitBlt, you can implement DrvCopyBits
like this:

BOOL
DrvCopyBits(SURFOBJ* psoDst, SURFOBJ* psoSrc,
CLIPOBJ* pco, XLATEOBJ* pxlo,
RECTL* prclDst, POINTL* pptlSrc)
{
return DrvBitBlt(psoDst, psoSrc, NULL, pco, pxlo, prclDst, pptlSrc,
NULL, NULL, NULL, ROP4_SRCCOPY);
}

I am writing a mirror driver and want to make all the surfaces as
engine-managed surfaces. Do I need to provide both of these two
routines? Could anyone tell me that in what cases they will be
invoked?

For a completely engine-managed surface, you don’t need either of these
functions. The framebuf sample in the DDK is an example of a nearly
minimal display driver.

> DrvCopyBits is a subset of DrvBitBlt, used when there is no mask surface

and no ROP. I am not sure what the motivation was for including
DrvCopyBits; perhaps it was intended as a low-overhead method of
handling the simple calls.

From what I know, DrvCopyBits is intended for devices with non-standard surface
formats unaccessible for GRE (like VGA16). With such a device, DrvBitBlt only
copies from device format to device format, and DrvCopyBits converts between
the device format and the GRE standard formats.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim S. Shatskih wrote:

>DrvCopyBits is a subset of DrvBitBlt, used when there is no mask surface
>and no ROP. I am not sure what the motivation was for including
>DrvCopyBits; perhaps it was intended as a low-overhead method of
>handling the simple calls.
>
>

>From what I know, DrvCopyBits is intended for devices with non-standard surface
formats unaccessible for GRE (like VGA16). With such a device, DrvBitBlt only
copies from device format to device format, and DrvCopyBits converts between
the device format and the GRE standard formats.

That would be a nice explanation, but it isn’t so. Even with a
device-managed frame buffer, DrvBitBlt is often called with system
memory surfaces. Either the source or destination will always be a
device surface, but there’s no promise that both are.

DrvCopyBits is a proper subset of DrvBitBlt. The only advantage is that
you don’t have to have a big switch statement based on the ROP and the
presence of a mask. Even if you assume a very slow processor, that
overhead is still dwarfed by the graphics processor’s drawing time.

As I said, I don’t get it.

Thank you both.

Here is the EngCreateDeviceSurface() function.

HSURF
EngCreateDeviceSurface(
DHSURF dhsurf,
SIZEL sizl,
ULONG iFormatCompat
);

If we specify the iFormatCompat as BMP_16BPP, BMP_24BPP or BMP_32BPP
in EngCreateDeviceSurface() before we invoke EngAssociateSurface() in
DrvEnableSurface(), will all the surfaces appear in DrvBitBlt in the
same format as we have specified?

Thanks.

Lei
On Apr 5, 2005 5:02 PM, Tim Roberts wrote:
> Maxim S. Shatskih wrote:
>
> >>DrvCopyBits is a subset of DrvBitBlt, used when there is no mask surface
> >>and no ROP. I am not sure what the motivation was for including
> >>DrvCopyBits; perhaps it was intended as a low-overhead method of
> >>handling the simple calls.
> >>
> >>
> >
> >>From what I know, DrvCopyBits is intended for devices with non-standard surface
> >formats unaccessible for GRE (like VGA16). With such a device, DrvBitBlt only
> >copies from device format to device format, and DrvCopyBits converts between
> >the device format and the GRE standard formats.
> >
> >
>
> That would be a nice explanation, but it isn’t so. Even with a
> device-managed frame buffer, DrvBitBlt is often called with system
> memory surfaces. Either the source or destination will always be a
> device surface, but there’s no promise that both are.
>
> DrvCopyBits is a proper subset of DrvBitBlt. The only advantage is that
> you don’t have to have a big switch statement based on the ROP and the
> presence of a mask. Even if you assume a very slow processor, that
> overhead is still dwarfed by the graphics processor’s drawing time.
>
> As I said, I don’t get it.
>
> –
> - Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@gmail.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

> That would be a nice explanation, but it isn’t so. Even with a

device-managed frame buffer, DrvBitBlt is often called with system
memory surfaces.

Yes, but am I right that these system-memory surfaces have the same format as
the device surfaces? the non-GRE format?

DrvCopyBits is a proper subset of DrvBitBlt.

Which is IIRC used to convert between device surface formay and one of the
GRE’s ones.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Lei Zhang wrote:

Thank you both.

Here is the EngCreateDeviceSurface() function.

HSURF
EngCreateDeviceSurface(
DHSURF dhsurf,
SIZEL sizl,
ULONG iFormatCompat
);

If we specify the iFormatCompat as BMP_16BPP, BMP_24BPP or BMP_32BPP
in EngCreateDeviceSurface() before we invoke EngAssociateSurface() in
DrvEnableSurface(), will all the surfaces appear in DrvBitBlt in the
same format as we have specified?

No, there’s no guarantee of that. If an application calls
SetDIBitsToDevice with an 8-bit DIB, you’ll get a BMP_8BPP source bitmap
in your DrvBitBlt.

If you decide you don’t want to handle that bitblt and fail it (or call
EngBitBlt; I don’t remember which), GDI will call DrvCopyBits to copy
that section of your frame buffer to the iFormatCompat format. Then IT
will do the color space conversion and the bitblt operation, and then
call DrvCopyBits to put it back.

Maxim S. Shatskih wrote:

>That would be a nice explanation, but it isn’t so. Even with a
>device-managed frame buffer, DrvBitBlt is often called with system
>memory surfaces.
>
>

Yes, but am I right that these system-memory surfaces have the same format as
the device surfaces? the non-GRE format?

No, I don’t think that is true, but the fact that you seem so certain
makes me question my memory. The unfortunate fact is that you are right
more often than I am, Maxim.

It has actually been a few years since I had a display driver project,
but I’m almost positive that I could get arbitrary DIB formats in
DrvBitBlt. If an application calls SetDIBitsToDevice with an 8-bit DIB,
I will get a DrvBitBlt call with the destination being my surface (in
whatever format I picked), and the source being a BMP_8BPP system memory
surface.

It is certainly true that many of the display drivers I have worked on
have had switch statements to handle each of the BMP_xxBPP formats. I
can’t imagine they would all go to that trouble if it weren’t necessary.

> No, I don’t think that is true, but the fact that you seem so certain

makes me question my memory. The unfortunate fact is that you are right
more often than I am, Maxim.

I’m not so good in video, but let’s check the VGA 4bpp driver source source.

DrvCopyBits (which I think is called inside EngBitBlt for device surfaces)
punts to DrvBitBlt with SRCCOPY ROP in the following cases:

  • pallete xlate exists and the target is device or devbitmap
  • source and target are the same devbitmap are are intersecting
  • copy from 1bpp or 8bpp DIB to device or devbitmap
  • and some more.

So, DrvCopyBits uses the proprietary non-GRE code only for:

  • from device to device if there is no xlate
  • from devbitmap to 4bpp DIB
  • from devbitmap to devbitmap if src and dst do not intersect (DrvBitBlt is
    used otherwise), and there is no xlate
  • from devbitmap to device if there is no xlate
  • from 4bpp DIB to devbitmap (DrvBitBlt is used for 1bpp and 8bpp DIBs)
  • from 4bpp DIB to device (DrvBitBlt is used for 1bpp and 8bpp DIBs)
  • from 8bpp or 4bpp RLE DIBs to device
  • from device to 4bpp DIB

In all other cases DrvCopyBits punts to SimCopyBits, using the third temporary
4bpp DIB surface. Namely these cases are:

  • from device to device if there is xlate
  • from devbitmap to any DIB except 4bpp
  • from > 8bpp DIBs to devbitmap or device
  • from device or devbitmap to any RLE DIBs
  • from device to any DIB except 4pbb

SimCopyBits uses Src -> Tmp and then Tmp -> Dst blits. Since Tmp is a DIB,
EngCopyBits is used for DIB-to-DIB transfers in these procedures, and
DrvCopyBits is used from non-DIB surfaces to Tmp which is a 4bpp DIB. Such
DrvCopyBits always uses proprietary code.

Now about DrvBitBlt.

DrvBitBlt punts the following to EngBitBlt:

  • blits from device to device bitmap
  • blits from DIB source with > 8bpp to any target
  • blits from device to device with any ROP other then SRCCOPY
  • and some more cases.

You see - EngBitBlt is used for many kinds of blits, including the ones which
involve devbitmaps. So, I can only suggest that EngBitBlt calls DrvCopyBits for
some cases, at least for devbitmap/devbitmap, DIB/devbitmap and devbitmap/DIB
blits. Otherwise, EngBitBlt would have no chances on dealing with devbitmaps.

My conclusion is:

  • EngCopyBits cannot be used for non-GRE surfaces. It is a simple blit from GRE
    surface to GRE surface, which can only convert depths.
  • EngBitBlt calls DrvCopyBits internally if one of the sides is a devbitmap or
    device.
  • possibly (but I’m not sure of it) DrvCopyBits is called only from within
    EngBitBlt.
  • note the SimCopyBits existence. This means that DrvCopyBits can be called for
    any DIB from one side and device from another side.
  • so, looks like the minimal functionality of DrvCopyBits must be - blits with
    no DIB from any side (only devices or devbitmaps) and blits with any DIB from
    one side and device/devbitmap on another side. DvrCopyBits is free to use Tmp
    DIB surface and EngCopyBits to convert the depth, while using proprietary code
    for device <-> device and proper-depth-DIB <-> device transfers.

People with GRE source access can shed more light here. What is interesting is
a) what is the exact list of operations DrvCopyBits must support and b) am I
correct that DrvCopyBits is only called from within EngBitBlt c) am I correct
that EngCopyBits only supports 2 DIBs and does not call any DrvXxx routines?

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

I looked into the framebuf sample. When it calls
EngCreateDeviceSurface(), it take ppdev as the first parameter, other
than a block of memory allocated by EngAllocMem(). Is it the key point
to create a engine-managed surface?

And for a engine-managed surface, can any other DrvXxxx functions access them?

Thanks.

Lei

So the engine-managed surface will not be passed to any

On 4/5/05, Tim Roberts wrote:
>
> For a completely engine-managed surface, you don’t need either of these
> functions. The framebuf sample in the DDK is an example of a nearly
> minimal display driver.
>
> –
> - Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
> —
> Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@gmail.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Lei Zhang wrote:

I looked into the framebuf sample. When it calls
EngCreateDeviceSurface(), it take ppdev as the first parameter, other
than a block of memory allocated by EngAllocMem(). Is it the key point
to create a engine-managed surface?

Actually, the key point that allows a surface to be drawn on directly by
GDI is the call to EngModifySurface. If you pass it a pointer to bits
and a stride value, then GDI knows it can draw on it. If you pass NULL,
then the driver must handle all drawing on its own.

(This is different from the process in NT 4.0, by the way.)

And for a engine-managed surface, can any other DrvXxxx functions access them?

Sure. Your driver owns the surface. GDI just “borrows” it for drawing
from time to time.