Improving Window Drawing Performance
The following sections describe how to optimize drawing performance in your object graphics programs. See Performance Tuning Object Graphics for general notes on rendering performance.
Retained Graphics and Expose Events
During the course of an IDL session, it is possible that an IDL window will be obscured by another window. When the hidden window is brought to the front, its contents need to be regenerated. The user interface toolkit portions of the window are repaired automatically. However, the drawable portion of the window (in which graphics are rendered) requires special attention. The user can choose between two methods to handle this situation. The first option is to set the RETAIN property on the IDLgrWindow object to 2, which suggests that IDL is required to retain a backing store of the entire contents of the window. When the window is exposed, the backing store will be copied to the screen. The second option is to set the RETAIN property to 0 (no retention), and to request that expose events are to be reported for draw widgets. Whenever a portion of the window becomes exposed, an event is generated. The event handler for the drawable can then re-issue a draw of the appropriate contents for that window.
While the second option may seem a bit more complicated, it is to the users advantage to take this approach for performance reasons. When RETAIN is 0, the window device drivers are able to utilize a double-buffered rendering scheme that can capitalize on hardware acceleration. For interactive applications, this hardware acceleration can have a crucial impact on the perceived manipulation capabilities of the interface. When RETAIN is 2, on the other hand, IDL will render to an off screen pixmap, which often relies on a software implementation. If several drawing calls are issued in a row, the performance may be noticeably slower.
Instancing to Improve Redraw Performance
Within interactive graphics applications, it is often necessary to redraw a given view over and over again (for example, as the user clicks and drags within the view to manipulate one or more objects). During those redraws, it may be that only a small subset of the objects within the view is changing, while the remaining objects are static. In such a case, it may be more efficient to take a snapshot of the unchanged portion of the view. This snapshot can be reused for each draw, and only the changing portion of the view needs to be re-rendered. This process is called instancing.
It is to your advantage to use instancing only in cases where displaying the snapshot image is faster than rendering each of the objects that remain unchanged.
The following example shows how a typical instancing loop would be set up. First, hide the objects in the view that will be changing. In this example, we assume that the objects that change continuously are contained by a single model object, with the object reference myChangingModel. We set the HIDE property for this model to remove it from the rendered view.
myChangingModel->SetProperty, HIDE=1 ;Next, create an instance of the remaining portion ;of the view by setting the CREATE_INSTANCE keyword to ;the window's Draw method: myWindow->Draw, myView, /CREATE_INSTANCE ;Next, hide the unchanging objects. ;Assume that the unchanging portion of the ;scene is contained in a single model object. myUnchangingModel->SetProperty, HIDE=1 ;Set the HIDE property for the changing model ;object equal to zero, revealing the object: myChangingModel->SetProperty, HIDE=0 ;Set the view object's TRANSPARENT property. ;This ensures that we will not erase the ;instance data (the unchanging part of the scene) ;when drawing the changing model. myView->SetProperty, /TRANSPARENT ;Next, we set up a drawing loop that will render ;the changing model. For example, this loop might ;rotate the changing model in 1 degree increments. ROT = 0 FOR i=0,359 DO BEGIN ROT=ROT+1 myChangingModel->Rotate, [0,1,0], ROT myWindow->Draw, myView, /DRAW_INSTANCE ENDFOR ;After the drawing loop is done, ensure nothing is hidden, ;and that the view erases as it did before: myUnchangingModel->SetProperty, HIDE=0 myView->SetProperty, TRANSPARENT=0