Jump to content

PDRREF:Design Considerations for All Drivers: Difference between revisions

From EDM2
Ak120 (talk | contribs)
Ak120 (talk | contribs)
m prepare
Line 21: Line 21:


==Angles==
==Angles==
Angles are passed as signed 32-bit numbers. Zero refers to the direction of the positive X-axis; 360 represents 360ø. Positive values represent counterclockwise angles from the positive X-axis.  
Angles are passed as signed 32-bit numbers. Zero refers to the direction of the positive X-axis; 360 represents 360ø. Positive values represent counterclockwise angles from the positive X-axis.


==Bounds computations==
==Bounds computations==
All presentation drivers must accumulate bounds for unclipped primitives. Application bounds (COM_BOUND) are accumulated in model space. User bounds (COM_ALT_BOUND) are accumulated in device-coordinate space.  
All presentation drivers must accumulate bounds for unclipped primitives. Application bounds (COM_BOUND) are accumulated in model space. User bounds (COM_ALT_BOUND) are accumulated in device-coordinate space.


==Clipping==
==Clipping==
Line 36: Line 36:


==Coordinate values==
==Coordinate values==
All coordinates are passed to the presentation driver as 32-bit values. Unless stated otherwise, these values represent world coordinates. The graphics engine function, GreConvert, can be called to convert coordinates from one type to another. Coordinates must be converted back to world coordinates before returning to the presentation driver. Notice that screen coordinates are device coordinates to which the DC origin has been added.  
All coordinates are passed to the presentation driver as 32-bit values. Unless stated otherwise, these values represent world coordinates. The graphics engine function, GreConvert, can be called to convert coordinates from one type to another. Coordinates must be converted back to world coordinates before returning to the presentation driver. Notice that screen coordinates are device coordinates to which the DC origin has been added.


==Positions within text functions==
==Positions within text functions==
When positions are used, a text function takes the position from the base line of the text box. Descenders, such as the tail of a lowercase character "y," are expressed as a negative value relative to the base line.  
When positions are used, a text function takes the position from the base line of the text box. Descenders, such as the tail of a lowercase character "y," are expressed as a negative value relative to the base line.


==Return codes==
==Return codes==
The presentation driver must always return a full 32-bit (LONG) value. For example, BOOLEAN TRUE and FALSE are defined as:
The presentation driver must always return a full 32-bit (LONG) value. For example, BOOLEAN TRUE and FALSE are defined as:
 
#define TRUE  (1L);
    #define TRUE  (1L);
#define FALSE  (0L);
    #define FALSE  (0L);


==Transform matrix values==
==Transform matrix values==
Transform matrix elements are represented in fixed point notation, that is, as a 16-bit signed integer and a 16-bit fractional part. These precision limits apply during graphics engine matrix multiplication for all initial, intermediate, and final matrix element values.  
Transform matrix elements are represented in fixed point notation, that is, as a 16-bit signed integer and a 16-bit fractional part. These precision limits apply during graphics engine matrix multiplication for all initial, intermediate, and final matrix element values.


==Allocating Memory==
==Allocating Memory==
Presentation drivers can allocate and manage memory by using:
Presentation drivers can allocate and manage memory by using:
* A Dosxxx function such as DosAllocMem.
* A Dosxxx function such as DosAllocMem.
* The SSxxx functions described in System Functions.  
* The SSxxx functions described in System Functions.
 
Display drivers, or presentation drivers that share objects such as bit maps and regions, must use the SSxxx functions to allocate memory for these objects. Memory allocated through calls to these functions is "shared memory", controlled by the memory allocator component of the graphics engine. Ownership of the memory can be transferred or (when the owning device context ceases to exist) marked as having no owner.
Display drivers, or presentation drivers that share objects such as bit maps and regions, must use the SSxxx functions to allocate memory for these objects. Memory allocated through calls to these functions is "shared memory", controlled by the memory allocator component of the graphics engine. Ownership of the memory can be transferred or (when the owning device context ceases to exist) marked as having no owner.  


==Error Strategy==
==Error Strategy==
Line 61: Line 59:


