
MINIDRIVER2

The MiniDriver2 (MD2) is sample, beta, skeleton, 32-bit source code
for a Presentation Manager hardcopy driver.

MiniDriver2 expects to run on OS/2 Graphics Engine (GRE) levels 0x0220
and higher. This level of GRE appears in OS/2 Warp (OCT94) and later
versions of OS/2. MiniDriver2 will not run on OS/2 2.1 or 2.11.

MD2 takes a pure raster approach to page rendering; that is, it
lets GRE22 do the work of drawing a page in memory, then MD2
sends down the page, using raster printer commands, to the
hardcopy device.

Unlike the first MiniDriver, MD2 generates Hewlett-Packard(C)
PCL5(C) printer control language, so it will drive an HP LaserJet
or compatible printer. MiniDriver2 does not use the display for
output.

The areas of MD2 code that are device specific are marked with an
eyecatcher: DEVICE_SPECIFIC. Developers basing drivers on the MD2
skeleton should grep the code for DEVICE_SPECIFIC and replace
these portions of the code with their own.

You will improve MD2 by adding code. Several places to improve MD2
are marked in the comments. Grep the code using the regular
expression

                needs.*work

MD2 supports 4 devices:

   300 DPI 8:1 LaserJet
   300 DPI 1:1 LaserJet
   600 DPI 8:1 LaserJet
   600 DPI 1:1 LaserJet

The 8:1 drivers have 8 bits per pel logical colors, and 1 bit per pel
physical colors. This is a preferred mode of operation. The GRE will
dither 256 colors and prepare the raster output so it prints nicely on a
monochrome printer.

The GRE will not dither or simulate colors for the 1:1 driver. It is
faster, and less less memory is used, but the output does not look as
nice.

Color devices support 256 logical and 256 physical colors (8:8). Such a
modification requires changes to the DEVICESURFACE data structure. See
enable.c and caps.c and newframe.c.

See the Developer Connection for OS/2 Newsletter Volume 5 for the
article "New and Improved, the GRE22 Printer Device Driver Model."
The article is included below with permission of the Developer
Connection for OS/2. 1-800-6DEVCON.





BUILDING MINIDRIVER2

MD2 requires new versions of PMDDI.H, DDI.H for the GRE22 graphic
engine. These appear on the Developer Connection Device Driver
Source Kit for OS/2, Version 1.0 CD-ROM.

MD2 uses the Generic Printer Library, a suite of subroutines for
PM hardcopy device drivers. The MD2 makefile sets an include path
to GENPLIB include files, and another path to GENPLIB.LIB for the
linker.

The Generic Printer Library provides several areas of support
including output threads, memory management, semaphores. MD2 uses
the journaling subroutines for banding.

MD2 builds with IBM C Set/2 compiler.

MD2 makefile builds retail, debug, and IPMD versions. The debug
versions include assertions, conditional code that helps in
debugging. The readme for MiniDriver1 has details about this
building/debugging strategy.

To build the retail version, enter one of these commands:

          nmake
          nmake retail

To build the debug kernel version, enter this command:

          nmake debug

To build the IPMD debugger version, enter this command:

          nmake ipmd


For hard-coded INT 3 debug breakpoints, MiniDriver2 does not call
an assembler language subroutine as MiniDriver1 did.  Instead, the
code includes IBM C Set/2 <builtin.h> and uses the built-in,
in-line function

          _interrupt(3);

DRVNAMES.EXE is a utility to attach the .EXPAND extended
attribute to the driver DRV file. It is similar in function to
DEVNAMES.EXE. Both these utilities temporarily load the driver
and call OS2_PM_DRV_DEVICENAMES to get a list of individual
printer models supported by the driver. This list, placed in an
EA on the DRV file, lets the Workplace Shell install the driver
much faster. The shell queries the EA instead of loading the
driver from diskette.




INSTALLING MINIDRIVER2

An installable MiniDriver2 diskette may be created by copying these
files to a diskette, then using the Workplace Shell Print Object to
install the driver.

            MDRIVER.DRV    (required)
            MDRIVER.SYM    (optional)







USING IPMD TO DEBUG MINIDRIVER2

It is quite possible to debug printer drivers at source level
using IPMD.EXE, the PM debugger that comes with IBM C Set/2
compiler.

Notes on using IPMD for printer drivers...

. Compile the driver with /Ti+ and /O-, link with /DEBUG. See
makefile build target IPMD.

. Point to the MD2 source code with the CONFIG.SYS environment
variable PMDPATH. Example:

       SET PMDPATH=.;C:\TMP;C:\SRC\MDRIVER2

. Extend LIBPATH to include the location of your driver.

       SET LIBPATH=C:\OS2\DLL\MDRIVER; ... and so on ...

