--- a/graphicshwdrivers/surfacemgr/src/extension.cpp Fri Aug 13 15:11:40 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1699 +0,0 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
-// All rights reserved.
-// This component and the accompanying materials are made available
-// under the terms of "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:
-//
-// Description:
-//
-
-
-#include <kernel/kern_priv.h>
-#include <graphics/surface.h>
-#include <graphics/surfacetypes.h>
-#include <graphics/surfacemanager.h>
-#include "surfacemanager_dev.h"
-#include <kernel/cache.h>
-
-/**
-Convert the surface Id to an index of the array
-based on the least significant 4 bits of the first word of the ID
-@param aSurfaceId Const reference to the surface Id
-@internalTechnology
-*/
-static TInt SurfaceIdToIndex(const TSurfaceId& aSurfaceId)
- {
- return static_cast<TInt>(aSurfaceId.iInternal[0]&(KMaxLists-1));
- }
-
-/**
-Removes an item from a linked list
-@param aList Pointer to the head of a linked list of type T
-@param aOwner Pointer to the object to be removed
-@internalTechnology
-*/
-template<class T>
-static void UnlinkListItem(T** aList, const T* aItem)
- {
- TRACE(Kern::Printf("SM UnlinkListItem list %08x object %08x \n", aList, aItem);)
-
- __ASSERT_DEBUG(aItem != NULL, Kern::Fault("Surface Manager", __LINE__));
- __ASSERT_DEBUG(*aList != NULL, Kern::Fault("Surface Manager", __LINE__));
-
- if (*aList == aItem) //one we want is at the head of the list
- {
- *aList = aItem->iNext;
- return;
- }
-
- T* p = *aList;
- T* q = (*aList)->iNext;
- while (q)
- {
- if (q == aItem)
- {
- p->iNext = q->iNext;
- return;
- }
- p = q;
- q = q->iNext;
- }
- }
-
-
-
-
-/**
-Returns a pointer to the surface owner object for the specified process, for this surface.
-@param aProcess Pointer to the process object
-@return pointer to the surface owner object if found, else NULL
-@internalTechnology
-*/
-
-TProcessListItem* TSurface::ProcessOwnerInfo(const DProcess* aProcess)
- {
- TProcessListItem* so = iOwners;
- while(so)
- {
- if (aProcess == so->iOwningProcess)
- {
- break;
- }
- so = so->iNext;
- }
- return so;
- }
-
-/**
-Creates a shared chunk surface.
-@param aParams Package buffer containing the surface creation parameters.
-@param aId Will be set to the surface id of the newly created surface.
-@return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
-otherwise one of the other system wide error codes.
-@see RSurfaceManager::TSurfaceCreationAttributes
-@internalTechnology
-*/
-
-TInt DSurfaceManager::CreateSurface(const TDesC8* aParams, TSurfaceId* aId)
- {
-
- RSurfaceManager::TSurfaceCreationAttributesBuf buf;
- RSurfaceManager::TSurfaceCreationAttributes& attribs = buf();
-
- Kern::KUDesGet(buf, *aParams); //fetch input parameters
- if( (attribs.iHintCount > KMaxHintsPerSurface) || (attribs.iHintCount<0) )
- {
- return KErrArgument;
- }
-
- RSurfaceManager::THintPair tempSurfaceHints[KMaxHintsPerSurface];
- if( (attribs.iHintCount>0) && attribs.iSurfaceHints)
- {
- kumemget(tempSurfaceHints, attribs.iSurfaceHints, attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
- attribs.iSurfaceHints = tempSurfaceHints;
- }
- else
- {
- attribs.iSurfaceHints=NULL;
- }
-
- //validate input parameters and calculate chunk size
- TInt roundedBufferSize = attribs.iOffsetBetweenBuffers;
- TUint dummyActualSize = 0;
-
- TInt chunkSize = ValidateAndCalculateChunkSize(attribs, roundedBufferSize, dummyActualSize, ETrue);
- if (chunkSize == 0)
- {
- return KErrArgument;
- }
-
- TSurfaceId sid;
- TInt r = KErrNone;
- TSurface* surface = NULL;
- do //in the unlikely event that we generate a duplicate surface id, try again.
- {
- GenerateSurfaceId(sid);
-
- NKern::FMWait(&iMutex);
- surface = FindSurfaceById(sid);
- NKern::FMSignal(&iMutex);
- }
- while (surface);
-
- //create a shared chunk for the surface memory
- TChunkCreateInfo info;
- info.iType = TChunkCreateInfo::ESharedKernelMultiple; //multi process mappable
- info.iMaxSize = chunkSize;
- info.iOwnsMemory = ETrue;
-
-//iMapAttr is valid only for hardware devices and will not make any effect in wins
-#ifndef __WINS__
- info.iMapAttr = (attribs.iCacheAttrib == RSurfaceManager::ECached) ? EMapAttrCachedMax : EMapAttrL1Uncached;
-#else
- info.iMapAttr = 0;
-#endif
-
- TLinAddr kernAddr;
- TUint32 mapAttr;
-
- NKern::ThreadEnterCS();
- DChunk* chunk;
- r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
- if (KErrNone != r)
- {
- NKern::ThreadLeaveCS();
- return r;
- }
-
- //commit the memory
- TUint32 paddr;
- if (attribs.iContiguous)
- {
- r = Kern::ChunkCommitContiguous(chunk, 0, chunkSize, paddr);
- }
- else
- {
- r = Kern::ChunkCommit(chunk, 0, chunkSize);
- }
-
- if (KErrNone != r)
- {
- //problem committing the memory,
- //destroy the chunk and cleanup
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- return r;
- }
-
- //create a surface structure for the new surface
- surface = new TSurface;
- TRACE(Kern::Printf("SM A %08x TSurface CreateSurface",surface);)
- if (!surface)
- {
- //destroy the chunk and cleanup, out of memory
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- surface->iId = sid;
- surface->iSize = attribs.iSize;
- surface->iBuffers = attribs.iBuffers;
- surface->iPixelFormat = attribs.iPixelFormat;
- surface->iStride = attribs.iStride;
- surface->iOffsetToFirstBuffer = attribs.iOffsetToFirstBuffer;
- surface->iAlignment = attribs.iAlignment;
- surface->iContiguous = attribs.iContiguous;
- surface->iChunk = chunk;
- surface->iOffsetBetweenBuffers = roundedBufferSize;
- surface->iCacheAttrib = attribs.iCacheAttrib;
- surface->iMappable = attribs.iMappable;
- if(attribs.iHintCount>0)
- {
- memcpy(surface->iSurfaceHints,tempSurfaceHints,attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
- }
- memclr(surface->iSurfaceHints+attribs.iHintCount, (KMaxHintsPerSurface-attribs.iHintCount)*sizeof(RSurfaceManager::THintPair));
-
- //create a surface owner for this surface
- TProcessListItem* owner = new TProcessListItem;
- TRACE(Kern::Printf("SM A %08x TProcessListItem CreateSurface",owner);)
-
- if (!owner)
- {
- //destroy the chunk and cleanup, out of memory
- Kern::ChunkClose(chunk);
- delete(surface);
- TRACE(Kern::Printf("SM D %08x TSurface CreateSurface",surface);)
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- owner->iCount = 1; //mark it as open in this process
- owner->iOwningProcess = &Kern::CurrentProcess();
- owner->iNext = NULL;
-
- surface->iOwners = owner; //only 1 owner at creation time
-
- //at this point we have a fully constructed TSurface
-
- //add surface to head of surfaces list
- NKern::FMWait(&iMutex);
- //Mask off the bottom log2(KMaxLists) bits of the first word of the surfaceID as an index
- //add the new surface to the beginning of the list
- TInt index = SurfaceIdToIndex(sid);
- surface->iNext = iSurfacesIndex[index];
- iSurfacesIndex[index] = surface;
-
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
-
- //write surface id back to user side
- kumemput(aId, &sid, sizeof (TSurfaceId));
- return KErrNone;
- }
-
-
-/**
-Validate that a chunk contains physical memory for the used areas.
-
-This function should be called in Critical Section in order to be completed even if the thread
-or process is killed and so be able to free the memory allocated (TUint32[pageList])
-
-@param aChunk Chunk that the user supplied.
-@param aAttribs Surface Creation Attributes.
-@param aBuffersize Calculated size of each buffer.
-@param aMapAttr Filled in with the mapping attributes of the memory.
-@param aIsContiguous Lets the caller know if the surface is physically contiguous or not.
-@return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
-KErrBadHandle if aChunkHandle is of an invalid shared chunk memory,
-otherwise one of the other system wide error codes.
-@see RSurfaceManager::TSurfaceCreationAttributes
-@internalTechnology
-*/
-TInt DSurfaceManager::ValidatePhysicalMemory(DChunk* aChunk, const RSurfaceManager::TSurfaceCreationAttributes& aAttribs,
- TUint aBuffersize, TUint32& aMapAttr, TBool &aIsContiguous)
- {
- TLinAddr kernAddr;
- TUint32 physAddr;
-
- //Get the physical address for a region in a shared chunk
- TInt pageSize = Kern::RoundToPageSize(1);
- TInt pageList = 1 + (aChunk->iSize + pageSize - 2) / pageSize;
- TUint32* physAddr2 = new TUint32[pageList];
- if(!physAddr2)
- {
- return KErrNoMemory;
- }
-
- // Unless proven otherwise, the memory is not contiguous.
- aIsContiguous = EFalse;
- TInt r = Kern::ChunkPhysicalAddress(aChunk, 0, aChunk->iSize, kernAddr, aMapAttr, physAddr, physAddr2);
- if (KErrNone == r)
- {
- aIsContiguous = ETrue;
- }
-
-
- TRACE(Kern::Printf("SM CreateSurface ChunkPhysicalAddress r %d chunk %08x chunk size %d", r, aChunk, aChunk->iSize);)
- TRACE(Kern::Printf("SM CreateSurface kernAddr %08x", kernAddr);)
- TRACE(Kern::Printf("SM CreateSurface mapAttr %08x", aMapAttr);)
- TRACE(Kern::Printf("SM CreateSurface physAddr %08x", physAddr);)
- TRACE(Kern::Printf("SM CreateSurface physAddr2 %08x", physAddr2);)
-
- if(r < KErrNone)
- {
- // Error means that there isn't memory in the whole chunk - so check the
- // relevant areas - it is allowed to have gaps between the buffers, but not
- // within the actual regions that are used for buffers.
-
- // So, we first check the area before first buffer up to "offsettofirstbuffer", which all should be valid
- if (aAttribs.iOffsetToFirstBuffer != 0)
- {
- r = Kern::ChunkPhysicalAddress(aChunk, 0, aAttribs.iOffsetToFirstBuffer,
- kernAddr, aMapAttr, physAddr, physAddr2);
- }
- else
- {
- r = KErrNone;
- }
-
- // If that's a pass, loop through and check the actual buffers (leave loop if it fails).
- for(TInt i = 0; i < aAttribs.iBuffers && KErrNone <= r; i++)
- {
- r = Kern::ChunkPhysicalAddress(aChunk,
- aAttribs.iOffsetToFirstBuffer + aAttribs.iOffsetBetweenBuffers * i,
- aBuffersize, kernAddr, aMapAttr, physAddr, physAddr2);
- }
- }
-
- // Fix up weird ChunkPhysicalAddress behaviour - it returns 1 to indicate that memory is non-contiguous.
- if (1 == r)
- {
- r = KErrNone;
- }
-
- delete[] physAddr2;
- return r;
- }
-
-
-/**
-Creates a surface in an existing shared chunk.
-@param aParam Package buf containing the surface creation parameters and id to be set to the surface id of the newly created surface.
-@param aChunkHandle Existing valid shared chunk handle.
-@return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
-KErrBadHandle if aChunkHandle is of an invalid shared chunk memory,
-otherwise one of the other system wide error codes.
-@see RSurfaceManager::TSurfaceCreationAttributes
-@internalTechnology
-*/
-TInt DSurfaceManager::CreateSurface(RSurfaceManagerDriver::TDeviceParam* aParam, TInt aChunkHandle)
- {
- RSurfaceManager::TSurfaceCreationAttributesBuf buf;
- RSurfaceManager::TSurfaceCreationAttributes& attribs = buf();
-
- //Get the input parameters
- RSurfaceManagerDriver::TDeviceParam param;
- kumemget(¶m, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
- Kern::KUDesGet(buf, *(reinterpret_cast<const TDesC8*>(param.iBuffer)));
- if( (attribs.iHintCount > KMaxHintsPerSurface) || (attribs.iHintCount<0) )
- {
- return KErrArgument;
- }
-
- RSurfaceManager::THintPair tempSurfaceHints[KMaxHintsPerSurface];
- if( (attribs.iHintCount>0) && attribs.iSurfaceHints)
- {
- kumemget(tempSurfaceHints, attribs.iSurfaceHints, attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
- attribs.iSurfaceHints = tempSurfaceHints;
- }
- else
- {
- attribs.iSurfaceHints=NULL;
- }
-
- //validate input parameters and calc size
- TInt roundedBufferSize = attribs.iOffsetBetweenBuffers;
- TUint actualBufferSize = 0;
- TInt chunkSize = ValidateAndCalculateChunkSize(attribs, roundedBufferSize, actualBufferSize);
- if (chunkSize == 0)
- {
- return KErrArgument;
- }
-
- NKern::ThreadEnterCS();
-
- //Open an existing shared chunk
- DChunk* chunk = Kern::OpenSharedChunk(NULL, aChunkHandle, EFalse);
- if(chunk == NULL)
- {
- NKern::ThreadLeaveCS();
- return KErrBadHandle;
- }
-
- //Check for chunk type as kernel multiple
- if(chunk->iChunkType != ESharedKernelMultiple)
- {
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- return KErrBadHandle;
- }
-
- //Check for enough chunk size to create surface for requested attributes
- if (chunk->iSize < attribs.iOffsetToFirstBuffer + attribs.iBuffers * actualBufferSize)
- {
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- TSurfaceId sid;
- TSurface* surface = NULL;
- do //in the unlikely event that we generate a duplicate surface id, try again.
- {
- GenerateSurfaceId(sid);
-
- NKern::FMWait(&iMutex);
- surface = FindSurfaceById(sid);
- NKern::FMSignal(&iMutex);
- }
- while (surface);
-
- //create a surface structure for the new surface
- surface = new TSurface;
- TRACE(Kern::Printf("SM A %08x TSurface CreateSurface",surface);)
- if (!surface)
- {
- //destroy the chunk and cleanup, out of memory
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- TUint32 mapAttr = 0;
- TBool isContiguous;
- TInt r = ValidatePhysicalMemory(chunk, attribs, actualBufferSize, mapAttr, isContiguous);
- if (r != KErrNone)
- {
- //destroy the surface and close the chunk
- delete(surface);
- Kern::ChunkClose(chunk);
- NKern::ThreadLeaveCS();
- if (r != KErrNoMemory)
- {
- r = KErrArgument;
- }
- return r;
- }
-
- surface->iId = sid;
- surface->iSize = attribs.iSize;
- surface->iBuffers = attribs.iBuffers;
- surface->iPixelFormat = attribs.iPixelFormat;
- surface->iStride = attribs.iStride;
- surface->iOffsetToFirstBuffer = attribs.iOffsetToFirstBuffer;
- surface->iAlignment = attribs.iAlignment;
- surface->iContiguous = isContiguous;
- surface->iChunk = chunk;
- surface->iOffsetBetweenBuffers = (attribs.iOffsetBetweenBuffers) ? attribs.iOffsetBetweenBuffers : roundedBufferSize;
- surface->iMappable = attribs.iMappable;
-#ifndef __WINS__ //Creation attribute field will not considered for iCacheAttrib
- TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
- TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
- TBool chunkIsNotcached = ((level2Info == EMapAttrL2Uncached) &&
- ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
- (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
- surface->iCacheAttrib = (chunkIsNotcached) ? RSurfaceManager::ENotCached : RSurfaceManager::ECached;
-#else
- surface->iCacheAttrib = RSurfaceManager::ENotCached;
-#endif
-
- if(attribs.iHintCount>0)
- {
- memcpy(surface->iSurfaceHints,tempSurfaceHints,attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
- }
- memclr(surface->iSurfaceHints+attribs.iHintCount, (KMaxHintsPerSurface-attribs.iHintCount)*sizeof(RSurfaceManager::THintPair));
-
- //create a surface owner for this surface
- TProcessListItem* owner = new TProcessListItem;
- TRACE(Kern::Printf("SM A %08x TProcessListItem CreateSurface",owner);)
-
- if (!owner)
- {
- //destroy the chunk and cleanup, out of memory
- Kern::ChunkClose(chunk);
- delete(surface);
- TRACE(Kern::Printf("SM D %08x TSurface CreateSurface",surface);)
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- owner->iCount = 1; //mark it as open in this process
- owner->iOwningProcess = &Kern::CurrentProcess();
- owner->iNext = NULL;
-
- surface->iOwners = owner; //only 1 owner at creation time
-
- NKern::FMWait(&iMutex);
- //at this point we have a fully constructed TSurface
- //add surface to head of surfaces list
-
- //Mask off the bottom log2(KMaxLists) bits of the first word of the surfaceID as an index
- //add the new surface to the beginning of the list
- TInt index = SurfaceIdToIndex(sid);
- surface->iNext = iSurfacesIndex[index];
- iSurfacesIndex[index] = surface;
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
-
- //write surface id back to user side
- kumemput(reinterpret_cast<TSurfaceId*>(param.iSurfaceId), &sid, sizeof (TSurfaceId));
- return KErrNone;
- }
-
-
-/**
-Opens a surface. If the current process already is in the owners list, its usage count is
-incremented. If this is an open from a different process, a new surface owner object is added
-to the surface's list of owners and its usage count is set to 1.
-@param aId The surface id of the surface to be opened.
-@return KErrNone if successful, otherwise a system error code
-@internalTechnology
-*/
-TInt DSurfaceManager::OpenSurface(const TSurfaceId* aId)
- {
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, aId, sizeof (TSurfaceId));
- NKern::ThreadEnterCS();
- TProcessListItem* owner = new TProcessListItem; //speculative creation
- TRACE(Kern::Printf("SM A %08x TProcessListItem OpenSurface", owner);)
-
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- delete owner; //free the memory just allocated
- TRACE(Kern::Printf("SM D %08x TProcessListItem OpenSurface", owner);)
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (so)
- {
- //already an owner so inc the ref count
- ++so->iCount;
- }
- else
- {
- //new process trying to open it
- if (!owner)
- {
- //the creation of the owner information object failed, out of memory
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- owner->iCount = 1; //mark it open in this process
- owner->iOwningProcess = &Kern::CurrentProcess();
-
- //add the owner to the list of owners
- owner->iNext = surface->iOwners;
- surface->iOwners = owner;
- owner = NULL;
- }
- NKern::FMSignal(&iMutex);
- delete owner; //free if not used.
- TRACE(Kern::Printf("SM D %08x TProcessListItem OpenSurface", owner);)
- NKern::ThreadLeaveCS();
- return KErrNone;
- }
-
-
-
-/**
-Closes a surface. Decrements the usage count in the surface owner object
-if the usage count is then zero, removes this surface owner from the surface.
-If this results in a surface with no owners, the surface is deleted and the
-surface shared chunk is closed.
-@param aId The id of the surface to be closed
-@return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface,
-KErrAccessDenied if the surface is not open in the current process, otherwise a system wide
-error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::CloseSurface(const TSurfaceId* aId)
- {
-
- TSurfaceId sid;
- kumemget(&sid, aId, sizeof (TSurfaceId)); //fetch surface id from user memory
- //look it up
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied;
- }
-
- //current process is a surface owner so decrement the open count
- TSurface* surfaceToDelete = NULL;
- TProcessListItem* ownerToDelete = NULL;
- DChunk* chunkToClose = NULL;
- if (--so->iCount == 0)
- {
- //if count is now zero remove the owner
- //surface->RemoveOwner(so);
- UnlinkListItem(&surface->iOwners, so);
- ownerToDelete = so;
-
- //check to see if the surface has any owners
- if (!surface->iOwners)
- {
- //no more owners of the surface
- chunkToClose = surface->iChunk;
-
- //remove the surface from the list
- UnlinkListItem(&(iSurfacesIndex[SurfaceIdToIndex(surface->iId)]), surface);
- surfaceToDelete = surface;
- }
- }
-
- NKern::FMSignal(&iMutex);
-
- if (chunkToClose)
- {
- //surface has no more owners so close the chunk
- Kern::ChunkClose(chunkToClose);
- }
-
- delete surfaceToDelete;
- TRACE(Kern::Printf("SM D %08x TSurface CloseSurface",surfaceToDelete);)
- delete ownerToDelete;
- TRACE(Kern::Printf("SM D %08x TProcessListItem CloseSurface",ownerToDelete);)
- NKern::ThreadLeaveCS();
-
- return KErrNone;
- }
-
-
-/**
-Maps the surface memory into the process of the calling thread. This will fail if
-the surface is not open in this process, or if the handle to the chunk cannot be created.
-@param aId The id of the surface to be mapped in.
-@return KErrNone if successful, KErrArgument if the surface ID does not refer to a
-surface, KErrAccessDenied if the surface is not open in the current process,
-KErrNotSupported if the surface is not mappable, KErrOverflow if the chunk limit has been
-exceeded in the moving memory model, otherwise a system wide error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::MapSurface(const TSurfaceId* aId)
- {
- TSurfaceId sid;
- kumemget(&sid, aId, sizeof (TSurfaceId)); //fetch surface id from user memory
-
- //look it up
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument; //surface id is not valid or in the list of surfaces
- }
- if(!surface->iMappable)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrNotSupported;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied; //can't map it in, it's not open in this process
- }
-
- DChunk* chunk = surface->iChunk;
- TInt r = chunk->Open();
- NKern::FMSignal(&iMutex);
- TRACE(Kern::Printf("SM MapSurface chunk open r %d\n",r);)
-
- if (r == KErrGeneral)
- {
- NKern::ThreadLeaveCS();
- return KErrAccessDenied;
- }
-
- //if we are here, got the surface and we are the owner.
- //if we are the owner we must have it open at least once
-
- r = Kern::MakeHandleAndOpen(NULL, chunk);
- chunk->Close(NULL);
- TRACE(Kern::Printf("SM MapSurface handle open r: %d\n",r);)
-
- NKern::ThreadLeaveCS();
-
- return r;
- }
-
-
-/**
-Record a new connection to the driver.
-Adds an element to the reference counted list of connected processes if the connection
-is from a new process, otherwise it increments the reference count.
-@param aProcess The process which has opened a driver channel.
-@internalTechnology
-*/
-TInt DSurfaceManager::AddConnection(const DProcess* aProcess)
- {
- TRACE(Kern::Printf("SM AddConnection process %08x\n", aProcess);)
- NKern::ThreadEnterCS();
- TProcessListItem* connectedProcess = new TProcessListItem; //speculative creation
- TRACE(Kern::Printf("SM A %08x TProcessListItem AddConnection", connectedProcess);)
- NKern::FMWait(&iMutex);
- TProcessListItem* p = FindConnectedProcess(aProcess);
- if (p) //already connected, found the process
- {
- ++p->iCount;
- }
- else
- {
- //add a new connected process
- if (!connectedProcess)
- {
- //the creation of the owner information object failed, out of memory
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
- connectedProcess->iOwningProcess = (DProcess*)aProcess;
- connectedProcess->iCount=1;
-
- connectedProcess->iNext = iConnectedProcesses;
- iConnectedProcesses = connectedProcess;
- connectedProcess = NULL;
- }
- NKern::FMSignal(&iMutex);
- delete connectedProcess;
- TRACE(Kern::Printf("SM D %08x TProcessListItem AddConnection", connectedProcess);)
- NKern::ThreadLeaveCS();
- return KErrNone;
- }
-
-
-
-/**
-Called when the driver channel is closed.
-Decrements the reference count for the connected process, if the last connection
-for this process is closed (reference count reaches 0) it removes the process from the list.
-@param aProcess The process which has closed the driver channel.
-@internalTechnology
-*/
-void DSurfaceManager::RemoveConnection(const DProcess* aProcess)
- {
- TRACE(Kern::Printf("SM RemoveConnection process %08x\n", aProcess);)
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- TProcessListItem* p =FindConnectedProcess(aProcess);
- TProcessListItem* toDelete = NULL;
- if (p) //already connected, found the process
- {
- if (--p->iCount == 0) //last connection in process has disconnected
- {
- //remove the process from the list and cleanup
- UnlinkListItem(&iConnectedProcesses, p);
- toDelete = p;
- }
- }
- NKern::FMSignal(&iMutex);
- delete toDelete;
- TRACE(Kern::Printf("SM D %08x TProcessListItem RemoveConnection ", toDelete);)
-
-
- if (toDelete) // if a process has closed its last channel, remove process from the surface owners.
- {
- CloseSurfaceHandlesForProcess(aProcess);
- }
-
- NKern::ThreadLeaveCS();
- }
-
-
-
-
-/**
-Closes all the surfaces belonging to the process which has just terminated.
-If this is the only owner of a surface, delete the surface.
-@param aProcess The process which has terminated.
-@pre must be called in critical section
-@internalTechnology
-*/
-void DSurfaceManager::CloseSurfaceHandlesForProcess(const DProcess* aProcess)
- {
-
- NKern::FMWait(&iMutex);
-
- TSurface* p = NULL;
- TSurface* surfacesTodelete = NULL;
- TProcessListItem* ownersTodelete = NULL;
- TProcessListItem* so;
- // There are 16 doubly linked lists managed by Surface Manager
- for (TInt index = 0; index < KMaxLists; index++)
- {
- p = iSurfacesIndex[index];
- while(p)
- {
- //see if the process which has just died is an owner of any surfaces
- TSurface* surface = p;
- p=p->iNext;
- so = surface->ProcessOwnerInfo(aProcess);
- if (so)
- {
- UnlinkListItem(&surface->iOwners, so);
- so->iNext = ownersTodelete; //add the owner to the list of owner objects to remove
- ownersTodelete = so;
-
- if (!surface->iOwners) //if the surface hasn't any owners
- {
- //remove the surface from the list
- UnlinkListItem(&iSurfacesIndex[index], surface);
- surface->iNext = surfacesTodelete; //add the surface to the list of surfaces to remove
- surfacesTodelete = surface;
- }
- }
- }
- }
- NKern::FMSignal(&iMutex);
-
- while(surfacesTodelete)
- {
- p = surfacesTodelete->iNext;
- Kern::ChunkClose(surfacesTodelete->iChunk);
- TRACE(Kern::Printf("SM Close chunk %08x CloseSurfaceHandlesForProcess",surfacesTodelete->iChunk);)
- delete surfacesTodelete;
- TRACE(Kern::Printf("SM D %08x TSurface CloseSurfaceHandlesForProcess",surfacesTodelete);)
- surfacesTodelete = p;
- }
-
- while(ownersTodelete)
- {
- so = ownersTodelete->iNext;
- delete ownersTodelete;
- TRACE(Kern::Printf("SM D %08x TProcessListItem CloseSurfaceHandlesForProcess",ownersTodelete);)
- ownersTodelete = so;
- }
- }
-
-
-/**
-Returns the metadata information about the specified surface.
-@param aId The id of the surface.
-@param aInfo Pointer to user side descriptor to receive the information.
-@return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface,
-KErrAccessDenied if the surface is not open in the current process, otherwise a system wide
-error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::SurfaceInfo(const TSurfaceId* aId, TDes8* aInfo)
- {
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, aId, sizeof (TSurfaceId));
-
- RSurfaceManager::TInfoBuf buf;
- RSurfaceManager::TSurfaceInfoV01& info = buf();
-
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- return KErrAccessDenied; //can do this, not open
- }
-
- //at this point, we have a surface, we are the owner and it's mapped in
- info.iSize = surface->iSize; // Visible width/height in pixels
- info.iBuffers = surface->iBuffers; // Number of Buffers
- info.iPixelFormat = surface->iPixelFormat; // pixel format
- info.iStride = surface->iStride; // Number of bytes between start of one line and start of next
- info.iContiguous = surface->iContiguous; // is it physically contiguous
- info.iCacheAttrib = surface->iCacheAttrib; // Underlying chunk is CPU cached or not
- info.iMappable = surface->iMappable; // Is the surface Mappable
- NKern::FMSignal(&iMutex);
-
- //copy it back to user side
- Kern::InfoCopy(*aInfo, buf);
- return KErrNone;
- }
-
-
-
-/**
-Generates a unique surface id
-@param aId Surface id reference to receive the generated id.
-@internalTechnology
-*/
-void DSurfaceManager::GenerateSurfaceId(TSurfaceId& aId)
- {
- TSurfaceId id;
-
- for (TInt x = 0; x < 4; ++x)
- {
- id.iInternal[x] = Kern::Random();
- };
-
- //package up the handle,
- //set the type identifier
- id.iInternal[3] &= 0x00FFFFFF;
- id.iInternal[3] |= TSurfaceTypes::ESurfaceManagerSurface << 24;
- aId = id;
- TRACE(Kern::Printf("SM GenerateSurfaceId id = %u %u %u %u\n",id.iInternal[0],id.iInternal[1],id.iInternal[2],id.iInternal[3]);)
- };
-
-
-
-/**
-Validates the surface creation attributes and calculates the size of the chunk required.
-@param aAttribs The surface creation attributes used to specify the surface requirements.
-@param aOffset Set to the offset between buffers on successfull return.
-@param aNewChunk If this is true, surface is created in a new chunk otherwise the surface is created in an existing chunk
-@return The size of chunk required. A size of 0 indicates a problem.
-*/
-TInt DSurfaceManager::ValidateAndCalculateChunkSize(RSurfaceManager::TSurfaceCreationAttributes& aAttribs,
- TInt& aOffset, TUint &aActualBufferSize, const TBool aNewChunk)
- {
-/*
- TRACE(Kern::Printf("SM width = %d height = %d\n", aAttribs.iSize.iWidth, aAttribs.iSize.iHeight);)
- TRACE(Kern::Printf("SM buffers = %d\n", aAttribs.iBuffers);)
- TRACE(Kern::Printf("SM format = %d\n", aAttribs.iPixelFormat);)
- TRACE(Kern::Printf("SM stride = %d\n", aAttribs.iStride);)
- TRACE(Kern::Printf("SM offset to first buffer = %d\n", aAttribs.iOffsetToFirstBuffer);)
- TRACE(Kern::Printf("SM offset between buffer = %d\n", aOffset);)
- TRACE(Kern::Printf("SM alignment = %d\n", aAttribs.iAlignment);)
- TRACE(Kern::Printf("SM contiguous = %d\n\n", aAttribs.iContiguous);)
- TRACE(Kern::Printf("SM cacheAttrib = %d\n\n", aAttribs.iCacheAttrib);)
-*/
- //check for negative values
- if(aAttribs.iOffsetToFirstBuffer < 0 || aOffset < 0 )
- {
- TRACE(Kern::Printf("SM Validate offset for negative value");)
- return 0;
- }
-
- //check aligment is sensible
- TInt alignmentMask = 0;
- switch(aAttribs.iAlignment)
- {
- case 1:
- case 2:
- case 4:
- case 8:
- case 16:
- case 32:
- alignmentMask = 31;
- break;
- case 64:
- alignmentMask = 63;
- break;
- case RSurfaceManager::EPageAligned:
- break;
- default:
- TRACE(Kern::Printf("SM Validate alignment");)
- return 0;
- }
-
- //check alignment issues.
- if(aAttribs.iAlignment != RSurfaceManager::EPageAligned)
- {
- if(aNewChunk)
- {
- if(aAttribs.iCacheAttrib == RSurfaceManager::ECached) // Surface is CPU cached, so the alignment will be based on either 32 or 64 byte
- {
- //offset to first buffer needs to fit alignment
- aAttribs.iOffsetToFirstBuffer = aAttribs.iOffsetToFirstBuffer + alignmentMask & ~alignmentMask;
- //alignment with respect to offsetbetweenbuffers
- aOffset = aOffset + alignmentMask & ~alignmentMask;
- }
- else // Surface is NOT CPU cached, so the alignment will be based on surface attribute alignment
- {
- TUint alignMask = aAttribs.iAlignment-1;
- //offset to first buffer needs to fit alignment
- aAttribs.iOffsetToFirstBuffer = aAttribs.iOffsetToFirstBuffer + alignMask & ~alignMask;
- //alignment with respect to offsetbetweenbuffers
- aOffset = aOffset + alignMask & ~alignMask;
- }
- }
- else // existing chunk
- {
- TUint alignMask = aAttribs.iAlignment-1;
- //check alignment issues. offset to first buffer needs to fit alignment
- if (aAttribs.iOffsetToFirstBuffer & alignMask)
- {
- TRACE(Kern::Printf("SM Validate offset to first pixel misaligned");)
- return 0;
- }
-
- //check alignment for offsetbetweenbuffers. offset between buffer needs to fit alignment for existing chunks
- if (aOffset & alignMask)
- {
- TRACE(Kern::Printf("SM Validate offset between buffers misaligned");)
- return 0;
- }
- }
- }
- else //page aligned
- {
- if(aNewChunk)// if its a new chunks and doesn't match exact alignment then do the rounding
- {
- TUint32 pageSize = Kern::RoundToPageSize(1);
- //offset to first buffer needs to fit alignment
- aAttribs.iOffsetToFirstBuffer = (aAttribs.iOffsetToFirstBuffer + (pageSize - 1)) & ~(pageSize - 1);
- //alignment with respect to offsetbetweenbuffers
- aOffset = (aOffset + (pageSize - 1)) & ~((pageSize - 1));
- }
- else // for existing chunks don't do any rounding operation
- {
- TUint32 pageSize = Kern::RoundToPageSize(1);
- TUint alignmask = aAttribs.iOffsetToFirstBuffer & (pageSize - 1);
- if (alignmask)
- {
- TRACE(Kern::Printf("SM Validate offset to first pixel misaligned");)
- return 0;
- }
-
- alignmask = aOffset & (pageSize - 1);
- if (alignmask)
- {
- TRACE(Kern::Printf("SM Validate offset between buffers misaligned");)
- return 0;
- }
- }
- }
-
- //check width and height
- if(aAttribs.iSize.iWidth <= 0 || aAttribs.iSize.iHeight <= 0)
- {
- TRACE(Kern::Printf("SM Validate width/height");)
- return 0;
- }
-
-
- //check there is at least 1 buffer
- if (aAttribs.iBuffers <= 0)
- {
- TRACE(Kern::Printf("SM Validate buffers");)
- return 0;
- }
-
- //Sort the array and also check for duplication
- if (!SortHints(aAttribs.iSurfaceHints,aAttribs.iHintCount))
- {
- TRACE(Kern::Printf("SM Validate Duplicate hint key");)
- return 0;
- }
-
- TUint size = 0;
- //calculate buffer size and round it to alignment or to page size
- TInt64 bufferSize = aAttribs.iStride;
- bufferSize *= aAttribs.iSize.iHeight;
-
- if (I64HIGH(bufferSize) > 0) //too big
- {
- TRACE(Kern::Printf("SM Validate chunk buffer size is out of range");)
- return 0;
- }
-
- TUint bsize = I64LOW(bufferSize);
- if (bsize > KMaxTInt)
- {
- TRACE(Kern::Printf("SM Validate buffer size is out of range for TInt");)
- return 0;
- }
-
- if(aAttribs.iAlignment == RSurfaceManager::EPageAligned)
- {
- bsize = Kern::RoundToPageSize(bsize); //page alignment
- }
- else if(aAttribs.iCacheAttrib == RSurfaceManager::ECached)
- {
- bsize = bsize + alignmentMask & ~alignmentMask; //CPU cached byte alignment, for minimum of the specified alignment(32 or 64)
- }
- else
- {
- bsize = bsize + (aAttribs.iAlignment-1) & ~(aAttribs.iAlignment-1); //NON CPU cached byte alignment for 1, 2, 4, 8, 16, 32 and 64
- }
-
- bufferSize = bsize;
- // Remember the actual size.
- aActualBufferSize = bsize;
-
- //if offset between buffers is zero, then assign the calculated value as offset between buffers
- if(aOffset == 0)
- {
- //buffer size rounded to alignment as offset between buffers
- aOffset = I64INT(bufferSize);
- }
- else if(aOffset < I64INT(bufferSize))
- {
- TRACE(Kern::Printf("SM Offset between the buffer is less than the required size");)
- return 0;
- }
- else
- {
- //use the buffer size specified
- bufferSize = aOffset;
- }
-
-
- TInt64 totalSize = aAttribs.iOffsetToFirstBuffer + (aAttribs.iBuffers * bufferSize);
-
- if (I64HIGH(totalSize) > 0) //too big
- {
- TRACE(Kern::Printf("SM Validate chunk size is out of range for RoundToPageSize");)
- return 0;
- }
-
- size = I64LOW(totalSize);
- if (size > KMaxTInt)
- {
- TRACE(Kern::Printf("SM Validate size is out of range for TInt");)
- return 0;
- }
-
- size = Kern::RoundToPageSize(size);
-
- //check the size isn't greater than will fit in a TInt
- if (size > KMaxTInt)
- {
- TRACE(Kern::Printf("SM Rounded size is out of range for TInt");)
- return 0;
- }
-
- TRACE(Kern::Printf("SM After validate - offset to first buffer = %d\n", aAttribs.iOffsetToFirstBuffer);)
- TRACE(Kern::Printf("SM After validate - offset between buffer = %d\n", aOffset);)
- TRACE(Kern::Printf("SM CalculateChunkSize size = %d\n", size);)
- return size;
- }
-
-
-/**
-Find the surface in the list.
-@param aId The surface id of the surface to find in the surface list
-@return pointer to the surface object
-@internalTechnology
-*/
-TSurface* DSurfaceManager::FindSurfaceById(const TSurfaceId& aId)
- {
- TSurface *p = iSurfacesIndex[SurfaceIdToIndex(aId)];
- while (p)
- {
- if (aId == p->iId)
- {
- //found it
- return p;
- }
-
- p = p->iNext;
- }
- return NULL;
- }
-
-
-/**
-Find the index of the hint key from the surface list using binary search.
-@param aHintsArray Pointer to the first element in the array of surface hints
-@param aKey The surface hint key uid value to search in the surface list
-@return index of the hint pair key in the surface list, KErrNotFound if key not found
-@internalTechnology
-*/
-TInt DSurfaceManager::FindHintKey(const RSurfaceManager::THintPair* aHintsArray, TUint32 aKey) const
- {
- __ASSERT_DEBUG(aHintsArray != NULL, Kern::Fault("Surface Manager", __LINE__));
-
- TInt bottom = 0;
- TInt top = KMaxHintsPerSurface - 1;
- TInt mid;
- while (bottom <= top)
- {
- mid = (bottom + top) / 2;
- if((TUint) aHintsArray[mid].iKey.iUid == aKey)
- {
- return mid;
- }
- else if ((TUint)aHintsArray[mid].iKey.iUid < aKey)
- {
- top = mid - 1;
- }
- else
- {
- bottom = mid + 1;
- }
- }
- return KErrNotFound; //Hint key not found
- }
-
-TProcessListItem* DSurfaceManager::FindConnectedProcess(const DProcess* aProcess)
- {
- TProcessListItem * p = iConnectedProcesses;
- while (p)
- {
- if (aProcess == p->iOwningProcess)
- {
- //found it
- return p;
- }
-
- p = p->iNext;
- }
- return NULL;
- }
-
-/**
-Searches for a right place to insert the new hint pair in a sorted array.
-@param aHintsArray Pointer to the first element in the sorted array
-@param aKey The surface hint key uid value to search in the surface list
-@pre, there is at least one empty place in the array
-@return KErrNone if a new hint pair key inserted in the surface list, KErrAlreadyExists if duplicated
-@internalTechnology
-*/
-TInt DSurfaceManager::InsertHintKey(RSurfaceManager::THintPair* aHintsArray, const RSurfaceManager::THintPair& aHintPair) const
- {
- __ASSERT_DEBUG(aHintsArray != NULL, Kern::Fault("Surface Manager", __LINE__));
- __ASSERT_DEBUG(aHintsArray[KMaxHintsPerSurface-1].iKey.iUid == NULL, Kern::Fault("Surface Manager", __LINE__));
-
- TInt pos = 0;
- if (aHintsArray[pos].iKey.iUid != 0)
- {
- while((TUint)aHintsArray[pos].iKey.iUid>(TUint)aHintPair.iKey.iUid && pos < KMaxHintsPerSurface-1)
- {// find the right place to insert
- ++pos;
- }
-
- if((TUint)aHintsArray[pos].iKey.iUid==(TUint)aHintPair.iKey.iUid)
- {
- //Duplicate key
- return KErrAlreadyExists;
- }
- else
- {
- // Shift right
- memmove(aHintsArray+pos+1, aHintsArray+pos, (KMaxHintsPerSurface-pos-1)*sizeof(RSurfaceManager::THintPair));
- }
- }
- aHintsArray[pos] = aHintPair;
- return KErrNone;
- }
-
-/**
-Sort the surface hint array in descending order.
-@param aHintsArray The surface hintpair in the surface list
-@param aNumberOfHints The number of hints
-@return ETrue if sorting is finished or it is an empty array, EFalse if key duplicated
-@internalTechnology
-*/
-TBool DSurfaceManager::SortHints(RSurfaceManager::THintPair* aHintsArray, TInt aNumberOfHints) const
- {
- TInt in = 0;
- TInt out = 0;
- RSurfaceManager::THintPair temp;
- if(!aHintsArray)
- {
- return ETrue;
- }
- for(out = 0; out < aNumberOfHints; ++out)
- {
- if(aHintsArray[out].iKey.iUid != 0)
- {
- temp = aHintsArray[out];
- in = out; // start shifting at out
- while(in > 0 && (TUint)aHintsArray[in-1].iKey.iUid <= (TUint)temp.iKey.iUid)
- {
- if ((TUint)aHintsArray[in-1].iKey.iUid == (TUint)temp.iKey.iUid)
- {
- return EFalse; //duplicate hint keys are not allowed
- }
- aHintsArray[in] = aHintsArray[in-1]; // shift item to the right
- --in; // go left one position
- }
- aHintsArray[in] = temp; // insert marked item
- }
- }
- return ETrue;
- }
-
-
-/**
-Ensures the memory is updated consistently before/after triggering non CPU hardware access.
-@param aParam The suface id and buffer number (0 based).
-@param aOperation The type of the synchronize operation.
-@return KErrNone if successful, KErrArgument if the surface ID is invalid or
-buffer number is invalid, KErrAccessDenied if the surface is not open in this
-process, otherwise a system wide error code.
-@see RSurfaceManager::TSyncOperation
-@internalTechnology
-*/
-TInt DSurfaceManager::SynchronizeCache(RSurfaceManagerDriver::TDeviceParam* aParam, RSurfaceManager::TSyncOperation aOperation)
- {
- //Parse the parameters
- RSurfaceManagerDriver::TDeviceParam param;
- kumemget(¶m, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
- TSurfaceId sid;
- kumemget(&sid, param.iSurfaceId, sizeof(TSurfaceId));
- TInt buffer = (TInt)param.iBuffer;
-
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied;
- }
-
- // surfaces have to have at least one buffer
- __ASSERT_DEBUG(surface->iBuffers > 0, Kern::Fault("Surface Manager", __LINE__));
-
- //Validate the buffer number is within range
- if((buffer >= surface->iBuffers) || (buffer < 0))
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- DChunk* chunk = surface->iChunk;
- TInt offsetBetweenBuffers = surface->iOffsetBetweenBuffers;
- NKern::FMSignal(&iMutex);
-
- TUint32 kernAddr;
- TUint32 mapAttr;
- TUint32 physAddr;
- TInt pageList = chunk->iSize / Kern::RoundToPageSize(1) + 1;
- TUint32* physAddr2 = new TUint32[pageList];
- if(!physAddr2)
- {
- NKern::ThreadLeaveCS();
- return KErrNoMemory;
- }
-
- TRACE(Kern::Printf("SM %08x DChunk SynchronizeCache", chunk);)
-
- //Retrieve the kernel address and mapping attribute from the chunk
- TInt err = Kern::ChunkPhysicalAddress(chunk, surface->iOffsetToFirstBuffer + (buffer * offsetBetweenBuffers), offsetBetweenBuffers, kernAddr, mapAttr, physAddr, physAddr2);
- delete[] physAddr2;
- if(err >= KErrNone)
- {
- TRACE(Kern::Printf("SM %08x kernAddr SynchronizeCache", kernAddr);)
- TRACE(Kern::Printf("SM %08x mapAttr SynchronizeCache", mapAttr);)
- err = KErrNone;
-
- // Do the sync operation
- switch(aOperation)
- {
- case RSurfaceManager::ESyncBeforeNonCPURead:
- Cache::SyncMemoryBeforeDmaWrite(kernAddr, offsetBetweenBuffers, mapAttr);
- break;
- case RSurfaceManager::ESyncBeforeNonCPUWrite:
- Cache::SyncMemoryBeforeDmaRead(kernAddr, offsetBetweenBuffers, mapAttr);
- break;
- case RSurfaceManager::ESyncAfterNonCPUWrite:
- Cache::SyncMemoryAfterDmaRead(kernAddr, offsetBetweenBuffers);
- break;
- default:
- err = KErrArgument;
- break;
- }
- }
- NKern::ThreadLeaveCS();
-
- return err;
- }
-
-
-/**
-Get the surface hint value for the given surface ID and hint pair key.
-@param aSurfaceId The surface identifier originally returned when the surface was created.
-@param aHintPair The hint value for the requested hint pair key.
-@return KErrNone if successful, KErrArgument if the surface ID is invalid or
-invalid hint pair key used, KErrAccessDenied if the surface is not open in the
-current process, otherwise a system wide error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::GetSurfaceHint(const TSurfaceId* aSurfaceId, RSurfaceManager::THintPair* aHintPair)
- {
- RSurfaceManager::THintPair hintPair;
- kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
-
- if (hintPair.iKey.iUid == 0)
- {
- TRACE(Kern::Printf("SM GetSurfaceHint Hint key is invalid");)
- return KErrArgument; //Invalid Hint key
- }
-
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
-
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- return KErrAccessDenied;
- }
-
- //at this point, we have a surface, we have to find the hint value based on the hint pair key
- TInt index = FindHintKey(surface->iSurfaceHints, hintPair.iKey.iUid);
-
- if (index == KErrNotFound)
- {
- TRACE(Kern::Printf("SM GetSurfaceHint Hint key not found");)
- NKern::FMSignal(&iMutex);
- return KErrArgument; //Hint key not found
- }
-
- RSurfaceManager::THintPair hint = surface->iSurfaceHints[index];
- NKern::FMSignal(&iMutex);
-
- TRACE(Kern::Printf("SM GetSurfaceHint Hint value %d", hint.iValue);)
- //write it back to user side
- kumemput(aHintPair, &hint, sizeof(RSurfaceManager::THintPair));
- return KErrNone;
- }
-
-
-/**
-Set the surface hint value for an existing surface hint key of the surface Id.
-@param aSurfaceId The surface identifier originally returned when the surface was created.
-@param aHintPair The value of the hint pair to set.
-@return KErrNone if successful, KErrArgument if the surface ID is invalid or if invalid
-hint key used, KErrAccessDenied if the hint pair is immutable or the surface is not open
-in the current process, otherwise a system wide error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::SetSurfaceHint(const TSurfaceId* aSurfaceId, const RSurfaceManager::THintPair* aHintPair)
- {
- RSurfaceManager::THintPair hintPair;
- kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
-
- //Check for valid hint key
- if (!hintPair.iKey.iUid)
- {
- TRACE(Kern::Printf("SM SetSurfaceHint Hint key is invalid");)
- return KErrArgument; //Invalid Hint key
- }
-
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
-
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied;
- }
-
- //at this point, we have a surface, we have to find the hint value based on the hint pair key
- TInt index = FindHintKey(surface->iSurfaceHints, hintPair.iKey.iUid);
- if (index == KErrNotFound)
- {
- TRACE(Kern::Printf("SM SetSurfaceHint Hint key not found or invalid");)
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument; //Hint key not found or invalid
- }
-
- //Check for mutability
- if(!surface->iSurfaceHints[index].iMutable)
- {
- TRACE(Kern::Printf("SM SetSurfaceHint Hint is immutable");)
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied; //Hint pair is immutable
- }
- TRACE(Kern::Printf("SM SetSurfaceHint Hint key found and updated its value %d for the surface %08x \n", aHintPair->iValue, &sid);)
-
- //set the hint pair value now
- memcpy(&surface->iSurfaceHints[index], &hintPair, sizeof(RSurfaceManager::THintPair));
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
-
- return KErrNone;
- }
-
-/**
-Add a new surface hint value for the surface Id.
-@param aSurfaceId The surface identifier originally returned when the surface was created.
-@param aHintPair The value of the hint pair to Add.
-@return Returns KErrNone if successful, KErrArgument if the surface ID is invalid or the
-hint pair has invalid key UID, KErrAccessDenied if the surface is not open in the current
-process, KErrAlreadyExists if duplicate hint key used, KErrOverflow if no space to add new
-pair, otherwise a system wide error code.
-@internalTechnology
-*/
-TInt DSurfaceManager::AddSurfaceHint(const TSurfaceId* aSurfaceId, const RSurfaceManager::THintPair* aHintPair)
- {
- RSurfaceManager::THintPair hintPair;
- kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
-
- //Check for valid hint key
- if (hintPair.iKey.iUid == 0)
- {
- TRACE(Kern::Printf("SM AddSurfaceHint Hint key is invalid");)
- return KErrArgument; //Invalid Hint key
- }
-
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
-
- NKern::ThreadEnterCS();
- NKern::FMWait(&iMutex);
- //look it up
- TSurface* surface = FindSurfaceById(sid);
- if (!surface)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrArgument;
- }
-
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrAccessDenied;
- }
-
-
- //Check for empty hint pair
- if(surface->iSurfaceHints[KMaxHintsPerSurface - 1].iKey.iUid != 0)//at least end of sorted hint array should be 0 to add a new hint
- {
- TRACE(Kern::Printf("SM AddSurfaceHint there is no room to add the hint");)
- NKern::FMSignal(&iMutex);
- NKern::ThreadLeaveCS();
- return KErrOverflow; //No room for new hint
- }
- //We found room for a new hint pair, so insert it in the array
- // Meanwhile, we check for duplication, if it is, return KErrAlreadyExists
- TInt err = InsertHintKey(surface->iSurfaceHints,hintPair);
- NKern::FMSignal(&iMutex);
- TRACE(Kern::Printf("SM AddSurfaceHint Added new key ");)
- NKern::ThreadLeaveCS();
- return err;
- }
-
-/**
-Get the offset of the specified buffer from the base address of the underlying
-chunk.
-
-To obtain the address of the buffer, the offset returned must be added onto the
-base address of the RChunk returned in a call to MapSurface(). Note that
-buffer offsets are immutable during the lifetime of the surface.
-@param aParam The input parameters including the surface ID and buffer index.
-@pre The surface is open in the calling process.
-@return KErrNone if successful, KErrArgument if aSurfaceId or aBuffer are invalid,
-KErrAccessDenied if the surface is not open in the current process, KErrNotSupported if
-the surface is not mappable, otherwise a system wide error code.
-*/
-TInt DSurfaceManager::GetBufferOffset(RSurfaceManagerDriver::TDeviceParam* aParam,TUint* aOffset)
- {
- //Get the input parameters
- RSurfaceManagerDriver::TDeviceParam param;
- kumemget(¶m, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
- TSurfaceId sid;
- //fetch surface id from user memory
- kumemget(&sid, param.iSurfaceId, sizeof(TSurfaceId));
- //(TAny*)iBuffer holds the buffer number in its value
- TInt bufferNumber = (TInt) param.iBuffer;
-
- TSurface* surface = NULL;
- NKern::FMWait(&iMutex);
- surface = FindSurfaceById(sid);
- if(NULL == surface || (bufferNumber >= surface->iBuffers))
- {
- NKern::FMSignal(&iMutex);
- return KErrArgument;
- }
- if(!surface->iMappable)
- {
- NKern::FMSignal(&iMutex);
- return KErrNotSupported;
- }
- //find the owner
- TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
- if (!so)
- {
- NKern::FMSignal(&iMutex);
- return KErrAccessDenied;
- }
- TInt bufferOffset = surface->iOffsetToFirstBuffer + bufferNumber*surface->iOffsetBetweenBuffers;
- NKern::FMSignal(&iMutex);
-
- kumemput(aOffset, &bufferOffset, sizeof (TInt));
- return KErrNone;
- }
-
-/**
-Returns information specific to the Surface Manager implementation.
-@param aAttrib: Attribute to retrieve
-@param aValue : Output parameter where we write the value for the specified attribute
-@return KErrNone if successful or KErrArgument if the attribute UID is not recognized
-@internalTechnology
-*/
-TInt DSurfaceManager::GetSurfaceManagerAttrib(RSurfaceManager::TSurfaceManagerAttrib* aAttrib,TInt* aValue)
- {
- RSurfaceManager::TSurfaceManagerAttrib attrib;
- kumemget(&attrib, aAttrib, sizeof(RSurfaceManager::TSurfaceManagerAttrib));
-
- TInt out=KErrNone;
- TInt value;
- switch (attrib)
- {
- case RSurfaceManager::EMaxNumberOfHints:
- value=KMaxHintsPerSurface;
- break;
-
- default:
- out=KErrArgument;
- break;
- };
-
- if (out==KErrNone)
- {
- kumemput(aValue, &value, sizeof (TInt));
- }
- return out;
- }