diff -r ae94777fff8f -r 59758314f811 Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita --- a/Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita Fri Jun 11 12:39:03 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita Fri Jun 11 15:24:34 2010 +0100 @@ -1,137 +1,129 @@ - - - - - -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 + + + + + +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 typically have two or more 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 composition surface has two buffers. 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