. Use IPMD to debug a PM testcase application that prints. (The
test program does not have to be compiled for debugging, nor it is
necessary to have the source code for the application.)

. Set a load occurence breakpoint. This way, IPMD will stop when
the process under debug loads your driver. When IPMD stops, set
breakpoints elsewhere in the driver.

. Depending on the code path you want to debug, you may want to
disable the spooler.

When the spooler is disabled, you will always print in a "direct"
fashion. In the direct case, your driver will be generating
printer-specific output. This is the usual case for the
PMSPOOL.EXE process when it plays metafiles into your driver.

If the spooler is enabled, and the job is OD_QUEUED with data
type "PM_Q_STD" then you will be debugging your driver's metafile
creation code.

To enable/disable the spooler, open OS/2 System folder and click
mouse button 2 on the Spooler icon.










ARTICLE FROM DEVELOPER CONNECTION NEWSLETTER VOLUME 5

New and Improved:  The GRE22 Printer Device Driver Model

by Michael R. Cooper and Monte Copeland

The OS/2 graphics engine, the heart of Presentation Manager, is
changing and making it easier to develop PM printer drivers.
Beginning with an overview of PM printer drivers, this article
describes graphics engine support for a new-model PM printer
driver.



What is a PM Printer Driver?

Presentation Manager (PM) hardcopy drivers are ring-3 DLLs that
hold a collection of device-dependent routines called by the
OS/2 graphics engine, hereafter referred to as GRE. Drivers bear
a .DRV filename extension instead of .DLL.   The Printer object
installs these drivers into subdirectories below \OS2\DLL and
makes entries into the system .INI file to record their
presence. The routines in a PM printer driver can be subdivided
into three major groups:



User Interface Functions:  A set of dialogs and window
procedures for configuring print jobs and the printer itself.
The driver must export a function named OS2_PM_DRV_DEVMODE()
through which the GRE accesses these dialogs.  When an
application calls DevPostDeviceModes(), the GRE calls
OS2_PM_DRV_DEVMODE().



Drawing Functions: An important GRE data structure is the dispatch
table, an array of over 200 pointers to functions that accomplish
drawing tasks such as image, bitblt, lines, and text.



As the GRE enables a driver for printing, the driver must replace
certain function pointers in the dispatch table with pointers to
its own drawing routines. Consider a laser printer capable of
vector line drawing. Its driver will replace function 0x19 in the
dispatch table, PolyLine(), (see PMDDIM.H in the Developer's
Toolkit for OS/2 2.1) because rendering lines in vector language
typically performs better than in raster.



Of all the functions in the dispatch table, primitive drawing
functions are mandatory; that is, the driver must replace those
pointers in the dispatch table. Some functions are simulated; the
driver may replace them. If not, the existing functions will
simulate the drawing using the mandatory functions.



Enable Functions:  Enable means open.  When an application calls
DevOpenDC(), GRE opens a device context (DC) in the driver by
calling its exported function OS2_PM_DRV_ENABLE().  It is during
this function that the driver replaces dispatch table function
pointers with its own.



The driver allocates an internal data structure called a device
drawing context (DDC) and returns the pointer (PDDC) to the GRE.
The GRE supplies the PDDC on subsequent calls to the driver.

OS2_PM_DRV_ENABLE() is an overloaded driver entry. GRE performs
multiple operations, including open and close, by calling this
one function.




GRE Version 220 Changes and Enhancements

GRE Version 220 offers a new printer driver programming model. (Hex
0x0220 is the binary-coded-decimal representation of GRE version.
The GRE version number is supplied on Enable subfunction
FillLogicalDeviceBlock.) In this article, GRE22 refers to graphics
engine version 0x0220. The distinctive difference in GRE22 is:
There are only three mandatory functions. Compare this to 60 in
previous versions. The benefit to developers is that GRE22 will
simulate all drawing functions.



The three mandatory functions are:



Escape:  This function has always been required.  When an
application calls DevEscape() to start the document
(DEVESC_STARTDOC) or to eject the page (DEVESC_NEWFRAME), the
GRE calls the driver's Escape function through the dispatch
table.



QueryHardcopyCaps: As before, a driver reports available forms
using this function. When an application calls
DevQueryHardcopyCaps(), the GRE dispatches QueryHardcopyCaps in the
driver.



DevicePalette: This is a new mandatory function. GRE22 manages
color tables and palettes. The presentation driver is responsible
only for setting and returning its hardware palette. If the device
has no hardware palette, then the function may do nothing and
return success.



None of these mandatory functions are drawing functions.  So,
the question arises:  When GRE22 simulates all drawing, where
does the drawing go?



New System Routines:  Softdraw BitBlt, Softdraw Line