The component that implements a function must provide error checking for the environment, objects, and resources associated with it. The presentation driver requires the following error checking:
The component that implements a function must provide error checking for the environment, objects, and resources associated with it. The presentation driver requires the following error checking:
* Fail-safe on routines that set attributes and transformation values. Any routine that changes attributes or transformation values must be able to restore the initial values if an error occurs during the change.
* Fail-safe on routines that set attributes and transformation values. Any routine that changes attributes or transformation values must be able to restore the initial values if an error occurs during the change.
* Full error checking on symbol sets, fonts, bit maps, and regions.
* Full error checking on symbol sets, fonts, bit maps, and regions.
* With segment drawing, drawing primitives, and primitive attributes in draw mode, unchecked parameters are passed directly to the graphics engine or the presentation driver. When one of these functions is hooked by the presentation driver, the handling routine must perform the necessary error checking and log any errors, or reset any invalid values to their defaults, as appropriate.
* With segment drawing, drawing primitives, and primitive attributes in draw mode, unchecked parameters are passed directly to the graphics engine or the presentation driver. When one of these functions is hooked by the presentation driver, the handling routine must perform the necessary error checking and log any errors, or reset any invalid values to their defaults, as appropriate.
* For any function with coordinates as parameters, the presentation driver must check that the values passed are valid. When an invalid coordinate is detected, the handling routine must log an error or use a default coordinate value, as appropriate.  
* For any function with coordinates as parameters, the presentation driver must check that the values passed are valid. When an invalid coordinate is detected, the handling routine must log an error or use a default coordinate value, as appropriate.
 
For any defined error, the application sees the same error code regardless of whether the error was logged by the Graphics Programming Interface (GPI), graphics engine, or presentation driver.
For any defined error, the application sees the same error code regardless of whether the error was logged by the Graphics Programming Interface (GPI), graphics engine, or presentation driver.  


===Severity===
===Severity===
Four ascending severity levels are defined for error messages:
Four ascending severity levels are defined for error messages:
*Warning
*Error
*Severe error
*Unrecoverable error


    Warning
;Warning:The function detected a problem, took corrective action, and was able to complete processing successfully.
    Error
;Error:The function detected a problem for which no sensible corrective action is possible. The function is not executed and the system remains at the same state as when the function was requested.
    Severe error
;Severe Error:The function detected a problem from which the system cannot reestablish its state. The function has partially executed and the application must now make some corrective action to restore the system to a known state.
    Unrecoverable error
;Unrecoverable Error:The function detected an error from which it is impossible for the system to reestablish the state that it held at the time that the function was called. It is also impossible for the application to restore the system to a known state.
 
====Warning====
The function detected a problem, took corrective action, and was able to complete processing successfully.  


