OS/2's Multiple Video Alternatives

In theory, the OS/2 Kernel is for character mode and the Presentation Manager is for graphics, but in practice there's a way to do graphics under the Kernel and vice versa.

In my last column I discussed the VIO interface included in the OS/2 Kernel. OS/2 programs use the VIO functions for character mode video I/O. These functions are considerably faster than their equivalent functions in MS-DOS and the IBM PC BIOS, and they are nearly as fast as directly accessing the video memory buffer.

The VIO interface in the OS/2 Kernel is primarly intended for character mode: it has limited graphics support. Graphics support in OS/2 is instead part of the OS/2 Presentation Manager.

Ostensibly, then, programmers have a clear-cut choice between two environments under OS/2: the Kernel is for traditional character mode programs, and the Presentation Manager is for windowed graphics programs. A program running under the Presentation Manager uses the Graphics Programming Interface (GPI) for all graphics and text output. The Presentation Manager also includes built-in facilities that allow programs to implement a consistent and easy user interface very similar to that in found in Windows 2.0.

Yet this simple distinction between the Kernel (character mode) and the Presentation Manager (graphics) does not tell the whole story. Programmers can use graphics under the OS/2 Kernel and they can even use the VIO functions under the Presentation Manager. Let's take a look at these video alternatives.

THE OS/2 KERNEL AND GRAPHICS
The EGA43 program presented in last issue's column showed how to use the VioSetMode function to switch to the EGA 43-line mode. In the version of the OS/2 Kernel distributed with the OS/2 Software Development Kit, the VioSetMode function can also switch to a CGA or EGA graphics mode. Obviously, the retail version of OS/2 will also include VGA support, as well.

But after a program gets into a graphics mode, there is not much additional support in the Kernel to do anything with it. Unlike the PC BIOS character output functions, the OS/2 VIO functions do not translate text strings into graphics pixel patterns. When a program calls the VIO output functions while in a graphics mode, they basically write garbage to the screen.

The only real support in the OS/2 Kernel for graphics output involves the CGA graphics modes. If a program switches into a CGA graphics mode (320 by 200 with 4 colors or 640 by 200 with 2 colors), it can call VioGetBuf to get access to a 16K "logical buffer" that corresponds to the CGA graphics memory. It can draw graphics on this buffer and then update the real screen by calling VioShowBuf.

For the EGA graphics modes, however, VioGetBuf returns an error code. The basic problem is that the logical buffer for the EGA (640 by 350 with 16 colors) would have to be about 112K. For the VGA, it would be about 160K. And for the IBM 8514 adapter board, which operates in 1024 by 768 resolution with 256 simultaneous colors, the buffer would be almost 800K.

Clearly, we're talking about huge chunks of memory here. It wouldn't be quite so bad if only one graphics program were be running at any time. But the OS/2 Kernel supports multiple screen groups and would have to retain these large buffers when switching between screen groups. That simply becomes prohibitive.

But this doesn't mean you can't write an EGA or VGA graphics program that runs under the OS/2 Kernel It's just that it's not nearly as easy as using character mode.

HARDWARE ACCESS UNDER OS/2
In previous columns I've said that it is intolerable for individual applications to directly access the hardware under a multitasking operating system. This is, of course, the traditional assumption.

However, the OS/2 Kernel does not enforce this rule with rigid authoritarianism. In fact, the OS/2 Kernel includes several documented functions that do allow applications to access the PC's hardware directly. These are designed primarily to allow programs direct access to video adapter boards.

Doing this starts out fairly simply. A program calls the DosPortAccess function to get access to a range of I/O ports, and it calls the VioGetPhysBuf function to get selectors (segment addresses) for video memory. The program can then write to the video board I/O ports and memory just as it can under the non-protected DOS environment.

Well, not quite. One of the ways in which 80286 protected mode protects the integrity of the operating system is through four "privilege levels." Every code segment running under protected mode runs in one of these four privilege levels. The code with the highest privileges runs is level 0. In OS/2, level 0 is reserved for core Kernel functions. Most OS/2 applications run at level 3, the lowest privilege level. A code segment that accesses I/O ports must run at privilege level 2. (Level 1 is not used in OS/2.)

An OS/2 program that directly accesses machine hardware must contain at least two code segments, one running in privilege level 3 and the other running in privilege level 2. The level 3 code segment contains the bulk of the program; subroutines in the level 2 segment access the I/O ports of the video adapter board. A programmer can specify that this second segment runs in level 2 by creating a small "module definition file" that describes the attributes of the program's code segments. In this file, the level 2 segment is indicated by the keyword IOPL ("I/O Privilege Level"). LINK reads the module definition file when creating the program's .EXE file. The level 2 segment is flagged as such in the .EXE file so that OS/2 can give it proper privileges when the program is loaded into memory to run.

When a program calls a routine in a higher privilege level segment, the call passes through a "call gate" that changes the privilege level. (This process is transparent to the program.) These call gates allow transition only to a higher privilege level, such as a call from level 3 to a routine in level 2. The routine in level 2 can access the I/O ports and then return to the level 3 code that called it.

Most of the entry points to OS/2 Kernel functions are in level 3 code segments. Thus, the OS/2 Kernel functions can only be called from a code segment also running in level 3. This has a very simple implication: If a program has a code segment running in level 2, that code segment cannot make any calls to OS/2 Kernel functions. All calls to OS/2 Kernel functions must be from the program's other code segment, which running in level 3.

SCREEN GROUP SWITCHES
So far, these requirements are not particularly onerous. The programmer divides the program's code into two more more segments. The level 3 segment makes calls to the OS/2 functions VioSetMode to switch to a graphics mode, and DosPortAccess and DosGetPhysBuf to get access to the video adapter board hardware and memory. The level 3 segment then calls routines in level 2 to access the video adapter and do the graphics output.

But here's the problem: The OS/2 Kernel supports multiple screen groups. OS/2 must be able to switch away from the screen group running the graphics program. This could happen for several reasons: The user could switch to another screen group by pressing the Alt-Esc keys. A program running in the background may want to gain control of the screen by calling the VioPopUp function. OS/2 itself might need to use VioPopUp to report a critical error of the "abort, retry, ignore" variety.

When switching away from a screen group, OS/2 has to save the current state of the video adapter board and the contents of video memory. It has to restore these when switching back to the screen group. Normally, this is simple. The screen groups running in character mode use only a few kilobytes of video memory. OS/2 knows the state of the video adapter board because all changes to it have gone through the OS/2 VIO functions.

But when a program is directly accessing the video display hardware, this job becomes insuperable. In general, OS/2 cannot save the state of the video adapter board because most registers on the EGA are write-only. (Registers on the PS/2 VGA board are read-write, so that's a help.) OS/2 would also have to save the entire contents of video memory. For the EGA and VGA, this is 256K. After switching away from the screen group containing the graphics program, the program cannot be allowed to write to the screen because it would interfere with other programs. The program itself would have to be suspended, and for some applications this is simply not tolerable.

So, rather than attempt to do all this, the OS/2 Kernel shifts all this responsibility to the program itself. The program must save its own video state during screen group switches.

Here's where it gets hairy. A program that directly accesses video hardware must start up two additional "threads" of execution. (Threads are routines in the program that run simultaneously with the rest of the program.) One of these threads calls the VioModeWait function; the other calls VioSaveRedrawWait. These functions serve to notify the program when a screen group switch is about to occur. When the graphics program wants to write to the screen it calls VioScrLock to temporarily prevent screen group switches and VioScrUnlock to again allow screen group switches.

The key here is that the program is notified of imminent screen group switches when a thread returns from the VioModeWait or VioSaveRedrawWait functions. The program itself can then save the current video state and the contents of the video memory buffer. OS/2 can then switch away from the screen group without saving any part of the video memory.

If the program is running in the background and attempts to call VioScrLock to write to the screen, then VioScrLock can either return immediately with an error or not return at all until the program is once again running in the foreground. (The program specifies which of these two options is preferable.) This prevents the program from accessing the display when the program is running in the background.

Forcing the program to take the responsibility for saving the video state and memory during screen group switches has definite advantages. In most cases, the program knows best how to recreate the video display when the screen group is restored. For example, the program may be displaying a simple bar graph. The program has all the data it needs to recreate this graph. It's probably just a few numbers. In such a case, the program doesn't need to save the contents of the video display buffer at all: it can recreate the screen by redrawing the bar graph from the stored data.

All this stuff with multiple threads might sound incredibly complex (and it is), but the code involved is likely to be insignificant in comparison with everything else a program needs to do EGA and VGA graphics. Think of it this way: Normally, a multitasking operating system would not allow programs to directly access hardware. OS/2 allows it. This complexity is the price you pay.

But the real alternative to this complexity is to avoid doing graphics under the OS/2 Kernel at all. A program that needs to use graphics is better off taking advantage of the extensive graphics support built into the OS/2 Presentation Manager.

PRESENTATION MANAGER GRAPHICS
As of this writing (late September) only the specifications of the Presentation Manager have been distributed as part of the OS/2 Software Development Kit. Judging from the specifications (and other public information), the Presentation Manager is a graphical windowing environment that runs multiple programs. It has a look and feel very much like Microsoft Windows 2.0.

The Presentation Manager is composed of two major parts: a set of functions that give a program access to the various elements of the user interface (windows, menus, dialog boxes, scroll bars, etc.); and the Graphics Programming Interface (GPI).

GPI is hot stuff. It is derived in large part from IBM's mainframe Graphical Data Display Manager (GDDM) and is consequently much more sophisticated than any currently available microcomputer graphics system.

GPI is a device-independent graphics interface. A Presentation Manager application does not need to have its own drivers for each type of video board. GPI handles all that. GPI implements a system of "stored graphics" that allows a program to construct a graphics image out of a series of saved pieces. After an image is displayed, GPI has an automatic "hit-testing" mechanism that allows a program to determine what graphics primitive a user is pointing at with the mouse. The GPI drawing functions excel particularly in curved lines, including several ellipse functions, a spline function, and facilities to do parabolic, hyperbolic, and elliptical interpolations between points.

GPI is part of the Presentation Manager. A program that wants to use GPI must run under the Presentation Manager and use the various windowing and user interface functions. The structure of a Presentation Manager program (like that of a Windows program) is based on a message-passing architecture. For programmers whose previous experience is limited to traditional operating systems (such as MS-DOS and the OS/2 Kernel), there's a steep learning curve ahead.

Some people find that the messaging architecture of Windows and the Presentation Manager is an enormous improvement over the structure of traditional programs. For them, the graphics are icing on the cake. To other programmers, however, the messaging, windowing, and user interface aspects of Windows and the Presentation Manager are a curse that has to be endured in order to use the graphics.

Because the Presentation Manager runs in a graphics mode, it becomes responsible for dealing with the screen group switching problems I discussed above. In theory, the Presentation Manager doesn't have to save the contents of video memory when the user switches away from the Presentation Manager screen group. The Presentation Manager can restore the screen by sending "repaint" messages to all the individual programs running under it so they update their own respective areas of the screen.

ADVANCED VIO: TOPVIEW LIVES?
From the programmer's perspective, one problem with Windows and with the Presentation Manager is that all screen output uses graphics functions. Even if a program needs to display only simple monospaced text, the program must calculate line spacing increments to position the text correctly on the screen. Text output in a Windows or Presentation Manager program is generally more complex than text output from an OS/2 Kernel program.

However, the OS/2 Presentation Manager has an alternative to graphics text output. It's called "Advanced VIO" and it allows a Presentation Manager program to use the OS/2 Kernel VIO functions (discussed in last issue's Environments column) for text output.