The GRE22 drawing functions send their output to new GRE22
routines: SDBitBlt and SDLine.



      APIRET APIENTRY SDBitBlt( PBITBLTINFO, PDDC );

      APIRET APIENTRY SDLine( PLINEINFO, PDDC );



Code 1: Function prototypes for SDBitBlt and SDLine, two new
functions in the 0x0220 version of the OS/2 graphics engine.
When GRE22 performs the drawing, it will reduce it to raster or
lines and call SDBitBlt or SDLine respectively.  All drawing
parameters are supplied in BITBLTINFO and LINEINFO structures.
See new DDI.H and PMDDI.H for the definition of these structures.

Before calling these routines, the GRE22 prepares the drawing
such that:

. All drawing is pre-clipped

. All colors and coordinates are mapped to the physical device

. Source, pattern, and destination origins and extents are provided

. Engine font glyphs, scan lines, and polylines are sent in
optimized batches

. All bitmaps required for the raster operation are included:
source, pattern, and destination



The SDBitBlt and SDLine routines place the drawing in memory
allocated by the hardcopy driver. When drawing on a page is
complete, as signaled by DevEscape(DEVESC_NEWFRAME),  the driver
fetches the raster image from memory and sends it to the
printer.  Some new GRE22 data structures are required to make
this happen.



New Data Structures for GRE22

There are several new GRE22-specific data structures; an
important one is DEVICESURFACE.  New drivers must support a new
OS2_PM_DRV_ENABLE subfunction called QueryDeviceSurface, which
the GRE22 calls to collect the capabilities of the device and
the current form.

---------------------------------------------------------------

  OS2_PM_DRV_ENABLE: Subfunction 0Eh - QueryDeviceSurface

        Parameters:
        ULONG           ulSubfunction (0x0E)
        PDEVICESURFACE  pds
        PULONG          pddc

        Returns(LONG):
        0               Success (supported)
        -1              Failure (not supported)


Code 2:  Parameters for new enable subfunction
QueryDeviceSurface.  If supported, GRE22 assumes a new-model
driver.  (Old model drivers return -1 for all non-supported
enable subfunctions.) PDDC is the pointer the driver returned
from enable subfunction EnableDC.

Early in driver initialization, GRE22 will call OS2_PM_DRV_ENABLE
subfunction 14 with null pds and pddc. In this case, a new-model
driver should do nothing and return 0 to indicate to the GRE22
that it supports subfunction 14.

GRE22 again calls this subfunction after EnableDC and before
CompleteOpenDC with non-null pointers. GRE22 has allocated the
memory to which PDEVICESURFACE points.


---------------------------------------------------------------

  typedef struct _BMAPINFO {
     ULONG  ulLength;
     ULONG  ulType;
     ULONG  ulWidth;
     ULONG  ulHeight;
     ULONG  ulBpp;
     ULONG  ulBytesPerLine;
     PBYTE  pBits;
  } BMAPINFO;
  typedef BMAPINFO  *PBMAPINFO;

Code 3:  BMAPINFO defines a bitmap format used for internal
bitmap representation. Differs from external OS/2 bitmap format
that is always dword aligned. See new DDI.H

---------------------------------------------------------------

   typedef struct _DEVICESURFACE          /* devsur */
   {
      ULONG         ulLength;
      BMAPINFO      SurfaceBmapInfo;
      ULONG         ulDSFlgs;
      ULONG         ulStyleRatio;
      BMAPINFO      abmapinfoDefPattern[DEFAULT_PATTERNS_NUMBER];
      PVOID         pHWPalette;
      DITHERMATRIX  DitherMatrix;
      PFN           pfnDevLockDC;
      PFN           pfnDevUnLockDC;
      PFN           pfnBitBlt;
      PFN           pfnLine;
      PFN           pfnReserved;
      PFN           pfnLockPhysDev;
      PFN           pfnUnLockPhysDev;
      ULONG         ulReserved[5];
      ULONG         ulCapsCnt;
      ULONG         DevCaps[CAPS_MAX_CAPS + 1];
   } DEVICESURFACE;
   typedef DEVICESURFACE *PDEVICESURFACE; /* pdevsur */

Code 4:  DEVICESURFACE defines more than just the surface of the
hardcopy form.  The DevCaps[] array describes the capabilities
of the printer including resolution, raster, and color.  The
Softdraw BitBlt and Line function pointers reside in this
structure, which the driver may replace with its own routines.
See new PMDDI.H.

---------------------------------------------------------------


GRE allocates a DEVICESURFACE for each DC. The driver obtains the
pointer when GRE22 calls QueryDeviceSurface subfunction after
EnableDC and before CompleteOpenDC. The driver should store the
DEVICESURFACE pointer in its per-DC data structure (DDC).



