Professional Documents
Culture Documents
2 Developer’s Guide
Introduction
DfMirage is “cutting edge" video driver mirroring technology for the Windows NT OS family. It
is a driver for a virtual video device managed at the DDML level of the graphics system that
exactly mirrors the drawing operations of one or more physical display devices. A detailed
explanation of how a mirroring video driver works may be found in the Windows DDK. Display
mirroring technology is widely employed by remote desktop applications such as: NetMeeting,
PC Anywhere, VNC, Webex, etc. Mirroring is a technically superior method when compared to
primitive screen grabbing, because it allows the capture of only the minimally updated regions
and retrieves the data directly, bypassing the intermediate copy. Using the DfMirage driver
solves the problem of reliably and efficiently detecting modified areas on the screen. This driver
may be used transparently with office, CAD and other types of business and utility applications.
An example is the open-source TightVNC application which uses the DfMirage driver with great
success.
Installation
To setup the DfMirage driver, run MirageSetup.exe.
The underlying virtual display device uses plug-n-play technology, so the installation requires no
reboot. When the driver is installed, it appears in device manager as shown in the following
picture: http://www.demoforge.com/support/dfmirror-devmgr.png
To ensure that the installation was successfull run dfstudio-mirage.exe (this is a special build of
DemoForge Studio 2 which uses DfMirage driver internally) and the press the Record button.
You may then locate the file just recorded in your %TEMP% folder. This file may be played
back. It is rather large because it contains only raw, uncompressed data. If you compress it using
any modern archival software, you will see a considerable difference in size. You may also save
the recorded file to DML format to see the image data which has been captured by the mirage
driver.
Uninstallation
The uninstallation of DfMirage is fully supported. The uninstaller is registered with the
“Add/Remove Programs” applet of Control Panel.
Removing the device is a two-phase process. This is due to shortcomings within the Windows
system video port driver. Microsoft has promised to resolve this issue with the release of
Windows Vista. When the first phase is finished, the system must be rebooted. The 2nd phase
will automatically begin following the reboot, when any member of the local Administrators
group logs in. For a more detailed explanation of DfMirage setup considerations see the file
“Mirage\Setup\Installer\Guide.en.doc”.
Operating principles
The DfMirage driver tracks the minimal areas of screen update and enables the client software to
retrieve those updates directly (by means of the screen memory shared between the driver and
application). This method provides excellent results in terms of traffic and CPU usage, while still
maintaining its ease of use features. The Mirror driver follows the standard bi-component model
of NT video drivers. That is, it uses miniport and display driver modules. Miniport is a low-level
component. It represents a virtual video device. It is loaded by the OS IO manager and remains
in memory until the OS is terminated. The miniport device is inaccessible to user-mode code.
The display driver is loaded and unloaded on demand by changes in video mode. Basically,
when it is loaded and running, video mirroring takes place. The DfMirage driver maps its screen
surface into the user-mode application’s virtual memory space. Normally, the format and size of
the buffer corresponds exactly to the format and size of the primary screen surface. This is not
the case when its color format is overridden – (there is available, a registry-based switch for the
driver to enforce the fixed color depth of the mirrored screen surface). The mapping of memory
is performed via a file mapping object (or a “Section” using NT kernel slang). In this way an
application “sees” everything that’s being drawn on the mirrored screen surface, resulting in the
application’s ability to perform a direct copy of the modified screen area. It has but read-only
access to this buffer.
The driver provides an application with the ability to retrieve ONLY those areas, which are
modified, in spite of this, the entire screen buffer is always available to the application for read
access.
The user-mode application communicates with the DfMirage driver via the ExtEscape()
Windows API function. ExtEscape serves the role of an extensible escape hatch for the
Windows GDI as it allows the passing of custom or non-standard requests to the video driver.
There are a number of private escape codes defined by DfMirage. Escape function codes and
input/output structures are declared in display-esc.h (This is an interface header shared among
the driver and application code modules).
The API
Following is a brief description of this API:
The buffers are mapped upon receiving this escape request. The output buffer format for the
request is GETCHANGESBUF. GETCHANGESBUF::Userbuffer is actually a pointer to the
mirror screen surface view. GETCHANGESBUF::buffer points to the queue of modified
rectangles. The screen surface is “top to bottom, so the 1st line of pixels in the screen surface
commences with the 1st byte of screen memory. For example, you can address the 2nd line of
pixels by adding a fixed positive value (stride, also known as a pitch or delta) to the address of
the 1st line. The userbuffer value actually points to the line 0. Surface dimensions correspond
to the dimensions of the primary display. The stride of the surface is DWORD-aligned upwards.
(The stride is calculated as follows: (screen_width*(screen_bits_per_pel>>3)+3)&-4.)
Options
There are some registry-based switches that affect the driver’s behavior.
All switches are derived from the values located in one of the following registry keys:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\dfmirage\Device0] or
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Hardware Profiles\Current\
System\CurrentControlSet\SERVICES\dfmirage\DEVICE0]
“Pointer.Enabled”=dword: 0 (default) or 1.
First (simple) mode (Pointer.Enabled=1) just renders the mouse pointer movements and
animation and produces only simple update events from these. Second mode
(Pointer.Enabled=0) excludes the mouse from the screen buffer, posting only position and status
events.
There are 2 types of events that bypass the “update buffer” regarding the mouse pointer capture:
• 48 (dmf_dfo_Ptr_Engage): show the pointer (cursor) [in a position specified]
• 49 (dmf_dfo_Ptr_Avert): hide the pointer.
The current pointer shape is queried via a special call.
An application can disable mouse pointer rendering if it wants to draw it on its own.
“Screen.ForcedBpp”=dword: 0 (default), 16, 24 or 32.
This switch forces the mirror screen color depth. 0 enables the native color depth of a primary
display device to be used for a mirror screen. There are 3 valid values of color depth that may be
enforced – 16, 24 and 32 bits per pixel. No values other than 0, 16, 24 and 32 are allowed.
NOTE that 16 bits per pixel forced color depth option is available only in driver version 1.2+.
Color depth enforcement may sometimes be useful. Through the use of this feature, an
application may implement only true color encoding, resulting in its not having to deal with
palettes or worry about color depth switching. Nevertheless, it should still be noted that native 8-
bit or 16-bit screen images are more compact.
“Cap.DfbBackingMode”=dword: 0, 2, or 3 (default).
This is the powerful switch of screen memory backing mode.
Backing mode 3 (the default and recommended option) results in an “opaque” mirror screen.
That is -- a screen that cannot be accessed by GDI directly. This means nothing drawn on the
mirror screen escapes the notice of the driver. This option guarantees the maximum mirroring
consistency possible in the Windows GDI.
Backing mode 0 disables memory backing of the mirroring screen altogether. The mirroring
screen cannot be accessed by the GDI and applications either. Beware,
GETCHANGESBUF::Userbuffer is NULL in this mode. Memory is not allocated and no
rendering is performed. The driver in this mode only collects update regions. This mode may be
useful for applications that bypass the driver when retrieving the screen image.
Backing mode 2 is somewhat experimental. The mirror screen is transparent to the GDI in this
mode. Rendering is on and screen image is accessible. When the screen is transparent, the GDI is
not always accurate when using the driver’s hooks to perform the rendering, and screen
mirroring consistency may become compromised under certain circumstances.
Still, some customers claim that certain graphic-intensive applications such as video players
perform significantly faster in this mode. This mode is not recommended unless you know
exactly what you’re doing.
The following options are new to Mirage driver version 1.2+:
“Order.BltCopyBits.Enabled” = dword: 0 (default) or 1.
Enables or disables generation of dmf_dfo_SCREEN_SCREEN update events in case of screen-
2-screen BitBlt.
“Cap.Bootup” = dword: 0 (default), 1 or 2.
Controls “boot-time checker” which normally checks if the driver is unintentionally attached to
screen during the system boot and disables the attachment. Value 0 corresponds to usual
behavior. Value 1 enables for 1-time (this boot only) driver attach from system boot. Value 2
(and higher) suppresses the check at all, thus the driver will always be attached to screen right
from the system startup.
This switch is generally useless with modern (Windows 2000+) OSes because applications
should load and unload the driver dynamically. If it is anyway needed (for instance, on NT4), use
it with caution.
Performance considerations
Screen grabbing with the DfMirage driver is as simple as performing a direct memory copy of
the modifications made to the framebuffer. The driver provides direct read access to the screen
framebuffer for the client application. The DfMirage driver enables a far more efficient screen
capture method when compared to the usual way of blitting from the screen DC. Using BitBlt
from the screen requires at least one syscall (BitBlt), a global screen update lock performed
internally by BitBlt plus an extra memory copy operation. The DfMirage driver requires no
syscalls or screen locks.
In principle, you can grab the screen, or any part of it when you need or want to, resulting in
flexible performance and instant on-the-fly tuning, for example, to accommodate high-stress
conditions).
The application receives prompt notifications of regions which have been modified, but they
may be allowed to accumulate if the updates are occurring faster than desired. They also may be
accumulated for short periods simply to minimize the traffic. You are not compelled to keep up
with the real screen video driver, but you can. It is very flexible.
Updates are often small, such as those resulting from a single mouse pointer motion. The
application only needs to grab and update the small area behind the pointer. In this case there is
very little CPU consumption. But from time to time of course, there will be major updates which
will then need to be handled.
The present driver’s API requires a poll of the CHANGES_BUF::counter. As a matter of fact,
the poll in itself doesn’t consume much in the way of CPU resources. Yes, an Event could be
used to check for new modifications, but as strange as it may seem, the poll method is much
faster and provides much better performance. To illustrate:
VNC applications typically prefer to accumulate the modifications every, 100 ms or so or even
for a longer period. It may simply use a 100ms timer and process all of the modifications
discovered (which may overlap each other) at once. The poll scenario therefore, requires no
direct interaction with the driver at all. Now imagine the extremely taxing demands of
synchronous notification when an event object is used. The application is interrupted for every
single update! For example, a mere mouse pointer motion may produce tens or even hundreds of
events per second. More importantly, each update event must be individually confirmed to reset
the raised notification event object. This is rarely considered desirable behavior! Note that we
now have an extra confirmation “syscall” from the application to the driver. This may introduce
notable latency under high load conditions. This also makes it more difficult to accumulate the
updates. According to our own observations, we have concluded that the poll method is typically
more CPU efficient than event-based synchronization whether under low or high load conditions.
If there is someone who would like to test the method, an event-based sync (with the ability to
accumulate the confirmations) may be implemented upon customer request.
CPU consumption of the client application can result from either of two things. First, the
rendering (or mirroring) of the graphics commands in the mirrored framebuffer (which takes
place in the driver). This is always commensurate with the same CPU consumption in the real
screen video driver. Graphics acceleration for the DfMirage driver are managed by the Windows
graphics engine. The driver, with the assistance of Windows, renders the complete image to the
framebuffer surface, thus minimizing CPU consumption. Second, (this takes place in the
application itself,) the overhead of copying of and sending/storing the updates. It depends on the
application whether it does data processing, compression, etc.
This technology may certainly be used for VNC applications, even on older machines (in fact,
the performance of a slow machine will greatly depend on the data compression and network
operation).
Known problems
When the video mirroring driver is active, all DirectDraw capabilities of the system are
temporarily disabled.
DirectDraw applications, especially full-screen 3D games are affected by this. It is a known
problem of all mirror drivers, due to DirectDraw DDI’s design which did not have mirror drivers
in mind at design-time. In spite of this, most office DirectDraw applications (including Windows
Media Player) are able to work with the driver in a manner similar to their operation in Terminal
Server sessions, with NetMeeting, or other remote desktop systems. When DfMirage is not
running (i.e. the driver is unloaded), DirectDraw capabilities are fully available. We have
arduously researched this issue and have plans to implement support for DirectDraw in the near
future.
On Windows XP when there are multiple video adapters, the DirectDraw capabilities of
the display are enabled even when the mirror driver is loaded.
This may cause problems, e.g. when recording a media player’s screen because media players
usually render video to hardware overlay surfaces and the mirror driver appears not to work.
There is no such problem with Windows 2000. This problem is currently being researched.
Various problems may be introduced by software which sets or uses various non-standard
video modes.
PowerStrip is one example of one such software package which suffers this problem. This
application allows the user to set such unusual or non-standard video modes. Though DfMirage
has support for many popular non-standard modes, an unsupported mode may still be set. In this
case, the driver will simply refuse to load. (The ChangeDisplaySettingsEx() call will fail
with the DISP_CHANGE_BADMODE code). The solution recommended by Microsoft (hiding a
list of unsupported video modes) does not work with PowerStrip at all. In fact, PowerStrip is
driven crazy by it. This is a problem common to all mirror drivers. A universal solution is
currently under development.
A change of Video mode, especially when the display resolution or color depth is changed
will likely result in the DfMirage driver being reloaded.
This is normal and is by design of the Windows NT graphics system. An application may
examine the stream of events it receives for the dmf_dfn_assert_off event. This event appears
when the driver is deactivated unexpectedly. It usually indicates a change of video mode. When
the driver is deactivated, it terminates the capture and begins preparation for unload. The driver
is not aware whether the deactivation is temporary or permanent, so it errs on the side of
preparing for the permanent scenario.
When the application detects this situation, it should clean up the memory mapping (as usual)
and simply reconnect the driver again (i.e., unmap --> DeleteDC --> CreateDC --> map).
Changing to fullscreen text mode (for example, a DOS box) will cause the driver (as well as
hardware video drivers) to be suspended.
The driver is restored as soon as this mode is terminated. In principle, an application may treat
this situation as a general video mode change. We have plans to implement a solution similar to
the one from Terminal Server, by simply disabling fullscreen text mode (subject to the user’s
preference, of course).
TightVNC 1.3dev7 (best with May 2006 patches from DemoForge) for Windows and later
versions of TightVNC may be used FOR REFERENCE.
See
.\winvnc\VideoDriver.h and
.\winvnc\VideoDriver.cpp files.
Windows 2000 or XP DDK headers and libraries are required to build the driver.
The following tools are used to build the entire project:
• MSFT Visual C++ .NET 7.1 (MSFT Visual C++ 6.0 compiler or the Windows XP
DDK (2600) compiler also may be used),
• InnoSetup installer (version 4 or later).
The client samples (driver management code) are in C/C++ and Object Pascal languages, but this
code can easily be adapted for C# or other modern platform.
Q2: In 16 bit per pixel mode my captured screen colors appear corrupt.
Mirage driver always uses the same bitmasks for 16 bit color mode, known as 565 format color
mask. Most likely, your application tries to interpret the Mirage screen in 555 color mask. Please
set the correct bitmasks explicitly.
565 color format has the following masks:
RED: 0xf800
GREEN: 0x07e0
BLUE: 0x001f,
whereas 555 color format has these masks:
RED: 0x7c00
GREEN: 0x03e0
BLUE: 0x001f.
Technical support
For technical support, please email us at mirrdrv@demoforge.com.