diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita --- a/Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,137 +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 + + + + + +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