sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @publishedPartner sl@0: @prototype sl@0: sl@0: */ sl@0: sl@0: #include "surfacemanager.h" sl@0: #include sl@0: #include "surfacemanagerdriver.h" sl@0: sl@0: sl@0: /** sl@0: Default constructor sl@0: */ sl@0: EXPORT_C RSurfaceManager::RSurfaceManager() sl@0: { sl@0: __ASSERT_COMPILE(sizeof(RSurfaceManagerDriver) <= sizeof(iDriverBuf)); sl@0: new(iDriverBuf) RSurfaceManagerDriver(); sl@0: } sl@0: sl@0: /** sl@0: Opens a connection to the Surface Manager. sl@0: sl@0: The connection needs to be closed by calling Close() when it is no longer required. sl@0: @return Returns KErrNone if successful, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::Open() sl@0: { sl@0: TInt err = User::LoadLogicalDevice( RSurfaceManagerDriver::Name() ); sl@0: if(! ((KErrNone == err) || (KErrAlreadyExists == err))) sl@0: { sl@0: return err; sl@0: } sl@0: return Driver().Open(); sl@0: } sl@0: sl@0: /** sl@0: Closes the connection to the Surface Manager. sl@0: sl@0: Cleanup is performed by the Surface Manager when a client process exits or sl@0: closes its last connection. It is not guaranteed that the resources held by the sl@0: Surface Manager are going to be released synchronously. sl@0: */ sl@0: EXPORT_C void RSurfaceManager::Close() sl@0: { sl@0: Driver().Close(); sl@0: } sl@0: sl@0: /** sl@0: Returns information specific to the Surface Manager implementation. sl@0: @param aAttrib Attribute to retrieve sl@0: @param aValue Output parameter set to the value for the specified attribute sl@0: @return KErrNone if successful, KErrNotReady if the Surface Manager hasn't been sl@0: opened, KErrArgument if the attribute UID is not recognized, otherwise a system sl@0: wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::GetSurfaceManagerAttrib(TSurfaceManagerAttrib aAttrib, TInt& aValue) sl@0: { sl@0: return Driver().GetSurfaceManagerAttrib(aAttrib, aValue); sl@0: } sl@0: sl@0: /** sl@0: Opens a surface. sl@0: sl@0: If the surface is already open in this process, this call increments the sl@0: reference count for the surface for this process. If the surface hasn't been opened sl@0: in this process, it opens the surface in this process and sets the reference count sl@0: to 1 for this process. sl@0: sl@0: A surface will be deleted when all its reference counts are 0. sl@0: @param aSurfaceId The surface id originally returned when the surface was created. sl@0: @pre The surface id is for an existing surface. sl@0: @post The surface is open in this process. sl@0: @return KErrNone if successful otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::OpenSurface(const TSurfaceId& aSurfaceId) sl@0: { sl@0: return Driver().OpenSurface(aSurfaceId); sl@0: } sl@0: sl@0: /** sl@0: Creates a surface and returns its global unique identifier. sl@0: sl@0: Depending on the implementation, this method will allocate the surface in a new sl@0: shared chunk or in external memory. Surfaces created in external memory cannot sl@0: be mapped (see TSurfaceInfoV01::iMappable for more information). If the creation sl@0: succeeds, the surface will be opened with a reference count of 1 in the calling sl@0: process. sl@0: sl@0: The Surface Manager implementation should validate at least the following: sl@0: - The alignment is 1, 2, 4, 8, 16, 32, 64 or TPageAlignment::EPageAligned. sl@0: - The offset to first buffer is correctly aligned. sl@0: - The width and height are both greater than zero. sl@0: - There is at least one buffer. sl@0: - The calculated chunk size isn't so big that it will exceed a signed int. sl@0: - The caching attribute is valid sl@0: - If the offset between the start of one buffer and the next is specified sl@0: (not zero), it must be correctly aligned and at least as big as the sl@0: buffer size calculated from the height and stride. sl@0: - A surface hint key of zero is allowed when creating a surface, it is ignored sl@0: sl@0: The Surface Manager implementation will treat iStride, iOffsetToFirstBuffer, and sl@0: iOffsetBetweenBuffers as minimum values as opposed to required values. The caller sl@0: of this method must not rely on the passed values as it is not guaranteed that sl@0: they remain the same after surface creation (SurfaceInfo() and GetBufferOffset() sl@0: should be used instead). sl@0: sl@0: If iOffsetBetweenBuffers is zero, the Surface Manager implementation will layout sl@0: buffer at its own discretion. Although, a buffer's offset must remain constant sl@0: during the surface's lifetime. sl@0: sl@0: If iMappable is EFalse the surface won't be mappable, hence calls to MapSurface() sl@0: will fail. sl@0: sl@0: @param aReqs Input parameter, specifies attributes of the surface required. sl@0: @param aSurfaceId Output parameter, the surface ID, set if the call succeeds. sl@0: @pre The Surface Manager has been successfully opened. sl@0: @post The surface is created and opened in the creating process. sl@0: @return KErrNone if it succeeds, KErrArgument if the surface attributes are incorrect, sl@0: KErrNoMemory if the surface cannot be created due to out of memory, KErrOverflow if sl@0: the chunk limit has been exceeded in the moving memory model, otherwise a standard sl@0: Symbian error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::CreateSurface(const TSurfaceCreationAttributesBuf& aReqs, TSurfaceId& aSurfaceId) sl@0: { sl@0: return Driver().CreateSurface(aReqs,aSurfaceId); sl@0: } sl@0: sl@0: /** sl@0: Creates a surface in an existing shared chunk specified by the caller and returns sl@0: its global unique identifier. sl@0: sl@0: If the creation succeeds, the surface will be opened with a reference count of 1 in the calling sl@0: process. sl@0: sl@0: The Surface Manager implementation should validate at least the following: sl@0: - The alignment is 1, 2, 4, 8, 16, 32, 64 or TPageAlignment::EPageAligned. sl@0: - The offset to first buffer is correctly aligned. sl@0: - The width and height are both greater than zero. sl@0: - There is at least one buffer. sl@0: - The calculated chunk size isn't so big that it will exceed a signed int. sl@0: - The caching attribute is valid sl@0: - If the offset between the start of one buffer and the next is specified sl@0: (not zero), it must be correctly aligned and at least as big as the sl@0: buffer size calculated from the height and stride. sl@0: - A surface hint key of zero is allowed when creating a surface, it is ignored sl@0: sl@0: If iOffsetBetweenBuffers is zero, the Surface Manager implementation will layout sl@0: buffer at its own discretion. Although, a buffer's offset must remain constant sl@0: during the surface's lifetime. sl@0: sl@0: The attributes iContiguous and iCacheAttribute are ignored for existing chunks. sl@0: sl@0: Also, note that surface manager will not do any rounding for offset to first sl@0: buffer and offset between buffers. It is up to the user, to give exact aligned sl@0: values for this attributes, otherwise surface creation will fail. sl@0: sl@0: If iMappable is EFalse the surface won't be mappable, hence calls to MapSurface() sl@0: will fail. sl@0: sl@0: @param aReqs Input parameter, specifies attributes of the surface required. sl@0: @param aSurfaceId Output parameter, the surface ID, set if the call succeeds. sl@0: @param aChunkHandle Handle of the existing shared chunk. sl@0: @pre The Surface Manager has been successfully opened. sl@0: @pre A valid shared chunk exists. The shared chunk type should be Shared Kernel sl@0: multiple and should be right the size, i.e. the size should be calculated as sl@0: Offset to first buffer + (the number of buffers * ((stride * height * sl@0: pixel depth in bytes) rounded up to the specified alignment) all rounded to a page size sl@0: @post The Surface Manager has opened the chunk. sl@0: @post The surface is created and opened in the creating process. sl@0: @return KErrNone if it succeeds, KErrArgument if the surface attributes are incorrect. sl@0: KErrNotReady if the handle is of an invalid shared chunk memory sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::CreateSurface(const TSurfaceCreationAttributesBuf& aReqs, TSurfaceId& aSurfaceId, const RChunk& aChunkHandle) sl@0: { sl@0: return Driver().CreateSurface(aReqs,aSurfaceId,aChunkHandle); sl@0: } sl@0: sl@0: /** sl@0: Closes the surface. Decrements the reference count for the surface for the calling sl@0: process. sl@0: sl@0: If the surface has other owners, it will not be deleted from memory. If this is sl@0: the last process to close the surface, the surface will be deleted and the sl@0: surface ID will become invalid. Resources associated with the surface are not sl@0: guaranteed to be released synchronously. sl@0: @param aSurfaceId The surface identifier originally returned when the surface was created. sl@0: @pre The surface is open. sl@0: @post The surface is closed. sl@0: @return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface, sl@0: KErrAccessDenied if the surface is not open in the current process, otherwise a system wide sl@0: error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::CloseSurface(const TSurfaceId& aSurfaceId) sl@0: { sl@0: return Driver().CloseSurface(aSurfaceId); sl@0: } sl@0: sl@0: /** sl@0: Maps the surface into the current client process address space. sl@0: sl@0: The actual memory will remain mapped into the calling process for as long as sl@0: the RChunk handle aChunk is open. sl@0: sl@0: Whether or not a surface is mappable is determined at creation time, see sl@0: TSurfaceCreationAttributes::iMappable. sl@0: sl@0: The address of the pixel data in buffer N is chunk.Base() + GetBufferOffset(N). sl@0: sl@0: Surfaces created with existing shared chunks will get the same chunk handle. sl@0: sl@0: The RChunk handle is owned by the calling thread, so will need to be duplicated sl@0: if passed to other threads in the process. sl@0: @param aSurfaceId The surface identifier originally returned when the surface was created. sl@0: @param aHandle Output parameter, handle to the implementation specific Shared Chunk. sl@0: @pre The surface is open. sl@0: @post The surface memory will be mapped into the calling process's address space. sl@0: The surface is mapped. sl@0: @return KErrNone if successful, KErrArgument if the surface ID does not refer to a sl@0: surface, KErrAccessDenied if the surface is not open in the current process, sl@0: KErrNotSupported if the surface is not mappable, KErrOverflow if the chunk limit has been sl@0: exceeded in the moving memory model, otherwise a system wide error code. sl@0: @see RChunk sl@0: @see RHandleBase::Duplicate sl@0: @see TSurfaceCreationAttributes::iMappable sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::MapSurface(const TSurfaceId& aSurfaceId, RChunk& aHandle) sl@0: { sl@0: return Driver().MapSurface(aSurfaceId,aHandle); sl@0: } sl@0: sl@0: /** sl@0: Returns information about a particular surface identified by its surface ID. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aInfo TInfoBuf to receive the information about the surface. sl@0: @pre The surface is open in the calling process. sl@0: @return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface, sl@0: KErrAccessDenied if the surface is not open in the current process, otherwise a system wide sl@0: error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::SurfaceInfo(const TSurfaceId& aSurfaceId, TInfoBuf& aInfo) sl@0: { sl@0: return Driver().SurfaceInfo(aSurfaceId,aInfo); sl@0: } sl@0: sl@0: /** sl@0: This function ensures the memory is updated consistently before and/or after sl@0: triggering non CPU hardware access. Also ensures the CPU cache and the physical sl@0: memory are in a consistent state before and after non CPU hardware or DMA access sl@0: to the physical memory. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aBuffer The buffer number indexed from 0 within the surface whose memory sl@0: region is to be flushed. sl@0: @param aOperation Specifies the sync operation as before non CPU hardware reads sl@0: or before non CPU hardware writes or after non CPU hardware writes between sl@0: physical memory of the surface and the cache contents. sl@0: @pre The surface is open in the calling process. sl@0: @post The surface buffer memory will be synchronized properly with cache contents. sl@0: @return KErrNone if successful, KErrArgument if the surface ID is invalid or sl@0: buffer number is invalid, KErrAccessDenied if the surface is not open in this sl@0: process, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::SynchronizeCache(const TSurfaceId& aSurfaceId, TInt aBuffer, TSyncOperation aOperation) sl@0: { sl@0: return Driver().SynchronizeCache(aSurfaceId,aBuffer,aOperation); sl@0: } sl@0: sl@0: /** sl@0: Get the surface hint value for the given surface ID and hint pair key. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aHint The hint value for the requested hint pair key. sl@0: @pre The surface is open in the calling process. sl@0: @pre Hint key should be a key for a hint set for this surface. sl@0: @post The hint value will be updated in the hint pair. sl@0: @return KErrNone if successful, KErrArgument if the surface ID is invalid or sl@0: invalid hint pair key used, KErrAccessDenied if the surface is not open in the sl@0: current process, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::GetSurfaceHint(const TSurfaceId& aSurfaceId, THintPair& aHint) sl@0: { sl@0: return Driver().GetSurfaceHint(aSurfaceId,aHint); sl@0: } sl@0: sl@0: /** sl@0: Set the surface hint value for the surface ID. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aHint The value of the hint pair to set. sl@0: @pre The surface is open in the calling process. sl@0: @pre The hint key should be a key for a hint set for this surface. sl@0: @pre Only mutable hints can be updated. sl@0: @post The hint value will be updated in the surface hint pair. sl@0: @return KErrNone if successful, KErrArgument if the surface ID is invalid or if invalid sl@0: hint key used, KErrAccessDenied if the hint pair is immutable or the surface is not open sl@0: in the current process, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::SetSurfaceHint(const TSurfaceId& aSurfaceId, const THintPair& aHint) sl@0: { sl@0: return Driver().SetSurfaceHint(aSurfaceId,aHint); sl@0: } sl@0: sl@0: /** sl@0: Adds a new surface hint to the surface. sl@0: sl@0: This function will fail if the surface already has its maximum number of hints sl@0: or if the hint key is a duplicate or invalid. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aHint The value of the hint pair to add. sl@0: @pre The surface is open in the calling process. sl@0: @pre At least one free space to add a hint pair. sl@0: @pre The new hint key should be non zero and unique for this surface. sl@0: @post New hint pair will be added in the surface. sl@0: @return Returns KErrNone if successful, KErrArgument if the surface ID is invalid or the sl@0: hint pair has invalid key UID, KErrAccessDenied if the surface is not open in the current sl@0: process, KErrAlreadyExists if duplicate hint key used, KErrOverflow if no space to add new sl@0: pair, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::AddSurfaceHint(const TSurfaceId& aSurfaceId, const THintPair& aHint) sl@0: { sl@0: return Driver().AddSurfaceHint(aSurfaceId,aHint); sl@0: } sl@0: sl@0: /** sl@0: Get the offset of the specified buffer from the base address of the underlying sl@0: chunk. sl@0: sl@0: To obtain the address of the buffer, the offset returned must be added onto the sl@0: base address of the RChunk returned in a call to MapSurface(). Note that sl@0: buffer offsets are immutable during the lifetime of the surface. sl@0: @param aSurfaceId The surface identifier originally returned when the surface sl@0: was created. sl@0: @param aBuffer The buffer for which the offset is requested. Indexed from 0. sl@0: @param aOffset Output parameter set to the offset within the chunk. sl@0: @pre The surface is open in the calling process. sl@0: @return KErrNone if successful, KErrArgument if aSurfaceId or aBuffer are invalid, sl@0: KErrAccessDenied if the surface is not open in the current process, KErrNotSupported if sl@0: the surface is not mappable, otherwise a system wide error code. sl@0: */ sl@0: EXPORT_C TInt RSurfaceManager::GetBufferOffset(const TSurfaceId& aSurfaceId, TInt aBuffer, TInt& aOffset) sl@0: { sl@0: return Driver().GetBufferOffset(aSurfaceId, aBuffer, aOffset); sl@0: } sl@0: sl@0: /** sl@0: Get a reference of the implementation of the surface manager. sl@0: @return reference of the implementation of the surface manager sl@0: */ sl@0: inline RSurfaceManagerDriver& RSurfaceManager::Driver() sl@0: { sl@0: return reinterpret_cast(*iDriverBuf); sl@0: } sl@0: