The Window Server client-side buffer enables drawing functions to be buffered and executed in sequence. This saves many client-server context switches and makes the system fast and responsive.
The Window Server handles many application function calls as follows:
The client packages the information to send to the server.
A context switch to the server.
Processing in the Window Server—with possible inter-thread communication to and from the client.
A context switch back to the client.
This guarantees that operations are performed in the right sequence and that operations have been performed when control returns to the application program.
However, for drawing and many other function calls, this approach is too slow, and is not strictly necessary.
The overheads of the client/server communication swamp the time needed for drawing and cause severe system degradation.
It is unnecessary because the client program does not need a result from drawing functions. This is also true for some non-drawing functions.
Because of this, drawing functions, and other functions that do not need a synchronous response, are buffered by the client interface in a command buffer. When necessary, this buffer is flushed by a call to the Window Server, which executes all the drawing functions in sequence. Thus, two context switches are sufficient for an entire buffer full of drawing requests.
The Window Server buffer is flushed when:
It is full.
A function requiring a result is called.
One of the event-request
functions is called (RWsSession::EventReady()
, RWsSession::RedrawReady()
, RWsSession::PriorityKeyReady()
).
Certain high-level functions
are called by the client, such as CWindowGc::DrawPolyLine()
,
which involve mass data transfer which would overflow the buffer, and which
may fail.
An explicit RWsSession::Flush()
call
is made.
After any function call
if the RWsSession::SetAutoFlush()
auto flushing function
is set on.
It is desirable that the buffer is flushed when the application has finished
a unit of drawing. This is usually done as a natural consequence of calling
the function to wait for the next event from the Window Server. This covers
all cases where drawing is initiated in response to a Window Server event.
There are a few cases where drawing is initiated in response to other events.
In these cases, an explicit Flush()
call must be made.
The use of a buffer has two main impacts on drawing logic:
While debugging, client requests do not immediately result in screen updates. This can make debugging confusing at times.
If this is a problem, the application program can turn on auto-flushing, which causes flushing after each function call. The Uikon UI provides a hot-key, CTRL+ALT+SHIFT+F, to turn on auto-flushing. (The resulting degradation in performance is a convincing demonstration of the need for the buffer).
The GDI is so fast that most drawing activity that takes place within the context of a single flush appears as an almost instantaneous update. If, however, a drawing sequence is interrupted by a flush, there may be a perceptible delay. In some circumstances, this may result in flicker.
The aesthetics of a
program can be badly affected by flicker during drawing. Applications should
use flicker-free functions (such as DrawText()
with a rectangle),
and try to minimize flushing during critical redraw sequences. If completely
flicker-free drawing is impossible, short drawing sequences that are flush-free
may sometimes be an acceptable alternative.
The Window Server manages the buffer intelligently so as to minimize flushing. The opcodes stored in the buffer are short, and repeated use of the same graphics context is indicated by a single bit rather than repeated reference to the graphics context.
Applications may modify the size, or the maximum size of the buffer to tune performance or to accommodate long messages. A larger buffer may reduce flicker by collecting more drawing commands. A smaller buffer uses less memory. Setting a maximum size allows the Window Server to perform its own optimizations.
If a message is too big for the buffer, a panic (#5 - EW32PanicDataExceedsBufferLength
)
occurs. optimizations