====Error====
===Presentation Manager Error Codes===
The function detected a problem for which no sensible corrective action is possible. The function is not executed and the system remains at the same state as when the function was requested.
====Severe Error====
The function detected a problem from which the system cannot reestablish its state. The function has partially executed and the application must now make some corrective action to restore the system to a known state.
====Unrecoverable Error ====
The function detected an error from which it is impossible for the system to reestablish the state that it held at the time that the function was called. It is also impossible for the application to restore the system to a known state.
===Presentation Manager Error Codes===  
Error codes are defined in the header file. These codes fall into general and specific groups. General error codes that are appropriate to many Grexxx functions include:
Error codes are defined in the header file. These codes fall into general and specific groups. General error codes that are appropriate to many Grexxx functions include:
{|class="wikitable"
{|class="wikitable"
Line 113: Line 104:
==Exit List Processing==
==Exit List Processing==
An exit list is a list of routines that are given control when the current process ends, either normally or abnormally. The following is an example of exit list processing:
An exit list is a list of routines that are given control when the current process ends, either normally or abnormally. The following is an example of exit list processing:
* When the presentation driver's Enable Subfunction 01H - FillLogicalDeviceBlock is called, the driver can call function DosExitList:
* When the presentation driver's Enable Subfunction 01H - FillLogicalDeviceBlock is called, the driver can call function DosExitList:
   #define ROUTINE_ORDER 0x1000
   #define ROUTINE_ORDER 0x1000
Line 121: Line 111:


* When MyExitProc is called, the presentation driver can perform any necessary cleanup such as releasing any semaphores. The last call in MyExitProc is another call to DosExitList:
* When MyExitProc is called, the presentation driver can perform any necessary cleanup such as releasing any semaphores. The last call in MyExitProc is another call to DosExitList:
 
usResult = DosExitList (EXLST_EXIT, (PFNEXITLIST)MyExitProc);
            usResult = DosExitList (EXLST_EXIT, (PFNEXITLIST)MyExitProc);
This allows the operating system to transfer control to the next function in the list of exit list processing functions for the process that has terminated. For more information, refer to DosExitList in the ''OS/2 Control Program Programming Reference'' and ''OS/2 Programming Guide''.
 
This allows the operating system to transfer control to the next function in the list of exit list processing functions for the process that has terminated. For more information, refer to DosExitList in the OS/2 Control Program Programming Reference and OS/2 Programming Guide.  


At Enable time, the presentation driver must place an entry in the exit list for the application or process that opens the DC. This entry is a pointer identifying the routine in the presentation driver that releases all resources owned by the DC.
At Enable time, the presentation driver must place an entry in the exit list for the application or process that opens the DC. This entry is a pointer identifying the routine in the presentation driver that releases all resources owned by the DC.


'''Note:''' When writing a presentation driver, consider what would happen if another thread of the process were to terminate.
'''Note:''' When writing a presentation driver, consider what would happen if another thread of the process were to terminate.
==Per-Thread Exception Management==
==Per-Thread Exception Management==
Per-thread exception management is available to 32-bit EXEs, DLLs, and presentation drivers. The per-thread exception management model is a superset of DosExitList processing found in 16-bit OS/2 programming.
Per-thread exception management is available to 32-bit EXEs, DLLs, and presentation drivers. The per-thread exception management model is a superset of DosExitList processing found in 16-bit OS/2 programming.
Line 149: Line 138:


The goals of a 32-bit driver that uses exception management are:
The goals of a 32-bit driver that uses exception management are:
* When passed bad parameters that cause exceptions, drivers can call WinSetErrorInfo and return suitable result codes for the application to inspect.
* When passed bad parameters that cause exceptions, drivers can call WinSetErrorInfo and return suitable result codes for the application to inspect.
* When threads are terminated while executing driver code, the driver can clean up before the thread exits.
* When threads are terminated while executing driver code, the driver can clean up before the thread exits.
Line 160: Line 148:
At exception time, the handler's main activity is to jump out of the handler function back into the function that caused the trap. The handler does an inter-function jump using ANSI C setjmp() and longjmp().
At exception time, the handler's main activity is to jump out of the handler function back into the function that caused the trap. The handler does an inter-function jump using ANSI C setjmp() and longjmp().


After the inter-function jump, the thread is now executing at a known point in the function that had a problem, and doing clean up there is far easier than in the handler.  
After the inter-function jump, the thread is now executing at a known point in the function that had a problem, and doing clean up there is far easier than in the handler.


===Sample Code===
===Sample Code===
Line 182: Line 170:


ULONG _System DriverHandler( PEXCEPTIONREPORTRECORD p1,
ULONG _System DriverHandler( PEXCEPTIONREPORTRECORD p1,
                                PREGREC p2,
                            PREGREC p2,
                                PCONTEXTRECORD p3,
                            PCONTEXTRECORD p3,
                                PVOID pv )
                            PVOID pv )
{
{
   // handle interesting exceptions
   // handle interesting exceptions
Line 238: Line 226:
   return lResult;
   return lResult;
}
}
</PRE>
</PRE>


Line 248: Line 235:


An example of a typical EnterDriver routine for a display driver is as follows:
An example of a typical EnterDriver routine for a display driver is as follows:
<PRE>
<PRE>
  /***************** Typical EnterDriver Routine ***********************/
  /***************** Typical EnterDriver Routine ***********************/
Line 277: Line 263:
   }  while (TRUE);
   }  while (TRUE);
  }
  }
</PRE>
</PRE>


Line 286: Line 271:


