diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,137 @@ + + + + + +Implementing +eglSwapBuffersThis topic explains how to implement eglSwapBuffers() on the Symbian +platform. It provides information about how to handle a window resize and +the preserve buffer option. +
Promoting buffers to the screen

EGL +composition surfaces have two buffers, known as the front and back buffers. +Call RSurfaceUpdateSession::SubmitUpdate() to initiate +the composing of a specified buffer of a composition surface to the screen. +This is an asynchronous operation. If you want to be notified when it has +finished, call RSurfaceUpdateSession::NotifyWhenAvailable() immediately +before you call SubmitUpdate().

RSurfaceUpdateSession::NotifyWhenAvailable() takes +a TRequestStatus, which you can wait on in the usual way—for +example, by using an active object or User::WaitForRequest().

If +a TRequestStatus is waiting for the first buffer to complete +composition, you need to submit the second buffer before the first buffer's TRequestStatus is +signaled (unless there is an error). This means that there is interleaving +between the two buffers.

+
Synchronization and threads

First +let us consider a scenario that illustrates how eglSwapBuffers() works. +The front buffer (Buffer 0) is in the process of being displayed and +the back buffer (Buffer 1) is receiving drawing commands for the next +animation frame. The client calls eglSwapBuffers() when all +of the drawing commands for the next frame have been issued.

eglSwapBuffers() can +promote Buffer 1 to the screen by calling RSurfaceUpdateSession::SubmitUpdate(), +passing in its index. This makes Buffer 1 the front buffer and Buffer +0 should become the new back buffer and all drawing commands should be +directed to it.

However, suppose the application runs faster than +the composition engine. Buffer 0 cannot become the new back buffer +until its composition is complete. You therefore need to wait for Buffer +0 to complete composition before allowing eglSwapBuffers() to +return. This means that after you submit Buffer 1 for composition, +you must wait for Buffer 0 (not Buffer 1) to complete composition +before returning.

In practice it may not be possible to use active +objects to do the waiting because eglSwapBuffers() must block +on the TRequestStatus supplied to RSurfaceUpdateSession::SubmitUpdate(). +Using a nested CActiveScheduler is not recommended because +it can cause re-entrant issues. A call to User::WaitForRequest() may +therefore be required. However, doing this from within a thread that has an +active scheduler can cause stray signal panics (because each buffer has a TRequestStatus but +we only wait for one of these at a time). EGL has no control over whether +the thread has an active scheduler because the thread is owned by the application.

A +possible solution is to create a separate worker thread that is owned by the +EGL implementation and has no active scheduler. This thread calls RSurfaceUpdateSession::NotifyWhenAvailable() and RSurfaceUpdateSession::SubmitUpdate(). It can safely call User::WaitForRequest() to wait for +each TRequestStatus to be signaled, because the thread +is guaranteed not to have an active scheduler. Signaling based on semaphores +can be used to control interaction between the thread that calls eglSwapBuffers() and +the worker thread that owns the RSurfaceUpdateSession.

+
+
Handling a window resize event

A +change in the size of an RWindow can be detected in eglSwapBuffers(), +by calling RWindow::Size() and comparing the result with +the previously recorded size. If the values differ, a resize has occurred. +A typical approach on a resize is as follows (and is illustrated in the following +diagram):

    +
  1. Promote the current +back buffer to the front buffer for display as usual.

  2. +
  3. Create a new composition +surface with the new dimensions and with one of its buffers designated as +the back buffer to receive the next set of drawing commands.

  4. +
  5. On the next call to eglSwapBuffers(), +register the new composition surface as the window's background surface and +promote its back buffer to the front buffer for display. (This step is marked +with the number 3 in the following diagram)

  6. +
  7. Close the previous composition +surface.

  8. +
+The buffers in the typical approach to handling a window resize event + +
+
Handling +preserve buffers

When the preserve buffer option is in use, +a typical implementation promotes the current back buffer to the front buffer +for display as usual, and copies the back buffer content to the new back buffer. +The client application then provides incremental drawing operations on the +new back buffer. On the next call to eglSwapBuffers(), the +back buffer is again promoted for display and the content is preserved.

The +following diagram shows the scenario of a client application drawing A and +later B on a surface with the preserve buffers enabled. Notice that eglSwapBuffers() promotes +the back buffer to the front buffer and then immediately copies the contents +of the newly promoted buffer to the new back buffer.

+Handling preserve buffers + +
+
Handling a window resize event with the preserve buffer option

If +there is a window resize event when the preserve buffer option is in use, eglSwapBuffers() creates +a new surface and typically copies into it any pixels that overlap the previous +surface. To illustrate how this works, consider the following scenario:

    +
  1. A window is a wide rectangle +showing an A.

  2. +
  3. The application draws +a B so that the window shows AB.

  4. +
  5. The user resizes the +window to a tall thin rectangle which can only show A.

  6. +
  7. After calling eglSwapBuffers(), +the application draws a C below the A.

  8. +

The following diagram illustrates a typical implementation. There +are more details below the diagram.

+Handling a window resize with the preserve buffer option + +

The first eglSwapBuffers() call (marked X in the +diagram above) does the following:

    +
  1. Promotes the current +back buffer (showing AB) to the front buffer for display as usual.

  2. +
  3. Copies the back buffer +content to the new back buffer (showing AB).

  4. +
  5. Creates a new surface + with the new dimensions.

  6. +
  7. Designates one of the +new buffers as the back buffer and copies the overlapping pixels into it. +The new back buffer is then ready to receive new drawing operations.

  8. +

The Window Server continues to use the old surface s1 until the next +call to eglSwapBuffers().

The second eglSwapBuffers() call +(marked Y in the diagram above) does the following:

    +
  1. Promotes the back buffer +(showing A and C) to the front buffer for display as usual.

  2. +
  3. Copies the back buffer +content to the new back buffer (showing A and C).

  4. +
  5. Destroys the old surface +s1.

  6. +

The Window Server now uses the new surface s2.

+
+Window Surface +Implementation Overview +Implementing +eglCreateWindowSurface +
\ No newline at end of file