|
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-8DF46A11-874A-52E5-9298-C083EA633BA0" xml:lang="en"><title>Implementing |
|
13 Dynamic DSA Allocation</title><shortdesc>This topic describes how device creators can allocate the Direct |
|
14 Screen Access (DSA) buffer dynamically. This feature is new in Symbian^3 (S^3). </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <p> <b>Target audience</b>: Device creators. </p> |
|
16 <section><title>Overview</title> <p>Before the introduction of ScreenPlay, |
|
17 applications (such as video and EGL games) that required high frame rates |
|
18 used Direct Screen Access (DSA) to bypass the Window Server and draw directly |
|
19 to the frame buffer (video memory). However, some interaction with the Window |
|
20 Server was necessary in order to prevent the application from drawing over |
|
21 other applications' data. The frame buffer was allocated at device startup |
|
22 and was never freed. </p> <p>In ScreenPlay, applications that require a high |
|
23 frame rate can render directly to <xref href="GUID-ADA8CECB-0E70-5B9C-8F36-0714AAF0CD13.dita">composition |
|
24 surfaces</xref>. In ScreenPlay the Window Server's content is also rendered |
|
25 to a composition surface, which is known as the <b>UI surface</b>. This means |
|
26 that the Window Server and its render stages do not render directly to the |
|
27 frame buffer. However, DSA is still supported in order to provide backwards |
|
28 compatibility. </p> <p>The DSA buffer is now just another buffer (known as |
|
29 the <b>DSA buffer</b>), which the Window Server process makes use of only |
|
30 when a client uses DSA on a visible window. This means that it is no longer |
|
31 necessary to allocate the DSA buffer at startup and not free it. In fact to |
|
32 do so in ScreenPlay is wasteful of resources. </p> <p>For this reason, it |
|
33 is now possible to allocate the DSA buffer as a <xref href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita">shared |
|
34 chunk</xref> and free it when it is not in use. This requires changes in the |
|
35 implementation of the LCD Driver (also known as the <xref href="GUID-8C22AF20-EE0E-5AD2-BEFD-FED5A7DBB09B.dita">LCD |
|
36 Extension</xref>). For example, in order to free the DSA buffer when it is |
|
37 no longer in use, the LCD Driver must keep track of the processes that use |
|
38 the buffer and when they finish with it. These changes can be implemented |
|
39 regardless whether ScreenPlay is in use. </p> <p> <i>Note</i>: Semi-transparent |
|
40 UI content over content provided by Direct Screen Access (DSA) has never been |
|
41 supported and ScreenPlay does not change this. </p> </section> |
|
42 <section><title>DSA client-side API changes</title> <p>To use DSA, the client |
|
43 creates an instance of <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita"><apiname>CDirectScreenAccess</apiname></xref>. This allows |
|
44 the client to draw directly to the DSA buffer and to determine the visible |
|
45 area of its window and be notified when the visible area changes. DSA is typically |
|
46 performed by using the <xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref> returned by <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita#GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129/GUID-9528CBFF-7D01-3B62-81B1-7F9B2C799C14"><apiname>CDirectScreenAccess::ScreenDevice()</apiname></xref>. </p> <p>However, |
|
47 applications can call the HAL user-side API (described below) to allocate |
|
48 the DSA buffer (if not already allocated) and obtain the DSA buffer's address |
|
49 directly. Clients that do this can now use DSA simply in order to be notified |
|
50 when the visible area changes and not for accessing the DSA buffer itself. |
|
51 This is called <b>region-tracking DSA</b>. (<xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref> also |
|
52 obtains the DSA address through the use of the HAL user-side API.) </p> <p>To |
|
53 use region-tracking DSA, call the following overload of the <codeph>CDirectScreenAccess::NewL()</codeph> function |
|
54 and pass <codeph>ETrue</codeph> as the final argument: </p> <p> <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita#GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129/GUID-6C26D5CD-0B55-3D30-B365-9C431BDD3721"><apiname>CDirectScreenAccess::NewL(RWsSession&,CWsScreenDevice&,RWindowBase&,MDirectScreenAccess&,TBool)</apiname></xref> </p> <p>This does not allocate a screen device and graphics context. It |
|
55 therefore does not cause the DSA buffer to be allocated. </p> <p>Here is an |
|
56 example that shows how to create a <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita"><apiname>CDirectScreenAccess</apiname></xref> object |
|
57 to track visible regions only: </p> <codeblock id="GUID-E378E1D5-C700-5AC6-AE3B-6CF9DA993671" xml:space="preserve">CDirectScreenAccess * cDsa = NULL; |
|
58 |
|
59 // Specify additional parameter to NewL to indicate region tracking only. |
|
60 cDsa = CDirectScreenAccess::NewL(TheClient->iWs,*TheClient->iScreen,*win, |
|
61 *this, ETrue); |
|
62 |
|
63 // In this mode, the client cannot get a screen device or graphics |
|
64 // context from the DSA object. |
|
65 CFbsScreenDevice sd = cDsa->ScreenDevice(); |
|
66 CFbsBitGc gc = cDsa->Gc(); |
|
67 |
|
68 ASSERT(sd == NULL) |
|
69 ASSERT(gc == NULL) |
|
70 </codeblock> </section> |
|
71 <section> <title>User-side HAL API changes</title> <p>The user-side HAL API |
|
72 is a set of static functions that get and set the hardware attributes of the |
|
73 device. For general information about the interface to HAL, see <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita">User-Side |
|
74 Hardware Abstraction Technology</xref>. </p> <p>The <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> function |
|
75 is used to obtain information about the DSA buffer memory. </p> <codeblock id="GUID-A50C3B6C-364C-58B8-B5FC-6472C5C8FF09" xml:space="preserve">static IMPORT_C TInt Get(TAttribute aAttribute, TInt &aValue); |
|
76 static IMPORT_C TInt Get(TInt aDeviceNumber, TAttribute aAttribute, |
|
77 TInt &aValue);</codeblock> <p>In versions earlier than S^3, in order |
|
78 to obtain the memory address of the DSA buffer, a client calls <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> with |
|
79 an attribute of <xref href="GUID-8BE90160-2C60-3582-82C8-4A108C7C0317.dita#GUID-8BE90160-2C60-3582-82C8-4A108C7C0317/GUID-4702237B-185B-33B1-B0B6-DE388DBDE294"><apiname>HALData::EDisplayMemoryAddress</apiname></xref>. If successful, |
|
80 the call returns <codeph>KErrNone</codeph> and sets the <codeph>aValue</codeph> parameter |
|
81 to the virtual address of the DSA buffer in the caller’s process. If the DSA |
|
82 buffer cannot be allocated, the call returns <codeph>KErrNoMemory</codeph> and |
|
83 sets the <codeph>aValue</codeph> parameter to NULL. </p> <p>From S^3 onwards, |
|
84 a client can obtain a handle to the DSA buffer by calling <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> with |
|
85 an attribute of <xref href="GUID-8BE90160-2C60-3582-82C8-4A108C7C0317.dita#GUID-8BE90160-2C60-3582-82C8-4A108C7C0317/GUID-6124E485-D8A6-3399-AA6C-7021D130591D"><apiname>HALData::EDisplayMemoryHandle</apiname></xref>. If successful, |
|
86 the call returns <codeph>KErrNone</codeph> and sets the <codeph>aValue</codeph> parameter |
|
87 to the value of an <xref href="GUID-326A2F4D-0E99-31C0-A35D-E8BF45913F07.dita"><apiname>RChunk</apiname></xref> handle in the caller’s process. |
|
88 If the DSA buffer cannot be allocated, the call returns <codeph>KErrNoMemory</codeph> and |
|
89 sets the <codeph>aValue</codeph> parameter to 0. </p> <p>The advantage of |
|
90 using a handle is twofold: </p> <ul> |
|
91 <li id="GUID-187317E0-0EED-5C8F-AB31-542D6EA0CBF2"><p>The memory chunk exists |
|
92 for as long as the handle is open. </p> </li> |
|
93 <li id="GUID-7984A11D-F7A2-5C1A-AB11-628911BCA292"><p>The handle is automatically |
|
94 closed by the kernel if the process holding it exits prematurely. </p> </li> |
|
95 </ul> <p>When possible, legacy clients should be changed to take advantage |
|
96 of the new <xref href="GUID-8BE90160-2C60-3582-82C8-4A108C7C0317.dita#GUID-8BE90160-2C60-3582-82C8-4A108C7C0317/GUID-6124E485-D8A6-3399-AA6C-7021D130591D"><apiname>HALData::EDisplayMemoryHandle</apiname></xref> attribute. This |
|
97 means that you need to modify <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> calls |
|
98 to use <xref href="GUID-8BE90160-2C60-3582-82C8-4A108C7C0317.dita#GUID-8BE90160-2C60-3582-82C8-4A108C7C0317/GUID-6124E485-D8A6-3399-AA6C-7021D130591D"><apiname>HALData::EDisplayMemoryHandle</apiname></xref> to obtain a handle |
|
99 to the DSA's shared chunk. You also need to add code to close this handle |
|
100 when the memory is no longer required. </p> <p>For example, replace the following |
|
101 code: </p> <codeblock id="GUID-DAB0136B-A5A9-5B15-9C88-1A37B04804AB" xml:space="preserve">err = HAL::Get(screenId, HALData::EDisplayMemoryAddress, dsaAddr);</codeblock> <p>With something like this: </p> <codeblock id="GUID-BD8049BB-378C-5C56-A19B-96227C71A325" xml:space="preserve">err = HAL::Get(screenId, HALData::EDisplayMemoryHandle, val); |
|
102 if (err == KErrNone) |
|
103 { |
|
104 RChunk chunk; |
|
105 err = chunk.SetReturnedHandle(val); |
|
106 if (err == KErrNone) |
|
107 { |
|
108 iDSAChunk = chunk; |
|
109 err = iDSAChunk.Duplicate(RThread(), EOwnerProcess); |
|
110 chunk.Close(); |
|
111 if (err == KErrNone) |
|
112 { |
|
113 dsaAddr = (TInt) iDSAChunk.Base(); |
|
114 } |
|
115 else if (err == KErrNotSupported) |
|
116 { |
|
117 err = HAL::Get(screenId, HALData::EDisplayMemoryAddress, dsaAddr); |
|
118 } |
|
119 </codeblock> </section> |
|
120 <section><title>Kernel-side HAL changes</title> <p>HAL requests are handled |
|
121 on the kernel side by HAL handlers. A single HAL handler deals with all the |
|
122 HAL attributes defined in a particular HAL group. Each HAL group has a one-to-one |
|
123 relationship with a HAL handler. <codeph>EHalGroupDisplay</codeph> identifies |
|
124 the group associated with the HAL display attributes. </p> <p>In S^3 the <xref href="GUID-BB011D9B-105F-345C-9FC0-39B0BA509394.dita"><apiname>TDisplayHalFunction</apiname></xref> enum |
|
125 has two new attributes—<codeph>EDisplayHalGetDisplayMemoryAddress</codeph> and <codeph>EDisplayHalGetDisplayMemoryHandle</codeph>. |
|
126 These allow the generic user-side HAL code to obtain the DSA buffer's address |
|
127 and handle independently of all of the other display attributes. </p> </section> |
|
128 <section><title>Handling HAL::Get(EDisplayMemoryAddress)</title> <p>In versions |
|
129 earlier than S^3, the DSA buffer address is returned from the HAL handler |
|
130 as part of a <xref href="GUID-C4712A78-6C58-39ED-AF84-11038DB8571D.dita"><apiname>TVideoInfoV01</apiname></xref> class in response to an <codeph>EDisplayHalCurrentModeInfo</codeph> request. |
|
131 The user-side HAL code then extracts the address from the <xref href="GUID-C4712A78-6C58-39ED-AF84-11038DB8571D.dita"><apiname>TVideoInfoV01</apiname></xref> structure |
|
132 and returns it. </p> <p><b>Configuration file setting </b> </p> <p>The HAL |
|
133 configuration file <filepath>config.hcf</filepath> therefore includes the |
|
134 following: </p> <codeblock id="GUID-F496B803-B7B8-57D4-B083-9219D4F849DB" xml:space="preserve">EDisplayMemoryAddress=ProcessDisplayCurrentModeInfo</codeblock> <p><b>Modifications |
|
135 to generic HAL code </b> </p> <p>In S^3 the switch case for <codeph>EDisplayMemoryAddress</codeph> in <codeph>ProcessDisplayCurrentModeInfo()</codeph> is as follows: </p> <codeblock id="GUID-7E2FC07B-670D-57BA-BF3E-A4432BF83E81" xml:space="preserve">case HAL::EDisplayMemoryAddress: |
|
136 |
|
137 // If the address is zero, the actual address |
|
138 // is returned by EDisplayHalGetDisplayMemoryAddress |
|
139 if (info.iVideoAddress == 0) |
|
140 { |
|
141 r = UserSvr::HalFunction(EHalGroupDisplay, |
|
142 EDisplayHalGetDisplayMemoryAddress, |
|
143 aInOut, (TAny*)EFalse, aDeviceNumber); |
|
144 } |
|
145 else |
|
146 { |
|
147 *(TInt*)aInOut = info.iVideoAddress; |
|
148 } |
|
149 break; |
|
150 </codeblock> <p><b>Dealing with HAL::GetAll() </b> </p> <p> <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-EF03B832-E9AA-32CF-903F-DFFA63A3E9AB"><apiname>HAL::GetAll()</apiname></xref> sets |
|
151 the input parameters passed to the HAL handler to -1. You can use this in |
|
152 the LCD Driver to determine whether the call for the DSA buffer's address |
|
153 is from <codeph>HAL::GetAll()</codeph> and if it is, to not allocate the memory. |
|
154 For example: </p> <codeblock id="GUID-8734B0EF-A2A2-5929-972F-56F7E0195940" xml:space="preserve">case EDisplayHalGetDisplayMemoryAddress: |
|
155 { |
|
156 TInt val = 0; |
|
157 TInt passedIn = 0; |
|
158 kumemget32(&passedIn, a1, sizeof(TInt)); |
|
159 |
|
160 // Not from a GetAll(). |
|
161 if (passedIn != -1) |
|
162 { |
|
163 r = DisplayMemoryAddress(aDeviceNumber, val); |
|
164 } |
|
165 else |
|
166 { |
|
167 r = KErrNone; |
|
168 } |
|
169 |
|
170 // Write the value returned back to the user side. |
|
171 kumemput32(a1, &val, sizeof(TInt)); |
|
172 } |
|
173 break; |
|
174 </codeblock> <p><b>Keeping track of processes that call HAL::Get(EDisplayMemoryAddress) </b> </p> <p>Legacy |
|
175 DSA clients request the DSA buffer address rather than the handle and assume |
|
176 that the address will remain valid for the lifetime of the process. The LCD |
|
177 Driver needs to keep track of processes that call <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> and |
|
178 free the DSA buffer when the last of these processes has exited. </p> <p>The |
|
179 LCD Driver must therefore maintain a list of the relevant processes and the |
|
180 address of the DSA buffer for each one. When the number of processes using |
|
181 a buffer address returns to zero, the buffer is freed. </p> <p>To track the |
|
182 usage, the LCD Driver creates a new shared chunk for each process that calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph>. |
|
183 The LCD Driver then calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-BA56B205-60D8-326E-8340-3F78CCEA3DD1"><apiname>Kern::MakeHandleAndOpen()</apiname></xref> to |
|
184 create a user handle to the shared chunk for the calling process. The LCD |
|
185 Driver closes the kernel-side handle to the chunk. </p> <p>There is then a |
|
186 handle to the shared chunk in the user process, which means that the shared |
|
187 chunk stays open for as long as the process exists. When the user process |
|
188 exits, the kernel closes any open handles that the process owns. This causes |
|
189 the deletion of the shared chunk and its Deferred Function Call (DFC) to run. |
|
190 The DFC removes the process from the list and decrements the reference count |
|
191 of users of the DSA memory. </p> <p>Here is the sequence when a process calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> for |
|
192 the first time: </p> <ol id="GUID-DA7B9F91-6F52-532C-8E67-8DE89B1EFD42"> |
|
193 <li id="GUID-2055954D-2B13-5307-93A6-78936172416C"><p>Legacy process <i>X</i> implicitly |
|
194 calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> for the first time |
|
195 by creating a DSA session that creates a <xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref>. </p> </li> |
|
196 <li id="GUID-33A00E2F-B04C-51CE-9993-661DFF5BE00B"><p>The driver looks for |
|
197 process <i>X</i> in the list of processes and addresses and does not find |
|
198 it. </p> </li> |
|
199 <li id="GUID-A8E33530-C089-5C85-9563-A39BBA9259F2"><p>The driver creates a |
|
200 shared chunk for process <i>X</i> with a destruction DFC. </p> </li> |
|
201 <li id="GUID-19CDF330-315D-5806-AB3D-9AB8857A02A4"><p>The driver creates a |
|
202 user-side handle to the shared chunk. </p> </li> |
|
203 <li id="GUID-E13883F3-6418-5920-A16A-8327744E6AF1"><p>The driver closes its <xref href="GUID-85454082-6734-3F1D-983F-734D4C2AB12D.dita"><apiname>DChunk</apiname></xref> handle |
|
204 to the shared chunk. </p> </li> |
|
205 <li id="GUID-8CF22900-AD3C-528D-B88A-74AC59BAAA20"><p>The driver calls <xref href="GUID-AC098719-7AD6-3B48-9BE3-7DCEADA3530B.dita#GUID-AC098719-7AD6-3B48-9BE3-7DCEADA3530B/GUID-0632CC60-AF0C-36F5-8E8F-3D8AD2568E31"><apiname>TUint8* |
|
206 Kern::ChunkUserBase(DChunk* aChunk, DThread* aThread)</apiname></xref> to |
|
207 get the address of the shared chunk in the user process . </p> </li> |
|
208 <li id="GUID-0180A075-BF6B-53E4-8B6F-38BE083C58DA"><p>The driver stores the |
|
209 calling process's ID and the address of the shared chunk in a table. </p> </li> |
|
210 <li id="GUID-3663A069-09FA-55DF-9EA7-F1875B379569"><p>The driver returns the |
|
211 address of the shared chunk to the calling process. </p> </li> |
|
212 </ol> <p>Here is the sequence when the same process calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> again: </p> <ol id="GUID-E7D5E120-364C-5CA6-BE4E-56563F58A293"> |
|
213 <li id="GUID-57947C06-0BA1-5CB0-AB3F-493D71510A95"><p>Legacy process <i>X</i> implicitly |
|
214 calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> again by creating a |
|
215 DSA session that creates a <xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref>. </p> </li> |
|
216 <li id="GUID-493E5ABC-5032-5653-A87B-27441F0AF88E"><p>The driver looks for |
|
217 the process in the list of processes and addresses. </p> </li> |
|
218 <li id="GUID-6CF1A43C-966E-59EF-BA68-BB1D5CA5A4F0"><p>The driver returns the |
|
219 address previously given to the process. </p> </li> |
|
220 </ol> <p>Here is the sequence when the same process exits: </p> <ol id="GUID-388DC71E-FD9B-5A56-8B3D-520159FA8939"> |
|
221 <li id="GUID-B95DB340-C730-5419-ADB8-0B5B10F46556"><p>The kernel cleans up |
|
222 any open handles for the exiting process. </p> </li> |
|
223 <li id="GUID-E8654886-77E4-5748-A0BE-A0E3CCCC752A"><p>The shared chunk destruction |
|
224 DFC executes and removes the process from the list and decrements the DSA |
|
225 usage count. </p> </li> |
|
226 <li id="GUID-68624448-1DCF-591E-97EF-F0B46F656FC8"><p>The DFC checks the DSA |
|
227 usage count and if it is zero, the DFC frees the DSA memory. </p> </li> |
|
228 </ol> </section> |
|
229 <section><title>Handling HAL::Get(EDisplayMemoryHandle)</title> <p>In S^3 |
|
230 there is a new <codeph>GetDisplayMemoryHandle()</codeph> function in the user-side |
|
231 HAL implementation. This function is the handler for the new <codeph>EDisplayMemoryHandle</codeph> attribute. </p> <p><b>Configuration |
|
232 file setting </b> </p> <p>The following line therefore needs to be added to |
|
233 the <filepath>config.hcf</filepath> file: </p> <codeblock id="GUID-90AEC511-D592-5755-A569-7703A09EE40C" xml:space="preserve">EDisplayMemoryHandle=GetDisplayMemoryHandle</codeblock> <p><b>Dealing with HAL::GetAll() </b> </p> <p> <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-EF03B832-E9AA-32CF-903F-DFFA63A3E9AB"><apiname>HAL::GetAll()</apiname></xref> sets |
|
234 the input parameters passed to the HAL handler to -1. You can use this in |
|
235 the LCD Driver to determine whether the call for the DSA buffer's address |
|
236 handle is from <codeph>HAL::GetAll()</codeph> and to take appropriate action. |
|
237 For example: </p> <codeblock id="GUID-22A22111-1B29-59F4-B3F7-83E43077E0FD" xml:space="preserve">case EDisplayHalGetDisplayMemoryHandle: |
|
238 { |
|
239 TInt val = 0; |
|
240 TInt passedIn = 0; |
|
241 kumemget32(&passedIn, a1, sizeof(TInt)); |
|
242 |
|
243 // Not from a GetAll(). |
|
244 if (passedIn != -1) |
|
245 { |
|
246 r = CreateNewChunkToRepresentDSABuffer(aDeviceNumber, val); |
|
247 } |
|
248 else |
|
249 { |
|
250 r = KErrNone; |
|
251 } |
|
252 |
|
253 |
|
254 kumemput32(a1, &val, sizeof(TInt)); |
|
255 } |
|
256 break; |
|
257 </codeblock> <p><b>Keeping track of processes that call HAL::Get(EDisplayMemoryHandle) </b> </p> <p>New |
|
258 DSA clients request the DSA buffer handle rather than the address. After a |
|
259 process obtains the handle, the DSA buffer is in use for this process until |
|
260 the handle is closed or the process exits (which implicitly closes the handle). </p> <p>To |
|
261 track the usage, the LCD Driver creates a new shared chunk every time a process |
|
262 calls <codeph>HAL::Get(EDisplayMemoryHandle)</codeph>. The LCD Driver then |
|
263 calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-BA56B205-60D8-326E-8340-3F78CCEA3DD1"><apiname>Kern::MakeHandleAndOpen()</apiname></xref> to create a user handle |
|
264 to the shared chunk for the calling process. The LCD Driver closes the kernel-side |
|
265 handle to the shared chunk and returns the user-side handle to the calling |
|
266 process. </p> <p>When the user process closes the handle, the shared chunk |
|
267 is deleted and its deletion DFC runs. The DFC decrements the reference count |
|
268 of users of the DSA memory. </p> <p>Here is the sequence when a process calls <codeph>HAL::Get(EDisplayMemoryHandle)</codeph> for |
|
269 the first time: </p> <ol id="GUID-A92B09E9-5E76-5B6C-B281-64A4F4A65467"> |
|
270 <li id="GUID-0CF94725-F9BA-5C92-9429-4206D38040CF"><p>The driver creates a |
|
271 new shared chunk for this process with a destruction DFC. </p> </li> |
|
272 <li id="GUID-8521F99F-A890-5F82-9EB0-C0C1E9ABDE5B"><p>The driver creates a |
|
273 user-side handle to the shared chunk. </p> </li> |
|
274 <li id="GUID-876EECF6-BC1C-5E57-8555-55D3F5AD01E3"><p>The driver closes its <xref href="GUID-85454082-6734-3F1D-983F-734D4C2AB12D.dita"><apiname>DChunk</apiname></xref> handle |
|
275 to the shared chunk. </p> </li> |
|
276 <li id="GUID-F705B1B9-F9F4-56F2-800B-93E4B8FBE75B"><p>The driver returns the |
|
277 user-side handle to the calling process. </p> </li> |
|
278 </ol> <p>Here is the sequence when a process closes the DSA buffer: </p> <ol id="GUID-2310D2DC-76BA-5B87-A964-DCA01051CB3E"> |
|
279 <li id="GUID-65CE3E41-D418-59C5-A0FA-A90195A7FE23"><p>The shared chunk destruction |
|
280 DFC executes and decrements the DSA usage count. </p> </li> |
|
281 <li id="GUID-96386F96-FF1E-5BD3-B98A-E0B180463AFB"><p>The DFC checks the DSA |
|
282 usage count and if it is zero, the DFC frees the DSA memory. </p> </li> |
|
283 </ol> </section> |
|
284 </conbody><related-links> |
|
285 <link href="GUID-8C22AF20-EE0E-5AD2-BEFD-FED5A7DBB09B.dita"><linktext>LCD Extension</linktext> |
|
286 </link> |
|
287 <link href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita"><linktext>Shared Chunks</linktext> |
|
288 </link> |
|
289 <link href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita"><linktext>User-Side |
|
290 Hardware Abstraction Technology</linktext></link> |
|
291 <link href="GUID-4C166A49-31F7-5315-B797-F97DB52600BC.dita"><linktext>Display Driver |
|
292 Component</linktext></link> |
|
293 </related-links></concept> |