This graphics engine has two major changes from OS/2 2.1 and previous versions:
This graphics engine has two major changes from OS/2 2.1 and previous versions:
*Device-independent functions merged into the graphics engine
*Device-independent functions merged into the graphics engine
*System rasterization support (referred to as SOFTDRAW)  
*System rasterization support (referred to as SOFTDRAW)
 
This design is intended to do the following:
This design is intended to do the following:
* Make presentation drivers simple and easy to develop
* Make presentation drivers simple and easy to develop
Line 308: Line 291:
'''Note:'''
'''Note:'''


; 16BPD : Presentation Driver compiled as 16 bit
;16BPD : Presentation Driver compiled as 16 bit
; 32BPD : Presentation Driver compiled as 32 bit
;32BPD : Presentation Driver compiled as 32 bit
; NMPD : New model of Presentation Driver
;NMPD : New model of Presentation Driver


[[Category:PDRREF]]
[[Category:PDRREF]]

Revision as of 15:00, 3 January 2019

Presentation Device Driver Reference for OS/2
  1. Introduction to OS/2 Presentation Drivers
  2. Design Considerations for All Drivers
  3. Graphics Engine/Presentation Driver Design Changes
  4. Design Considerations for Display Drivers
  5. Design Considerations for Hardcopy Drivers
  6. Display Drivers
  7. Distributed Console Access Facility (DCAF) Architecture
  8. Graphics Engine Hardcopy Drivers
  9. Queue Drivers
  10. Port Drivers
  11. Presentation Manager Function Categories
  12. Exported Driver Function Reference
  13. Mandatory and Simulated Graphics Engine Function Reference
  14. Device Support Function Reference
  15. DBIDI Command Structures and Command Flow

Appendixes

A - OS/2 Version Compatibility Considerations
B - Syntax Conventions
C - Format of the Journal File
D - Bit-Map Simulation for 16-Bit Hardcopy Drivers
E - Data Types
F - Notices

Miscellaneous

G - Glossary

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

This chapter describes various design considerations involved in creating a presentation driver. The following list includes the topics covered in this chapter:

  • Angles
  • Bounds computations
  • Clipping
  • Closing figures in areas and paths
  • Coordinate values
  • Positions within text functions
  • Return codes
  • Transform matrix values
  • Allocating Memory
  • Error Strategy
  • Presentation Manager Error Codes
  • Exit List Processing
  • Per-Thread Exception Management
  • Using Macro Assembler Instructions
  • Protecting Objects or Device Contexts

Angles

Angles are passed as signed 32-bit numbers. Zero refers to the direction of the positive X-axis; 360 represents 360ø. Positive values represent counterclockwise angles from the positive X-axis.

Bounds computations

All presentation drivers must accumulate bounds for unclipped primitives. Application bounds (COM_BOUND) are accumulated in model space. User bounds (COM_ALT_BOUND) are accumulated in device-coordinate space.

Clipping

The presentation driver must perform clipping for drawing and text functions, except for GreDrawLinesInPath and GrePolyShortLine. Clipping for these two functions is done by the graphics engine. The minimum requirement is to render each primitive clipped to a single rectangle and to clip each rectangle in turn. The rectangles can be enumerated as described in GreGetClipRects.

Note: Rectangles might not always be valid. See Drawing to Display Devices.

Closing figures in areas and paths

The graphics engine generates closure lines for figures within areas and paths unless the presentation driver has opted to hook all the path and area functions. In this case, the presentation driver is responsible for closing any figures. For details, see Area and Path Functions.


Coordinate values

All coordinates are passed to the presentation driver as 32-bit values. Unless stated otherwise, these values represent world coordinates. The graphics engine function, GreConvert, can be called to convert coordinates from one type to another. Coordinates must be converted back to world coordinates before returning to the presentation driver. Notice that screen coordinates are device coordinates to which the DC origin has been added.

Positions within text functions

When positions are used, a text function takes the position from the base line of the text box. Descenders, such as the tail of a lowercase character "y," are expressed as a negative value relative to the base line.

Return codes

The presentation driver must always return a full 32-bit (LONG) value. For example, BOOLEAN TRUE and FALSE are defined as:

#define TRUE   (1L);
#define FALSE  (0L);

Transform matrix values

