Direct Screen Access

Using the drawing mechanisms outlined so far, the influence of the Window Server is evident at every step. There is good reason for this, as Series 60 devices must be aware of many external events outside the realm of the currently active application. For example, users need to be informed of incoming messages or telephone calls. Consequently, there is a need for extra processing in management of the device screen, and this can result in a performance overhead.

For standard applications, where redrawing is infrequent, this is not such a concern. However, for graphically intensive applications, such as games , things are much more problematic .

The Direct Screen Access ( DSA ) classes are designed to work in conjunction with the Window Server for external event management, while providing improved performance when accessing the screen. All of the methods already covered for drawing images, text and shapes can be used with Direct Screen Access. In fact, from a programmer's point of view, the only thing that changes is the graphics context object.

Direct Screen Access architecture is examined in this section. The example application illustrating Direct Screen Access is a simple game, Skiing .

Architectural Overview

The Direct Screen Access architecture comprises four key classes, each playing a vital role in the drawing and screen management process. Their roles are defined in Table 11-11.

Table 11-11. Direct Screen Access Classes

Class

Role

RDirectScreenAccess

Makes asynchronous requests to directly use the device screen.

CDirectScreenAccess

Active Object which reissues requests and manages an abort on completion.

MAbortDirectScreenAccess

Mechanism to stop the Active Object, so that the Window Server can process an external event.

MDirectScreenAccess

Mechanism to restart the Active Object when external event processing is complete.


The two areas to be addressed in order to understand Direct Screen Access are illustrated in the following two diagrams. In Figure 11-15, a request is issued to the Window Server to operate in Direct Screen Access mode, which if successful will provide an area on the screen that can be drawn to.

Figure 11-15. Requesting use of direct screen access.


In Figure 11-16, an event takes place that demands that the Window Server take control of a portion of the screenfor example, displaying a menu. This will result in Direct Screen Access being stopped . Then a new request is made; however, this time the region available for drawing will differ , to account for the Window Server requirements (in this case, displaying a menu).

Figure 11-16. Responding to external/window server events when using direct screen access.


Key Classes for Direct Screen Access

Table 11-11 provided a brief introduction to the DSA classes. A more thorough examination of each of the key classes is provided here, and their role is further explained with support from code snippets taken from the Skiing application.

RDirectScreenAccess

The RDirectScreenAccess class represents the client interface to the Direct Screen Access Server. Using the RDirectScreenAccess::Request() function, a request is made to the Window Server to operate in Direct Screen Access mode. If the request is granted, the region of the screen available to be directly drawn to is returned. It is important to understand that this region may change if menus or dialogs are displayedfor example, system notifications, such as "message received" notes.

The Request() function is asynchronous and must be passed a trequestStatus objectthis request will complete only if Direct Screen Access must be aborted. RDirectScreenAccess also has a Cancel() method which tells the Window Server that Direct Screen Access mode is no longer required.

In the example Skiing game, exposure to RDirectScreenAccess is minimal as the necessary interactions are encapsulated by the use of the CDirectScreenAccess class. If you were to take the step of writing your own wrapper class then the key interaction issues would be:

  • Handling the completion of RDirectScreenAccess::Request() (abortion of DSA) via a Window Server session.

  • Managing the graphics device and context being drawn to.

  • Keeping track of the region of the screen being drawn to, as this can change if menus or dialogs are displayed.

In most cases, it is far simpler to merely use the provided CDirectScreenAccess class, but advanced developers need to be aware of the above issues relating to the use of RDirectScreenAccess .

RDirectScreenAccess

CDirectScreenAccess hides the complexity of managing RDirectScreenAccess by creating a high-priority Active Object "wrapper" around it. Following a successful request to use Direct Screen Access, you are free to draw using the graphics context provided by the CDirectScreenAccess::Gc() function.

If Direct Screen Access has to be aborted, the trequestStatus that was earlier passed into RDirectScreenAccess::Request() completes, and this will result in the CDirectScreenAccess::RunL() function being called. The application is informed of completion via a MDirectScreenAccess observer object that is passed in to CDirectScreenAccess at construction (see "MAbortDirectScreenAccess and MDirectScreenAccess" later in this section).

CDirectScreenAccess is a high-priority Active Object, so the RunL() method will be called quickly.

As applications need to be aware of external events, you may find it useful to write an "Adapter" or "Wrapper" class around CDirectScreenAccess in order to make handling these events more manageable. In the Skiing game, the CDSAWrapper class performs this task.


In the example Skiing game CDirectScreenAccess is constructed in the following way:

 ... iDSA = CDirectScreenAccess::NewL(iWs, iScreenDevice, iWindow, aObserver); ... 

The parameters passed into CDirectScreenAccess::NewL() all play a vital role. The Window Server session of your application, iWs , is used as the channel for interaction with the Window Server. The screen device, iScreenDevice , is used to provide the framework with a pointer to the graphics device in use by the Window Server. The window parameter, iWindow , represents a handle to the window that will be drawn to. The final parameter, aObserver , is the class being used to manage the aborting and restarting of Direct Screen Access.

As CDirectScreenAccess is an Active Object, it needs to be active in order to handle the completed requests of RDirectScreenAccess . This is achieved by simply calling the CDirectScreenAccess::StartL() function, which, in turn , issues RDirectScreenAccess::Request() and stores the region available to draw to:

 ... if (iDSA && !iDSA->IsActive())    {    iDSA->StartL();    } ... 

In order to perform drawing, a handle to the graphics context being used by the Direct Screen Access framework is needed. Once all drawing is complete, it is necessary to update the screen by calling the Update() function of the graphics device:

 ... // obtain handle to DSA graphics context CFbsBitGc* gc = iDSA->Gc(); ... // call some drawing functions on gc ... // Update DSA graphics device iDSA->ScreenDevice()->Update(); ... 

MAbortDirectScreenAccess and MDirectScreenAccess

MAbortDirectScreenAccess and MDirectScreenAccess are the mixin interface classes that specify the functions used to stop and then restart Direct Screen Access. Each adds a single function definition AbortNow() in the case of MAbortDirectScreenAccess , and Restart() in the case of MDirectScreenAccess .

Both of these functions have a single parameter of type RDirectScreenAccess::TTerminationReasons , which provides you with the reason why Direct Screen Access had to be stopped. Note that different approaches may be required when handling an abort or restart, depending on the value of this parameter.

The MDirectScreenAccess observer reference passed into the constructor for CDirectScreenAccess allows your application to be informed when Direct Screen Access must be stopped (by calling AbortNow() ) or can be restarted (by calling Restart() ). Note that MDirectScreenAccess is derived from MAbortDirectScreenAccess and so actually provides both of these function definitions. Your concrete observer class must derive from MDirectScreenAccess and implement these functionsin the Skiing game, the CSkiGameLoop class performs this task.

As a rule of thumb, your observer class should at least have a reference to the CDirectScreenAccess class. It is highly likely that when AbortNow() is called, CDirectScreenAccess::Cancel() will be called. Likewise, when MDirectScreenAccess::Restart() is invoked, a resulting call to CDirectScreenAccess::StartL() will probably take place.

Implementation Considerations

In order to make applications respond properly to external events, it is essential that the CAknAppUi::HandleForegroundEventL(TBool aForeground) function be overridden. If aForeground is Etrue , the application has come into focus and Direct Screen Access should be started; if it is EFalse , then focus has been lost and Direct Screen Access should be stopped. The implementation from the Skiing game example is given here:

 void CSkiingAppUi::HandleForegroundEventL(TBool aForeground)    {    // This is necessary so that the application behaves    // itself just in case there's another application    // that is using Direct Screen Access    if (aForeground)       {       if (!iGamePaused)          {          iAppContainer->StartDSA();          }       SetKeyBlockMode(ENoKeyBlock);       }    else       {       iAppContainer->StopDSA();       SetKeyBlockMode(EDefaultBlockMode);       }    } 

An issue of concern when employing the Direct Screen Access classes is that only one application can instantiate them at any given point in timewhen stopping Direct Screen Access due to HandleForegroundEventL() or similar, you should delete your DSA class instances so that another application can potentially use Direct Screen Access.

From within an application's AppUi class, calling CAknAppUi::SetKeyBlockMode(ENoKeyBlock) enables applications to be responsive to users pressing more than one key simultaneously . This is essential for games, when implementing functionality such as running and jumping at the same time.


In order to ensure smooth drawing, you should use double buffering before drawing to the graphics context provided by Direct Screen Access. Choosing an appropriate redraw rate is also important, and you should be aware that this will be hardware dependentdo not exceed the physical refresh rate of the device.



Developing Series 60 Applications. A Guide for Symbian OS C++ Developers
Developing Series 60 Applications: A Guide for Symbian OS C++ Developers: A Guide for Symbian OS C++ Developers
ISBN: 0321227220
EAN: 2147483647
Year: 2003
Pages: 139

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net