During the processing of QueryDeviceSurface, the driver must
complete the DevCaps[] array of ULONGs. Important capabilities are
horizontal and vertical resolution, the size of the current form in
pels, and logical (simulated) and physical color counts. Driver
writers will recognize this array; it used to be set in the
dispatched function QueryDeviceCaps().



The driver must assign values to the SurfaceBmapInfo structure.
These describe the physical surface of the device. For the device
context to be set up correctly, all parameters except pBits must be
filled in. The Softdraw routines raster output to memory pointed to
by SurfaceBmapInfo.pBits. You may defer allocating this memory
until DevEscape(DEVESC_STARTDOC) time.



The abmapinfoDefPattern[] structure contains image information for
a default set of 8 x 8 mono patterns. These are very small patterns
-- small for 300 DPI printers and too small for 600 DPI. Some
drivers generate 32 x 32 patterns on the fly and produce pleasing
results at all resolutions. (All patterns in this array must be the
same size.)



GRE22 will perform dithering when 1) converting from external to
internal bitmap format, 2) stretching an internal bitmap, and 3)
converting an internal logical color bitmap to an internal physical
color bitmap. GRE22 implements one of several dithering techniques
determined by the settings in the DitherMatrix structure, or you
can provide a pointer to your own dithering routine.



pfnDevLockDC and pfnDevUnLockDC point to system functions used for
serializing access to the DC. pfnDevLockDC returns DC state
information such as attribute bundles. Drivers replacing drawing
functions in the dispatch table will require DC state information.
For example, most printers have device fonts, so they will replace
CharStringPos(). When called, the driver locks the DC and obtains
the character attribute bundle which contains the character box
attribute needed to size the font.



Drivers can update the DEVICESURFACE data structure during a print
job. (This will usually happen at DEVESC_STARTDOC or
DEVESC_NEWFRAME time.) To do this, they must call a new API called
SetDeviceSurface(). For example, you can defer the allocation of
SurfaceBmapInfo.pBits until DEVESC_STARTDOC. If you are generating
output, allocate SurfaceBmapInfo.pBits and call SetDeviceSurface().



More About Softdraw BitBlt and Line

Softdraw BitBlt and Line are the two drawing functions used by
GRE22.  When a driver does not replace the drawing functions in
the dispatch table, GRE22 performs the drawing and sends the
output to Softdraw BitBlt and Line.



(A driver can replace a drawing function in the dispatch table,
and then decide not to handle the drawing.  Assuming the driver
kept a copy of the original pointer, it can call back to the
GRE22 to perform the drawing.  GRE22 will call Softdraw BitBlt
and Line to output the drawing, as above.)



Softdraw BitBlt and Line support color depths of 1-, 4-, 8-,
16-, and 24-bits per pel.  For 16- and 24-bits per pel, Softdraw
supports multiple formats including 5/6/5 and BGR.  All support
is 1-plane, packed-pixel images.  Softdraw supports monochrome
expansion and color-to-color transfer.



GRE22 may send multiple BitBlt or Line operations in a single
call.  Batch drawing is suited for complex clip regions to the
destination surface, but it is also useful for groups of
rastered character glyphs.



Softdraw BitBlt supports 256 ROPs and source, pattern, and
destination transparency, as well as hardware mixing where
foreground and background bits require different mix operations.



Softdraw Line supports 16 pattern and destination operations.
All drawing information is provided in the LINEPACK structure,
including Bresenham error values used for drawing from the
visible point of a clipped line.



Replacing Softdraw BitBlt and Line

A printer driver may  bypass the system-supplied BitBlt and Line
routines. If so, the driver saves allocating memory for Softdraw
BitBlt and Line output. The driver receives the calls directly
from GRE22 drawing routines and draws bitblts and lines directly
onto the device.



In the DEVICESURFACE structure, there are function pointers to
the system-supplied Softdraw BitBlt and Line routines (pfnBitBlt
and pfnLine). When drawing, GRE22 calls these functions
indirectly. The driver can replace these pointers with pointers
to functions that perform like Softdraw, but whose output is the
device, not raster data in memory.



Future Considerations

This driver model applies to GRE Versions 0x0220 and greater.
This is the new programming model for OS/2 and OS/2 for PowerPC.
Hardcopy driver sources will be compatible between OS/2 running
GRE22 and OS/2 for the PowerPC.



Future plans for Softdraw include 32-bit-per-pel bitmaps and
4-plane support for 4-bit-per-pel images.




TRADEMARKS:

HP is a trademark of Hewlett-Packard Company.
PCL and PCL5 are trademarks of Hewlett-Packard Company.
LaserJet is a trademark of Hewlett-Packard Company.