Transform matrix elements are represented in fixed point notation, that is, as a 16-bit signed integer and a 16-bit fractional part. These precision limits apply during graphics engine matrix multiplication for all initial, intermediate, and final matrix element values.

Allocating Memory

Presentation drivers can allocate and manage memory by using:

  • A Dosxxx function such as DosAllocMem.
  • The SSxxx functions described in System Functions.

Display drivers, or presentation drivers that share objects such as bit maps and regions, must use the SSxxx functions to allocate memory for these objects. Memory allocated through calls to these functions is "shared memory", controlled by the memory allocator component of the graphics engine. Ownership of the memory can be transferred or (when the owning device context ceases to exist) marked as having no owner.

Error Strategy

Presentation drivers support the error strategy implemented by the Presentation Manager interface. When an error occurs, the driver calls WinSetErrorInfo (see WinSetErrorInfo) to log the appropriate error code and set the return code to show that an error was detected.

The component that implements a function must provide error checking for the environment, objects, and resources associated with it. The presentation driver requires the following error checking:

  • Fail-safe on routines that set attributes and transformation values. Any routine that changes attributes or transformation values must be able to restore the initial values if an error occurs during the change.
  • Full error checking on symbol sets, fonts, bit maps, and regions.
  • With segment drawing, drawing primitives, and primitive attributes in draw mode, unchecked parameters are passed directly to the graphics engine or the presentation driver. When one of these functions is hooked by the presentation driver, the handling routine must perform the necessary error checking and log any errors, or reset any invalid values to their defaults, as appropriate.
  • For any function with coordinates as parameters, the presentation driver must check that the values passed are valid. When an invalid coordinate is detected, the handling routine must log an error or use a default coordinate value, as appropriate.

For any defined error, the application sees the same error code regardless of whether the error was logged by the Graphics Programming Interface (GPI), graphics engine, or presentation driver.

Severity

Four ascending severity levels are defined for error messages:

  • Warning
  • Error
  • Severe error
  • Unrecoverable error
Warning
The function detected a problem, took corrective action, and was able to complete processing successfully.
Error
The function detected a problem for which no sensible corrective action is possible. The function is not executed and the system remains at the same state as when the function was requested.
Severe Error
The function detected a problem from which the system cannot reestablish its state. The function has partially executed and the application must now make some corrective action to restore the system to a known state.
Unrecoverable Error
The function detected an error from which it is impossible for the system to reestablish the state that it held at the time that the function was called. It is also impossible for the application to restore the system to a known state.

Presentation Manager Error Codes

Error codes are defined in the header file. These codes fall into general and specific groups. General error codes that are appropriate to many Grexxx functions include:

Error Code Must be logged by:
PMERR_COORDINATE_OVERFLOW Functions requiring matrix computation
PMERR_INSUFFICIENT_MEMORY Functions resulting in memory allocation
PMERR_INV_HBITMAP Functions with hbm as an explicit or implicit parameter
PMERR_INV_HRGN Functions with hrgn as an explicit or implicit parameter
PMERR_INV_COORDINATE Functions with coordinate parameters
PMERR_INV_IN_AREA Functions that are invalid inside an open area bracket
PMERR_BASE_ERROR Functions that directly or indirectly issue DOS routines
PMERR_DEV_FUNC_NOT_INSTALLED Functions not supported by the presentation driver

Specific error codes listed in the descriptions of each Grexxxfunction are found in Mandatory and Simulated Graphics Engine Function Reference.

To set an error code and the error's severity, the presentation driver must call WinSetErrorInfo (see WinSetErrorInfo). All error codes are listed and explained in the Presentation Manager Programming Reference.

Exit List Processing

An exit list is a list of routines that are given control when the current process ends, either normally or abnormally. The following is an example of exit list processing:

  • When the presentation driver's Enable Subfunction 01H - FillLogicalDeviceBlock is called, the driver can call function DosExitList:
 #define ROUTINE_ORDER 0x1000
 usResult = DosExitList (EXLST_ADD | ROUTINE_ORDER, (PFNEXITLIST)MyExitProc);

