Symbian3/PDK/Source/GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-42984078-3DEB-41C7-AC76-C769F7CDB4D0" xml:lang="en"><title>Implementing
       
    13 eglSwapBuffers</title><shortdesc>This topic explains how to implement eglSwapBuffers() on the Symbian
       
    14 platform. It provides information about how to handle a window resize and
       
    15 the preserve buffer option.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    16 <section>       <title>Promoting buffers to the screen </title>       <p>EGL
       
    17 composition surfaces have two buffers, known as the front and back buffers.
       
    18 Call <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-2B032364-97A0-31A1-A08C-6D8E8ACC16E1"><apiname>RSurfaceUpdateSession::SubmitUpdate()</apiname></xref> to initiate
       
    19 the composing of a specified buffer of a composition surface to the screen.
       
    20 This is an asynchronous operation. If you want to be notified when it has
       
    21 finished, call <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-E8A784F8-4733-38D0-B282-B7CBD0AE4DCB"><apiname>RSurfaceUpdateSession::NotifyWhenAvailable()</apiname></xref> immediately
       
    22 before you call <codeph>SubmitUpdate()</codeph>. </p> <p> <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-E8A784F8-4733-38D0-B282-B7CBD0AE4DCB"><apiname>RSurfaceUpdateSession::NotifyWhenAvailable()</apiname></xref> takes
       
    23 a <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref>, which you can wait on in the usual way—for
       
    24 example, by using an active object or <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-50223158-D05D-33FE-A3DD-FFA9E2F464FF"><apiname>User::WaitForRequest()</apiname></xref>. </p> <p>If
       
    25 a <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> is waiting for the first buffer to complete
       
    26 composition, you need to submit the second buffer before the first buffer's <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> is
       
    27 signaled (unless there is an error). This means that there is interleaving
       
    28 between the two buffers. </p>     </section>
       
    29 <section>       <title>Synchronization and threads </title>       <p>First
       
    30 let us consider a scenario that illustrates how <codeph>eglSwapBuffers()</codeph> works.
       
    31 The front buffer (<i>Buffer 0</i>) is in the process of being displayed and
       
    32 the back buffer (<i>Buffer 1</i>) is receiving drawing commands for the next
       
    33 animation frame. The client calls <codeph>eglSwapBuffers()</codeph> when all
       
    34 of the drawing commands for the next frame have been issued. </p> <p> <codeph>eglSwapBuffers()</codeph> can
       
    35 promote <i>Buffer 1</i> to the screen by calling <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-2B032364-97A0-31A1-A08C-6D8E8ACC16E1"><apiname>RSurfaceUpdateSession::SubmitUpdate()</apiname></xref>,
       
    36 passing in its index. This makes <i>Buffer 1</i> the front buffer and <i>Buffer
       
    37 0</i> should become the new back buffer and all drawing commands should be
       
    38 directed to it. </p> <p>However, suppose the application runs faster than
       
    39 the composition engine. <i>Buffer 0</i> cannot become the new back buffer
       
    40 until its composition is complete. You therefore need to wait for <i>Buffer
       
    41 0</i> to complete composition before allowing <codeph>eglSwapBuffers()</codeph> to
       
    42 return. This means that after you submit <i>Buffer 1</i> for composition,
       
    43 you must wait for <i>Buffer 0</i> (not <i>Buffer 1</i>) to complete composition
       
    44 before returning. </p> <p>In practice it may not be possible to use active
       
    45 objects to do the waiting because <codeph>eglSwapBuffers()</codeph> must block
       
    46 on the <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> supplied to <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-2B032364-97A0-31A1-A08C-6D8E8ACC16E1"><apiname>RSurfaceUpdateSession::SubmitUpdate()</apiname></xref>.
       
    47 Using a nested <xref href="GUID-B4C76104-EA1B-3FC3-A31E-86A976598171.dita"><apiname>CActiveScheduler</apiname></xref> is not recommended because
       
    48 it can cause re-entrant issues. A call to <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-50223158-D05D-33FE-A3DD-FFA9E2F464FF"><apiname>User::WaitForRequest()</apiname></xref> may
       
    49 therefore be required. However, doing this from within a thread that has an
       
    50 active scheduler can cause stray signal panics (because each buffer has a <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> but
       
    51 we only wait for one of these at a time). EGL has no control over whether
       
    52 the thread has an active scheduler because the thread is owned by the application. </p> <p>A
       
    53 possible solution is to create a separate worker thread that is owned by the
       
    54 EGL implementation and has no active scheduler. This thread calls <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-E8A784F8-4733-38D0-B282-B7CBD0AE4DCB"><apiname>RSurfaceUpdateSession::NotifyWhenAvailable()</apiname></xref> and <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita#GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06/GUID-2B032364-97A0-31A1-A08C-6D8E8ACC16E1"><apiname>RSurfaceUpdateSession::SubmitUpdate()</apiname></xref>. It can safely call <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-50223158-D05D-33FE-A3DD-FFA9E2F464FF"><apiname>User::WaitForRequest()</apiname></xref> to wait for
       
    55 each <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> to be signaled, because the thread
       
    56 is guaranteed not to have an active scheduler. Signaling based on semaphores
       
    57 can be used to control interaction between the thread that calls <codeph>eglSwapBuffers()</codeph> and
       
    58 the worker thread that owns the <xref href="GUID-FAFD23EB-90EF-3F0C-BAB3-74FEC8DF0E06.dita"><apiname>RSurfaceUpdateSession</apiname></xref>. </p> 
       
    59    </section>
       
    60 <section>       <title>Handling a window resize event </title>       <p>A
       
    61 change in the size of an <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita"><apiname>RWindow</apiname></xref> can be detected in <codeph>eglSwapBuffers()</codeph>,
       
    62 by calling <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-2E019F5A-6110-3940-B088-AB13F0EE6AD5"><apiname>RWindow::Size()</apiname></xref> and comparing the result with
       
    63 the previously recorded size. If the values differ, a resize has occurred.
       
    64 A typical approach on a resize is as follows (and is illustrated in the following
       
    65 diagram): </p> <ol id="GUID-529E2F6E-21A1-5618-920C-231CA3FCD2AB">
       
    66 <li id="GUID-FA1DF0D4-DE06-56AA-8203-1EB42351D2DE"><p>Promote the current
       
    67 back buffer to the front buffer for display as usual. </p> </li>
       
    68 <li id="GUID-D254B182-2BC6-5BDF-A76E-CE2FD4527BB1"><p>Create a new composition
       
    69 surface with the new dimensions and with one of its buffers designated as
       
    70 the back buffer to receive the next set of drawing commands. </p> </li>
       
    71 <li id="GUID-DA7BB534-9565-5127-8B40-CA150E90D710"><p>On the next call to <codeph>eglSwapBuffers()</codeph>,
       
    72 register the new composition surface as the window's background surface and
       
    73 promote its back buffer to the front buffer for display. (This step is marked
       
    74 with the number 3 in the following diagram) </p> </li>
       
    75 <li id="GUID-4209FD9D-C668-5902-863C-DB49343ED634"><p>Close the previous composition
       
    76 surface. </p> </li>
       
    77 </ol> <fig id="GUID-B793BDDF-7607-5BCD-94C2-44F8349D7BC5">
       
    78 <title>The buffers in the typical approach to handling a window resize event</title>
       
    79 <image href="GUID-ADC9B349-3CE4-5017-B437-A7F8890C7F0F_d0e246447_href.png" placement="inline"/>
       
    80 </fig>    </section>
       
    81 <section id="GUID-CF08037B-2A6A-4B79-9766-E8C730C086F3">       <title>Handling
       
    82 preserve buffers </title>       <p>When the preserve buffer option is in use,
       
    83 a typical implementation promotes the current back buffer to the front buffer
       
    84 for display as usual, and copies the back buffer content to the new back buffer.
       
    85 The client application then provides incremental drawing operations on the
       
    86 new back buffer. On the next call to <codeph>eglSwapBuffers()</codeph>, the
       
    87 back buffer is again promoted for display and the content is preserved. </p><p>The
       
    88 following diagram shows the scenario of a client application drawing A and
       
    89 later B on a surface with the preserve buffers enabled. Notice that <codeph>eglSwapBuffers()</codeph> promotes
       
    90 the back buffer to the front buffer and then immediately copies the contents
       
    91 of the newly promoted buffer to the new back buffer.</p><fig id="GUID-B9C43452-0627-41FA-A68A-4C9726194A60">
       
    92 <title>Handling preserve buffers</title>
       
    93 <image href="GUID-9C54DAFB-843B-41A7-8E54-9B2A39F46527_d0e246471_href.png" placement="inline"/>
       
    94 </fig>    </section>
       
    95 <section><title>Handling a window resize event with the preserve buffer option</title><p>If
       
    96 there is a window resize event when the preserve buffer option is in use, <codeph>eglSwapBuffers()</codeph> creates
       
    97 a new surface and typically copies into it any pixels that overlap the previous
       
    98 surface. To illustrate how this works, consider the following scenario:</p><ol>
       
    99 <li id="GUID-167D0FD8-22E7-495D-9627-FF7A4DDF654A"><p>A window is a wide rectangle
       
   100 showing an A.</p></li>
       
   101 <li id="GUID-3F62A9F4-6830-4010-9327-88BFD33AA818"><p>The application draws
       
   102 a B so that the window shows AB. </p></li>
       
   103 <li id="GUID-D8575A54-D2A9-4FDF-999E-E711363AE19D"><p>The user resizes the
       
   104 window to a tall thin rectangle which can only show A.</p></li>
       
   105 <li id="GUID-89A1D882-B5DC-4093-98E5-34E3063BBF25"><p>After calling <codeph>eglSwapBuffers()</codeph>,
       
   106 the application draws a C below the A.</p></li>
       
   107 </ol><p>The following diagram illustrates a typical implementation. There
       
   108 are more details below the diagram.</p><fig id="GUID-D19DF371-8640-4A2B-AF56-57EF2387CEFD">
       
   109 <title>Handling a window resize with the preserve buffer option</title>
       
   110 <image href="GUID-8A8FA00B-58FA-4D4E-A018-70D5558BCBFE_d0e246511_href.png" placement="inline"/>
       
   111 </fig><p>The first <codeph>eglSwapBuffers()</codeph> call (marked X in the
       
   112 diagram above) does the following:</p><ol>
       
   113 <li id="GUID-70603721-5603-4015-B382-8D3F9D693139"><p>Promotes the current
       
   114 back buffer (showing AB) to the front buffer for display as usual. </p></li>
       
   115 <li id="GUID-7040357F-1F40-4E34-ACB2-170815B06D10"><p>Copies the back buffer
       
   116 content to the new back buffer (showing AB).</p></li>
       
   117 <li id="GUID-5950B197-5661-44B5-AB7A-475C056F184C"><p>Creates a new surface
       
   118  with the new dimensions.</p></li>
       
   119 <li id="GUID-90909C1D-7335-41BF-973F-B2F82403CF40"><p>Designates one of the
       
   120 new buffers as the back buffer and copies the overlapping pixels into it.
       
   121 The new back buffer is then ready to receive new drawing operations. </p></li>
       
   122 </ol><p>The Window Server continues to use the old surface s1 until the next
       
   123 call to <codeph>eglSwapBuffers()</codeph>.</p><p>The second <codeph>eglSwapBuffers()</codeph> call
       
   124 (marked Y in the diagram above) does the following:</p><ol>
       
   125 <li id="GUID-05E4F40D-568A-425A-93F8-C30606C50DA8"><p>Promotes the back buffer
       
   126 (showing A and C) to the front buffer for display as usual.</p></li>
       
   127 <li id="GUID-84200E5B-CD20-4F4A-8D9D-0460B30D40CA"><p>Copies the back buffer
       
   128 content to the new back buffer (showing A and C).</p></li>
       
   129 <li id="GUID-D300A85C-88C3-499A-86A7-EC2B35020E0C"><p>Destroys the old surface
       
   130 s1.</p></li>
       
   131 </ol><p>The Window Server now uses the new surface s2.</p></section>
       
   132 </conbody><related-links>
       
   133 <link href="GUID-0B2421FD-8431-5DDA-9FE3-046734AE495E.dita"><linktext>Window Surface
       
   134 Implementation Overview</linktext></link>
       
   135 <link href="GUID-599C9890-3AC8-46D3-A8C3-34CAAB5A61CF.dita"><linktext>Implementing
       
   136 eglCreateWindowSurface</linktext></link>
       
   137 </related-links></concept>