DDDR/2 - Distributed Console Access Facility (DCAF): Difference between revisions
No edit summary |
|||
Line 1,673: | Line 1,673: | ||
=== Typical Uses of DCAF === | === Typical Uses of DCAF === | ||
*View and control another PC | |||
*Control unattended PCs remotely | |||
*Support customers and provide help remotely | |||
*Diagnose and solve problems on another PC by modem or over a LAN | |||
*Transfer text and data between PCs | |||
*Run DOS, Windows and OS/2 on an unattended PC by modem or over a LAN | |||
*Remote Help Desk assistance for applications, online education, and maintenance of application programs. | |||
*Remote problem determination for trace and dump analysis, including file transfer of data. | |||
*Remote control of unattended workstations (for example, LAN servers). | |||
*Remote management of Personal System/2 (PS/2) workstations and accessibility to data and programs stored on a PS/2 (for example, in the home or in the office) | |||
*Remote access to system consoles when they are implemented on PS/2s. | |||
Here is a typical scenario of the DCAF Help Desk function: | Here is a typical scenario of the DCAF Help Desk function: | ||
*A target user is having difficulty understanding the company's new accounting program. | |||
*The target user contacts the Help Desk person who, in turn, opens a session with that particular target workstation. | |||
*With the target workstation accounting program on the screen, the controller (Help Desk person) switches to active state and types the correct keystrokes to run the accounting program. | |||
*The target user observes this process and learns how to use the new accounting program. | |||
*After demonstrating how to use the accounting program, the controller switches to the monitoring state and returns control to the target user. | |||
=== Understanding the DCAF Environment === | === Understanding the DCAF Environment === |
Revision as of 12:52, 25 April 2016
Distributed Console Access Facility (DCAF)
Seamless Windows support is provided in DCAF for installations that require remote console functions between programmable workstations. See Distributed Console Access Facility (DCAF)for specific information.
In OS/2 2.1, Seamless Windows is supported by allowing the Windows display driver to draw directly on the Presentation Manager (PM) screen. This means that Seamless Windows updates do not go through the PM drawing functions and, therefore, will not update the active screen change area (SCA) in the usual way. As a result, Seamless Windows requires special treatment.
Prior to drawing on the PM screen, the Seamless Windows driver calls the PM driver through an exported entry point, SeamlessExcludeCursor. This call excludes the PM cursor from the area in which the Seamless Driver is about to draw. The modified XGA display driver intercepts this call and passes the rectangle coordinates to AccumulateScreenBounds.
Under DCAF, during PM display driver initialization, Seamless Windows must be granted addressability to all data and code that it will access during the call to SeamlessExcludeCursor. In order to add the supplied rectangle to all active SCAs, which can reside anywhere in the display driver heap, there is a single, static SSA (Seamless Screen Area called scaSeamless) used for this purpose. All Seamless bounding rectangles will be accumulated in scaSeamless; then, this SCA is merged with the other active SCAs when a query is issued via GreGetScreenChangeArea.
As a result, at initialization (in InitializeSeamless), the Seamless Windows driver is given access to AccumulateScreenBounds, to scaSeamless and to the DDT display driver control block, in order to retrieve the screen dimension at seamless time. The addresses of this data are stored in the SeamlessAddresses control block, owned by the Windows driver.
Before writing to the PM screen, the Seamless Windows driver will call SeamlessExcludeCursor. The exclusion rectangle will be passed in the following registers in so-called AI coordinates (i.e., 16-bit inclusive; 0, 0 is top left of screen):
Left cx
Top dx
Right si
Bottom di
The display driver will determine whether the new bounds accumulation is needed by checking the value of the pStartSCA pointer and, in SeamlessExcludeCursor32, will call AccumulateSeamlessBounds to initiate the bounds accumulation. AccumulateSeamlessBounds converts the passed rectangle to EXCLUSIVE SCREEN coordinates, clips the rectangle to the screen dimensions and calls AccumulateScreenBounds. This causes the rectangle supplied to SeamlessExcludeCursor to be added to only scaSeamless. When an SCA is queried using GreGetScreenChangeArea, the Seamless SCA is merged with the active SCAs and then reset to NULL.
Seamless Design Issues
There are multiple design issues in the seamless environment. The critical issues (those generating the most questions), are documented in the following sections:
�Determination of code and data to be shared between the PM and Windows display drivers
�Coordination of off-screen video RAM
�Save/restore processing of the video hardware registers/environment
�Implementation of semaphore and heartbeatprocessing
�Conversion of Windows cursors and icons in the PM environment
�Palette handling
�Sharing of cursor exclusion and Enable/Disable code, including problems to be avoided
�Setup and sharing of a pointer to video RAM.
Each design of seamless PM and Windows driver pairsrequires its own shared data/code structure, because each driver implementation and its underlying video hardware are unique. The contents of the structure varies across implementations. The shared data/code structure for seamless XGA is included in the following example:
PMDD_IO_STRUC struc LevelID dd ? ; 4 bytes to sync interface to PMDD. ; The following variables are in the PM DD's default data segment. ulMemRegBase dd ? ; 16:16 addr of memory mapped XGA regs usIORegBase dw ? ; Base of IO XGA regs ulVramBase dd ? ; 32-bit physical memory addr of VRAM ulVramSize dd ? ; Size of VRAM in bytes bfUseExternalPolling db ? ; TRUE if external polling is supported usScreenWidthMM dw ? usScreenHeightMM dw ? usScreenWidthPels dw ? usScreenHeightPels dw ? bBitsPerPel db ? pSemaphore dd ? ; Flat pointer to FSRamSemaphore pHeartBeat dd ? ; Flat pointer to heartbeat counter pNumDefaultColors dd ? ; Flat ptr to # of default colors in use pCursorStatus dd ? ; Byte ptr: bit 0x80 set if sfw cursor pExcludeCursor dd ? ; 16:16 addr of exclude cursor function pDisableCursor dd ? ; 16:16 addr of disable cursor function pEnableCursor dd ? ; 16:16 addr of enable cursor function WindowsPrivateArea db WINDOWS_PRIVATE_AREA_SIZE dup (?) ;------------------------------------------------------------------ ; Information shared among the XGA Windows' drivers. ; Multiple Windows drivers can exist, running in multiple DOS sessions. ; SecondaryFontStart dd ? ; SecondaryFontEnd dd ? ; ; SystemFontTable dd 256 dup (?) ; SecondaryFontTable dd 256 dup (?) ; ; SystemFontHeight dw ? ; SystemFontPoints dw ? ; SystemFontWidth dw ? ; SystemFontCached db 0 ; ; SecondaryFontName db 0 ; db 32 dup (?) ; Max facename length=32. ; ; SecondaryFontNameLen dw 1 ; SecondaryFontHeight dw 0 ; SecondaryFontPoints dw 0 ; SecondaryFontWidth dw 0 ; ; SecondaryFontHdr db 32 dup(0) ; SystemFontHdr dw 16 dup(0) ; PaddedField db 32 dup(0) ; Remaining reserved. ;------------------------------------------------------------------ ; Total 2200 bytes reserved by the PM driver for Windows' drivers. bfPaletteIsFixed db ; TRUE if palette manager not enabled ulLastPalUpdate dd ; Timestamp of last foreground realize pHWPalette dd ; 16:16 ptr to HWPalette structure PMKWSPhysicalBase dw ; Physical addr of 64KB kernel workspace for ; bus-mastering into/out of system memory PMKWSLinearBAse dd ; Linear addr of 64KB workspace PMDD_IO_STRUC ends
The initial entry in this shared structure must be a driver signature. For XGA, the signature is XG01. For VGA, the signature is VG01. This field must be checked by the Windows driver at initialization. If an incorrect entry is found, the Windows driver must report initialization failure to the GDI. This mechanism prohibits the running of non-compatible seamless driver pairs (for example, using a VGA seamless windows driver with a Presentation Manager XGA driver).
Coordination of Off-Screen Video RAM
A static division of off-screen video memory is typically employed to permit access to this resource for both the Presentation Manager and seamless windows drivers. Alternatively, dynamic allocation or total dedication of the memory to one driver is used. However, these alternatives could decrease performance.
At a minimum, both the PM and seamless windows drivers' character caches are maintained in off-screen video memory for the sake of performance.
Save/Restore Processing of Video Registers/Hardware
A straightforward approach to save/restore processing is to force both the PM and seamless windows drivers to explicitly set video hardware registers anytime the registers are required. Since the video FSRamSemaphoremust be used to coordinate hardware access, this semaphore can be obtained, the necessary register(s) set and used, and the semaphore released with no problem.
An alternative approach is to design the necessary save/restore processing and mark the associated registers and resources with handles(such as SessionIDs).
Implementation of Semaphore Processing
Most 16-bit presentation drivers use the FSRamSemaphoremechanism to serialize output. This same mechanism is used by the PM and seamless windows drivers in the 32-bit environment. FSRamSemaphoresuse the drivers' data area to store the semaphore. Therefore, the Presentation Manager driver must establish the semaphore and provide its address to the seamless windows driver in the shared data/code structure. This logic flow is true for both the 16-bit and 32-bit environments.
In the 32-bit environment, there are new FSRamSemaphoreentry points, and 16-bit drivers now have alternative entry points. The new entry points have been optimized for efficiency. The following is a list of both the new and alternative semaphore entry points:
/-------------------------------------------------------------\ |New and Alternative Entry |Original Entry Points | |Points | | |------------------------------+------------------------------| |RAMSEMREQUEST16 |FSRSemEnter | |------------------------------+------------------------------| |RAMSEMCLEAR16 |FSRSemLeave | |------------------------------+------------------------------| |RAMSEMREQUEST32 | | |------------------------------+------------------------------| |RAMSEMCLEAR32 | | \-------------------------------------------------------------/
The semaphore entry points all have one parameter-a pointer to a FSRamSemaphorestructure. The structure contains the following fields:
usLength Length of structure usPadding usProcessID ID of owning process usThreadID ID of owning thread usUsage Usage counter usClient Client field, see note below ulTimeout System default timeout value ulRamSem Semaphore
Note:The usClientfield is the only field that, for normal processing, the presentation driver should access directly. This field is initialized as 0 when the semaphore is first acquired and thereafter is controlled by the driver. The intention is to give a DC some way of flagging a semaphore to notify the driver's ExitList processing routine of any special action it needs to take when releasing the semaphores.
The RAMSEMREQUESTxx functions return 0 if successful, and a nonzero error code otherwise.
The RAMSEMCLEARxx functions have no return information, and are void functions.
To support FSRamSemaphores, 32-bit Presentation Manager drivers must link with the OS2386 library, and 16-bit drivers must link with the OS2286 library.
To use FSRamSemaphoresfor coordinating hardware access, the seamless windows drivers must implement request_semaphore() and clear_semaphore() code logic. The purpose of request_semaphore() is to own the semaphore; clear_semaphore() relinquishes ownership.
When requesting the semaphore (if it is already owned by the current process), the semaphore's usage count must be incremented. If the semaphore is available, it is marked as owned by the current process. However, if the semaphore is owned by a different process, a call is made (indirectly) to the OS/2 kernel to block the thread until the semaphore is released. The mechanism for calling the OS/2 block_semaphore function is to issue an INT 66h to VWIN with some parameters passed through registers. VWIN then calls OS/2 block_semaphore on behalf of the seamless windows driver to wait on the specified FSRamSemaphore. The following code section illustrates how to acquire the FSRamSemaphore:
mov ax, _DATA mov ds, ax assumes ds , Data ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get our process ID and thread ID ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov cx , init _ struct . thread _ id ; Get the current thread ID mov dx , init _ struct . proc _ id ; and current process ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Get addressability to the hardware semaphore structure ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov di , PMDD _ IO _ SEL ; PM selector mov fs , di mov edi , init _ struct . pmdd _ io ; FS : EDI - > pmdd _ io struct mov edi , fs : [ edi ] . pSemaphore ; FS : EDI - > pSemaphore sem _ retry : mov ax , word ptr fs : [ edi ] . fs _ ProcID ; Touch the page cli mov ax , word ptr fs : [ edi ] . fs _ ProcID ; Is the semaphore owned ? or ax , ax jnz SHORT sem _ owned ; Yes , see if it is caller ? ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Here , if the semaphore is currently unowned , marked as owned by the ; current process ID and thread ID ; set the usage count to 1 and mark ; the RAM semaphore as SET . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - mov WORD PTR fs : [ edi ] . fs _ ProcID , dx mov WORD PTR fs : [ edi ] . fs _ ThrdID , cx mov ax , 1 mov fs : [ edi ] . fs _ Usage , ax ; Set usage count to 1 . mov fs : [ edi ] . fs _ RAMSem . RamSemOwner , al ; Set RAM semaphore . sti jmp SHORT request _ semaphore _ exit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Here , if the semaphore is currently owned . Check to see if current ; owner is the caller . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - sem _ owned : cmp ax , dx ; Is the semaphore owned by caller ? ; Essentially , pidOwner = = pidCaller ? jne SHORT sem _ owned2 ; No , go wait . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; If the semaphore is already owned by the current process ID and ; thread ID , then nothing to do but increment the usage count . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inc fs : [ edi ] . fs _ Usage sti jmp SHORT request _ semaphore _ exit ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; If the semaphore is already owned by some other process ID and ; thread ID , then perform an INT 66h to request the VDD ( VWIN ) ; to call the CPDOS RAM Semaphore mechanism on our behalf . When ; it returns , jump back to the beginning of this function to try ; to get the semaphore again . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - sem _ owned2 : sti ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; Block this thread until the semaphore is available . ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; AH = 82H ( Function Code for VWIN ) xor ax , ax mov ah , VWIN _ SEM _ BLOCK ; Block for semaphore function ; ECX - > Semaphore timeout mov ecx , fs : [ edi ] . fs _ Timeout ; EBX - > CPDOS RAM Semaphore ; Thunk the high word of the 32 - bit offset in esi into 16 : 16 addr in ebx ; ie , multiply high word by 8 and set the LS 3 bits on . lea esi , fs : [ edi ] . fs _ RAMSem shld ebx , esi , 19 or bx , 7 shl ebx , 16 mov bx , si ; Set DS : SI to " VWIN " mov si , OFFSET vwin _ id ; Block on the semaphore pushf call DWORD PTR init _ struct . pfvwin ; * * * * int 66h jmp sem _ retry ; Go back and try to get it request _ semaphore _ exit : mov edi , Heartbeat inc DWORD PTR fs : [ edi ] ; Increment the heartbeat counter . . . . .
When clearing the semaphore, the seamless windows driver should decrement the FSRamSemaphore's usage count. When this usage count reaches 0 (after decrementing), the semaphore's RamSemFlagfield is saved, and then the entire semaphore structure is set as not owned. The saved RamSemFlagis checked (TRUE or FALSE) to determine whether any processes that are being blocked by the semaphore need to be unblocked. To unblock a requesting process, an INT 66h is issued to VWIN with the parameters passed in the appropriate registers. VWIN then invokes the OS/2 kernel wake_up function. The following code fragment shows how to clear the FSRamSemaphore:
mov ax, _DATA mov ds, ax assumes ds, Data ;--------------------------------------------------------------------- ; Get our process ID and thread ID ;--------------------------------------------------------------------- mov cx, init_struct.thread_id ; Get current thread ID mov dx, init_struct.proc_id ; and current process ID ;--------------------------------------------------------------------- ; Get addressability to the Hardware Semaphore structure ;--------------------------------------------------------------------- mov di, PMDD_IO_SEL ; PM selector mov fs, di mov edi, Init_struct.pmdd_io ; FS:DI -> pmdd_io struct mov edi, fs:[edi].pSemaphore ; FS:DI -> pSemaphore mov ax, fs:[edi].fs_ProcID ; Touch the page cli ;--------------------------------------------------------------------- ; See if semaphore is owned by calling process/thread ;--------------------------------------------------------------------- cmp fs:[edi].fs_Usage, 0 ; See if owned je SHORT sem_leavebad ; No, declare an error mov ax, fs:[edi].fs_ProcID cmp dx, ax ; pidOwner == pidCaller? jne SHORT sem_leavebad ; No, declare an error jmp SHORT sem_leaveok ; Yes, proceed sem_leavebad: sti jmp SHORT exit_clear_semaphore sem_leaveok: ;--------------------------------------------------------------------- ; Decrement the usage count ;--------------------------------------------------------------------- dec fs:[edi].fs_Usage ; Decrement the usage count jz SHORT release_sem sti jmp exit_clear_semaphore ;--------------------------------------------------------------------- ; Release the semaphore by setting the process ID and thread ID ; fields to 0, clearing the RAM semaphore and remembering if any ; other threads were waiting on the RAM semaphore. If not, re-enable ; interrupts and return. ;--------------------------------------------------------------------- release_sem: xor dx, dx mov word ptr fs:[edi].fs_ProcID, dx ; Clear pid mov word ptr fs:[edi].fs_ThrdID, dx ; Clear tid mov fs:[edi].fs_Client, dx ; Clear client mov fs:[edi].fs_RAMSem.RamSemOwner, dl ; Clear ramsemowner xor cx, cx ; Clear the cx register xchg fs:[edi].fs_RAMSem.RamSemFlag, cl ; and set it to the sem flag or cx, cx ; Is the sem being requested? jnz SHORT sem_waiting ; Yes, call wakeup sti jmp SHORT exit_clear_semaphore ;--------------------------------------------------------------------- ; Some other process/thread is waiting for this semaphore. Perform an ; INT 66h with the appropriate function, which will call the CPDOS ; wakeup code (done through the VDD) to unblock all of the waiting ; threads. Non-deterministic as to which one will actually get the ; semaphore first. The others will have to wait again. ;--------------------------------------------------------------------- sem_waiting: sti ;-------------------------------------------------------------------- ; Issue the INT 66h call to wake up any threads that are blocked on ; the semaphore. ;-------------------------------------------------------------------- ; AH = 83H ( Function Code for VWIN ) xor ax, ax mov ah, VWIN_SEM_WAKE ; Wake function ; Set DI:SI to "VWIN" mov si, OFFSET vwin_id ; EBX -> CPDOS RAM Semaphore ; Thunk the high word of the 32-bit offset in edit into 16:16 addr in ebx ; ie, multiply the high-word by 8 and set the LS 3 bits ON. lea edi, fs:[edi].fs_RAMSem shld ebx, edi, 19 or bx, 7 shl ebx, 16 mov bx, di ; Block on the semaphore. CX should contain the old RamSemFlag value. pushf call DWORD PTR init_struct.pfvwin ;**** int 66H exit _ clear _ semaphore : . . . . .
At times, the PM driver must free the video semaphore to continue processing. This might be required in the case of a DOS session failure when the seamless windows driver is the semaphore owner. Sample semaphore release processing is included in the following code fragment. It is important to note that, in freeing the semaphore, the PM driver's process ID and thread ID (PID/TID) must be placed in the semaphore structure.
VOID SeamlessForceSemRelease(VOID) { PTIB pThreadInfo; PPIB pProcessInfo; /***********************************************************/ /* Set the semaphore owner to be us. The changing of the */ /* semaphore owner must be atomic to avoid letting in any */ /* other threads. */ /***********************************************************/ DosGetInfoBlocks(&pThreadInfo, &pProcessInfo); // FSRDriverSem.ProcID = (USHORT) pProcessInfo->pib_ulpid; // FSRDriverSem.ThrdID = (USHORT) pThreadInfo->tib_ptib2->tib2_ultid; *((PULONG)&FSRDriverSem.ProcID) = ((pThreadInfo->tib_ptib2->tib2_ultid) << 16) | (pProcessInfo->pib_ulpid); /****************************************************************/ /* Free the semaphore. */ /****************************************************************/ while (FSRDriverSem.Usage != 0) { ReleaseDriverSemaphore(); } }
Implementation of Heartbeat Processing
For seamless windows drivers, the only heartbeat processing required is to increment the heartbeat counter in the PM and Windows shared data/code structure. This counter must be incremented after obtaining the video hardware semaphore and prior to accessing the hardware.
The counter is checked by the PM driver as part of its semaphore timeout logic. Upon a second timeout, if the semaphore owner is unchanged and the heartbeat counter also is unchanged, the Presentation Manager driver will assume that the DOS session is hung and try to force release of the video semaphore. The following code sequence demonstrates this processing logic:
/********************************************************************/ /* This function carries out PM Heartbeat Processing. */ /* It detects when the Windows driver has stopped while */ /* holding the semaphore and tidies up if need be. */ /********************************************************************/ VOID SeamlessHeartbeat(VOID) { HVDD hSeamlessVDD; ULONG ulReturnCode; /******************************************************************/ /* If seamless windows is not enabled, we do nothing. */ /******************************************************************/ if (fSeamlessEnabled) { /**************************************************************/ /* See if we are timing out for the second time with the same */ /* PID, TID, and heartbeat. */ /**************************************************************/ if ( (usHeartBeatPID == FSRDriverSem.ProcID) && (usHeartBeatTID == FSRDriverSem.ThrdID) && (ulHeartBeat == 0)) { /**********************************************************/ /* This is the second time we have timed out with the */ /* same PID and TID owning the semaphore and the heart */ /* beat has not changed. We must call VWIN to see if a */ /* clean up is required. */ /**********************************************************/ /**********************************************************/ /* Open the seamless VDD ("VWIN"). */ /**********************************************************/ ulReturnCode = DosOpenVDD("VWIN", &hSeamlessVDD); if (ulReturnCode != 0) { /******************************************************/ /* The DosOpenVDD call encountered an error of some */ /* sort! */ /******************************************************/ LogDosError(ulReturnCode); return; } /**********************************************************/ /* Send VWIN the timeout on semaphore signal. */ /**********************************************************/ ulReturnCode = DosRequestVDD(hSeamlessVDD, NULL, VWIN_HEARTBEAT, FSRDriverSem.ProcID, NULL, FSRDriverSem.ThrdID, NULL); if ((ulReturnCode == 0) || (ulReturnCode == 2)) { /******************************************************/ /* The return code indicates that we should clean up. */ /******************************************************/ SeamlessForceSemRelease(); /******************************************************/ /* Clean up other heartbeat stuff. */ /******************************************************/ usHeartBeatPID = 0; usHeartBeatTID = 0; ulHeartBeat = 0; } /**********************************************************/ /* Close the handle to VWIN. */ /**********************************************************/ DosCloseVDD(hSeamlessVDD); } else { /**********************************************************/ /* Just record the PID and TID of the semaphore owner and */ /* reset the heartbeat counter. */ /**********************************************************/ usHeartBeatPID = FSRDriverSem.ProcID; usHeartBeatTID = FSRDriverSem.ThrdID; ulHeartBeat = 0; } } }
Windows Cursors and Icons in the PM Environment
The Windows standard cursors (crossbar, arrow, etc.) have been converted to PM resources as part of the seamless VGA and XGA development. These resources are used, unchanged, by the PM driver. It is important to notice that when the cursor is over a seamless windows application, Windows cursors should appear, not Presentation Manager resources. The converted standard Windows cursors are provided as PM resource files.
Non-standard Windows cursors and icons are passed by the Win Shield component to the PM Shield and, ultimately, to the PM driver, for conversion when they are created by an application.
Palette Handling
Seamless palette management is achieved using the existing seamless components, hardware synchronization, and event-flow mechanisms. Currently, the Windows GDI component handles all palette issues, calling the Windows driver only to actually set the hardware registers. This processing must be modified for seamless palette management. to permit only palette realizations by PM, using the PM driver palette logic.
Note:PM Palette Management is actually a superset of Windows Palette Management in that PM must coordinate logical color table processing ( default palette) as well as permit palette changes by way of the Palette Management interface. There is so much similarity in the PM and Windows palette application calls and processing that permitting PM to process a Windows palette realization is quite straightforward.
The Windows GDI has been modified to request palette entries and changes through normal OS/2 GPI/GRE processing. Also, the color mapping of the 20 Windows system colors must be supported in the PM driver palette. This requires a remapping of the PM palette, moving the 20 Windows colors to the top 10 slots and bottom 10 slots of the physical palette. Remapping the PM palette involves moving entries such that the closest entry to the Windows default color is at the specified location. Later, a translation table is used by PM when the driver selects a "closest fit" color, using its algorithms. The result of the algorithms is run through the translation table to determine the selected color's actual palette location. This has a negligible effect (fewer than 50 clock cycles) on performance.
The key item is that seamless palette management can exist because the Windows and PM palette APIs, and associated functionality are so similar. In both Windows and PM, an application creates, selects, and realizes a palette (in that order). In addition, there is a concept of palette animation in both Windows and PM. Animation permits a palette entry's color to be changed quickly, without affecting the rest of the palette or redrawing the image. Therefore, all Windows palette manipulation can be requested through normal GPI/PMWIN APIs, with the exception of animation. Animation is even simpler. It can be handled directly by the Windows GDI once PM has defined the animateable palette slot and returned this information to GDI.
The most straightforward way to describe the design of seamless palette management is to look at the processing flow:
1.At PM seamless startup, a PM and Windows shared memory area is established and initialized. Several entries are added to this shared area for seamless palette management, as follows:
�FixedPMPalette (Boolean, indicating a non-Palette Management PM Driver)
-If the PM Driver is not palette-aware, the GDI will operate, assuming a fixed palette. This assumption is accounted for in the GDI code, since Windows drivers exist for fixed palette hardware.
-For XGA and SVGA, because the drivers incorporate palette management, the flag is always FALSE.
�TimeLastPalUpdate(timestamp of the last reorganization of the palette due to focus change and resultant realize request)
-When the focus changes and the application now in focus realizes, the entire palette is reshuffled. This invalidates the current GDI palette entries. The time stamp is a mechanism for the GDI to be instantly aware of this change.
Note:For simplicity, this could also be implemented as a counter.
�PtrPhysicalPalette (Pointer to a shadow of the physical hardware palette)
2.After Windows driver initialization, the GDI issues a Driver Control() call requesting the address of the data described above. (A Control() call is really the end result of an application deviceescape. The GDI is responsible for translating Escape() calls to Windows Driver Control() functions.) After this call, the GDI has addressability to all the necessary PM palette information.
The format of the Control() function is:
rc = Control ( lpDevice, SEAMLESS_PAL_INIT, lpInDate, lpOutData) where lpDevice = a long pointer to a data structure of type PDEVICE, the destination device bit map SEAMLESS_PAL_INIT = a word of value 6010 lpInData = NULL lpOut Data = a long pointer to a structure that contains: bfPaletteIsfixed ulLastPalUpdate pHWPalette (These are the palette-related entries in the PM/Windows shared data/code area).
3.In the course of normal seamless processing, if the GDI requires a hardware palette change, the GDI requests this change through PM's GPI/GRE, using the Windows and PM Shields. However, the GDI also issues a standard call to OEMSetPalettein the seamless windows driver. In this call, a null pointer is passed, instead of a pointer to a valid palette, to notify the seamless windows driver that a palette change has occurred through PM. In this case, the seamless windows driver updates only its private image copy of the palette, using the data pointed to by the 16:16 hardware palette address (pHWPalette) in the PM and Windows shared data/code area.
Note:The first 10 entries and last 10 entries of the palette in the shared data/code area are not exact matches to the static Windows** colors set forth by Microsoft**. They are the closest fitcolors available in the PM default palette. Therefore, these 20 entries must never be modified in the seamless windows driver private image.
When the palette address pointer in OEMSetPaletteis not NULL (that is, when a valid color table is passed), the seamless windows driver must update the video hardware palette as usual, as well as update its private image copy of the palette. This only occurs in seamless processing when a Windows application is animating the palette. It is important that the seamless windows driver first requests the video semaphore and then clears the semaphore after updating the hardware palette.
4.The Win Shield and PM Shield are responsible for forwarding all RealizePaletterequests to the Windows DOS sessions and Presentation Manager applications. These requests are received and processed as usual.
5.On a palette realization for GDI, the PM Shield returns the logical-to- physical mapping of the requested color table to the DOS session's Windows GDI. This information is obtained from the PM driver using a GRE call that is hooked by the PM driver - GREQueryPaletteRealization. When the PM Shield calls this function and passes a device context and a pointer to an array of ULONGS, the PM driver returns the mapping from the logical color table to the hardware palette in the ULONG array. Seamless operation requires no special flags or different processing.
6.There is one additional requirement in seamless Presentation Manager. In the Windows OEMUpdateColorsfunction, the seamless windows driver must add the hardware serialization code to its processing logic before performing any video hardware access. The video FSRamSemaphoremust be requested, and cleared upon exit of this routine. If this is not done, screen and font damage can occur.
As always, before requesting the video fSRamSemaphore, the seamless windows driver should check the hardware access state. If the driver is not enabled , the Windows driver should call Win Shield, requesting a repaint of the Windows Desktop.
Sharing Cursor Exclusion and Enable/Disable Code
Cursor exclusion or disable code is always required when software cursors are in use. The seamless windows driver must use the PM cursor routines. Even when hardware cursors are used, it is recommended that the PM cursor routines be called by the seamless windows driver. This enables the PM driver to accumulate bounding rectangles of modified areas of the screen to support applications such as remote help-desk screen access.
The example of a PM and Windows shared data/code area given previously for XGA demonstrates how cursor exclusion and enable/disable can be implemented .
That example includes the following entries in the shared structure:
pCursorStatus dd ? ; Byte ptr: bit 0x80 set if sfw cursor pExcludeCursor dd ? ; 16:16 addr of exclude cursor function pDisableCursor dd ? ; 16:16 addr of disable cursor function pEnableCursor dd ? ; 16:16 addr of enable cursor function
In this example, the seamless windows driver has the option of calling the PM cursor routines, but only when a software cursor is in use (by checking the CursorStatus byte). However, in the current XGA implementation, the seamless windows driver calls the PM routines whenever it requests the video FSRamSemaphore and the destination is the screen. (This enables the XGA PM driver to accumulate bounding rectangles of all screen windows.) The seamless windows driver calls the PM ExcludeCursor routine when a hardware cursor is in use, DisableCursor when a software cursor is in use, and EnableCursor whenever the video FSRamSemaphore is cleared and the destination is the screen. For XGA, the cursor exclusion rectangle coordinates are passed on the stack.
The PM cursor functions are accessed by a 16:16 address (entry point) that is exported by the PM driver. At this address is the PM thunk code and the call to the actual PM 32-bit cursor function. The thunk is not compiled but done by hand in the code itself. Sample code from the XGA PM driver is included in the following code fragment:
;----------------------------------------------------------------------- ; ; SeamlessExcludeCursor is the thunked entry point to eddm_ExcludeCursor. ; The exclusion rectangle is passed in the following registers in AI coords ; (that is, 0,0 is top left of screen). ; ; left top right bottom ; cx dx si di ; ;----------------------------------------------------------------------- align 4 _SeamlessExcludeCursor proc far ; If we are not using a software cursor, we can go for a ; fast exit. We know that the Windows driver always has ; fs set up to be the flat selector, so we use it here to ; access our 32-bit data. mov eax, offset FLAT:_cursor_data.cd_cursor_status test byte ptr fs:[eax], CURSOR_SOFTWARE jz short SEC_exit ; Save ds and es on the 16-bit stack. push ds push es ; Get the FLAT selector into ds and es. mov ax, SEG FLAT:_DATA mov ds, ax mov es, ax ; Before we start using esp and eip, we must disable interrupts. ; An interrupt can damage the top half of the registers ; because it thinks we are 16-bit. Touch all the pages we might ; access before disabling interrupts (a page fault is non-maskable ; and will re-enable interrupts). call SeamlessTouchPages cli ; Save ss:sp (that is, 16-bit stack) in ebx. mov bx, ss rol ebx, 16 mov bx, sp ; Set up the 32-bit stack. mov ax, SEG FLAT:_DATA mov ss, ax mov esp, offset FLAT:_SeamlessStack+SEAMLESS _ STACK _ SIZE ; Now on 32 - bit stack , ; save the 16 - bit ss : sp on the 32 - bit stack . push ebx ; Jump into the 32 - bit code , which will call the 32 - bit exclusion code . jmp far ptr FLAT : SeamlessExcludeCursor32 ret _ from _ exclude32 : pop eax mov dx , ax rol eax , 16 mov ss , ax movzx esp , dx ; Now on 16 - bit stack sti pop es pop ds SEC _ exit : retf _ SeamlessExcludeCursor endp
Note:
Interrupts must be disabled before setting and using esp and eip. This is done to prevent entering 32-bit interrupt handling code when the current task, the DOS session, is known to be 16-bit. In this case, the ip and sp pointers would be set for a 16-bit environment, not 32-bit.
All code pages that might be required by the execution of the shared seamless functions must be present in memory before disabling interrupts. A page fault cannot be taken while in the seamless shared code.
Care must be taken that an STI instruction is not included in the PM cursor routines when executed by a DOS session. Interrupts must remain disabled ( when executed by a DOS session) until returning through the thunk logic and being enabled.
Care also must be taken not to cause any ring transitions (from Ring 3) within the PM code executed from a DOS session. Therefore, there cannot be any operating system calls, etc. executed.
Set Up and Sharing of a Pointer to Video RAM
A shared pointer to video memory might be required in a seamless environment.
To establish the pointer in a 32-bit environment, the PM display driver calls PMDD.SYS (using DOSDevIOCtl) at initialization. The PM driver passes in the physical address of video RAM and its size, and gets back a Ring 2- or Ring 3-accessible linear address for the video memory. This address is then included and initialized in the seamless shared data/code area. VWIN handles the sharing requests necessary to access the pointer from the seamless windows driver.
To support the allocation of the global pointer to VRAM, the function AllocGlobalVRAM has been added to PMDD.SYS:
AllocGlobalVRAM - (Function 0x7E) Called via: DosDevIOCtl( pData, pParms, 0x7E, 3, hDev ) where: pData points to a ULONG in which the flat address to VRAM will be returned. pParms points to a structure of the following type: struct _PARMS { ULONG PhysicalAddress; ULONG Length; ULONG Flags; } PARMS; where: PhysicalAddress is the beginning of the video RAM. Length is the length of video RAM in bytes. Flags is a field of flags of which only the least significant bit is currently defined. If the first bit is set, the pointer returned will be shareable and can be used to access VRAM at any privilege level. If the first bit is 0, the pointer returned will be global and only accessible from Ring 0. All other bits are reserved and should be 0. (For the seamless environment, Flags should be 1.) hDev is the handle returned from a DosOpen call of the SINGLEQ$ device. Returns: 0 if successful, or a non-zero error code on failure.
As mentioned above, all addressability to the video memory for the seamless windows drivers is handled by VWIN. However, if additional PM processes also require addressability, they must issue an AccessGlobalVRAM call to PMDD.SYS. (Please note that the process that allocates the pointer does not require this AccessGlobal call. The AllocGlobalVRAM function performs all necessary processing to allow the calling process' access of video memory.)
AccessGlobalVRAM - (Function 0x7F) Called via: DosDevIOCtl( NULL, pParms, 0x7F, 3, hDev ) Where: pParms points to a structure of the following type: struct _PARMS { ULONG FlatAddress; ULONG Length; } PARMS; where: FlatAddress is a pointer that was returned from a previous call to AllocGlobalVRAM. Length is the length of Video Memory in bytes. hDev is the handle returned from a DosOpen call of the SINGLEQ$ device. Returns: 0 if successful, or a non-zero error code on failure.
PM Driver Calls to VWIN - Accessed via DOSRequestVDD
�Function = Pass initialization structure
HVDD = Handle of VDD (returned from DosOpenVDD) SGID = NULL ULONG = 0x000000C0 ULONG = Number of array elements PVOID = Pointer to array of SM_PMDISP structures ULONG = 0 PVOID = NULL typedef struct _SM_PMDISP { ULONG flOptions;/* BIT1 BIT0=xx ring level if BIT3=1 */ /* BIT2=0 for DATA BIT2=1 for CODE */ /* BIT3=0 for 16:16 BIT3=1 for 0:32 */ /* BIT4=0 for mapping BIT4=1 for */ /* passthru; if passthru, VWIN does */ /* not touch */ /* BIT5=1 to force linear addresses */ /* to match otherwise, 16:16 addrs */ are remapped in the DOS session */ /* BIT6 - BIT31 reserved (must be 0) */ ULONG ulLength; /* Length of the data in bytes */ union /* Pointer to the beginning address */ /* of shared memory structure */ { PVOID p16; /* for 16:16 (BIT3=0) */ ULONG p32; /* for 0:32 (BIT3=1) */ } Start; } SM_PMDISP;
�Function = Signal timeout of the hardware semaphore
HVDD = Handle of VDD (returned from DosOpenVDD) SGID = NULL ULONG = 0x000000C1 ULONG = PID to test/kill PVOID = NULL ULONG = TID to test/kill PVOID = NULL Returns 0 for "valid Seamless VDM PID/TID was killed" 1 for "valid PID/TID was not killed" (held by a PM driver) 2 for "non-valid PID/TID" (went away or is going away)
�Function = DOS session Dirtynotification (Send)
HVDD = Handle of VDD (returned from DosOpenVDD) SGID = -1 indicates broadcast; the PM display driver always broadcasts ULONG = 0x000000C2 ULONG = Function code to use for the interrupt ( 0x4001 or 0x4002 ) PVOID = NULL ULONG = Force Repaint ( 0 = NO, 1 = YES ) PVOID = NULL
Sends VWIN a DOS session Dirtynotification. This is used at PM death and resurrection to indicate to the DOS sessions to suspend drawing or resume redrawing and repainting.
�Function = Set VMOUSE Display Resolution
HVDD = Handle of VDD (returned from DosOpenVDD) SGID = NULL ULONG = 0x000000C4 ULONG = sizeof(VMSSIZE structure) PVOID = pointer to VMSSIZE structure ULONG = NULL PVOID = NULL typedef struct vmss_s { ULONG vmss_nb; // Size of structure, in bytes (36) LONG vmss_lMode; // Video mode (eg, 00h-13h, or -1) ULONG vmss_ulWidth; // Width of screen, in pels ULONG vmss_ulHeight; // Height of screen, in pels ULONG vmss_ulCellWidth; // Width of screen cells, in pels ULONG vmss_ulCellHeight; // Height of screen cells, in pels ULONG vmss_ulPtrWidth; // Width of ptr drawing size, pels ULONG vmss_ulPtrHeight; // Height of ptr drawing size, pels ULONG vmss_ulPtrUnitWidth; // Width of ptr drawing unit, pels } VMSSIZE;
Windows Driver Calls to VWIN - Accessed via INT 66h
�Windows DD - Initialization
Input: AH = 0x81 - VWIN_INITIALIZE DS:SI = "VWIN" CX = SIZEOF windd_init EBX = windd_init struc WINDD_INIT struc proc_id dw 0 ; (out) WinDD's process id thread_id dw 0 ; (out) WinDD's thread id pfvwin dd ? ; (out) VWIN's interrupt handler pmdd_io dd 0 ; (out) pointer to pmdd_io structure WINDD_INIT ends
Note:
After this initialization call, instead of issuing INT 66H, the seamless windows driver can call directly into VWIN's interrupt handler using the pfvwin function pointer, passed in the WINDD_INIT structure. If this mechanism is used, the seamless windows driver must first perform a "pushf" before calling VWIN's handler.
The pmdd_iofield is a pointer passed directly from the PM display driver. This pointer addresses a structure of values that are shared between the PM and seamless windows display drivers. The definition of this structure is set by the display driver pair. However, as noted above, the first four bytes of the structure must contain some type of signature value agreed on by the display driver pair.
Output: AX = 0... success n... failure code defined by VWIN
�Windows DD - Block on FSRamSemaphore
Input: AH = 0x82 - VWIN_SEM_BLOCK EBX = CPDOS RAM Semaphore ECX = Timeout value DS:SI = "VWIN" Output: AX = 0... success n... failure
Note:Most of the driver semaphore handling is at Ring 3. However, this exception (interrupt) is necessary because the seamless windows driver DOS session cannot make a kernel call. When the video hardware semaphore is in use, the Driver must block, and this requires a call to the kernel through VWIN.
�Windows DD - Wakeup FSRamSemaphore request
Input: AH = 0x83 - VWIN_SEM_WAKE EBX = CPDOS RAM Semaphore CX = old RamSemFlag value DS:SI = "VWIN"
Note:When freeing and resetting the FSRamSemaphore, the seamless windows driver first checks whether RamSemFlag in the semaphore structure is 0. If the flag is nonzero, the seamless windows driver must call INT 66h, VWIN_ SEM_WAKE. The RamSemFlag value before being reset is the "old RamSemFlag value".
Output: AX = 0. . . success (call cannot fail)
�Windows DD - Request hardware
Input: AH = 0x84 - VWIN_REQUEST_VVIDEO DS:SI = "VWIN" Output: AX = 0. . . success (call cannot fail; call will block until hardware is available)
Note:In seamless processing, three components share the video hardware. These are:
VVIDEO
PM
Windows
PM and Windows coordinate access to the hardware via a FSRamSemaphore. However, virtual video drivers do not have this mechanism available. A virtual driver is never sure when a DOS application is finished accessing the screen; therefore, this interrupt exists to signal to VWIN (which forwards the request to the virtual video driver) that the seamless windows driver needs hardware access. Before making the call, the driver must obtain the hardware semaphore. Upon return, the seamless windows driver is guaranteed exclusive use of the video. (This mechanism of obtaining the semaphore and checking with VVIDEO already exists in the PM Driver code and is not unique to seamless operation.)
�Windows DD - Notify that hardware is available.
Input: AH = 0x85 - VWIN_NOTIFY_VVIDEO DS:SI = "VWIN" Output: AX = 0. . . success (call cannot fail)
�Windows DD - Critical section processing
Input: AH = 0x86 - VWIN_WINDD_ENTERCRITSEC DS:SI = "VWIN" Output: AX = 0. . . success (call cannot fail)
Input: AH = 0x87 - VWIN_WINDD_EXITCRITSEC DS:SI = "VWIN" Output: AX = 0. . . success (call cannot fail)
Note:The enter/exit critical section calls can be nested and, therefore, must come in pairs. This interrupt usually is issued as part of INT 2Fh processing, when nonreentrant code is being executed. It requests VWIN to temporarily stop sending interrupts to the DOS session.
Device Escapes() from Win Shield and GDI to Seamless Windows Driver
�rc = Escape( hDC, SEAMLESS_ESC_INIT, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6000 - SEAMLESS_ESC_INIT nCount = 0 lpInData = Pointer to Win Shield "call-back" entry point lpOutData = NULL On Exit: rc = negative......Error rc = positive......Success
The SEAMLESS_ESC_INIT call is made by Win Shield at initialization time. On input, Win Shield provides the address of a call-back entry point. The seamless windows driver uses this entry point, in addition to passing a clip region, to cause an area of the Windows Desktop to be repainted. This function is used whenever the seamless windows driver is disabled but must write to the screen. Win Shield is responsible for accumulating the clip regions passed to it.
Note:
1.This call is made before the screen is enabled by the Win Shield via INT 2Fh.
2.The seamless driver must always invalidate the Windows Desktop when OEMUpdateColorsis called and the driver is in the disabled state. Miscellaneous translation table and color-mapping problems can otherwise occur.
�rc = Escape( hDC, SEAMLESS_ESC_ENABLE, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6002 - SEAMLESS_ESC_ENABLE nCount = 0 lpInData = NULL lpOutData = Pointer to hw_access On Exit: rc = negative......Error rc = positive......Success
SEAMLESS_ESC_ENABLE permits a Windows program to determine the current hardware state. The escape returns the address of the driver's internal variable, hw_access, which reflects the hardware state at any time.
�rc = Escape( hDC, SEAMLESS_ESC_EXIT, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6001 - SEAMLESS_ESC_EXIT nCount = 0 lpInData = NULL lpOutData = NULL On Exit: rc = negative......Error rc = positive......Success
Win Shield issues this call, requesting the seamless windows driver to reset its Win Shield call-back entry point. This is performed when the seamless windows DOS session is closing.
�rc = Escape( hDC, SEAMLESS_ESC_REQSEM, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6004 - SEAMLESS_ESC_REQSEM nCount = 0 lpInData = NULL lpOutData = NULL On Exit: rc = negative......Error rc = positive......Success
SEAMLESS_ESC_REQSEM requests the seamless windows driver to obtain the FSRamSemaphore on behalf of Win Shield.
�rc = Escape( hDC, SEAMLESS_ESC_CLRSEM, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6005 - SEAMLESS_ESC_CLRSEM nCount = 0 lpInData = NULL lpOutData = NULL On Exit: rc = negative......Error rc = positive......Success
SEAMLESS_ESC_CLRSEM requests the seamless windows driver to clear the FSRamSemaphore on behalf of Win Shield.
�rc = Escape( hDC, SEAMLESS_ESC_PALINIT, nCount, lpInData, lpOutData )
hDC = GetDC( hWnd ) nEscape = 6010 - SEAMLESS_ESC_PALINIT nCount = 0 lpInData = NULL lpOutData = Pointer to the start of the palette-related data in the PM and Windows shared data/code area On Exit: rc = negative......Error rc = positive......Success
SEAMLESS_ESCAPE_PALINIT permits the Windows GDI component to obtain the address of the palette-related data in the PM and Windows shared data/code area. There are three palette-related entries in this shared area, arranged in the following sequence:
bfPaletteIsFixed db ? ; TRUE if Palette Manager not enabled ulLastPalUpdate dd ? ; Timestamp of last foreground realize pHWPalette dd ? ; 16:16 ptr to HWPalette structure
Windows INT 2Fh Support
�Windows DD - Notify Background Switch
AX = 4001H CX = Seamless identifier "SM" DX = Seamless sub-function 0100H....disable hardware Write access 0101H....disable hardware Read/Write access
�Windows DD - Notify Foreground Switch
AX = 4002H CX = Seamless identifier "SM" DX = Seamless sub-function 0200H....enable hardware Write access 0201H....enable hardware Read/Write access 0202H....enable hardware Read/Write access and force repaint
Miscellaneous Windows Driver Information
�In addition to the enabled and disabled states, the Windows driver also can be in a Read-onlystate, for example, when the Windows driver is disabled, yet can legitimately transfer bit-map data from video memory to system memory.
These various states are normally used to optimize execution speed, based on the needs of the calling application.
When processing INT 2Fh/disable from the PM Display Driver, it is important for the Windows driver to remain disabled until notified (again, via INT 2Fh) by the PM driver. The PM driver is notifying of its death and resurrection. Alternately, if enabled by the PM driver but otherwise INT 2Fh disabled, then the Windows driver can optimize processing and enter the read-only state.
�The seamless windows driver must always check the hardware state before requesting the video FSRamSemaphore. If the hardware is disabled or in the "read-only" state, and the output destination is the screen, the driver should call Win Shield, requesting Win Shield to accumulate the screen areas (rectangles) requiring update.
There are two options when calling Win Shield for a repaint:
SEAMLESS_FORCEPAINT To cause the entire Windows desktop to be repainted. SEAMLESS_POSTPAINT To repaint the accumulated area collected by Win Shield.
�Normally, when a Windows session is switched to the background, its output is disabled. Then, when switched to the foreground, a repaint is forced, even if no modifications were made to the current screen. This is acceptable when running a full-screen Windows session. However, when running seamlessly, the PM Driver automatically saves the contents of the screen when it is switched to the background.
When Presentation Manager returns to foreground, the whole screen is restored (including the seamless windows). As a result, no refreshes from the seamless windows will be necessary unless the Windows program attempted a repaint while output was disabled. As a performance improvement, a repaint flag is implemented in Win Shield, which is set initially to FALSE. When the seamless windows driver is in the background, this flag is set by Win Shield to TRUE if any refresh of the screen is attempted by the driver (for example, if the driver calls-back to the Win Shield, passing a clip region). When the seamless driver is switched to the foreground, a repaint is forced only if the flag is TRUE.
�Errors have been observed in seamless windows due to the Windows driver's failure to account for being in the Disabled state. For example, damage to the Min/Max buttons for a seamless window was observed. This occurred because the Min/Max button conversion was performed in the DIBtoScreenfunction. In some scenarios, when this function was invoked, the seamless windows driver was disabled. In this case, the Windows driver could not process the DIBtoScreenand ignored it. However, when finally enabled, the driver was told only to do a block logical transfer (Blt) and not a DIBtoScreen. The solution was for the seamless windows driver to store a flag indicating that the button conversion had not been performed, and to process it at a later time, when enabled.
�The SaveScreenBitmapentry in the seamless windows driver should be disabled because the driver does not have full information of the Desktop when running seamlessly.
�The seamless windows driver must not issue any INT 10h calls.
�Previous seamless windows design assumed that the FS and GS registers were not modified once loaded. Under Windows 3.1 this is no longer a valid assumption. The seamless windows driver must save the FS and GS contents to global variables when FS and GS are initially loaded. Then, before these registers are used, the seamless driver should compare the contents to the global variables. If the contents have been modified, the registers must be reloaded.
�It is important to modify the virtual video device driver, as well as the PM and Windows drivers, to operate seamlessly. The virtual video driver, which normally traps all hardware I/O, must be modified to permit the seamless windows driver to access the hardware. If the virtual video changes are not complete, you will see the following error message box:
�ååå Error Message åååååååååååååååååååååååååååååååà � � � System does not support this session's video mode in � � a window. The program cannot continue running in a � � window. � � � �ååååååååååååååååååååååååååååå�
Seamless Testing
The essence of seamless windows testing is to run both OS/2 Presentation Manager and Windows applications together on the OS/2 Desktop. The tests should execute as many different Windows functions and options as possible, to stress the seamless drivers and environment.
The following situations and scenarios should be considered for seamless testing:
�Execute standard Presentation Manager and Windows functionality - move, resize, minimize, maximize and overlay windows of both PM and Windows applications. When minimizing, minimize to the OS/2 Desktop, to the Minimized Window Viewer and hide the applications. Open and close several PM and Windows applications.
When closing applications, exercise various mechanisms (close from the Window List, double click in the window's upper left corner, etc.). For the Windows applications, test within the same DOS session and in different DOS sessions.
�Use the Window List, mouse pointer and hot-key sequences (for example, Alt +Esc) to change window focus. Include full-screen, and DOS and OS/2 windowed sessions in some test scenarios.
�Verify application functionality - pull-down and pop-up menus, control keys, radio buttons, and so on. Are text font and positioning correct? Are valid colors displayed?
Actual Windows and PM applications should be executed to exercise seamless modifications.
A verification of Windows driver functionality can be obtained using the driver test routines from the Microsoft Windows Device Driver Kit. These tests should execute seamlessly.
�Drag both PM and Windows icons and move the cursor over the application windows. Test both hardware and software cursors if available. Exercise various bit map formats - device dependent (DDB), device independent (DIB) and run length encoded (RLE).
�Transfer data between Presentation Manager and Windows applications using the Clipboard and DDE.
�Exercise all supported hardware resolutions and bits per pels. A different set of problems may be detected at different resolutions and numbers of colors.
Three possible test scenarios are outlined below:
�Scenario A(Initial seamless verification):
Two passes:
-Pass One uses a single instance of Windows Clock on the OS/2 Desktop
-Pass Two has multiple instances
Active Sessions:
-Windows Clock
Move, resize, attempt both analog and digital display, overlay OS/2 folder icon view, clip by icon view, minimize, maximize.
�Scenario B:
Two passes:
-Pass One with one DOS session for both Windows applications
-Pass Two uses separate DOS sessions.
Exercise the outlined functionality by performing some tasks within an application, then change focus to the next application and continue to test , ultimately returning to the first application.
Active Sessions:
-PM - Jigsaw
Minimize, maximize, move, resize, overlay Windows applications, clip by Windows applications, play the game.
-Windows - Excel
Change fonts, copy data to Clipboard, resize, display chart, minimize, maximize, move, close, cut/paste, overlay PM and Windows applications, clipped by Presentation Manager and Windows applications, change height and width of cells, change colors in cells.
-Windows - Paintbrush
Select color, draw, fill, cut/paste, rotate, edit palette, view bit map, minimize, maximize, move, resize, clipped by and overlay other windows.
�Scenario C:
This scenario includes multiple focus changes between the various windows, and exercises hardware palette updates and switching to/from a full-screen session.
The functionality discussed (minimize, maximize, resize, clipping, etc.) should be exercised while changing focus and performing the session switches.
Active Sessions:
-PM - PalDisp
Display hardware palette for verification.
-PM - PalTest
Display bit map using PM Palette Management, and verify palette update.
-PM - Solitaire
Continuous play.
-Windows - ShowDIB
Display bit map using seamless windows Palette Management, and verify palette update.
-Windows - Clock
Analog and digital display.
-DOS Window - batch file in loop, text mode
Run batch file printing text messages, coded in an endless loop.
-DOS Full-Screen - graphics application
Run graphics application program.
Checklist for Palette Management Support
To enable current Windows driver palette management support in a seamless display driver, follow the steps below:
1.Make sure that the following structure is part of the PM-SL share data, that is, the PMDD_IO_STRUC structure defined in IPC.INC.
SL_PaletteData struc bfPaletteIsFixed db ? ;TRUE if palette manager not enabled. ulLastPalUpdate dd ? ;Time stamp of last foreground realize. pHWPalette dd ? ;16-bit pointer to HWPalette structure. SL_PaletteData ends
2.Add SEAMLESS_ESC_PALINIT function support in Windows entry Control ( lpDevice, Function, lpInData, lpOutData), do the following:
a.Claim the support of SEAMLESS_ESC_PALINIT when this function is being queried.
b.When Function = SEAMLESS_ESC_PALINIT, return the address of init_Struct- >pmdd_io.SL_PaletteData in the buffer whose address is in lpOutData.
This address, &(init_Struct->pmdd_io.SL_PaletteData), must be in 16-bit sel :offset format.
Note:
If init_Struct->pmdd_io is a 32-bit address of the PM-SL share area, you have to thunk the &(init_Struct->pmdd_io.SL_PaletteData) 32-bit address to 16-bit sel:off format, using the following algorithm:
sel = (high word of the 32-bit address * 8) | 7 off = the low word of the 32-bit address.
If this function is not implemented, or not correctly implemented, a General Protection Fault will occur.
3.Change Windows entry SetPalette() as follows:
if( lpPalette != NULL ) { a) Request_Semaphore(..) b) Update the hardware palette in exactly the same way as you do in regular Windows driver. c) Clear_Semaphore(..) } else { Update the private copy of the hardware palette image if there is one being kept in the data segment. }
4.Change Windows entry UpdateColors() as follows:
�Call check_hw_access() for HW_FORCEREADWRITE hardware state before any screen update.
�If check_hw_access() returns Success, call request_semaphore() as you do before all hardware access and clear_semaphore() after you are done updating the screen.
5.Change check_hw_access() in IPC.ASM as follows:
Add HW_FORCEREADWRITE as one of the possible values in AL when this call is made. Here is an example of code needed to add to check_hw_access():
check_hw_access PROC FAR ..... cmp al, HW_READWRITE ;Request for HW_READWRITE access? jnz check_forcereadwrite ;No, go check for HW_FORCEREADWRITE ;access. ..... check_forcereadwrite: cmp al, HW_FORCEREADWRITE ;Request for HW_FORCEREADWRITE access? jnz check_write_access ;No, go check for HW_WRITEONLY access. VWIN_ENTER_CRITSEC ;Turn off interrupts from VWIN. mov hw_virgin, HW_DOREPAINT ;Repaint when HW_READWRITE allowed. mov ax, SEAMLESS_FORCEPAINT ;Paint the whole VDM. call winshield_callback ; VWIN_EXIT_CRITSEC ;Turn on interrupts from VWIN. jmp check_exit_bad ;We are done. Exit. .... check_hw_access ENDP
6.Remarks
Values for symbolic names used above are as follows:
SEAMLESS_ESC_PALINIT equ 6010 ;Pass back address of 1st entry of the ;palette-related data in PM-SL share ;area. HW_FORCEREADWRITE equ 'F' ;Request R/W hardware state. If not ;available, ask winshield to do force ;repaint when the driver is once again ;allowed to draw the screen.
PM Palette Management Support
This chapter is a brief guide to Presentation Manager Palette Management. Palette support is an optional functionality that can be provided by a presentation device driver.
Introduction
If the driver does not, or cannot provide this functionality, it is simulated in the graphics engine. An application writer accesses palette function via Graphics Programming Interface (GPI) APIs.
The following topics are described:
�Palette Management Overview
�Color Support in OS/2 Version 1.3 - Logical Color Tables
�Palette Management Functionality
�Palette Management Conflicts
�XGA Support for Palette Management
-Terminology
-Default Palettes
-Realizing Palettes
-Seamless Modifications
-Dithering and BITBLTing
�Miscellaneous Palette Management Information
Overview
Palette Management is special code, enabling applications to specify exact RGB (color) values for a drawing or image on a particular device. The application's color requests are mapped as closely as possible to the actual colors available in the device's hardware color palette. When possible, the hardware palette is modified to provide the requested RGB values exactly.
Code supporting Palette Management is responsible for arbitrating the conflicting color requests that may occur between different applications running simultaneously. These conflicts arise when more colors are requested than can actually be physically displayed at one time, on the device.
For example, if applications request a total of 350 different RGB values, but the device supports only a 256-color hardware palette, then only a subset of the applications' color requests can be satisfied exactly. The Palette Management code must handle setting the hardware palette to satisfy the color requests, and mapping the remainder of the requests to the closest available color in the hardware palette. The application is relieved of the responsibility of managing its environment at the same time as ensuring that its color requests are satisfied to the best of the ability of the hardware.
Color Support in OS/2 Version 1.3 - Logical Color Tables
With OS/2 1.3, application colors can be specified by means of Logical Color Tables (LCTs), and their more powerful (but very dangerous) variant, the realizable Logical Color Table.
The use of Logical Color Tables to specify colors is limited. Although an application can request RGB color values, these requests are simply mapped to the default colors defined in the device's hardware palette. The color mapping is a nearest color search. The colors in the device's hardware palette are not modified. Consequently, the accuracy of colors obtained using Logical Color Tables is limited on devices which do not have a large number of default colors.
For example, an eight-bit-per-pel device has a maximum of 256 colors available. Such a device may have 20 to 30 red or orange shades defined in its default hardware palette. For most applications, this is an acceptable number. However, to display a sunset in varying shades of red and orange might require 150 different shades in the palette. This would not be possible with Logical Color Tables.
To address this problem in OS/2 1.3, the application used a realizable Logical Color Table. In this case, the application makes a GpiRealizeLCTcall, which forces the colors from the realizable Logical Color Table into the device's hardware palette, overwriting the default colors. This has the effect that the image created using the realizable Logical Color Table obtains the exact colors requested. However, the remainder of the desktop is repainted using a color mapping from the original default palette to the new colors in the device palette.
Unfortunately, some desktop objects (such as buttons, icons and bit maps created by other applications) do not repaint correctly. This is because these objects are "BLTed" to the screen, with no color conversion. Given this, it is strongly recommended that an application only make the GPIRealizeLCTcall when maximized, and then always restore the default palette before exiting.
Further limitations of realizable Logical Color Tables are that only one can be realized correctly at a time, and there is no method of arbitration. If a second application realizes a different Logical Color Table than a first application, the first application will draw with the wrong colors.
Lastly, it should be noted that the concept of Logical Color Tables has no corollary in Windows 3.0 or 3.1. Windows uses a Palette Management scheme as discussed in the preceding Overview.
Palette Management Functionality
This section describes the following:
Creating and Selecting Palettes
Creating and Selecting Palettes
A palette is created by passing an array of RGBs to the GpiCreatePalettefunction in a similar manner to creating a Logical Color Table. This call returns a handle to the palette created. This handle must be used to address the palette in all other related calls.
Unlike LCTs, palettes are global objects and are not confined to a particular presentation space. An application can create multiple palettes and use a different one for each of its tasks. Palette handles can even be passed between different applications to enable them to share the color palettes.
To start drawing with a particular palette in a Presentation Space (PS), the palette must be selected into the PS using the GpiSelectPalettefunction. This function associates the PS with the palette, and all subsequent color information is taken from the RGB values in the palette. The colors are addressed by an application in the same way as the colors within an LCT-by specifying indexes into the array of RGBs originally used to create the palette.
Realizing Palettes
If the Presentation Space being used is associated with a Direct Device Context (DC) such as the screen, then the application must call WinRealizePalette, passing the palette handle obtained in the GpiCreatePalettecall, before drawing using the palette. It is the WinRealizePalettefunction call that filters to the presentation driver to update the colors in the device's hardware palette. At this time, any palette/color conflicts that occur should be resolved.
Whenever the colors in the device's hardware palette are changed, a WM_ REALIZEPALETTE message is sent to every application. When an application that is using Palette Management APIs receives the WM_REALIZEPALETTE message, it should in turn call WinRealizePalette. The application uses WinRealizePaletteto re-realize every currently active (ie, realized) palette. In this way, WinRealizePaletteacquires information about the color requirements of the whole system and can resolve any conflicts.
WinRealizePaletteprocessing may cause a remapping of the colors that an application is using for an existing palette. This occurs as a result of another application realizing a new palette or as a result of a conflict. In this case, an indication will be returned to the application in one of the WinRealizePalettefunction parameters (pcclr). If pcclr is greater than 0, the application should invalidate its window and redraw its image to use the correct colors/color mapping.
For Presentation Spaces associated with Memory DCs such as bit maps, there is never a need to call WinRealizePalette. Memory DCs are not shared. Therefore, there can never be any palette conflicts. The application always gets the exact colors it requests (up to the limits of the bit map format).
Animating Palettes
If an application wishes to change the colors within its palette often and quickly, then it can use calls to GpiAnimatePalette. This function causes the colors within the application's array of RGBs and the device's hardware palette to change almost simultaneously. The call is filtered to the presentation driver in order to update the device's hardware palette. Changing both the application's colors and the device's palette simultaneously ensures that no repainting is required by the application. The image on the screen is updated by virtue of updating the underlying hardware palette.
To ensure that this process does not produce conflicts, a special flag is used when creating the palette. A palette entry can be marked PC_RESERVED, which indicates that the entry may be animated in the future. This prevents the PC_RESERVED palette entry from being shared with other applications. Therefore, the presentation driver can safely change the hardware entry without side effects in other applications.
BITBLT Conversions
As mentioned earlier, one of the problems with realizable LCTs is that there is no color conversion carried out during a BLT. Under Palette Manager, color conversions are automatically performed when "BLTing" between different color palette definitions in the source and destination. In this way, color consistency is maintained when transferring images between any LCT or palette combination by using a nearest color mapping.
Other Palette Operations
Other operations associated with Palette Manager include resizing palettes, changing the colors within palettes, deselecting palettes, and deleting palettes. Each of these operations is fairly straightforward.
Palette Management Conflicts
There are basically three types of conflict that can occur within a Palette Management system:
�The first type of conflict, and the easiest to resolve, occurs when different palettes are realized by various applications. In this case, the WinRealizePalettefunction (ultimately, the presentation driver) must choose which colors the device will display. If the device is capable of displaying all the colors requested, then there is no conflict. Otherwise, it must be decided which of the requested colors will be displayed exactly and which will be mapped to the nearest color. This conflict is easily resolved by giving priority to the palette associated with the application in focus. This ensures that the application with which the user is currently interacting, will get the exact colors it requests (up to the device palette color limit).
�The second type of conflict involves the relative priority of palette- aware versus Logical Color Table-based applications, when obtaining and using palette entries for drawing. An attempt is always made to grant the exact RGB color requests of a palette-aware application. On the other hand, the color requests of an LCT application are satisfied from the portion of the hardware palette designated as the "default palette". WinRealizePaletteprocessing degrades the number of colors in the default palette to grant the color requests of a palette-aware application. Potentially, the number of default palette entries can be degraded to the set of 20 OS/2 and Windows system colors. This situation is not corrected until the palette- aware application(s) stop processing WM_REALIZEPALETTE messages, as will be discussed in XGA Support for Palette Management - Realizing Palettes, below . Note that even on a focus change to the LCT application, the default palette remains degraded if a palette-aware application is processing WM_ REALIZEPALETTE messages.
�The third type of conflict derives from the second conflict. The manner in which Logical Color Tables are (and must be) handled affects how Palette Manager's default palette is defined. To understand this conflict, it is important to note that an LCT-based application is not limited to using only the colors in its logical color table. For example, an image composed of many colors may be BLTed to a PS associated with an LCT, perhaps specifying only 16 colors. The image is to be drawn using the nearest colors that are available on the device (defined by the device context associated with the PS). The image is not defined using the colors specified in the Logical Color Table. This is very different from BLTing to a PS associated with a palette. In this case, the colors in the image are mapped to the nearest colors available in the palette. In other words, if an application is using LCTs, there is no way of knowing exactly what colors will be used.
Palette Manager must ensure that there is always as wide a range of colors as possible in the default palette. This will in turn ensure that LCTs can be mapped to the nearest color with minimum color degradation. To further complicate the conflict, the entries in the device's hardware palette used to support LCTs (the entries in the default palette) must have physical indexes such that mixing default palette colors produces another default palette color (ie, mixing LCT-mapped colors produces another LCT-mapped color).
XGA Support for Palette Management - Terminology
The following sections address the XGA implementation of Palette Management .
Palette Manager for XGA is only implemented for systems supporting eight bits per pel (256 colors). At four bits per pel (16 colors), there are insufficient colors to make a Palette Management implementation worthwhile. At 16 bits per pel (64K colors), there are sufficient colors available to an application without requiring Palette Management.
To clarify the following discussion, it is necessary to define exactly what is meant by the following terms: Hardware Palette, Physical Index, Logical Palette, Logical Index, and Default Palette.
Hardware Palette:the array of RGBs that the physical device is displaying . It is the exact RGB values that the hardware's digital-to-analog converter uses when displaying each pel on the screen.
Physical Index:a value stored in memory (either video memory (VRAM) or system memory) which represents a single pel. A physical index stored in VRAM is an index into the Hardware Palette. The color information for each pel on the display screen is referenced by a physical index. By using this index into the hardware palette, a driver obtains the exact RGB value for the pel. A physical index stored in a system memory bit map is an index into whatever color information is associated with the bit map. This color information is defined by a Logical or a Default Palette.
Logical Palette:an array of RGB and mapping index pairs created by the device driver when defining a palette (as a result of a GpiCreatePalettecall). For each RGB in the Logical Palette, when the RGB is drawn to a direct DC, the corresponding mapping index is the Physical Index for the color (or nearest color) in the Hardware Palette. These indexes are generated when the Logical Palette is realized and are known collectively as the palette mapping. Note that a logical palette is not the same as a Logical Color Table.
Logical Index:an index into a Logical Palette. It is logical indexes that an application uses to address the colors within a Logical Palette that it has created.
Default Palette:an array of RGBs that specify the colors available for use by LCTs and LCT-based applications.
XGA Support for Palette Management - Default Palettes
The XGA solution for Palette Manager uses five default palettes. Each palette supports a different number of colors and can be distinguished by its size. The default palettes supported are the 256, 128, 64, 32 and 16 entry palettes.
Each default palette is designed to give the best possible range of colors for its size. For example, the 256 entry palette contains the colors used by the 8514/A display adapter in OS/2, Version 1.3. (This has proven to be a good palette for displaying color images and has become the standard for Presentation Manager 256 color bit maps and images defined using 256 color Logical Color Tables.) At the opposite end of the scale, the 16-entry default palette contains the standard VGA colors.
Which default palette is used in a presentation space depends on whether the device context associated with the PS is a Memory DC (a bit map) or a Direct DC (the screen).
Memory DCs
Color handling within a Memory DC is easy. There are never any color request conflicts because DCs are not shared, and bit maps can only be selected into one DC at a time. Therefore, only one application can be drawing into a particular bit map within the memory DC at a time. The color information associated with the bit map is inherited from whatever LCT or Palette is currently associated with the presentation space.
If the PS is using a Logical Color Table, the physical indexes in the bit map are indexes into the 256 entry default palette. This gives as broad a range of colors as possible for the application to use. (Remember that the colors used by an LCT application are not limited to the colors in the logical color table.)
If the PS is using a logical palette, then the physical indexes in the bit map are indexes into this logical palette. This means that the physical indexes are the same as the logical indexes used to draw into the bit map.
One important point to note is that because the color information within the bit map is obtained from the PS, changing the presentation space to be associated with a different logical palette (or switching between an LCT and a logical palette) actually changes the meaning of the indexes in the bit map.
Direct DCs
In a direct DC, the physical indexes stored for an image are indexes into the hardware palette. The hardware palette can be viewed as a combination of a default palette and a number of logical palettes.
At the "start of day" (that is, at power-on, when no Palette Manager applications are running and therefore no logical palettes are in existence ), the hardware palette contains the 256 entry default palette. This makes the best possible range of colors available to LCT applications.
Later, when applications are using logical palettes, any one of the smaller default palettes may be in use, leaving room in the hardware palette for color requests to support multiple logical palettes. For example, the hardware palette may contain the 128-entry default palette and (up to) 128 colors requested from several logical palettes. If the combination of logical palette color requests exceeds 128, the default palette must be reduced further in size to support these requests.
Using this scheme, a maximum of 240 colors in the hardware palette can be allocated to support logical palettes' color requests. The remaining 16 entries in the hardware palette are used for the 16 entry default palette, ensuring that LCT applications will always have available a sensible, minimum number of colors.
Note:The 16-color default palette can also be overwritten if an application creates its logical palette using the flag, LCOL_OVERRIDE_ DEFAULT_COLORS. When this flag is specified, the presentation driver should grant the full hardware palette to an application when it is in the foreground and when its color requests exceed 240.
The driver keeps track of which entries in the hardware palette are allocated to colors from logical palettes, using a set of flags associated with each hardware palette entry. These flags are stored in the fcOptions byte of the RGB2 structure of the hardware palette. (The XGA driver defines new flags in the high order nibble of the fcOptions byte. Doing this does not conflict with the system-defined fcOptions flags in the low order nibble.) Entries in the hardware palette that are allocated to logical palette requests are marked as PC_USED, while entries that are allocated to the default palette are marked PC_DEFAULT.
Each logical palette also keeps track of which entries it has been allocated using the its array of mapping indexes (known as the palette mapping, as discussed above).
The default palette is always divided in half when placed in the hardware palette. The two halves are placed at opposite ends of the palette leaving the central region for logical palette colors. This guarantees that logical mixes of the default colors, mapped to by LCTs, will always result in another LCT-mapped color. In other words, all the colors obtainable when using LCTs are in a closed set. This in an important aspect of the XGA Palette Manager implementation. For example, if this were not the case, a mix may result in an entry in the hardware palette that is allocated to an animating logical palette. This would be very dangerous!
The process of changing the default palette in use with a Direct DC, and allocating entries to logical palettes is described in more detail below under XGA Support for Palette Management - Realizing Palettes.
XGA Support for Palette Management - Realizing Palettes
Applications realize their palettes using the WinRealizePalettefunction. This function is passed to the graphics engine and onto the presentation driver through the RealizePalettedriver entry point. The driver returns values to WinRealizePaletteto indicate what actions are required to keep the system consistent. This makes the RealizePalettefunction the heart of the Palette Manager system.
Three values are returned from the driver's RealizePalettefunction to WinRealizePalette:
�Number of hardware palette entries changed. (A pointer to a ULONG, pcSlotsChanged, is passed as one of the function parameters).
�Number of logical palette mapping indexes changed. (This is the function's return value).
�Flag indicating that the default colors have changed. (A pointer to a set of flags defined as a ULONG, pflType, is passed as one of the function parameters. The flag, RP_DEFAULTSCHANGED, must be set to indicate a change in the default colors.)
The actions taken by WinRealizePaletteprocessing depend on the return values as follows:
�If the hardware palette is changed, WinRealizePalettewill invalidate any saved screen bits. (See the OS/2 Presentation Device Driver Referencefor details on saved screen bits).
�If the hardware palette is changed and the new logical palette is being realized in the foreground, WinRealizePalettewill send a WM_REALIZEPALETTE message to every application.
�If the logical palette mapping indexes are changed, the number of changed indices are passed back to the application to indicate that a repaint is required.
�If the default colors are changed, WinRealizePalettewill invalidate the entire desktop (forcing everything to be repainted).
When a logical palette is realized in the foreground (ie, the application making the WinRealizePalettecall has the focus), then that palette receives priority over any other palettes that were previously realized. To satisfy the color requests of the foreground WinRealizePalette, the driver should overwrite entries in the hardware palette that are allocated to other applications, if necessary.
If the hardware palette is changed, then all the palette mappings for the other logical palettes in the system are invalidated. The return value ( hardware palette entries changed in pcSlotsChanged) will trigger the WinRealizePalettefunction to send WM_REALIZEPALETTE messages to every other application. Each application will then re-realize its palette (in the background) and repaint if any of its palette color mappings differ from its previously realized mappings. As mentioned above, this is indicated by WinRealizePalette's return value.
When a palette is realized in the background (ie, the application making the WinRealizePalettecall does not have the focus), then the driver should not change any entries in the hardware palette that are already mapped by other logical palettes. The presentation driver must either modify hardware palette entries that are currently unused, modify the default palette size to make additional slots available, or locate nearest color matches.
When there are no unused entries in the hardware palette for either foreground or background WinRealizePalette requests, the size of the default palette currently in use is reduced. This makes additional hardware palette entries available to logical palettes. Obviously, the minimum default palette size is 16 entries.
A valid question to ask at this point is: "What do non-palette-aware applications do when they receive a WM_REALIZEPALETTE message?" Whenever a non-palette aware application receives this message, it is not expecting it and does not know how to process it. Traditionally, these types of messages are forwarded to the default window procedure for handling. In the default window procedure, the message processing for WM_REALIZEPALETTE makes a call to realize the default palette. This is not a signal, however, to the driver to actually realize the default 256-color palette. It is a signal that the driver uses to determine when to load the appropriately sized default palette and also to determine when to increase the default palette size. This is discussed in more detail below, but we first must understand how the default palette is established, loaded and decreased in size.
The XGA display driver has a number of default palettes, of varying sizes ( as discussed above), and the realization code is responsible for determining which is the appropriate default palette to use.
Actually realizing the default palette (or rather realizing the appropriate one of the default palettes) is extremely simple. The default palette is realized whenever the foreground application requests a "realize default palette" in response to the WM_REALIZEPALETTE message, and either of the following conditions is met:
�The default palette was not the last palette realized.
�The size of the default palette has changed.
To realize the default palette, the data is merely copied from the first half of the appropriate default palette structure to the start of the hardware palette, and from the last half of the default palette to the end of the hardware palette. (To ensure that mixing operations form a closed set, the default palette must occupy the extreme ends of the hardware palette). The data in the default palettes is preset, so that both the RGB data and the options field can be placed directly into the hardware palette structure.
A driver enabled for seamless operation also has to consider whether it needs to force additional Windows colors into the default palette, as detailed in XGA Support for Palette Management - Seamless Modifications, below.
It is easy to determine when to move from a larger to a smaller default palette. Simply, if a logical palette is being realized which requires more slots than are currently free in the hardware palette, and the default palette is not at its minimum size, then the presentation driver should move to the next smaller default palette. This process may need to be repeated if the smaller default palette still does not provide sufficient free slots to satisfy the logical palette's requirements.
Movement through the default palettes in the opposite direction (from smaller to larger) is not nearly as straight forward.
It is not enough to simply reinstate the 256-entry default palette as soon as the driver thinks that no logical palettes are in use, since the device driver has a very poor picture of when logical palettes are in effect. (For example, assume that an image is drawn on the screen using a logical palette, but that logical palette is no longer selected into any of the display drivers' presentation spaces, perhaps because a cached-micro PS was used. Then, even though the driver is still showing the image drawn with the logical palette, the driver is unaware that the palette is still active .) Therefore, the movement through progressively larger default palettes must be based on different criteria. It is designed to be closely tied to the driver's receipt of "realize default palette" requests.
Whenever XGA is asked to realize the default palette from a foreground application, it counts the number of unused slots in the hardware palette. If there were enough free slots the last time that the default palette was realized (to allow the next larger default palette to be used), and there are still enough free slots, then the size of the default palette is increased. (It may not always be the case, however, that the number of free slots remains unchanged. Some slots could have been taken by WinRealizePaletterequests from non-foreground palette aware applications. This is why there is a delay in increasing the default palette size.) Dependent on the number of free slots, the default palette size can be increased several times-until there are insufficient free slots to move to the next larger default palette, or until the maximum default palette (256 colors) is reached.
In order to prevent prematurely increasing the default palette size, whenever a logical palette is realized in the foreground, the value for "free slots the last time that the default palette was realized" is reset. This ensures that the next "realize default palette" request does not increase the size of the default palette.
If a call to realize the default palette in the foreground causes no increase in the default palette size, the XGA driver reports that there are no mapping changes, but that the hardware palette is changed. This causes the system to send WM_REALIZEPALETTE messages to all applications, and allows the driver to be notified of all logical palettes still in use. However, no repainting is needed since no color mapping changes are reported.
If realizing the default palette causes the default palette size to change, a flag is passed back to WinRealizePaletteto force a repaint of the entire desktop.
XGA Support for Palette Management - Seamless Modifications
Supporting seamless windows operation requires some redesign of the Palette Manager code. Briefly, the seamless windows modifications involve making the default Windows system colors available at all times. This is discussed in greater detail in Seamless Windows Support. In overview, seamless support requires the following changes to the Palette Manager design:
�The default palettes are modified so that the 20 Windows colors are moved to the first and last ten entries in the palettes. This modification does not update the default color entries to exactly match the 20 Windows colors , but moves the closest match to these colors to the top and bottom ten hardware palette entries. Also, the driver's search algorithms for the closest color match are not changed. After a color match has been calculated, a translation table is checked to determine if the location of the color has been modified due to seamless operation.
�The 32-color default palette is never used, since it does not contain the required 20 Windows colors. Therefore, the sequence of sizes for the default palettes in a seamless implementation are 256, 128, 64, and then 16 .
�Whenever the 16-color default palette (the VGA palette) is in effect, the four additional Windows colors are placed in the hardware palette in locations 8, 9, 246 and 247. The dithering algorithm (discussed below) is unchanged, and still behaves as if there are only 16 colors.
�Whenever a call to the presentation driver causes a change to be made to the hardware palette, a counter accessible to the seamless windows driver and Windows kernel is incremented. This allows the seamless windows driver and kernel to determine when their internal palette mappings are invalid. Both this counter and the hardware palette structure are part of the PM/WIN -OS/2 shared data area. Using the hardware palette structure, Windows code can determine the exact contents of the palette.
�The maximum number of colors available for a logical palette's color requests (without the application specifying the flag, LCOL_OVERRIDE_ DEFAULT_COLORS) is now 236.
XGA Support for Palette Management - Dithering and BITBLTing
The implementation of the dithering code in the XGA driver is simplified by the decision that only Logical Color Table-related requests are dithered. This is justified for two reasons:
�Applications that use logical palettes usually get the exact colors that they request. Therefore, dithering with logical palettes is not required.
�Dithering with an arbitrary set of colors (as is usually found in a logical palette) is a complex and time-consuming task. The loss in performance due to dithering would not balance the color quality gain.
Dither patterns used to satisfy LCT requests are made up of colors from the current default palette. There is a separate dither scheme for each default palette, specifically tuned to give the best dithering results and performance.
BLT (Block Logical Transfer) color conversions are done on the fly by the XGA's software drawing code. (The software drawing code is essentially a simulation of the XGA drawing hardware, and is used extensively within the XGA driver to avoid the performance costs due to the XGA hardware requiring access to arbitrary system memory). In the case of BLT color conversions, the software drawing code is used because the XGA hardware does not support these conversions. A performance gain is achieved using the simulation code over copying the data into a temporary buffer, converting it, and then BLTing it to its destination.
In all cases, the most accurate BLT conversion is always calculated. However, there are several instances when a conversion is not needed. This is true when converting:
�From a logical palette memory DC to a logical palette memory DC with the same logical palette.
�From an LCT memory DC to an LCT memory DC.
�From an LCT memory DC to an LCT direct DC when the hardware palette contains the 256-entry default palette.
�From or to a realizable LCT DC.
�From a bit map which is not associated with a DC.
The destination of the block transfer affects the color conversion scheme as follows:
�If the destination is an LCT direct DC, the converted colors are limited to those in the default palette currently selected into the hardware palette.
�If the destination is a logical palette direct DC, then the converted colors are limited to the colors mapped by the logical palette.
For example, an application might be BLTing from a color image in a memory DC to a logical palette direct DC. If the logical palette contains only shades of grey, then it is important that the image is converted to only those greys, even though other colors in the hardware palette may match the colors in the original image exactly.
As a simple optimization, the last conversion table used is cached and is reused if the next requested color conversion is identical. This saves having to recalculate the conversion table for each BLT. Even though only one conversion table is cached, this scheme is quite effective. For example , when the desktop is repainted, all the icons are BLTed to the screen in turn. Each will use the same conversion table resulting in a marked performance improvement. Obviously, the conversion table is invalidated if either the source or destination colors are changed.
Several operations are not supported in the XGA driver as such, but are simulated using the BITBLT primitive. These operations are SaveScreenBitsand RestoreScreenBits. Since the purpose of these operations is to save an area of the screen and restore it later, it is important that no color translation is performed during either the save BITBLT, or during the restore BITBLT. To accomplish this, a new option flag, BBO_NO_COLOR_INFO, is provided which informs the driver that color translation is not required on the BITBLT.
Miscellaneous Palette Management Information
�When an application defines a logical palette, it is assumed to be defined in priority order. In other words, entry 0 is the most important color, and subsequent entries are of decreasing importance. This means that the display driver should allocate hardware slots in order of the entries in the logical palette, rather than trying to match the most logical entries to physical ones. An extreme example of this is a palette with only two distinct RGB values in it, one in the first entry, and one in each of the other 255 entries, with no entry marked as PC_RESERVED or PC_NOCOLLAPSE.
If there is only one slot in the hardware palette, then this slot will be assigned the color of the logical palette's first entry only matching just one of the 256 entries, whereas the remaining 255 entries could have mapped to that same one slot, providing hardware backing for a much higher proportion of the logical palette. Although obviously contrived, similar situations can occur when the color table of an external bit map is used as a palette, where the color table is not subject to any prioritization of its entries.
�Although an application realizes a logical palette with entries in a specific order, the presentation driver does not guarantee that these logical palette entries are loaded into the hardware palette in this same order. In fact, as an optimization, the driver searches the current hardware palette for a match to a logical palette's color request and maintains the position/entry in the hardware palette, if a match is found. An application should not assume any particular hardware mapping order based on its logical palette definition.
�A degradation of the OS/2 desktop and LCT applications may occur when color tables from external bit maps are used as logical palettes. This occurs when an eight-bit-per-pel bit map actually uses far less than 256 colors, but the full 256 colors are used to define its palette. In this case, the Palette Management code will degrade the default palette to 16 entries, when (for example) only 64 distinct colors are used within the bit map. Ideally, a logical palette with only 64 entries should be defined, and the default palette degraded to only 128 (assuming that the default palette previously contained 256 entries).
�Although not specifically prohibited, it is strongly advised that palette operations are not performed via cached-micro presentation spaces. The problem from the display driver's viewpoint is that a cached-micro Presentation Space provides no continuity for the driver's view of the logical palette. The display driver is only asked to create its device palette when a logical palette is selected into a presentation space, and is then told to destroy its device palette when the logical palette is deselected from the Presentation Space (which for a cached-micro Presentation Space is normally very soon after it is selected). Consequently, if Palette Management functions are issued within cached- micro Presentation Spaces, the driver is continually creating and deleting palettes-even though the application has only created the palette once. In addition, this lack of continuity implies that palette animation within a cached-micro PS is impossible.
Distributed Console Access Facility (DCAF)
This chapter explains, in addition to the fundamentals of the Distributed Console Access Facility (DCAF), DCAF environment and its various components . It is important to understand this information if you are installing DCAF .
The IBM Distributed Console Access Facility (DCAF) product provides a remote console function that allows one programmable workstation, called a controllingworkstation, to control the keyboard and mouse input and monitor the display output of another programmable workstation, called a targetworkstation.
Operating States
The DCAF product has two main operating states: monitoring and active.
Monitoring State
When the DCAF session is in the monitoring state, the controlling- workstation user (hereafter referred to as the controller) sees a screen image of the target workstation's display. The target workstation user ( hereafter referred to as the target user) has complete control of the target workstation operations.
Active State
When the DCAF session is in the active state, the controller operates and controls the target workstation. The keystrokes typed by the controller are relayed to the target workstation and acted upon as if they were typed by the target user. The keystroke input and the resulting screen image are seen on both the controlling and target workstations.
During the active state, keystroke input from the target workstation is not accepted. However, if the hot key combination is enabled for the target workstation, the target user can invoke this key combination to regain control of the target workstation. The target user also can choose to change the session state (for example, from active to monitoring).
The controller can establish concurrent sessions with multiple target workstations and can access each session by switching to a different window . Multiple controlling workstations can be defined within the network, however, only one of them at a time can establish a session with any single target workstation.
The controlling and target workstations are connected by a communication link. [Artwork not shown]
The Sample DCAF Direct Connectionfigure above shows a direct connection between the controlling workstation and the OS/2 target workstation. Direct modem connections can be established between OS/2 workstations or between OS/2 controlling workstations and Windows Version 3.1 target workstations. [Artwork not shown]
The Sample DCAF Connectionfigure above shows a connection via a DCAF Gateway workstation that acts as an interface between the controlling workstation and the target workstations on a Local Area Network (LAN). Connections through the DCAF Gateway can be established from a DCAF controlling workstation to any kind of DCAF target (OS/2, DOS or Windows).
Benefits of using DCAF
Within a customer's network, DCAF's ability to monitor or control a remote workstation from a central site makes it a powerful tool for network management, network administration, network security, problem determination and diagnosis, and application assistance in the form of Help Desk functions.
This remote capability can save time and money, as well as increase the productivity of the administration and support personnel. Technical expertise can be centralized at the controlling site, reducing the need for highly skilled personnel at remote locations. Reduced operational requirements will decrease costs and allow for faster growth of distributed applications within the distributed intelligent workstation environment.
System management of a secure-session environment is streamlined and made easier with the location of the DCAF Security Administrator component at the controlling site. The DCAF secure-session security helps protect the customer's software assets because DCAF's logged connections create a security audit trail.
Typical Uses of DCAF
- View and control another PC
- Control unattended PCs remotely
- Support customers and provide help remotely
- Diagnose and solve problems on another PC by modem or over a LAN
- Transfer text and data between PCs
- Run DOS, Windows and OS/2 on an unattended PC by modem or over a LAN
- Remote Help Desk assistance for applications, online education, and maintenance of application programs.
- Remote problem determination for trace and dump analysis, including file transfer of data.
- Remote control of unattended workstations (for example, LAN servers).
- Remote management of Personal System/2 (PS/2) workstations and accessibility to data and programs stored on a PS/2 (for example, in the home or in the office)
- Remote access to system consoles when they are implemented on PS/2s.
Here is a typical scenario of the DCAF Help Desk function:
- A target user is having difficulty understanding the company's new accounting program.
- The target user contacts the Help Desk person who, in turn, opens a session with that particular target workstation.
- With the target workstation accounting program on the screen, the controller (Help Desk person) switches to active state and types the correct keystrokes to run the accounting program.
- The target user observes this process and learns how to use the new accounting program.
- After demonstrating how to use the accounting program, the controller switches to the monitoring state and returns control to the target user.
Understanding the DCAF Environment
DCAF offers two main levels of security, which limit users' ability to take over your target workstations. These levels, basic DCAF (or nonsecure) and secure DCAF, offer protection for your workstations to varying degrees. For typical nonsecure environments that deal with nonconfidential information, basic DCAF provides adequate protection. Secure DCAF is more complex and caters to environments, such as banks and insurance companies, that work with confidential material and require greater protection.
In order to be part of the DCAF environment, the workstations must have DCAF components installed.
The DCAF Components
Before you begin the installation, you should be familiar with the DCAF components. The role of each workstation in your network determines the component(s) you install on that workstation. All components, except targets, run on OS/2 workstations only.
You can install one or more components on the same workstation, but it is recommended that you install only the necessary components on each workstation. For example, on one workstation you might install a controller , on another, the gateway and LAN directory, and on a third, a target component.
The Controller
The controller enables you to control the keyboard and mouse input and monitor the display output of a target workstation. It enables you to transfer files between the controller and target.
The Target
The target runs on three kinds of operating systems:
�The OS/2target enables an OS/2 workstation to be monitored and controlled by the controller.
�The Windowstarget enables a Windows workstation to be monitored and controlled by the controller. The controller connects to the workstation whether it is operating in DOS full-screen mode or in a Windows graphic environment.
�The DOStarget enables a DOS workstation to be monitored and controlled by the controller. To install the DOS target, either create an installation package or use the CID method. Use the packager on an OS/2 workstation to create a DOS target installation package and then install the target on the DOS workstation.
In each case, the controller connects to the target directly if it is a basic DCAF target, or through a gateway if the workstation is secure.
The Gateway
The gateway links a controller with secure targets or with targets connected through an SNA backbone. The gateway always requires that you install a LAN directory on a workstation-any workstation-on the same LAN.
The gateway connects to all targets using the NetBIOS communication protocol. Therefore, install the gateway only in those parts of your network that use NetBIOS.
The gateway supports more than one session at a time so you probably need one gateway per logical LAN. To connect to secure targets, the gateway must be secure as well.
The LAN Directory
The LAN directory provides a list of the targets on a LAN that are available to the controller. When the controller connects directly with the targets via IPX/SPX, NetBIOS, or TCP/IP, the LAN directory is optional. When the controller connects with the targets through a gateway, the LAN directory is required.
Install one LAN directory per logical LAN. If you install more than one LAN directory on a logical LAN, give each a unique name.
The LAN directory also keeps a list that associates the workstation's physical address on the LAN with a nickname that makes the target name easy to remember. This list also enables the controller to find targets quickly. You can install the LAN directory on the target, gateway (if present), or on any workstation on the same LAN as the target.
The Security Administrator
The security administrator is necessary for secure DCAF only. It provides centralized maintenance of the databases for controllers, target access tables, secure target workstations, and security authenticators. Install one security administrator, typically on a controller, for your entire network if you are using secure DCAF. Safeguard this workstation from unauthorized access.
The security administrator keeps an encrypted database of authorized users, as well as an audit log file, EQNADMN.LOG. To be able to transfer security database files to the security authenticator, you must install either the security authenticator or a controller on the same workstation as the security administrator.
The Security Authenticator
The security authenticator is necessary for secure DCAF only. It authenticates sessions with secure targets. The security authenticator also gives access to secure targets based on security profiles for authorized controllers that it receives from the security administrator.
Install the security authenticator on an OS/2 target on the same LAN. Install it either on the security administrator workstation or on the secure OS/2 target workstation, so that it can receive security information from the security administrator.
If you install the security administrator on the LAN, you can install the security authenticator on the same workstation. Install at least one security authenticator for each logical LAN in your network.
The Packager
The packager is an installation aid only. It creates installation packages of DCAF components that you can install on other workstations. In addition, the packager enables you to prepare a component with the same personalization features to be installed in large numbers all over your network. Always install DOS targets using the packager.
The DCAF Network
The DCAF network includes the workstations that have DCAF installed and the communications that link them.
The Example of a Distributed Console Access Facility Environmentfigure, which follows, is one example of a basic DCAF environment. [Artwork not shown]
The DCAF workstations communicate with the following communication protocols:
- Advanced Peer-to-Peer Networking (APPN)
- Advanced Program-to-Program Communication or APPC); more specifically, Logical Unit Type 6.2
- Asynchronous (also called Asynchronous Communications Device Interface or ACDI)
- IPX/SPX (except for DOS targets)
- NetBIOS
- TCP/IP (except for DOS targets)
Controller Acommunicates directly with target E and with gateway B using switched asynchronous communication.
Controller Aalso communicates, via LU 6.2 over a Systems Network Architecture (SNA) network or backbone, through gateway Bto the targets on the LAN. The SNA backbone represents the part of the network that connects (via switched lines, leased lines, or satellite communications) host computers, communication controllers, and other computer hardware. Any connections over an SNA backbone must go through a gateway.
Controller Acommunicates directly with target Fvia LU 6.2. For LU 6.2 communications, the physical unit type for the controller, target workstation, and DCAF gateway workstation must be configured as a type 2.1 (PU2.1).
Controller Acommunicates via TCP/IP through a router with LAN directory Iand with target H.
Controller Acommunicates via IPX/SPX through a router with LAN directory Kand with target J.
Controller Acommunicates via NetBIOS directly with LAN directory Mand with targets L, N,and Oon the LAN.
OS/2 target workstations on the LAN require that OS/2 Communications Manager, LAN Adapter and Protocol Support (LAPS) from NTS/2, or the LAN Server 2.0 be installed to provide the NetBIOS device drivers. In order to run DCAF with other applications that require NetBIOS services, you may need to increase the NetBIOS resources via the OS/2 Communications Manager or LAN Services.
DOS target workstations on the LAN require that a LAN support program be installed, such as the IBM LAN Support product. DCAF supports DOS target workstations on the LAN only.
Levels of DCAF Security
DCAF provides the following levels of security:
�Basic (Nonsecure)
-No password
-Password-only
�Secure
-Secure session
Basic (Nonsecure) Level
A no passwordsession exists between a controlling workstation and a gateway or target workstation for which a password is not defined and, therefore, is not necessary.
A password-onlysession exists between a controlling workstation and a gateway or target workstation for which a password is defined. The controller must type the password before the session can be established.
In both the no passwordand password-onlycases, the target component was installed as basic, or nonsecure. Basic DCAF provides adequate protection for nonsecure environments that deal with nonconfidential information.
Secure Level
Secure DCAF offers a higher and more advanced level of security for environments such as banks and insurance companies that work with confidential material. You can make a target workstation almost impregnable to intruders by designating it as a secure target. The controller must access the secure target through a secure gateway.
A securesession exists between a controlling workstation and a gateway or target workstation that has been installed as a secure gateway or target. These secure workstations do not have passwords. Instead, the controller, authorized to access a secure gateway or target, has a personal pass phrase (a compound password) and an access-level profile for a specific secure workstation.
DCAF security works with the following communication connections only:
�A controller can connect to a secure gateway via APPC/APPN or asynchronous .
�The secure Gateway can connect to a secure target via NetBIOS only.
The Example of a DCAF Environment with Session Securityfigure shows some workstations in a secure DCAF environment. The gateway can use only NetBIOS to communicate with the secure targets. Secure targets must be on a LAN ( see targets Cand Din the following figure.) [Artwork not shown]
Controller Acommunicates via secure gateway Bwith the secure targets on the LAN. When the controller wants to take over secure target C,security authenticator Dverifies that the controller is authorized to access that workstation.
DOS or Windows target Eon the LAN is not secure and does not require authentication. It has password-only security. Controller Acan also establish a session with secure target workstation F.Typically, the secure DCAF gateway, LAN directory, and security authenticator reside on target workstation F.In this case, controller Aconnects to gateway Fvia APPC, and gateway Fconnects internally to target Fvia NetBIOS.
The security administrator is typically installed on a controller workstation. It provides security file maintenance, a message log file, and control access information used by the DCAF security authenticators, all in a central location. Security files are transferred from the security administrator via a secure session to all of the remote security authenticators. Security administrator workstation Gtransfers new or updated security files to security authenticators Dand F.
When the controller wants to change a pass phrase, the security authenticator verifies the authorization before a session is allowed, and keeps a log file of the authentication activity. The verification compares the controller's input with the ciphered data stored on the security authenticator. The advantage of this mechanism is that there is no way to intercept or discover the pass phrase during transmission, because only the ciphered data is sent.
For auditing purposes, the gateway logs all session connections and the communication errors that it filters.
Entry Points from DCAF to OS/2 Presentation Manager
This portion of the chapter describes the additional entry points that implement the new capabilities of the XGA Display Driver in order to efficiently track the screen region that is updated by Presentation Manager drawing functions and to handle the related data.
Modifications to the XGA Display Driver fall into two distinct areas:
�Efficient accumulation maintenance and querying of clipped screen bounds of all screen drawing operations. This is provided by the following new functions:
-GreOpenScreen Change Area
-GreGetScreenChangeArea
-GreCloseScreenChangeArea
�Compression of data from a specified area of the screen into a memory buffer and, usually after transmission over network, decompression of that data into an internal memory bit map. This is accomplished by the following new functions:
-GreGetScreenBits
-GreSetScreenBits
Data conversion must be performed between the different modes (bpp) and the different data formats (planar or packed), in order to allow the data interchange between XGA and VGA, between XGAs working in different internal formats and, in general, between all the display drivers providing these entry points.
GreOpenScreenChangeArea
Description:
GreOpenScreenChangeAreaallocates a data area internal to the display driver, in which the driver will accumulate screen changes. GreOpenScreenChangeArea returns a 32-bit handle that is required to identify the area in GreGetScreenChangeArea and GreCloseScreenChangeArea calls.
Parameters:
HDC hdc
PDC pdcArg
ULONG FunN
Refer to the chapter regarding mandatory and simulated graphics engine functions in the OS/2 Presentation Device Driver Referencefor details on this function.
GreGetScreenChangeArea
Description:
GreGetScreenChangeAreatakes an SCA handle and, for the identified SCA, adds its rectangles to the region pointed to by the phrgnfield. The SCA is reset to NULL as a result of this call.
Parameters:
HDC hdc
HSCA hsca
PHRGN phrgn
PDC pdcArg
ULONG FunN
Refer to the chapter regarding mandatory and simulated graphics engine functions in the OS/2 Presentation Device Driver Referencefor details on this function.
GreCloseScreenChangeArea
Description:
GreCloseScreenChangeAreafrees the data area internal to the display driver , identified by the SCA handle, that was accumulating screen changes.
Parameters:
HDC hdc
HSCA hsca
PDC pdcArg
ULONG FunN
Refer to the chapter regarding mandatory and simulated graphics engine functions in the OS/2 Presentation Device Driver Referencefor details on this function.
GreGetScreenBits
Description:
GreGetScreenBitsqueries a region of screen pixel data and saves it in the memory provided by the caller. The data is compressed, and can be converted into a format suitable for another supported display device. The process will stop when either of the following situations occurs:
�The supplied memory area is full
�The requested region has been returned
Parameters:
HDC hdc
HRGN hrgnApp
PBYTE pDest
PULONG pulLength
ULONG flCmd
PDC pdcArg
ULONG FunN
Refer to the chapter regarding mandatory and simulated graphics engine functions in the OS/2 Presentation Device Driver Referencefor details on this function.
GreSetScreenBits
Description:
GreSetScreenBitstakes compressed data, generated by a previous call to GreGetScreenBits, from a buffer and decompresses it into the currently selected memory bit map. The call is only valid for a memory DC that has a bit map selected that is the same size as the screen of the machine on which the GreGetScreenBits call was performed. There is no clipping; if a rectangle exceeds the bit-map dimensions, the function will terminate immediately with an error logged. The bit map may be left in a partially drawn state as prior rectangles may have been copied into it.
The function may be passed a region handle, in which case the area defined by the set bits will be added to the region.
The XGA driver may be passed 4bpp planar, 4bpp packed, 8bpp packed and 16bpp packed data.
Parameters:
HDC hdc
PBYTE pBuffer
ULONG cBytes
HRGN hrgn
PDC pdcArg
ULONG FunN
Refer to the chapter regarding mandatory and simulated graphics engine functions in the OS/2 Presentation Device Driver Referencefor details on this function.
Code Modifications Required in Base Driver for DCAF
The majority of the new code is contained within new modules that are simply linked with the base driver. The areas of the base driver code that must be modified include the following:
�The Dispatch Table, which contains the new Entry Points
�All drawing functions, which contain extra tests to determine whether they should accumulate clipped screen bounds and, if necessary, code to calculate the clipped bounding rectangle
�Seamless Windows cursor exclusion code, which is modified to call the new bounds accumulation routine.
Dispatch Table
In the EDDEFLDB.C, where the dispatch table is filled in with the display driver entry points, the five new entry points are included in the Driver Dispatch Table with the following function numbers:
GreOpenScreenChangeArea 0x4012
GreGetScreenChangeArea 0x4013
GreCloseScreenChangeArea 0x4014
GreGetScreenBits 0x401D
GreSetScreenBits 0x401E
Accumulating and Querying Screen Bounds
TraditionalPresentation Manager bounds are unclipped, and use a single rectangle to define their limits. In order to better define the bounding area, the DCAF-enabled display driver now has the ability to maintain one or more clipped, multirectangle regions (Screen Change Areas or SCAs) that are updated to indicate areas on the screen that have been drawn to.
This ability is provided by the following changes to the base driver:
�Three new entry points or functions to create, query and delete Screen Change Areas, as follows:
-GreOpenScreenChangeArea
-GreGetScreenChangeArea
-GreCloseScreenChangeArea
�Two bounds accumulation internal routines, which add a single rectangle to all of the currently active SCAs.
�An extra flag test in the path of every display driver drawing function ( for COM_SCR_BOUND in the high-order word in the last parameter of the GreXX calls, FunN).
If this flag is set and the drawing operation is going to the screen, the drawing function passes a clipped bounding rectangle of the drawing primitive to the bounds accumulation functions described above. The code required to do this is driver-specific.
�Interception of Windows cursor exclusion calls and passing the supplied exclusion rectangle to the new bounds accumulation function.
Compressing and Decompressing Data
The bounding routines described above and under Performing the Bounding Accumulationefficiently track the regions on the screen that are updated by Presentation Manager drawing functions. The DCAF-enabled display driver also provides the ability to compress, decompress and, if necessary, convert the format of screen data.
This ability is provided by the following two new entry points or functions :
- GetScreenBits
- SetScreenBits
The task is performed by the internal routine CompressRect in COMPRESS.ASM. The compressed data that is passed between display drivers uses a private format (that is, no external application or program has the right to examine, alter or make any assumptions about the content of the data). This allows the compression method to be improved in later versions of the driver. Definitions of the data structures are as follows:
1.PACKET HEADER
dd total_data_packet_length (including header)
dw data_format
2.RECTANGLE HEADER
dw xLeft
dw yBottom
dw xRight
dw yTop
3.RECTANGLE DATA
The rectangle data is split into individual rows. Each row is split into run-length encoded blocks (cells), each of which comprises a length field followed by one or more data fields. The sizes of both the length and data fields vary according to the format of the data being transmitted (as specified by the data_format field in the packet header), as follows:
4bpp field size is one byte (8 bits)
8bpp, 16bpp field size is two bytes (16 bits)
The following encoding rules are used:
�If the length field contains a positivevalue (most significant bit notset), then the following single data field is repeated (length) times. If the data field size is 8 bits, this value will be limited to a maximum of 127.
�If the length field contains a negativevalue (most significant bit set), then (length - most significant bit) fields of nonrepeating data follow. If the data field size is 8 bits, this value will be limited to a maximum of 127.
�If the length field is zero and the following field is nonzero, the nonzero field is a count of the number of times that the single previous row is repeated. If the data field size is 8 bits, this value will be limited to a maximum of 127. This will only appear as the first cell in a row, and only after there has been at least onerow of data.
�If the length field is zero and the following field is zero, the next ( third) field is a count of the number of times that the previous pair of rows are repeated. If the data field size is 8 bits, this value will be limited to a maximum of 127. This will only appear as the first cell in a row, and only after there have been at least tworows of data.
The following example shows the hexadecimal values of an 8bpp compressed bitmap:
0003 0004 00FA 0405 0706 0802 0104 0903 0001 ........... 0000 0003 0000 0000 0004 ... lf df lf df df df df df df lf df lf df df cell1 cell2 celln celln+1
This bitmap would expand as follows (two-digit values represent a color index for a single pixel):
00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 ............ row1 do three more identical rows (celln): 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 ............ row2 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 ............ row3 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row4 do four pairs of identical couples ( celln + 1 ) : 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row5 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row6 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row7 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row8 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row9 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row10 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row11 00 04 00 04 00 04 04 05 07 06 08 02 01 04 09 03 00 01 . . . . . . . . . . . . row12
The following example shows the hexadecimal values of a 4bpp compressed bitmap:
03 04 FA 04 05 07 06 08 02 ........... 00 03 00 00 04 ... lf df lf df df df df df df lf df lf df df cell1 cell2 celln celln+1
This bitmap would expand as follows (one-digit value represents a color index for a single pixel):
0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row1 do three more identical rows (celln): 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row2 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row3 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row4 do four pairs of identical couples (celln+1): 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row5 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row6 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row7 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row8 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row9 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row10 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row11 0 4 0 4 0 4 0 4 0 5 0 7 0 6 0 8 0 2 ............ row12
Standard Golomb Run Length Encoding compression is inefficient at compressing 2x2 dither patterns, which are commonly used by Presentation Manager Display Drivers. The modified compression algorithm handles these patterns efficiently for the following reasons:
�For 4bpp and 8bpp, the data field size is such that, when a row is compressed, pairs of adjacent pels are put in each data field. Note that there is no dithering at 16bpp.
�When searching for duplicate scanlines, the algorithm also searches for duplicate scanline pairs that will match and compress patterns that repeat on alternate scanlines.
The actual pixel data is stored in Motorola format; that is, the most significant bits of a byte contain the leftmost pels. An example is shown below for a pair of pixels (PEL1,PEL2):
for the 4bpp format: - PEL1 goes in bits 7..4 - PEL2 goes in bits 3..0 for the 8bpp format: - PEL1 goes in bits 15..8 - PEL2 goes in bits 7..0
All 4bpp data is defined as indices into the standard VGA palette. All 8bpp data is defined as indices into the standard XGA palette. All 16bpp data is defined as XGA-format 16-bit color values. (See the appendix regarding default color palettes in the IBM OS/2 Display Device Driver Referencefor details of these formats).
All changed drivers must convert their own internal format into one of these standard formats before transmission. Refer to the section on Converting Datalater in this chapter.
Maintaining and Tracking Screen Change Areas (SCAs)
A key part of the modifications concerns the maintenance and tracking of SCAs.
SCA Definition
These areas track, as efficiently as possible, regions of the screen that are altered by display driver drawing routines. This tracking is done by using multiple rectangles to define the area, rather than the usual single bounding rectangle provided by traditionalPresentation Manager bounding functions.
SCAs are maintained within the driver in an SCA data structure, defined in the new DCAF.H file. For details, refer to the SCA data structure in the Appendixes of the OS/2 Presentation Device Driver Reference. Instances of this structure are dynamically created and destroyed upon calls to GreOpenScreenChangeArea and GreCloseScreenChangeArea, respectively. For details, refer to these functions in the chapter of the OS/2 Presentation Device Driver Referencethat discusses mandatory and simulated graphics engine functions.
A global variable, pStartSCA,points to the latest SCA instance created. If pStartSCAis null, there are no active SCAs. All SCA instances are linked together in a list using the pscaNextfield of the SCA data structure. A null value in this field indicates the end of the list (the earliest created SCA). For example:
Memory loc. ------------------- pStartSCA = 250; | pscaNext = 200 | | | | 4th SCA | 0x250 ------------------- ------------------- | pscaNext = 150 | | | | 3th SCA | 0x200 ------------------- ------------------- | pscaNext = 100 | | | | 2nd SCA | 0x150 ------------------- ------------------- | pscaNext = 0 | | | | 1st SCA | 0x100 -------------------
Each SCA instance can store multiple rectangles, up to MAX_SCA_RECTS (14), which define the area on the screen that has changed since the SCA was created or last queried. These rectangles are stored in the array arcl[]. The number of rectangles stored within the array is kept in the cRectsfield, which will never exceed MAX_SCA_RECTS. If cRectsis zero, the SCA is a null area - the initial state.
The remaining field in the SCA data structure, aulRectSize[],is an array containing the sizes of the rectangles in arcl[]. This is not strictly necessary, because the sizes can be calculated on the fly using the dimensions in arcl[]. However, when accumulating a rectangle into a SCA, the size of each of the rectangles is frequently needed. Caching the rectangle sizes in this array saves having to recalculate the sizes every time, resulting in better performance.
The SCA data structure defines space for (MAX_SCA_RECTS+1) rectangles, but only MAX_SCA_RECTS are ever used to define the SCA. The extra rectangle is used to simplify the routine that accumulates rectangles into the SCA.
Creating a new SCA
Creating a new SCA, accomplished by GreOpenScreenChangeArea (SCRAREA.C), requires the following steps:
�Allocate memory for the new SCA instance
�Set the cRectsfield to be zero
�Set the pStartScaglobal variable to point to the new SCA address
�Link the instance to the linked list of SCAs
The newly created SCA will be identified by a 32-bit handle, which is the address of the SCA location in the display driver.
Accumulating a Rectangle into an SCA
All display driver functions that draw to the screen are modified to accumulate clipped bounding rectangles into all active SCAs when necessary. The drawing functions determine whether they should do this by examining the FunN (Function Number/COM_ flags) parameter. If the COM_SCR_BOUND flag is set, and the function is drawing to the screen, then bounding rectangles are accumulated into the active SCAs; otherwise, no accumulation takes place. The setting of COM_SCR_BOUND is controlled by the GreOpenScreenChangeArea and GreCloseScreenChangeArea functions. For details , refer to these functions in the chapter of the OS/2 Presentation Device Driver Referencethat discusses mandatory and simulated graphics engine functions.
In every drawing call, the following test is performed:
if (DCAFBoundsRequired(FunN)) { accumulate the bound } where the DCAFBoundsRequired macro is defined in DCAFEXTF.H as follows: #define DCAFBoundsRequired(FunN) \ ( (FunN & COM_SCR_BOUND) && \ /* COM_SCR_BOUND is set */ (FunN & COM_DRAW) && \ /* COM_DRAW is set */ (pdc->DCIDCType == OD_DIRECT) ) /* the destination is the screen */
When change-area tracking is not needed, COM_SCR_BOUND will never be set. The difference in operation and performance of the DCAF-enabled base driver will be negligible-one additional check of the COM_SCR_BOUND flag per drawing function.
Performing the Bounding Accumulation
Two routines (in SCBOUNDS.C) perform the bounding accumulation:
�VOID AccumulateScreenBounds( PRECTL prclArgBound);
�VOID AccumulateScreenBoundsThroughClips( pDevRect pBoundCoords, ULONG ulCoordType );
AccumulateScreenBounds
This routine is called by GreSetPel and GrePolyShortLine, the drawing functions that are able to pass preclipped bounding rectangles. Its task is to take the passed rectangle and accumulate it into all the current SCAs. The passed rectangle is in exclusive SCREEN coordinates.
AccumulateScreenBoundsThroughClips
This routine takes the supplied (unclipped) bounding rectangle, intersects it with each of the clip rectangles in the DC and accumulates each of the clipped bounds into the active SCAs. The supplied bounding rectangle can be in one of the following types of coordinates:
16-bit AI coordinates (COORD_AI) Origin is top-left of screen
16-bit Device coordinates (COORD_DEVICE_WORD) Origin is current DC origin
32-bit Screen Coordinates Origin is bottom-left of screen
The ulCoordtypefield specifies which of these coordinates is being supplied.
AccumulateScreenBoundsThroughClips can be called from the same point in drawing functions as the ordinary (unclipped) bounds are accumulated. This minimizes the complexity and number of changes required in the main drawing code. Before accumulating the bounding rectangle, according to the following accumulation algorithm, the coordinate conversion (if required) to exclusive SCREEN coordinates and the clipping of the passed rectangle must be performed. The clipping can be done against the DC cache clip rectangles, or it may require a call back to the Graphics Engine to get the clip set. When a rectangle is added into an SCA, it is done in such a way as to minimize the increase in area of the SCA.
The following accumulation algorithm accomplishes this:
for (pscaCurrent = each SCA in the linked list) : : // First check whether the new rect is already contained within this SCA : for (rclCurrent = each rectangle in current SCA) : : if rclNew lies completely within rclCurrent : : : no more work - skip straight to next SCA : : endif : endfor : // We have to add the rectangle to the SCA. : // First see if there is free space for the rectangle within the SCA. : if pscaCurrent->cRects < MAX_SCA_RECTS : : copy rect into SCA : : calculate size and store in SCA : : increment pscaCurrent->cRects : else : : // All of the SCA rects are used. : : // Copy the new rect into the SCA at position (MAX_SCA_RECTS+1) and the : : // problem then becomes: : : // We have MAX_SCA_RECTS+1 rectangles, which we have to reduce : : // to MAX_SCA_RECTS by merging two of the rectangles into a single rectangle. : : // The pair of rects that we merge are the two that will cause the smallest : : // increase in area. : : initialize ulSmallestAreaIncrease to be maximum possible value : : for (iRect1 = each rectangle in the SCA) : : : for (iRect2 = iRect1+1 to MAX_SCA_RECTS+1) : : : // This inner loop is the performance bottleneck. : : : // Make it as fast as possible, if you can!! : : : : if area increase of (iRect1,iRect2) merged < ulSmallestAreaIncrease : : : : : set ulSmallestAreaIncrease to be area increase of (iRect1,iRect2) merged : : : : : set best pair of rects to be (iRect1,iRect2) : : : : endif : : : endfor : : endfor : : : : merge best pair of rects found into the slot originally occupied by Rect1 : : if rclNew was not one of those merged : : : copy rclNew into vacant slot made by merging pair : : endif : endif endfor
When change-area tracking is active, this routine is called by every function that draws to the screen. Therefore, the routine must be as efficient as possible (particularly in the inner loop) to minimize the hit on performance.
Deleting an SCA
This task is performed by GreCloseScreenChangeArea (SCRAREA.C), as follows:
�Unlink the SCA instance from the linked list of SCAs
�Free the memory for the SCA instance
In a typical example, if we close the second SCA:
Memory loc. ------------------- pStartSCA = 250; | pscaNext = 200 | | | | 4th SCA | 0x250 ------------------- ------------------- | pscaNext = 150 | | | | 3th SCA | 0x200 ------------------- ------------------- | pscaNext = 100 | | | | 2nd SCA | 0x150 ------------------- ------------------- | pscaNext = 0 | | | | 1st SCA | 0x100 -------------------
we will get:
Memory loc. ------------------- pStartSCA = 250; | pscaNext = 200 | | | | 4th SCA | 0x250 ------------------- ------------------- | pscaNext = 100 | | | | 3th SCA | 0x200 ------------------- ------------------- | pscaNext = 0 | | | | 1st SCA | 0x100 -------------------
If the last remaining SCA is being freed, pStartSCA is set to NULL. If the latest SCA created is being freed, pStartSCA is set to the address of the SCA created immediately prior to it (the previous SCA).
Converting Data
The changed display drivers use different internal data formats:
�VGA 4bpp planar
�XGA 4bpp packed, 8bpp packed, 16bpp packed
When data is transmitted between display drivers, it is done at the lower bpp of the two drivers (or at the lowest bpp; for example, a pair of 16bpp DCAF-enabled drivers could communicate at 4bpp to reduce the amount of data transmitted). Therefore, the following conversion routines are required by the display driver:
XGA (4bpp, 8bpp, 16bpp packed) internal format required format 16bpp packed -> 8bpp packed (compression) 16bpp packed -> 4bpp packed (compression) 16bpp packed -> 4bpp planar (compression) 8bpp packed -> 8bpp packed (compression) 8bpp packed -> 4bpp packed (compression) 8bpp packed -> 4bpp planar (compression) 4bpp packed -> 4bpp planar (compression) external data format internal format (decompression) 8bpp packed -> 16bpp packed (decompression) 8bpp packed -> 8bpp packed (decompression) 4bpp packed -> 16bpp packed (decompression) 4bpp packed -> 8bpp packed (decompression) 4bpp planar -> 16bpp packed (decompression) 4bpp planar -> 8bpp packed (decompression) 4bpp planar -> 4bpp packed
The conversions from packed to planar and vice versa are assisted by the use of a lookup table to split packed bytes into bits that can be conveniently reassembled into planar format (and vice versa).
All conversions to planar format are done by first converting the bits per pel to 4 (still in packed format) and then performing an optimized 4bpp packed-to-planar conversion. In conversions from 4bpp planar a similar, but reverse, process is performed- converting from 4bpp planar to 4bpp packed and then to the required packed destination format.
Conversions from 4bpp and 8bpp use a lookup table to efficiently translate the colors. Conversions from 16bpp cannot use a direct lookup table because the size is prohibitive. Therefore, colors have to be searched for on a nearest colorbasis in the destination color table. This is much slower than a simple table lookup. To improve performance, a cache of the most recently calculated colors is kept, which saves having to repeatedly recalculate commonly used colors.
Seamless Windows Support
In OS/2 2.1, Seamless Windows is supported by allowing the Windows display driver to draw directly on the Presentation Manager (PM) screen. This means that Seamless Windows updates do not go through the PM drawing functions and, therefore, will not update the active screen change area (SCA) in the usual way. As a result, Seamless Windows requires special treatment.
Prior to drawing on the PM screen, the Seamless Windows driver calls the PM driver through an exported entry point, SeamlessExcludeCursor. This call excludes the PM cursor from the area in which the Seamless Driver is about to draw. The modified DCAF-enabled display driver intercepts this call and passes the rectangle coordinates to AccumulateScreenBounds.
Under DCAF, during PM display driver initialization, Seamless Windows must be granted addressability to all data and code that it will access during the call to SeamlessExcludeCursor. In order to add the supplied rectangle to all active SCAs, which can reside anywhere in the display driver heap, there is a single, static SSA (Seamless Screen Area), called scaSeamless, used for this purpose. All Seamless bounding rectangles will be accumulated in scaSeamless; then, this SCA is merged with the other active SCAs when a query is issued via GreGetScreenChangeArea.
As a result, at initialization (in InitializeSeamless), the Seamless Windows driver is given access to AccumulateScreenBounds, to scaSeamless and to the DDT display driver control block, in order to retrieve the screen dimension at seamless time. The addresses of this data are stored in the SeamlessAddresses control block, owned by the Windows driver.
Before writing to the PM screen, the Seamless Windows driver will call SeamlessExcludeCursor. The exclusion rectangle will be passed in the following registers in so-called AI coordinates (i.e., 16-bit inclusive; 0, 0 is top left of screen):
Left cx
Top dx
Right si
Bottom di
The display driver will determine whether the new bounds accumulation is needed by checking the value of the pStartSCA pointer and, in SeamlessExcludeCursor32, will call AccumulateSeamlessBounds to initiate the bounds accumulation. AccumulateSeamlessBounds converts the passed rectangle to EXCLUSIVE SCREEN coordinates, clips the rectangle to the screen dimensions and calls AccumulateScreenBounds. This causes the rectangle supplied to SeamlessExcludeCursor to be added to only scaSeamless. When an SCA is queried using GreGetScreenChangeArea, the Seamless SCA is merged with the active SCAs and then reset to NULL.