Symbian3/SDK/Source/GUID-8DB1C618-597C-560C-95A2-C0AB2CEBB027.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 13 48780e181b38
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-8DB1C618-597C-560C-95A2-C0AB2CEBB027" xml:lang="en"><title>Redraw Drawing</title><shortdesc>This topic provides background information about redraw
drawing and tips for updating old code to comply with the recommendation
that all drawing is migrated to redraw drawing. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p> <b>Variant</b>: Both (ScreenPlay and non-ScreenPlay). <b>Target
audience</b>: Application developers. </p>
<section id="GUID-71199005-1F00-434D-B130-47886DD53E92"><title>About
Redraw Drawing</title> <p>Symbian recommends that all <xref href="GUID-0AEE5955-C530-35F1-A904-69183331B294.dita"><apiname>CWindowGc</apiname></xref> drawing is <b>redraw drawing</b>, which means that it takes place
between <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-9337538E-7A53-3153-A330-968B5E4F2FF2"><apiname>RWindow::BeginRedraw()</apiname></xref> and <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-3DE16607-AD3B-3946-BEB3-88512EAAB9CE"><apiname>RWindow::EndRedraw()</apiname></xref> calls. <xref href="GUID-6C16417B-5B37-5310-B59A-750D971AA6D4.dita">The
UI Control Framework (CONE)</xref> automatically takes care of this
for you if you use the <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-250ED45A-76F3-3623-BA4B-22D31613A2EF"><apiname>CCoeControl::DrawNow(const TRect &amp;)const</apiname></xref> and <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-33A19096-F8D1-373C-862F-EF627981C782"><apiname>CCoeControl::DrawDeferred()const</apiname></xref> methods. </p> <p>For example, suppose an application wants to write the text "Hello!"
to a window and then add a red diagonal line below it (A in following
diagram). When this is performed as redraw drawing, the application
calculates the bounding rectangles of the "Hello!" text and the red
line (B). For each one, the application passes the rectangle to <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-F5E85A7B-0DAE-32C1-AF71-8FC2F5F01509"><apiname>RWindow::BeginRedraw(const TRect &amp;)</apiname></xref>, then calls the
draw commands and afterwards calls <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-3DE16607-AD3B-3946-BEB3-88512EAAB9CE"><apiname>RWindow::EndRedraw()</apiname></xref>. </p> <fig id="GUID-53B962F7-D425-5D72-8148-F822A3462243">
<image href="GUID-1DDFFB60-BBA8-500E-A9B1-F048EE5BFBD0_d0e189660_href.png" placement="inline"/>
</fig> <p>This has the advantage that the Window Server knows that
the area of the window that has the "Hello!" text is not affected
by the drawing of the red line. There are also advantages when some
or all of the window needs to be repainted. For example, suppose another
window (such as an OK dialog box) appears above the window (as shown
in C). When the dialog box is closed, the Window Server repaints the
screen behind the dialog box. Because in this example the OK dialog
box was entirely within the red line's bounding rectangle, the Window
Server simply replays that rectangle's drawing operations (D). This
is more efficient than repainting the whole window. </p> <p>However,
in earlier versions of Symbian you could, for example, draw the red
line without bracketing it within <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> calls. This is called <b>non-redraw drawing</b>. In ScreenPlay, each non-redraw drawing operation triggers the Window
Server to invalidate the entire window. This means that the client
application must then perform a full window redraw, as shown in the
next diagram. </p> <fig id="GUID-A36DF80C-6B53-5D9D-878B-0854BB36E44A">
<title>              Non-redraw drawing sequence            </title>
<image href="GUID-7C51BC7A-CB97-5A7E-A5EF-BB3623DFFFED_d0e189683_href.png" placement="inline"/>
</fig> <p>This is less efficient than the Window Server replaying
the draw operations for the affected area. </p> <p>Symbian recommends
that all drawing is now performed as redraw drawing. Typically this
involves dividing the window up into rectangular areas that represent
different aspects of the user interface—for example, as shown in the
following diagram. If anything spoils the screen, the Window Server
then only needs to redraw the corresponding portions of the user interface. </p> <fig id="GUID-BAD0C762-0EBD-51E2-BC64-DF38749CA7D8">
<image href="GUID-F2E8CB4B-C1BB-577D-B018-7FF231B70D8C_d0e189694_href.png" placement="inline"/>
</fig> <p>In earlier versions of Symbian, before the introduction
of the <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-250ED45A-76F3-3623-BA4B-22D31613A2EF"><apiname>CCoeControl::DrawNow(const TRect &amp;)const</apiname></xref> overload, developers sometimes used non-redraw drawing to update
a small part of a control. This technique has often been used for
virtual keyboards and calendar controls. This type of use case is
now particularly unsuited to non-redraw drawing because in ScreenPlay
each non-redraw drawing command triggers a server-initiated client
redraw of the entire window. This can be very slow if the window requires
many drawing operations to redraw the scene. </p> <p>Symbian recommends
that all non-redraw drawing is changed to redraw drawing. Migrating
non-redraw drawing to redraw drawing means that you must enclose all
drawing operations between <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-9337538E-7A53-3153-A330-968B5E4F2FF2"><apiname>RWindow::BeginRedraw()</apiname></xref> and <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-3DE16607-AD3B-3946-BEB3-88512EAAB9CE"><apiname>RWindow::EndRedraw()</apiname></xref> calls or migrate it
to use the <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-D5458F8C-E199-37DD-B821-050B749122C6"><apiname>CCoeControl::DrawNow()</apiname></xref> and <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-9FB682AC-0209-302A-83F3-7BCB1162B998"><apiname>CCoeControl::DrawDeferred()</apiname></xref> methods. Sometimes this causes
some subtle changes in behavior, as explained in the Notes below. </p></section>
<section id="GUID-E88E139C-F852-4CAB-B6EB-7E5861D607D6"><title>Restrictions</title> <ol id="GUID-3BE36F7E-CFEC-5BFD-A311-E36D67D9097D">
<li id="GUID-C6236CD8-C83E-5252-BCC6-336FE8677DCF"><p>You must supply <b>only</b> drawing operations between the <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> calls. For example, you must not
change the window extent between a <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> call. </p> </li>
<li id="GUID-616C81BF-6296-4D10-BA9F-5A037995D773"><p>For opaque windows,
you must define pixel content for the <b>entire area</b> being redrawn.
For example, when calling <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-250ED45A-76F3-3623-BA4B-22D31613A2EF"><apiname>CCoeControl::DrawNow(const TRect
&amp;)const</apiname></xref>, you must supply drawing operations for the
entire rectangle passed to the function. Similarly when calling the <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-8DE580DF-459C-3FCF-8ABA-B26741C294CC"><apiname>CCoeControl::DrawNow()const</apiname></xref> overload, you must supply drawing
operations for the entire window. However, this is not necessary for
transparent windows.</p></li>
<li id="GUID-652DF093-046F-58A3-961F-2A51DEB2FD74"><p>You must <b>not</b> call any functions that can leave between the <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> calls. This is because drawing
operations must never leave. </p> </li>
</ol> <p>Note: A redrawer's <codeph>RunL()</codeph> function must <b>never</b> perform any non-redraw drawing. See <xref href="GUID-7C75642D-C0C9-5392-9354-711F42DC2C61.dita">Server-Initiated
vs. Application-Initiated Redrawing</xref> for more information. </p> </section>
<section id="GUID-620268C0-2F67-4D87-BF99-E1843DBE9BCA"><title>Notes</title> <p><b>Performance </b> </p> <p>You can improve performance by passing
the smallest possible bounding rectangle to the <xref href="GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79.dita#GUID-683603DD-F3D3-3193-BEB3-8236C7DE7F79/GUID-9337538E-7A53-3153-A330-968B5E4F2FF2"><apiname>RWindow::BeginRedraw()</apiname></xref> and <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita#GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160/GUID-D5458F8C-E199-37DD-B821-050B749122C6"><apiname>CCoeControl::DrawNow()</apiname></xref> methods. If this still
results in poor performance, because, for example, there is a large
amount of incremental screen updating, the recommended solution in
ScreenPlay is to render to a surface. </p><p><b>High frequency rendering</b> </p><p>It is possible for a client to provide batches of redraw
drawing (that is, drawing bracketed in <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> calls) for the same region of a
window faster than they can be displayed on the screen.
When this happens, the Window Server may discard the drawing commands
in one or more of the earlier batches of redraw drawing and simply
draw the pixels defined in a later redraw batch to the screen. This
can result in missing frames, but is only likely to be noticeable
in an application like a game that performs high-frequency rendering.</p><p>The solution is to call <xref href="GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9.dita#GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9/GUID-B431DC60-D11F-3239-8F52-4257B9B0E0C9"><apiname>RWsSession::Finish()</apiname></xref> after each <codeph>EndRedraw()</codeph> call. This slows the client
so that it does not generate pixel content faster than the Window
Server can display it on the screen. </p><p>To summarize: When you
want to ensure that every single frame is shown on the screen, call <codeph>Finish()</codeph> after each <codeph>EndRedraw()</codeph> call.</p> <p><b>Delay of execution </b> </p> <p>After you migrate non-redraw
drawing to redraw drawing, the execution of the drawing operations
is deferred compared to previously. This means that if the arguments
of the drawing operations result in a panic, the panic also appears
later than before. </p> <p><b>CRemoteGc usage </b> </p> <p>Device
creators can use <xref href="GUID-9965F9F1-ACEE-398C-BDAB-B3D5D61D4EBE.dita"><apiname>CRemoteGc</apiname></xref> to create a data buffer
containing a series of drawing operations. These can then be executed
to display the drawing on the screen by using <xref href="GUID-B25363C2-8757-36D4-93D2-769CDA1BDF86.dita#GUID-B25363C2-8757-36D4-93D2-769CDA1BDF86/GUID-35C68602-7684-3A1C-ADA2-9C8822E18DE0"><apiname>CCommandBuffer::Play()</apiname></xref>. </p> <p>For example, consider a weather program that has one sub-system
responsible for deciding the drawing operations that comprise a weather
symbol and another sub-system that places weather symbols at different
locations on the screen. Here we potentially have a Cloud symbol buffer
created once and played many times. </p> <p>The points to note are: </p> <ul>
<li id="GUID-A8DCB4C4-9D80-5F0F-A894-512A432A9E11"><p>Any <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> commands
that are placed into the <codeph>CRemoteGc</codeph> buffer are <b>not</b> transferred to the target window when the buffer is played </p> </li>
<li id="GUID-4D5FB2B7-44F0-50F1-AB60-3A12B0AF287B"><p>You <b>must</b> bracket any call to <xref href="GUID-B25363C2-8757-36D4-93D2-769CDA1BDF86.dita#GUID-B25363C2-8757-36D4-93D2-769CDA1BDF86/GUID-35C68602-7684-3A1C-ADA2-9C8822E18DE0"><apiname>CCommandBuffer::Play()</apiname></xref> within <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> calls. </p> </li>
</ul> <p>It may be puzzling to understand why any <codeph>BeginRedraw()</codeph> and <codeph>EndRedraw()</codeph> commands would be placed in the <codeph>CRemoteGc</codeph> buffer at all. This facility is to allow the commands
already in the <codeph>CRemoteGc</codeph> buffer to be replaced with
new drawing operations. In the weather example, it might be done to
allow a "7<sup>o</sup> Celsius" label to partially occlude a cloud
graphic placed earlier into the <codeph>CRemoteGc</codeph> buffer. </p> </section>
<section id="GUID-D263317D-ED6F-45D2-8F89-95891F6B7540"><title>Configuring
the emulator to panic clients that ignore the           convention</title> <p>In both ScreenPlay and the non-ScreenPlay variant, you can configure
the TechView emulator to panic clients that ignore the convention
(described above) that all drawing operations are performed as redraw
drawing. </p> <p>To enable this feature, add the following line to
the <filepath>epoc32/data/epoc.ini</filepath> file: </p> <codeblock id="GUID-50D79AD9-BB89-5A49-91A3-DDDAF9543551" xml:space="preserve">debug_wserv_exe_EnforceRedrawCallingConvention 1</codeblock> <p>This feature is disabled if you do not specify this parameter
or if you set it to zero, like this: </p> <codeblock id="GUID-ACCA692B-42C6-593E-BA02-43D2EF52E9C8" xml:space="preserve">debug_wserv_exe_EnforceRedrawCallingConvention 0</codeblock> <p>The feature takes effect in debug emulator (WINSCW) builds only—it
never affects ARM builds. </p> <p>When a Window Server panic code
79 (<codeph>EWservPanicWindowBeginRedrawNotCalled</codeph>) then occurs,
it means that a non-redraw drawing operation has occurred. </p> <p>However, the Window Server buffers client requests. This means that
the drawing that is at fault may have been issued by the client some
time earlier. It is therefore helpful to enable <i>autoflushing</i>, because this removes the buffering between the client issuing the
drawing operations and the Window Server processing them. This makes
it easier to identify the drawing operation that is at fault. </p> <p>There are three ways to enable autoflushing: </p> <ol id="GUID-22E4AACD-5718-5774-B9B1-BF28D287ED76">
<li id="GUID-EF604CC8-5138-5747-AD4F-CA8BE8DC335A"><p>To enable autoflushing
globally across all clients, define <codeph>__AUTO_FLUSH</codeph> in <filepath>client/client.h</filepath> and re-compile the Window Server code. </p> </li>
<li id="GUID-ACC8C257-1530-5808-9838-B905D2483455"><p>To enable autoflushing
in your client-side code only, call <xref href="GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9.dita#GUID-643DDA78-C7A7-386D-AB3F-8710141DDDA9/GUID-85232F8B-9FB8-3E19-9ECD-E64B63748A11"><apiname>RWsSession::SetAutoFlush(ETrue)</apiname></xref>. </p> </li>
<li id="GUID-3CCA44EB-5375-59AA-B96B-E3C3E241D88B"><p>To enable autoflushing
on an ad hoc basis in the TechView emulator, press <userinput>Ctrl-Alt-Shift-F</userinput>. </p> </li>
</ol> </section>
</conbody><related-links>
<link href="GUID-484B51EC-2209-5492-8E9C-9D792AB0DF35.dita"><linktext>Graphics
and Drawing </linktext></link>
<link href="GUID-6C16417B-5B37-5310-B59A-750D971AA6D4.dita"><linktext>The
UI Control Framework (CONE)</linktext></link>
</related-links></concept>