Content Rendering Plug-ins (CRPs) Overview

Content Rendering Plug-ins (CRPs) are Window Server plug-ins that can perform custom drawing in response to client requests. The client simply calls CWindowGc::DrawWsGraphic(TWsGraphicId, TRect).

To the client, a CRP call appears like any other draw operation—the thing it most resembles is drawing a bitmap. In particular, a CRP call can be issued as part of a stream of draw operations. If there are draw operations before and after the CRP call, it may draw above some elements and other elements may be drawn above it. This is in contrast to anims and sprites, which always appear above other window drawing.

On the server side, the plugin provides a subclass of CWsGraphicDrawer. When the client’s CWindowGc::DrawWsGraphic() call is processed, the appropriate CWsGraphicDrawer subclass is called to perform the rendering.

CRPs have several benefits:

  • Content abstraction —the client has no knowledge of what is rendered—that is left to the plug-in. As a result, CRPs can enable the appearance of an application to be customized without any change to application code. (This is similar to the use of skin bitmaps to customize application appearance, but it goes further.)

  • Server-side execution —CRP rendering code executes inside the Window Server process. This means that it is less susceptible to interruptions under CPU loading than client-side code. However, it also means that CRPs must be written with greater care, because their failure can cause a device reset rather than a simple application exit.

  • Animation —CRPs are able to schedule their own reanimation within the Window Server. This is managed by the Window Server animation scheduler and so provides more reliable animation than can be achieved from the client-side alone.

CRPs are generally written by device creators for showing customized content on the screen. For example, a CRP might be an SVG renderer, where the client application provides data in the form of an SVG source file and the CRP decodes and renders it.

Unlike animations created using CAnim, other drawing can appear above the CRP-based content within the same window.

Architecture

The following diagram shows how the client application and the server-side CRP work together:

Figure 1. Figure 1: Relationship of a client application and the CRP
Client UI application

This originates the draw request that drives the system to render the result of a CRP to a given location of the screen.

Server-side CRP

This runs in the Window Server process. It has the priorities and privileges of the Window Server.

Prioritized scheduling and access to Window Server resources enable CRPs to function more efficiently than if they were modeled in the client UI application.

The typical workflow in the client application is as follows:

  1. Set up the necessary CRPs by calling constructors.

  2. Set application-specific values for the CRP by sending method calls from the client UI application to the client-side CRP proxy (there is more information about this below).

  3. Call the CWindowGc::DrawWsGraphic() command. This initiates the drawing, which is actually done by the CWsGraphicDrawer::DoDraw() method of the server-side CRP.

Graphic Drawer library details

The following table shows the DLLs that provide the server-side functionality.

DLL LIB Short description

wsgraphicdrawer_nga.dll

wsgraphicdrawer.lib

The server-side base classes for graphic drawers in the ScreenPlay variant.

wsgraphicdrawer_nonnga.dll

wsgraphicdrawer.lib

The server-side base classes for graphic drawers in the non-ScreenPlay variant.

APIs

Variant: ScreenPlay.

Assuming the construction of objects has been done, the client UI application issues a CWindowGc::DrawWsGraphic() call each time it wants a CRP to be shown on the screen. For our SVG rendering example, the UI application simply decides where on the screen the CRP is to be shown.

Any additional information (such as the location of the SVG file) is handled by the client-side CRP proxy. This is a subclass of CWsGraphic. You can pass application-specific data to the server-side CRP by implementing the CWsGraphic::SendMessage() method. When a client-side CRP invokes CWsGraphic::SendMessage(), the server-side CRP receives a CWsGraphicDrawer::HandleMessage() call.

The client-side UI application uses the GDI interface to issue draw commands. CWindowGc::DrawWsGraphic() can be considered to be just another draw command.

The server-side CRP interface is defined by the CWsGraphicDrawer interface. This cannot be extended. However, the CWsGraphicDrawer::HandleMessage() method that accepts a data buffer can be interpreted in an application-specific manner by the server-side CRP author.

Summary

API Description

CWsGraphicDrawer

The abstract base class for the server-side graphic drawer. Each CRP has a concrete implementation of this class. The most important function is CWsGraphicDrawer::DoDraw(MWsGc, TRect), which issues the drawing commands.

MWsGc

This is provided to the graphic drawer in the CWsGraphicDrawer::DoDraw(MWsGc, TRect) function. There main things to note about this interface:

CRPs do not need to hold onto a handle to a graphic context, because they are passed one every time they are required to draw. This means that other parts of the Window Server (specifically render stages) can safely redirect drawing without any concern that CRPs hold invalid graphics contexts.

CWsGraphic

This is the abstract base class for the client-side proxy. This serves a function similar to RAnim, enabling the client to control the CRP's state remotely.