This adds the function MyExitProc to the list of functions that are called when this process terminates (either normally or because of some error such as a General Protection fault).

  • When MyExitProc is called, the presentation driver can perform any necessary cleanup such as releasing any semaphores. The last call in MyExitProc is another call to DosExitList:
usResult = DosExitList (EXLST_EXIT, (PFNEXITLIST)MyExitProc);

This allows the operating system to transfer control to the next function in the list of exit list processing functions for the process that has terminated. For more information, refer to DosExitList in the OS/2 Control Program Programming Reference and OS/2 Programming Guide.

At Enable time, the presentation driver must place an entry in the exit list for the application or process that opens the DC. This entry is a pointer identifying the routine in the presentation driver that releases all resources owned by the DC.

Note: When writing a presentation driver, consider what would happen if another thread of the process were to terminate.

Per-Thread Exception Management

Per-thread exception management is available to 32-bit EXEs, DLLs, and presentation drivers. The per-thread exception management model is a superset of DosExitList processing found in 16-bit OS/2 programming.

Under 16-bit OS/2 architecture, a process cannot handle access violations. In the event of an access violation, the system terminates the process. Given that the trapping process had registered an exit-list function, it had one final chance to do clean up just prior to termination. Sixteen-bit drivers and DLLs usually add an exitlist. At process termination, 16-bit drivers perform per-process clean up in exit-list functions.

Programmers of 32-bit drivers have a choice concerning per-process clean up. They may use the 32-bit version of DosExitList(), or they may add code for the DLL termination case in the driver function _DLL_InitTerm(). The _DLL_InitTerm() function, if present and exported from the driver, will be called by OS/2 with parameter 0 on DLL instantiation and parameter 1 on DLL termination or unload. The _DLL_InitTerm() function provides process-granular clean up.

Furthermore, 32-bit OS/2 has exception handlers that are thread-granular. OS/2 lets each thread in a process handle exceptions that arise on that thread. Some of these exceptions are:

  • Accessing invalid or uncommitted memory
  • Stack overruns
  • Thread terminations
  • Floating point errors
  • Asynchronous (external) signals
  • User-raised exceptions (synchronous signals)
  • Invalid opcodes
  • Bounds
  • Divide by zero errors
  • Overflow errors

The goals of a 32-bit driver that uses exception management are:

  • When passed bad parameters that cause exceptions, drivers can call WinSetErrorInfo and return suitable result codes for the application to inspect.
  • When threads are terminated while executing driver code, the driver can clean up before the thread exits.

The Exception Handler

A misconception about exception handlers is that they must be able to fix every bad situation and resume execution. This is not a realistic expectation.

Assume that the handler function will not resume every exception. Instead, it will perform clean up, report errors, and return an appropriate result code. In this case, one exception handling function can handle all exceptions.

At exception time, the handler's main activity is to jump out of the handler function back into the function that caused the trap. The handler does an inter-function jump using ANSI C setjmp() and longjmp().

After the inter-function jump, the thread is now executing at a known point in the function that had a problem, and doing clean up there is far easier than in the handler.

Sample Code

The code fragment below shows how to set a handler while the calling thread is executing driver code. In the event of an exception, OS/2 calls the handler function, which jumps back to the point of setjmp().

#define INCL_DOS
#include <os2.h>
#include <setjmp.h>

// this exception registration record extends the OS/2-defined one in BSEXCPT.H
// by adding a C jmp_buf at the end
struct _regrec {
  PULONG    pNext;
  PFN       pfnHandler;
  jmp_buf   jmp;
}
typedef struct _regrec REGREC, *PREGREC;

// -------------------------------------------------------------------------
// an exception handler function that jumps back to setjmp()

ULONG _System DriverHandler( PEXCEPTIONREPORTRECORD p1,
                             PREGREC p2,
                             PCONTEXTRECORD p3,
                             PVOID pv )
{
  // handle interesting exceptions
  switch( p1->ExceptionNum ) {
  case XCPT_ACCESS_VIOLATION:
  case XCPT_INTEGER_DIVIDE_BY_ZERO:
  case XCPT_INTEGER_OVERFLOW:
  case XCPT_PROCESS_TERMINATE:
  case XCPT_ASYNC_PROCESS_TERMINATE:
    // setjmp() will return p1->ExceptionNum
    longjmp(p2)->jmp, p1->ExceptionNum );
  }
  // not interested; system should continue search
  return XCPT_CONTINUE_SEARCH;
}

