New and Improved: The GRE22 Printer Device Driver Model

From EDM2
Revision as of 11:35, 21 November 2018 by Ak120 (Talk | contribs)

Jump to: navigation, search

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 \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 DePostDeviceModes(), 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 );

Sample 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
      -1              Failure

Sample 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 E nableDC. GRE22 calls this subfunction after EnableDC and before CompleteOpenDC. GRE22 allocates the memory to which PDEVICESURFACE points.

typedef struct _BMAPINFO {
 ULONG  ulLength;
 ULONG  ulType;
 ULONG  ulWidth;               // Width in pels of the physical device surface
 ULONG  ulHeight;              // Height in pels of the physical device surface
 ULONG  ulBpp;                 // Number of Bytes per pel
 ULONG  ulBytesPerLine;        // Number of bytes per scan line
 PBYTE  pBits;                 // Pointer to a linear memory address
} BMAPINFO;
typedef BMAPINFO *PBMAPINFO;

Sample 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 {
 ULONG         ulLength;
 BMAPINFO      SurfaceBmapInfo;
 ULONG         ulDSFlgs;
 ULONG         ulStyleRatio;
 BMAPINFO      abmapinfoDefPattern[DEFAULT_PATTERNS_NUMBER];
 PRGB2         pHWPalette;
 DITHERMATRIX  DitherMatrix;
 PFN           pfnDevLockDC;
 PFN           pfnDevUnLockDC;
 PFN           pfnBitBlt;
 PFN           pfnLine;
 PFN           pfnLockPhysDev;
 PFN           pfnUnLockPhysDev;
 ULONG         ulCapsCnt;
 ULONG         DevCaps[CAPS_MAX_CAPS];
} DEVICESURFACE;
typedef DEVICESURFACE *PDEVICESURFACE;

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 memo ry 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.

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation