|
IntroductionQuickTime 6.4 includes a new double-buffering feature to improve screen updating for Windows applications. This feature uses a deferred flushing model, similar to that used on Mac OS X. It provides a complete off-screen (back) buffer for each QuickTime graphics port, flushing the buffer to the screen periodically or upon explicit request. This approach provides numerous benefits, including improved clipping and elimination of occasional flashing of UI elements. Here's more detail: Updated pixel data for QuickTime graphics ports are drawn into a back buffer -- they are not immediately drawn to the screen. The "dirty" area (the area that has changed) for each port is accumulated until a flush is performed, at which time the entire dirty region is drawn to the screen. IMPORTANT: QuickTime will automatically flush the dirty region to the screen when movies are drawn or when movies are idled. Your application can also explicitly perform a flush when appropriate (see New functions). Feature Is OptionalSome applications may choose not to use this feature, so its use is optional (see Important Notes below). To use it, your Windows application must activate it by passing the Listing 1: Activating QuickTime double-buffering. // enable QuickTime double-buffering InitializeQTML(kInitializeQTMLEnableDoubleBufferedSurface); Once the feature is activated, QuickTime will then automatically use double-buffering for screen updates to graphics ports associated with the requesting application. Simplest UseIf your application doesn’t perform any special processing of update regions, it can simply activate the feature as shown in Listing 1 above. QuickTime will use it by default to perform dirty region accumulation and basic flushing for normal screen update operations. In some cases, no further use of the API will be required. Using the New APIsIf your application does perform special processing of update regions, you will need to use the new double-buffering APIs to take advantage of this facility. This section briefly describes these APIs. New flagskInitializeQTMLEnableDoubleBufferedSurface The kQTMLNoDoubleBufferPort The New functionsThe following new APIs can be used to add a region ( QTMLAddRgnToDirtyRgn(GrafPtr port, RgnHandle *dirtyRgn) QTMLAddRectToDirtyRgn(GrafPtr port, Rect *dirtyRect) QTMLAddNativeRgnToDirtyRgn(GrafPtr port, void *dirtyHRGN) Use these new APIs to:
Note: The above calls are provided to allow you to add to the dirty region in a format convenient to your code, with a minimum of conversion. Use whichever call is appropriate for the update task at hand. QTMLFlushDirtyPorts Walks the list of all dirtied ports, flushing their dirtied regions to the screen. This call is intended to be used for periodic total flushes, not for flushes that are being invoked because of an immediate need to sync a particular port’s back buffer to the screen. QTMLFlushDirtyPorts() QTMLFlushPortDirtyRgn Flushes the dirty region of the specified port to the screen. This call is useful during QTMLFlushPortDirtyRgn(GrafPtr port) QTMLGetBackbufferHDC Allows GDI access to the back buffer. The caller must release the back buffer QTMLGetBackbufferHDC(GrafPtr port, HDC *backBufferHDC) QTMLReleaseBackbufferHDC Allows GDI access to the back buffer. The caller will have to call QTMLReleaseBackbufferHDC(GrafPtr port, HDC *backBufferHDC) Important NotesApplications should avoid combining QTML and Windows drawing on top of each other into a single window. Use of a child Another important consideration is your application must not cache the Drawing into a port generally falls into one of four categories which all behave slightly differently: QuickTimeQuickTime drawing involves a movie drawing visual elements into the port associated with the movie. This type of drawing will be done into the backbuffer if double buffering is enabled, and the dirty region will automatically be added to the port and flushed to the screen. QuickDrawDrawing done using QuickDraw calls will automatically add the appropriate dirty region to the port, but they will not automatically flush to the screen (this is done to allow you to perform batches of QuickDraw rendering, but only incur the expense of a single blit to the screen). The screen flush must be done either explicitly after the call(s) or through a periodic timer. GDIDrawing can be done into a port using GDI to render into the Direct PixMap AccessIf you are careful to lock the port, you can directly manipulate the pixels in the backbuffer since the As with any new feature, if you want to use the double-buffering feature but also wish to retain backwards compatibility with older QuickTime versions, be sure to check the QuickTime version when your application launches and do not attempt to use the new APIs on earlier QuickTime versions. These calls should function back to QuickTime 6.4. Here's code showing how to get the QuickTime version: Listing 2: Getting the QuickTime version. { /* check the version of QuickTime installed */ long version; OSErr result; result = Gestalt(gestaltQuickTime,&version); if ((result == noErr) && (version >= 0x06408000)) { /* we have version 6.4 or better! */ } } ExamplesExample 1 An application opting into this behavior may wish to handle Listing 3: Adding Windows update region to the port's dirty region, then flushing the port to the screen. case WM_PAINT: { RgnHandle macUpdateRgn = nil; HRGN winUpdateRgn = CreateRectRgn(0,0,0,0); macUpdateRgn = NewRgn(); BeginUpdate((GrafPtr) moviePort); // If your app does any special handling of update regions, // grab the Mac update region. Otherwise, // you can skip this. MacCopyRgn(moviePort->visRgn, macUpdateRgn); EndUpdate((GrafPtr) moviePort); // If there is any new drawing that your app wants to // do (in response to the MacUpdateRgn or for any other // reason) it should be done here. This drawing will // be done into the backbuffer, and flushed to the screen // at the end of this call. // Get the Windows update region GetUpdateRgn(hWnd, winUpdateRgn, FALSE); // Call BeginPaint/EndPaint to clear the update region BeginPaint (hWnd, &ps); EndPaint(hWnd, &ps); // Add to the dirty region of the port any region // that Windows says needs updating. This allows the // union of the two to be copied from the back buffer // to the screen on the next flush. QTMLAddNativeRgnToDirtyRgn((GrafPtr) moviePort, winUpdateRgn); DeleteObject(winUpdateRgn); // Flush the entire dirty region to the screen QTMLFlushPortDirtyRgn((GrafPtr) moviePort); } Example 2 It is often useful to combine a long series of drawing operations and use a single flush at the end to display them all simultaneously. The following example draws a series of inset rectangles, first using QuickDraw, and then using GDI to draw directly into the backbuffer Listing 4: Combining a long series of drawing operations and using a single flush to display them all simultaneously. { Rect myRect; Pattern currentPattern; myRect.top = myRect.left = 0; myRect.bottom = myRect.right = 200; SetPort(myWindowPort); // this drawing is done using QuickDraw. // QuickDraw drawing operations // will automatically add the area that // they have touched to the accumulated // dirty region for the port. while (myRect.top < 50) { // alternate patterns currentPattern = (currentPattern == pattern1) ? pattern2 : pattern1; // fill the current rect with the pattern MacFillRect(myRect, currentPattern); // inset the rect a tiny bit. MacInsetRect(myRect, 10, 10); } { RECT winRect; HDC backbufferHDC = NULL; // get the HDC of the Backbuffer for the port QTMLGetBackbufferHDC(myWindowPort, &backbufferHDC); // create a Windows RECT where we left off with our QuickDraw // rendering above winRect.top = myRect.top; winRect.left = myRect.left; winRect.bottom = myRect.bottom; winRect.right = myRect.right; // fill in yet another rect FillRect(backbufferHDC, &winRect, hBrush); // need to release that backbuffer HDC. QTMLReleaseBackbufferHDC(myWindowPort, &backbufferHDC); // since this drawing was done directly into the backbuffer, // we need to add the dirty region to the port. QTMLAddRectToDirtyRgn(myWindowPort, & myRect); } // now, go ahead and flush all that drawing to the screen QTMLFlushPortDirtyRgn(myWindowPort); } Document Revision History
Posted: 2005-10-18 |
|