When using Advanced VIO, the program requests a "presentation page" that contains a specific number of character rows and columns. This is a virtual screen and could be much larger than the actual screen. The program writes on this presentation page using the normal VIO functions. The program then specifies a row and column coordinate that the Presentation Manager uses to display a portion of this virtual screen within the program's window.

This concept might sound familiar. In fact, it is very similar to the video output interface in IBM's TopView. I thought that TopView died a long time ago during the "window wars," so I was particularly surprised to find the concept reborn in the Presentation Manager.

Advanced VIO reminds us again that the OS/2 Presentation Manager is a product of the IBM/Microsoft Joint Development Agreement. By any standard, a marriage between IBM and Microsoft has to be strange one and is likely to produce some mutant offspring. Advanced VIO - half OS/2 Kernel, half TopView--is certainly the oddest part of the Presentation Manager.

Table 1 presents a summary of the video output alternatives under OS/2. Bear in mind that the Presentation Manager always runs in a graphics mode. The text output from an Advanced VIO program is converted to graphics before being displayed on the screen. Advanced VIO simply gives a program a more convenient environment in which to output text.

CHARACTER MODE WINDOWING
In the months and weeks preceding the April 2nd announcement of OS/2 by IBM and Microsoft, rumors were flying about the new operating system. The most persistent rumor was that OS/2 would include a "character mode version of Windows." Just days before the official announcement, people I trust told me this was the truth. Some people apparently had actually seen the thing in operation. It looked like Windows, they said, but it ran in character mode.

The rumors were wrong. The only windowing environment in OS/2 is the Presentation Manager, which has a graphical interface.

But on April 2nd the Presentation Manager was far from ready for an actual demonstration. Instead, IBM showed off a silly-looking demo program that was supposed to simulate the operation of the real product. This mockup did run in character mode and looked like an ugly clone of Windows 2.0. Perhaps this demo was for the benefit of those people who had been asleep for the past 2-1/2 years and didn't know what Windows was. The demo let them poke at the screen with a mouse and see a menu drop down.

So the rumors did have a factual basis. People really had seen a character mode version of the Presentation Manager before April 2nd. They just didn't know they were looking at a phony demo. Rumors about a character mode windowing system for OS/2 refuse to die. Is there a possibility that OS/2 might someday run such a thing? Surely Advanced VIO leaves a door open. Any Presentation Manager program that uses only Advanced VIO for screen output could run without change in a character mode windowing system.

The single significant advantage of character mode is raw speed. Nothing else commends it. Character mode screens make inefficient use of space and have a much lower information density than graphics screens. Using a mouse is awful in character mode because the pointer skips around in character cell increments, and character mode is particularly ugly when windowing and color is involved.

Still, there's nothing to prevent a software manufacturer--not necessarily IBM or Microsoft--from developing a character mode windowing system that runs under the OS/2 Kernel. Some people see a real need for it. We'll see.