// -------------------------------------------------------------------------
// example of an exported driver function; return TRUE upon success
LONG _System ExportedDriverFunction( PVOID p )
{
  REGREC        regrec;
  ULONG         ulException;
  LONG          lResult;

  regrec.pfnHandler = (PFN)DriverHandler;
  DosSetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );

  // get thread state; normally rets 0, rets non-zero after longjmp()
  ulException = setjmp( regrec.jmp );

  if( ulException ) {
    // an exception occurred
    // clean up here: release memory, semaphores
    // must check for exiting thread case
    switch( ulException ) {
    case XCPT_PROCESS_TERMINATE:
    case XCPT_ASYNC_PROCESS_TERMINATE:
      // thread is ending or being terminated
      DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );
      DosExit( EXIT_THREAD, 0 );
    }
    WinSetErrorInfo( ... );
    lResult = FALSE;
    goto depart;
  }

  // do the work of the exported function here

  lResult = TRUE;

depart:
  DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );
  return lResult;
}

Using Macro Assembler Instructions

Presentation drivers never use the CLI and STI macro assembler instructions because these instructions can interfere with some of the base OS/2 system operations.

Protecting Objects or Device Contexts

A process that attempts to use a locked object will return an error such as PMERR_HDC_BUSY. Although a device context is owned by a single application or process, the owner can access the device context (DC) through multiple threads. The presentation driver must provide a mechanism whereby a DC can register that it is busy and block access from other threads. In its simplest form, this is performed by the EnterDriver and LeaveDriver routines, which are called at the start and end of each function-handling routine in the presentation driver.

An example of a typical EnterDriver routine for a display driver is as follows:

 /***************** Typical EnterDriver Routine ***********************/

enter_driver()
{
 do {                /* Lock DC for exclusive use of the current thread */
   SemEnter(Device); /* Some functions do not pass a Device Context (DC)*/
                     /* handle  */
   if (hdc == NULL)
       return(SUCCESS);  /* Check validity of the passed DC handle */

   if (hdc == ERROR) {
       WinSetErrorInfo (SEVERITY_ERROR, PMERR_INV_HDC);
       SemLeave(Device);
       return(ERROR);
                       }  /* DC region must be validated before */
                          /* driver draws into it.              */

   if (hdc_is_not_dirty)  /* Test the HDC_IS_DIRTY flag. */
                          /* If the flag is set, the DC         */
       return(SUCCESS);   /* must be recalculated by the system */

   SemLeave(Device);      /* Unlock DC.  Call back to engine    */
                          /* to force DC calculation.           */

   VisRegionNotify(hdc);  /* Loop back to reset lock and recheck*/
  }  while (TRUE);
 }

Changes to the Graphics Engine

In the Presentation Manager for OS/2 2.1 and previous versions, a presentation driver had to support more than 70 functions. In addition, it was also mandatory that the presentation driver keep device-contextual state information and, in the case of display presentation drivers, run some functions at interrupt time.

The design of the graphics engine in OS/2 Warp, Version 3 focuses on taking the complexity out of developing a presentation driver while keeping the expandability and flexibility it was originally designed to have.

This graphics engine has two major changes from OS/2 2.1 and previous versions:

  • Device-independent functions merged into the graphics engine
  • System rasterization support (referred to as SOFTDRAW)

This design is intended to do the following:

  • Make presentation drivers simple and easy to develop
  • Allow developers to add functionality in increments
  • Move contextual and state management out of the presentation drivers
  • Move common rasterization management out of the presentation drivers

The following table identifies the support for the Presentation Driver Model that is available in various versions of OS/2.

OS/2 Release 16BPD 32BPD NMPD
Runs on OS/2 1.X X
Runs on OS/2 2.0, 2.1 X X
Runs on OS/2 Warp, Version 3 X X X

Note:

16BPD
Presentation Driver compiled as 16 bit
32BPD
Presentation Driver compiled as 32 bit
NMPD
New model of Presentation Driver