--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/PDK/Source/GUID-8DF46A11-874A-52E5-9298-C083EA633BA0.dita Fri Jan 22 18:26:19 2010 +0000
@@ -0,0 +1,293 @@
+<?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-8DF46A11-874A-52E5-9298-C083EA633BA0" xml:lang="en"><title>Implementing
+Dynamic DSA Allocation</title><shortdesc>This topic describes how device creators can allocate the Direct
+Screen Access (DSA) buffer dynamically. This feature is new in Symbian^3 (S^3). </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p> <b>Target audience</b>: Device creators. </p>
+<section><title>Overview</title> <p>Before the introduction of ScreenPlay,
+applications (such as video and EGL games) that required high frame rates
+used Direct Screen Access (DSA) to bypass the Window Server and draw directly
+to the frame buffer (video memory). However, some interaction with the Window
+Server was necessary in order to prevent the application from drawing over
+other applications' data. The frame buffer was allocated at device startup
+and was never freed. </p> <p>In ScreenPlay, applications that require a high
+frame rate can render directly to <xref href="GUID-ADA8CECB-0E70-5B9C-8F36-0714AAF0CD13.dita">composition
+surfaces</xref>. In ScreenPlay the Window Server's content is also rendered
+to a composition surface, which is known as the <b>UI surface</b>. This means
+that the Window Server and its render stages do not render directly to the
+frame buffer. However, DSA is still supported in order to provide backwards
+compatibility. </p> <p>The DSA buffer is now just another buffer (known as
+the <b>DSA buffer</b>), which the Window Server process makes use of only
+when a client uses DSA on a visible window. This means that it is no longer
+necessary to allocate the DSA buffer at startup and not free it. In fact to
+do so in ScreenPlay is wasteful of resources. </p> <p>For this reason, it
+is now possible to allocate the DSA buffer as a <xref href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita">shared
+chunk</xref> and free it when it is not in use. This requires changes in the
+implementation of the LCD Driver (also known as the <xref href="GUID-8C22AF20-EE0E-5AD2-BEFD-FED5A7DBB09B.dita">LCD
+Extension</xref>). For example, in order to free the DSA buffer when it is
+no longer in use, the LCD Driver must keep track of the processes that use
+the buffer and when they finish with it. These changes can be implemented
+regardless whether ScreenPlay is in use. </p> <p> <i>Note</i>: Semi-transparent
+UI content over content provided by Direct Screen Access (DSA) has never been
+supported and ScreenPlay does not change this. </p> </section>
+<section><title>DSA client-side API changes</title> <p>To use DSA, the client
+creates an instance of <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita"><apiname>CDirectScreenAccess</apiname></xref>. This allows
+the client to draw directly to the DSA buffer and to determine the visible
+area of its window and be notified when the visible area changes. DSA is typically
+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,
+applications can call the HAL user-side API (described below) to allocate
+the DSA buffer (if not already allocated) and obtain the DSA buffer's address
+directly. Clients that do this can now use DSA simply in order to be notified
+when the visible area changes and not for accessing the DSA buffer itself.
+This is called <b>region-tracking DSA</b>. (<xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref> also
+obtains the DSA address through the use of the HAL user-side API.) </p> <p>To
+use region-tracking DSA, call the following overload of the <codeph>CDirectScreenAccess::NewL()</codeph> function
+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
+therefore does not cause the DSA buffer to be allocated. </p> <p>Here is an
+example that shows how to create a <xref href="GUID-24C7AE25-B44A-3B6F-AA05-EA90A8D36129.dita"><apiname>CDirectScreenAccess</apiname></xref> object
+to track visible regions only: </p> <codeblock id="GUID-E378E1D5-C700-5AC6-AE3B-6CF9DA993671" xml:space="preserve">CDirectScreenAccess * cDsa = NULL;
+
+// Specify additional parameter to NewL to indicate region tracking only.
+cDsa = CDirectScreenAccess::NewL(TheClient->iWs,*TheClient->iScreen,*win,
+ *this, ETrue);
+
+// In this mode, the client cannot get a screen device or graphics
+// context from the DSA object.
+CFbsScreenDevice sd = cDsa->ScreenDevice();
+CFbsBitGc gc = cDsa->Gc();
+
+ASSERT(sd == NULL)
+ASSERT(gc == NULL)
+</codeblock> </section>
+<section> <title>User-side HAL API changes</title> <p>The user-side HAL API
+is a set of static functions that get and set the hardware attributes of the
+device. For general information about the interface to HAL, see <xref href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita">User-Side
+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
+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);
+static IMPORT_C TInt Get(TInt aDeviceNumber, TAttribute aAttribute,
+ TInt &aValue);</codeblock> <p>In versions earlier than S^3, in order
+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
+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,
+the call returns <codeph>KErrNone</codeph> and sets the <codeph>aValue</codeph> parameter
+to the virtual address of the DSA buffer in the caller’s process. If the DSA
+buffer cannot be allocated, the call returns <codeph>KErrNoMemory</codeph> and
+sets the <codeph>aValue</codeph> parameter to NULL. </p> <p>From S^3 onwards,
+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
+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,
+the call returns <codeph>KErrNone</codeph> and sets the <codeph>aValue</codeph> parameter
+to the value of an <xref href="GUID-326A2F4D-0E99-31C0-A35D-E8BF45913F07.dita"><apiname>RChunk</apiname></xref> handle in the caller’s process.
+If the DSA buffer cannot be allocated, the call returns <codeph>KErrNoMemory</codeph> and
+sets the <codeph>aValue</codeph> parameter to 0. </p> <p>The advantage of
+using a handle is twofold: </p> <ul>
+<li id="GUID-187317E0-0EED-5C8F-AB31-542D6EA0CBF2"><p>The memory chunk exists
+for as long as the handle is open. </p> </li>
+<li id="GUID-7984A11D-F7A2-5C1A-AB11-628911BCA292"><p>The handle is automatically
+closed by the kernel if the process holding it exits prematurely. </p> </li>
+</ul> <p>When possible, legacy clients should be changed to take advantage
+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
+means that you need to modify <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> calls
+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
+to the DSA's shared chunk. You also need to add code to close this handle
+when the memory is no longer required. </p> <p>For example, replace the following
+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);
+if (err == KErrNone)
+ {
+ RChunk chunk;
+ err = chunk.SetReturnedHandle(val);
+ if (err == KErrNone)
+ {
+ iDSAChunk = chunk;
+ err = iDSAChunk.Duplicate(RThread(), EOwnerProcess);
+ chunk.Close();
+ if (err == KErrNone)
+ {
+ dsaAddr = (TInt) iDSAChunk.Base();
+ }
+else if (err == KErrNotSupported)
+ {
+ err = HAL::Get(screenId, HALData::EDisplayMemoryAddress, dsaAddr);
+ }
+</codeblock> </section>
+<section><title>Kernel-side HAL changes</title> <p>HAL requests are handled
+on the kernel side by HAL handlers. A single HAL handler deals with all the
+HAL attributes defined in a particular HAL group. Each HAL group has a one-to-one
+relationship with a HAL handler. <codeph>EHalGroupDisplay</codeph> identifies
+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
+has two new attributes—<codeph>EDisplayHalGetDisplayMemoryAddress</codeph> and <codeph>EDisplayHalGetDisplayMemoryHandle</codeph>.
+These allow the generic user-side HAL code to obtain the DSA buffer's address
+and handle independently of all of the other display attributes. </p> </section>
+<section><title>Handling HAL::Get(EDisplayMemoryAddress)</title> <p>In versions
+earlier than S^3, the DSA buffer address is returned from the HAL handler
+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.
+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
+and returns it. </p> <p><b>Configuration file setting </b> </p> <p>The HAL
+configuration file <filepath>config.hcf</filepath> therefore includes the
+following: </p> <codeblock id="GUID-F496B803-B7B8-57D4-B083-9219D4F849DB" xml:space="preserve">EDisplayMemoryAddress=ProcessDisplayCurrentModeInfo</codeblock> <p><b>Modifications
+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:
+
+// If the address is zero, the actual address
+// is returned by EDisplayHalGetDisplayMemoryAddress
+if (info.iVideoAddress == 0)
+ {
+ r = UserSvr::HalFunction(EHalGroupDisplay,
+ EDisplayHalGetDisplayMemoryAddress,
+ aInOut, (TAny*)EFalse, aDeviceNumber);
+ }
+else
+ {
+ *(TInt*)aInOut = info.iVideoAddress;
+ }
+break;
+</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
+the input parameters passed to the HAL handler to -1. You can use this in
+the LCD Driver to determine whether the call for the DSA buffer's address
+is from <codeph>HAL::GetAll()</codeph> and if it is, to not allocate the memory.
+For example: </p> <codeblock id="GUID-8734B0EF-A2A2-5929-972F-56F7E0195940" xml:space="preserve">case EDisplayHalGetDisplayMemoryAddress:
+ {
+ TInt val = 0;
+ TInt passedIn = 0;
+ kumemget32(&passedIn, a1, sizeof(TInt));
+
+ // Not from a GetAll().
+ if (passedIn != -1)
+ {
+ r = DisplayMemoryAddress(aDeviceNumber, val);
+ }
+ else
+ {
+ r = KErrNone;
+ }
+
+ // Write the value returned back to the user side.
+ kumemput32(a1, &val, sizeof(TInt));
+ }
+ break;
+</codeblock> <p><b>Keeping track of processes that call HAL::Get(EDisplayMemoryAddress) </b> </p> <p>Legacy
+DSA clients request the DSA buffer address rather than the handle and assume
+that the address will remain valid for the lifetime of the process. The LCD
+Driver needs to keep track of processes that call <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> and
+free the DSA buffer when the last of these processes has exited. </p> <p>The
+LCD Driver must therefore maintain a list of the relevant processes and the
+address of the DSA buffer for each one. When the number of processes using
+a buffer address returns to zero, the buffer is freed. </p> <p>To track the
+usage, the LCD Driver creates a new shared chunk for each process that calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph>.
+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
+create a user handle to the shared chunk for the calling process. The LCD
+Driver closes the kernel-side handle to the chunk. </p> <p>There is then a
+handle to the shared chunk in the user process, which means that the shared
+chunk stays open for as long as the process exists. When the user process
+exits, the kernel closes any open handles that the process owns. This causes
+the deletion of the shared chunk and its Deferred Function Call (DFC) to run.
+The DFC removes the process from the list and decrements the reference count
+of users of the DSA memory. </p> <p>Here is the sequence when a process calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> for
+the first time: </p> <ol id="GUID-DA7B9F91-6F52-532C-8E67-8DE89B1EFD42">
+<li id="GUID-2055954D-2B13-5307-93A6-78936172416C"><p>Legacy process <i>X</i> implicitly
+calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> for the first time
+by creating a DSA session that creates a <xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref>. </p> </li>
+<li id="GUID-33A00E2F-B04C-51CE-9993-661DFF5BE00B"><p>The driver looks for
+process <i>X</i> in the list of processes and addresses and does not find
+it. </p> </li>
+<li id="GUID-A8E33530-C089-5C85-9563-A39BBA9259F2"><p>The driver creates a
+shared chunk for process <i>X</i> with a destruction DFC. </p> </li>
+<li id="GUID-19CDF330-315D-5806-AB3D-9AB8857A02A4"><p>The driver creates a
+user-side handle to the shared chunk. </p> </li>
+<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
+to the shared chunk. </p> </li>
+<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*
+Kern::ChunkUserBase(DChunk* aChunk, DThread* aThread)</apiname></xref> to
+get the address of the shared chunk in the user process . </p> </li>
+<li id="GUID-0180A075-BF6B-53E4-8B6F-38BE083C58DA"><p>The driver stores the
+calling process's ID and the address of the shared chunk in a table. </p> </li>
+<li id="GUID-3663A069-09FA-55DF-9EA7-F1875B379569"><p>The driver returns the
+address of the shared chunk to the calling process. </p> </li>
+</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">
+<li id="GUID-57947C06-0BA1-5CB0-AB3F-493D71510A95"><p>Legacy process <i>X</i> implicitly
+calls <codeph>HAL::Get(EDisplayMemoryAddress)</codeph> again by creating a
+DSA session that creates a <xref href="GUID-B229156F-2344-3F46-8542-AC65882D80DE.dita"><apiname>CFbsScreenDevice</apiname></xref>. </p> </li>
+<li id="GUID-493E5ABC-5032-5653-A87B-27441F0AF88E"><p>The driver looks for
+the process in the list of processes and addresses. </p> </li>
+<li id="GUID-6CF1A43C-966E-59EF-BA68-BB1D5CA5A4F0"><p>The driver returns the
+address previously given to the process. </p> </li>
+</ol> <p>Here is the sequence when the same process exits: </p> <ol id="GUID-388DC71E-FD9B-5A56-8B3D-520159FA8939">
+<li id="GUID-B95DB340-C730-5419-ADB8-0B5B10F46556"><p>The kernel cleans up
+any open handles for the exiting process. </p> </li>
+<li id="GUID-E8654886-77E4-5748-A0BE-A0E3CCCC752A"><p>The shared chunk destruction
+DFC executes and removes the process from the list and decrements the DSA
+usage count. </p> </li>
+<li id="GUID-68624448-1DCF-591E-97EF-F0B46F656FC8"><p>The DFC checks the DSA
+usage count and if it is zero, the DFC frees the DSA memory. </p> </li>
+</ol> </section>
+<section><title>Handling HAL::Get(EDisplayMemoryHandle)</title> <p>In S^3
+there is a new <codeph>GetDisplayMemoryHandle()</codeph> function in the user-side
+HAL implementation. This function is the handler for the new <codeph>EDisplayMemoryHandle</codeph> attribute. </p> <p><b>Configuration
+file setting </b> </p> <p>The following line therefore needs to be added to
+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
+the input parameters passed to the HAL handler to -1. You can use this in
+the LCD Driver to determine whether the call for the DSA buffer's address
+handle is from <codeph>HAL::GetAll()</codeph> and to take appropriate action.
+For example: </p> <codeblock id="GUID-22A22111-1B29-59F4-B3F7-83E43077E0FD" xml:space="preserve">case EDisplayHalGetDisplayMemoryHandle:
+ {
+ TInt val = 0;
+ TInt passedIn = 0;
+ kumemget32(&passedIn, a1, sizeof(TInt));
+
+ // Not from a GetAll().
+ if (passedIn != -1)
+ {
+ r = CreateNewChunkToRepresentDSABuffer(aDeviceNumber, val);
+ }
+ else
+ {
+ r = KErrNone;
+ }
+
+
+ kumemput32(a1, &val, sizeof(TInt));
+ }
+ break;
+</codeblock> <p><b>Keeping track of processes that call HAL::Get(EDisplayMemoryHandle) </b> </p> <p>New
+DSA clients request the DSA buffer handle rather than the address. After a
+process obtains the handle, the DSA buffer is in use for this process until
+the handle is closed or the process exits (which implicitly closes the handle). </p> <p>To
+track the usage, the LCD Driver creates a new shared chunk every time a process
+calls <codeph>HAL::Get(EDisplayMemoryHandle)</codeph>. 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 create a user handle
+to the shared chunk for the calling process. The LCD Driver closes the kernel-side
+handle to the shared chunk and returns the user-side handle to the calling
+process. </p> <p>When the user process closes the handle, the shared chunk
+is deleted and its deletion DFC runs. The DFC decrements the reference count
+of users of the DSA memory. </p> <p>Here is the sequence when a process calls <codeph>HAL::Get(EDisplayMemoryHandle)</codeph> for
+the first time: </p> <ol id="GUID-A92B09E9-5E76-5B6C-B281-64A4F4A65467">
+<li id="GUID-0CF94725-F9BA-5C92-9429-4206D38040CF"><p>The driver creates a
+new shared chunk for this process with a destruction DFC. </p> </li>
+<li id="GUID-8521F99F-A890-5F82-9EB0-C0C1E9ABDE5B"><p>The driver creates a
+user-side handle to the shared chunk. </p> </li>
+<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
+to the shared chunk. </p> </li>
+<li id="GUID-F705B1B9-F9F4-56F2-800B-93E4B8FBE75B"><p>The driver returns the
+user-side handle to the calling process. </p> </li>
+</ol> <p>Here is the sequence when a process closes the DSA buffer: </p> <ol id="GUID-2310D2DC-76BA-5B87-A964-DCA01051CB3E">
+<li id="GUID-65CE3E41-D418-59C5-A0FA-A90195A7FE23"><p>The shared chunk destruction
+DFC executes and decrements the DSA usage count. </p> </li>
+<li id="GUID-96386F96-FF1E-5BD3-B98A-E0B180463AFB"><p>The DFC checks the DSA
+usage count and if it is zero, the DFC frees the DSA memory. </p> </li>
+</ol> </section>
+</conbody><related-links>
+<link href="GUID-8C22AF20-EE0E-5AD2-BEFD-FED5A7DBB09B.dita"><linktext>LCD Extension</linktext>
+</link>
+<link href="GUID-51514A4B-0220-557B-9F7A-FB110CEFEF10.dita"><linktext>Shared Chunks</linktext>
+</link>
+<link href="GUID-9AE254D4-AA60-579E-8D9D-F2797106A413.dita"><linktext>User-Side
+Hardware Abstraction Technology</linktext></link>
+<link href="GUID-4C166A49-31F7-5315-B797-F97DB52600BC.dita"><linktext>Display Driver
+Component</linktext></link>
+</related-links></concept>
\ No newline at end of file