graphicscompositionref/surfacemgrcommon/src/extension.cpp
changeset 0 91fe342bd9c4
child 2 47632b7dfb88
equal deleted inserted replaced
-1:000000000000 0:91fe342bd9c4
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 
       
    17 #include <kernel/kern_priv.h>
       
    18 #include <kernel/cache.h>
       
    19 #include <graphics/surface.h>
       
    20 #include <graphics/surfacetypes.h>
       
    21 #include <graphics/surfacemanager.h>
       
    22 #include "surfacemanager_dev.h"
       
    23 
       
    24 /**
       
    25 Convert the surface Id to an index of the array 
       
    26 based on the least significant 4 bits of the first word of the ID
       
    27 @param	aSurfaceId  Const reference to the surface Id
       
    28 @internalTechnology
       
    29 */
       
    30 static TInt SurfaceIdToIndex(const TSurfaceId& aSurfaceId)
       
    31 	{
       
    32 	return static_cast<TInt>(aSurfaceId.iInternal[0]&(KMaxLists-1));
       
    33 	}
       
    34 
       
    35 /**
       
    36 Removes an item from a linked list
       
    37 @param	aList  Pointer to the head of a linked list of type T
       
    38 @param	aOwner  Pointer to the object to be removed
       
    39 @internalTechnology
       
    40 */
       
    41 template<class T>
       
    42 static void UnlinkListItem(T** aList, const T* aItem)
       
    43 	{
       
    44 	TRACE(Kern::Printf("SM UnlinkListItem list %08x  object %08x \n", aList, aItem);)
       
    45 	
       
    46 	__ASSERT_DEBUG(aItem != NULL, Kern::Fault("Surface Manager", __LINE__));
       
    47 	__ASSERT_DEBUG(*aList != NULL, Kern::Fault("Surface Manager", __LINE__));
       
    48 
       
    49 	if (*aList == aItem)	//one we want is at the head of the list
       
    50 		{
       
    51 		*aList = aItem->iNext;
       
    52 		return;
       
    53 		}
       
    54 	
       
    55 	T* p = *aList;
       
    56 	T* q = (*aList)->iNext;
       
    57 	while (q)
       
    58 		{
       
    59 		if (q == aItem)
       
    60 			{
       
    61 			p->iNext = q->iNext;
       
    62 			return;
       
    63 			}
       
    64 		p = q;
       
    65 		q = q->iNext;
       
    66 		}
       
    67 	}
       
    68 
       
    69 
       
    70 
       
    71 
       
    72 /**
       
    73 Returns a pointer to the surface owner object for the specified process, for this surface.
       
    74 @param	aProcess  Pointer to the process object
       
    75 @return pointer to the surface owner object if found, else NULL
       
    76 @internalTechnology
       
    77 */
       
    78 
       
    79 TProcessListItem* TSurface::ProcessOwnerInfo(const DProcess* aProcess)
       
    80 	{
       
    81 	TProcessListItem* so = iOwners;
       
    82 	while(so)
       
    83 		{
       
    84 		if (aProcess == so->iOwningProcess)
       
    85 			{
       
    86 			break;
       
    87 			}
       
    88 		so = so->iNext;
       
    89 		}
       
    90 	return so;
       
    91 	}
       
    92 
       
    93 /**
       
    94 Creates a shared chunk surface.
       
    95 @param aParams  Package buffer containing the surface creation parameters.  
       
    96 @param aId  Will be set to the surface id of the newly created surface.
       
    97 @return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
       
    98 otherwise one of the other system wide error codes.
       
    99 @see RSurfaceManager::TSurfaceCreationAttributes
       
   100 @internalTechnology
       
   101 */
       
   102 
       
   103 TInt DSurfaceManager::CreateSurface(const TDesC8* aParams, TSurfaceId* aId)
       
   104 	{
       
   105 
       
   106 	RSurfaceManager::TSurfaceCreationAttributesBuf buf;
       
   107 	RSurfaceManager::TSurfaceCreationAttributes& attribs = buf();
       
   108 	
       
   109 	Kern::KUDesGet(buf, *aParams);		//fetch input parameters
       
   110 	if( (attribs.iHintCount > KMaxHintsPerSurface) || (attribs.iHintCount<0) )
       
   111 		{
       
   112 		return KErrArgument;
       
   113 		}	
       
   114 	
       
   115 	RSurfaceManager::THintPair tempSurfaceHints[KMaxHintsPerSurface];
       
   116 	if( (attribs.iHintCount>0) && attribs.iSurfaceHints)
       
   117 		{
       
   118 		kumemget(tempSurfaceHints, attribs.iSurfaceHints, attribs.iHintCount*sizeof(RSurfaceManager::THintPair));		
       
   119 		attribs.iSurfaceHints = tempSurfaceHints;
       
   120 		}
       
   121 	else
       
   122 		{
       
   123 		attribs.iSurfaceHints=NULL;
       
   124 		}
       
   125 
       
   126 	//validate input parameters and calculate chunk size
       
   127 	TInt roundedBufferSize = attribs.iOffsetBetweenBuffers;
       
   128 	TUint dummyActualSize = 0;	
       
   129 	
       
   130 	TInt chunkSize = ValidateAndCalculateChunkSize(attribs, roundedBufferSize, dummyActualSize, ETrue);
       
   131 	if (chunkSize == 0)
       
   132 		{
       
   133 		return KErrArgument;
       
   134 		}	
       
   135 
       
   136 	TSurfaceId sid;
       
   137 	TInt r = KErrNone;
       
   138 	TSurface* surface = NULL;
       
   139 	do		//in the unlikely event that we generate a duplicate surface id, try again.
       
   140 		{
       
   141 		GenerateSurfaceId(sid);
       
   142 
       
   143 		NKern::FMWait(&iMutex);
       
   144 		surface = FindSurfaceById(sid);
       
   145 		NKern::FMSignal(&iMutex);
       
   146 		}
       
   147 	while (surface);
       
   148 	
       
   149 	//create a shared chunk for the surface memory
       
   150 	TChunkCreateInfo info;
       
   151 	info.iType = TChunkCreateInfo::ESharedKernelMultiple;	//multi process mappable
       
   152 	info.iMaxSize = chunkSize;
       
   153 	info.iOwnsMemory = ETrue;
       
   154 
       
   155 //iMapAttr is valid only for hardware devices and will not make any effect in wins	
       
   156 #ifndef __WINS__
       
   157 	info.iMapAttr = (attribs.iCacheAttrib == RSurfaceManager::ECached) ? EMapAttrCachedMax : EMapAttrL1Uncached;
       
   158 #else
       
   159 	info.iMapAttr = 0;
       
   160 #endif
       
   161 
       
   162 #ifdef GRAPHICS_SURFACEMANAGER_SYBORG
       
   163 	// ChunkCommitPhysical method may only be used if the chunk was
       
   164 	// created with TChunkCreateInfo::iOwnsMemory set to false.
       
   165     info.iMapAttr = EMapAttrFullyBlocking;
       
   166     info.iOwnsMemory = EFalse;
       
   167 #endif
       
   168 
       
   169 	TLinAddr kernAddr;
       
   170 	TUint32 mapAttr;	
       
   171 	
       
   172 	NKern::ThreadEnterCS();
       
   173 	DChunk* chunk;
       
   174 	r = Kern::ChunkCreate(info, chunk, kernAddr, mapAttr);
       
   175 	if (KErrNone != r)
       
   176 		{
       
   177 		NKern::ThreadLeaveCS();
       
   178 		return r;
       
   179 		}
       
   180 
       
   181 	//commit the memory
       
   182 	TUint32 paddr;
       
   183 #ifdef GRAPHICS_SURFACEMANAGER_SYBORG 
       
   184     Kern::Printf("DSurfaceManager::CreateSurface: Allocate ");
       
   185     if( iVHWMemoryManager != NULL )
       
   186 		{
       
   187 	    paddr = iVHWMemoryManager->Allocate(chunkSize);
       
   188 		}
       
   189 	else
       
   190 		{
       
   191 		CreateMemory();
       
   192 	    paddr = iVHWMemoryManager->Allocate(chunkSize);
       
   193 		}
       
   194 
       
   195     
       
   196     if ( paddr )
       
   197         {
       
   198         r = Kern::ChunkCommitPhysical( chunk, 0, chunkSize, paddr );
       
   199 	    Kern::Printf("DSurfaceManager::CreateSurface: Commit %d from: 0x%08x success: %d",chunkSize, paddr, r );
       
   200         }
       
   201     else
       
   202         {
       
   203         r = KErrNoMemory;
       
   204         }
       
   205 #else // GRAPHICS_SURFACEMANAGER_SYBORG
       
   206 	if (attribs.iContiguous)
       
   207 		{
       
   208 		r = Kern::ChunkCommitContiguous(chunk, 0, chunkSize, paddr);
       
   209 		}
       
   210 	else
       
   211 		{
       
   212 		r = Kern::ChunkCommit(chunk, 0, chunkSize);
       
   213 		}
       
   214 #endif // GRAPHICS_SURFACEMANAGER_SYBORG
       
   215 
       
   216 	if (KErrNone != r)
       
   217 		{
       
   218 		//problem committing the memory,
       
   219 		//destroy the chunk and cleanup
       
   220 		Kern::ChunkClose(chunk);
       
   221 		NKern::ThreadLeaveCS();
       
   222 		return r;
       
   223 		}
       
   224 
       
   225 	//create a surface structure for the new surface
       
   226 	surface = new TSurface;
       
   227 	TRACE(Kern::Printf("SM A %08x TSurface CreateSurface",surface);)
       
   228 	if (!surface)
       
   229 		{
       
   230 		//destroy the chunk and cleanup, out of memory
       
   231 		Kern::ChunkClose(chunk);
       
   232 		NKern::ThreadLeaveCS();
       
   233 		return KErrNoMemory;
       
   234 		}
       
   235 
       
   236 	surface->iId = sid;
       
   237 	surface->iSize = attribs.iSize;
       
   238 	surface->iBuffers = attribs.iBuffers;
       
   239 	surface->iPixelFormat = attribs.iPixelFormat;
       
   240 	surface->iStride = attribs.iStride;
       
   241 	surface->iOffsetToFirstBuffer = attribs.iOffsetToFirstBuffer;
       
   242 	surface->iAlignment = attribs.iAlignment;
       
   243 	surface->iContiguous = attribs.iContiguous;
       
   244 	surface->iChunk = chunk;
       
   245 	surface->iOffsetBetweenBuffers = roundedBufferSize;
       
   246 	surface->iCacheAttrib = attribs.iCacheAttrib;
       
   247 	surface->iMappable = attribs.iMappable;
       
   248 	if(attribs.iHintCount>0)
       
   249 		{
       
   250 		memcpy(surface->iSurfaceHints,tempSurfaceHints,attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
       
   251 		}
       
   252 	memclr(surface->iSurfaceHints+attribs.iHintCount, (KMaxHintsPerSurface-attribs.iHintCount)*sizeof(RSurfaceManager::THintPair));
       
   253 	
       
   254 	//create a surface owner for this surface
       
   255 	TProcessListItem* owner = new TProcessListItem;
       
   256 	TRACE(Kern::Printf("SM A %08x TProcessListItem CreateSurface",owner);)
       
   257 
       
   258 	if (!owner)
       
   259 		{
       
   260 		//destroy the chunk and cleanup, out of memory
       
   261 		Kern::ChunkClose(chunk);
       
   262 		delete(surface);
       
   263 		TRACE(Kern::Printf("SM D %08x TSurface CreateSurface",surface);)
       
   264 		NKern::ThreadLeaveCS();
       
   265 		return KErrNoMemory;
       
   266 		}
       
   267 	
       
   268 	owner->iCount = 1;		//mark it as open in this process
       
   269 	owner->iOwningProcess =  &Kern::CurrentProcess();
       
   270 	owner->iNext = NULL;
       
   271 		
       
   272 	surface->iOwners = owner;	//only 1 owner at creation time
       
   273 
       
   274 	//at this point we have a fully constructed TSurface
       
   275 
       
   276 	//add surface to head of surfaces list
       
   277 	NKern::FMWait(&iMutex);
       
   278 	//Mask off the bottom log2(KMaxLists) bits of the first word of the surfaceID as an index
       
   279 	//add the new surface to the beginning of the list 
       
   280 	TInt index = SurfaceIdToIndex(sid);
       
   281 	surface->iNext = iSurfacesIndex[index];
       
   282 	iSurfacesIndex[index] = surface;
       
   283 
       
   284 	NKern::FMSignal(&iMutex);		
       
   285 	NKern::ThreadLeaveCS();
       
   286 	
       
   287 	//write surface id back to user side
       
   288 	kumemput(aId, &sid, sizeof (TSurfaceId));
       
   289 	return KErrNone;
       
   290 	}
       
   291 
       
   292 
       
   293 /**
       
   294 Validate that a chunk contains physical memory for the used areas.
       
   295 
       
   296 This function should be called in Critical Section in order to be completed even if the thread 
       
   297 or process is killed and so be able to free the memory allocated  (TUint32[pageList])
       
   298 
       
   299 @param aChunk  Chunk that the user supplied.   
       
   300 @param aAttribs  Surface Creation Attributes.
       
   301 @param aBuffersize  Calculated size of each buffer.
       
   302 @param aMapAttr  Filled in with the mapping attributes of the memory.
       
   303 @param aIsContiguous  Lets the caller know if the surface is physically contiguous or not. 
       
   304 @return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
       
   305 KErrBadHandle if aChunkHandle is of an invalid shared chunk memory,
       
   306 otherwise one of the other system wide error codes.
       
   307 @see RSurfaceManager::TSurfaceCreationAttributes
       
   308 @internalTechnology
       
   309 */
       
   310 TInt DSurfaceManager::ValidatePhysicalMemory(DChunk* aChunk, const RSurfaceManager::TSurfaceCreationAttributes& aAttribs, 
       
   311 								   TUint aBuffersize, TUint32& aMapAttr, TBool &aIsContiguous) 
       
   312 	{
       
   313 	TLinAddr kernAddr;
       
   314 	TUint32 physAddr;
       
   315 
       
   316 	//Get the physical address for a region in a shared chunk
       
   317 	TInt pageSize = Kern::RoundToPageSize(1);
       
   318 	TInt pageList = 1 + (aChunk->iSize + pageSize - 2) / pageSize;
       
   319 	TUint32* physAddr2 = new TUint32[pageList];
       
   320 	if(!physAddr2)
       
   321 		{
       
   322 		return KErrNoMemory;
       
   323 		}
       
   324 	
       
   325 	// Unless proven otherwise, the memory is not contiguous. 
       
   326 	aIsContiguous = EFalse;
       
   327 	TInt r = Kern::ChunkPhysicalAddress(aChunk, 0, aChunk->iSize, kernAddr, aMapAttr, physAddr, physAddr2);
       
   328 	if (KErrNone == r)
       
   329 		{
       
   330 		aIsContiguous = ETrue;
       
   331 		}
       
   332 	
       
   333 	
       
   334 	TRACE(Kern::Printf("SM CreateSurface ChunkPhysicalAddress r %d chunk %08x chunk size %d", r, aChunk, aChunk->iSize);)
       
   335 	TRACE(Kern::Printf("SM CreateSurface kernAddr %08x", kernAddr);)
       
   336 	TRACE(Kern::Printf("SM CreateSurface mapAttr %08x", aMapAttr);)
       
   337 	TRACE(Kern::Printf("SM CreateSurface physAddr %08x", physAddr);)
       
   338 	TRACE(Kern::Printf("SM CreateSurface physAddr2 %08x", physAddr2);)
       
   339 	
       
   340 	if(r < KErrNone)
       
   341 		{
       
   342 		// Error means that there isn't memory in the whole chunk - so check the
       
   343 		// relevant areas - it is allowed to have gaps between the buffers, but not 
       
   344 		// within the actual regions that are used for buffers. 
       
   345 		
       
   346 		// So, we first check the area before first buffer up to "offsettofirstbuffer", which all should be valid
       
   347 		if (aAttribs.iOffsetToFirstBuffer != 0)
       
   348 			{
       
   349 			r = Kern::ChunkPhysicalAddress(aChunk, 0, aAttribs.iOffsetToFirstBuffer, 
       
   350 					kernAddr, aMapAttr, physAddr, physAddr2);
       
   351 			}
       
   352 		else
       
   353 			{
       
   354 			r = KErrNone;
       
   355 			}
       
   356 		
       
   357 		// If that's a pass, loop through and check the actual buffers (leave loop if it fails).
       
   358 		for(TInt i = 0; i < aAttribs.iBuffers && KErrNone <= r; i++)
       
   359 			{
       
   360 			r = Kern::ChunkPhysicalAddress(aChunk, 
       
   361 					aAttribs.iOffsetToFirstBuffer + aAttribs.iOffsetBetweenBuffers * i, 
       
   362 					aBuffersize, kernAddr, aMapAttr, physAddr, physAddr2);
       
   363 			}
       
   364 		}
       
   365 
       
   366 	// Fix up weird ChunkPhysicalAddress behaviour - it returns 1 to indicate that memory is non-contiguous. 
       
   367 	if (1 == r)
       
   368 		{
       
   369 		r = KErrNone;
       
   370 		}
       
   371 
       
   372 	delete[] physAddr2;
       
   373 	return r;
       
   374 	}
       
   375 
       
   376 
       
   377 /**
       
   378 Creates a surface in an existing shared chunk.
       
   379 @param aParam  Package buf containing the surface creation parameters and id to be set to the surface id of the newly created surface.  
       
   380 @param aChunkHandle  Existing valid shared chunk handle.
       
   381 @return KErrNone if successful, KErrArgument if the creation attributes were incorrect,
       
   382 KErrBadHandle if aChunkHandle is of an invalid shared chunk memory,
       
   383 otherwise one of the other system wide error codes.
       
   384 @see RSurfaceManager::TSurfaceCreationAttributes
       
   385 @internalTechnology
       
   386 */
       
   387 TInt DSurfaceManager::CreateSurface(RSurfaceManagerDriver::TDeviceParam* aParam, TInt aChunkHandle)
       
   388 	{
       
   389 	RSurfaceManager::TSurfaceCreationAttributesBuf buf;
       
   390 	RSurfaceManager::TSurfaceCreationAttributes& attribs = buf();
       
   391 
       
   392 	//Get the input parameters
       
   393 	RSurfaceManagerDriver::TDeviceParam param;
       
   394 	kumemget(&param, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
       
   395 	Kern::KUDesGet(buf, *(reinterpret_cast<const TDesC8*>(param.iBuffer)));
       
   396 	if( (attribs.iHintCount > KMaxHintsPerSurface) || (attribs.iHintCount<0) )
       
   397 		{
       
   398 		return KErrArgument;
       
   399 		}	
       
   400 	
       
   401 	RSurfaceManager::THintPair tempSurfaceHints[KMaxHintsPerSurface];
       
   402 	if( (attribs.iHintCount>0) && attribs.iSurfaceHints)
       
   403 		{
       
   404 		kumemget(tempSurfaceHints, attribs.iSurfaceHints, attribs.iHintCount*sizeof(RSurfaceManager::THintPair));		
       
   405 		attribs.iSurfaceHints = tempSurfaceHints;
       
   406 		}
       
   407 	else
       
   408 		{
       
   409 		attribs.iSurfaceHints=NULL;
       
   410 		}
       
   411 		
       
   412 	//validate input parameters and calc size
       
   413 	TInt roundedBufferSize = attribs.iOffsetBetweenBuffers;
       
   414 	TUint actualBufferSize = 0;
       
   415 	TInt chunkSize = ValidateAndCalculateChunkSize(attribs, roundedBufferSize, actualBufferSize);
       
   416 	if (chunkSize == 0)
       
   417 		{
       
   418 		return KErrArgument;
       
   419 		}
       
   420 	
       
   421 	NKern::ThreadEnterCS();
       
   422 	
       
   423 	//Open an existing shared chunk
       
   424 	DChunk* chunk = Kern::OpenSharedChunk(NULL, aChunkHandle, EFalse);
       
   425 	if(chunk == NULL)
       
   426 		{
       
   427 		NKern::ThreadLeaveCS();
       
   428 		return KErrBadHandle;
       
   429 		}
       
   430 	
       
   431 	//Check for chunk type as kernel multiple
       
   432 	if(chunk->iChunkType != ESharedKernelMultiple)
       
   433 		{
       
   434 		Kern::ChunkClose(chunk);
       
   435 		NKern::ThreadLeaveCS();
       
   436 		return KErrBadHandle;
       
   437 		}
       
   438 	
       
   439 	//Check for enough chunk size to create surface for requested attributes
       
   440 	if (chunk->iSize < attribs.iOffsetToFirstBuffer + attribs.iBuffers * actualBufferSize)
       
   441 		{
       
   442 		Kern::ChunkClose(chunk);
       
   443 		NKern::ThreadLeaveCS();
       
   444 		return KErrArgument;
       
   445 		}
       
   446 
       
   447 	TSurfaceId sid;
       
   448 	TSurface* surface = NULL;
       
   449 	do		//in the unlikely event that we generate a duplicate surface id, try again.
       
   450 		{
       
   451 		GenerateSurfaceId(sid);
       
   452 
       
   453 		NKern::FMWait(&iMutex);
       
   454 		surface = FindSurfaceById(sid);
       
   455 		NKern::FMSignal(&iMutex);
       
   456 		}
       
   457 	while (surface);
       
   458 
       
   459 	//create a surface structure for the new surface
       
   460 	surface = new TSurface;
       
   461 	TRACE(Kern::Printf("SM A %08x TSurface CreateSurface",surface);)
       
   462 	if (!surface)
       
   463 		{
       
   464 		//destroy the chunk and cleanup, out of memory
       
   465 		Kern::ChunkClose(chunk);
       
   466 		NKern::ThreadLeaveCS();
       
   467 		return KErrNoMemory;
       
   468 		}
       
   469 
       
   470 	TUint32 mapAttr = 0;
       
   471 	TBool isContiguous;
       
   472 	TInt r = ValidatePhysicalMemory(chunk, attribs, actualBufferSize, mapAttr, isContiguous);
       
   473 	if (r != KErrNone)
       
   474 		{
       
   475 		//destroy the surface and close the chunk
       
   476 		delete(surface);
       
   477 		Kern::ChunkClose(chunk);
       
   478 		NKern::ThreadLeaveCS();
       
   479 		if (r != KErrNoMemory)
       
   480 			{
       
   481 			r = KErrArgument;
       
   482 			}
       
   483 		return r;
       
   484 		}
       
   485 	
       
   486 	surface->iId = sid;
       
   487 	surface->iSize = attribs.iSize;
       
   488 	surface->iBuffers = attribs.iBuffers;
       
   489 	surface->iPixelFormat = attribs.iPixelFormat;
       
   490 	surface->iStride = attribs.iStride;
       
   491 	surface->iOffsetToFirstBuffer = attribs.iOffsetToFirstBuffer;
       
   492 	surface->iAlignment = attribs.iAlignment;
       
   493 	surface->iContiguous = isContiguous;
       
   494 	surface->iChunk = chunk;
       
   495 	surface->iOffsetBetweenBuffers = (attribs.iOffsetBetweenBuffers) ? attribs.iOffsetBetweenBuffers : roundedBufferSize;
       
   496 	surface->iMappable = attribs.iMappable;
       
   497 #ifndef __WINS__	//Creation attribute field will not considered for iCacheAttrib
       
   498 	TUint32 level1Info = mapAttr & EMapAttrL1CacheMask;
       
   499 	TUint32 level2Info = mapAttr & EMapAttrL2CacheMask;
       
   500 	TBool chunkIsNotcached =  ((level2Info == EMapAttrL2Uncached) && 
       
   501 	    ((level1Info == EMapAttrFullyBlocking) || (level1Info == EMapAttrBufferedNC) ||
       
   502 	     (level1Info == EMapAttrBufferedC) || (level1Info == EMapAttrL1Uncached)));
       
   503 	surface->iCacheAttrib = (chunkIsNotcached) ? RSurfaceManager::ENotCached : RSurfaceManager::ECached;
       
   504 #else
       
   505 	surface->iCacheAttrib = RSurfaceManager::ENotCached;	
       
   506 #endif
       
   507 	
       
   508 	if(attribs.iHintCount>0)
       
   509 		{
       
   510 		memcpy(surface->iSurfaceHints,tempSurfaceHints,attribs.iHintCount*sizeof(RSurfaceManager::THintPair));
       
   511 		}
       
   512 	memclr(surface->iSurfaceHints+attribs.iHintCount, (KMaxHintsPerSurface-attribs.iHintCount)*sizeof(RSurfaceManager::THintPair));
       
   513 
       
   514 	//create a surface owner for this surface
       
   515 	TProcessListItem* owner = new TProcessListItem;
       
   516 	TRACE(Kern::Printf("SM A %08x TProcessListItem CreateSurface",owner);)
       
   517 
       
   518 	if (!owner)
       
   519 		{
       
   520 		//destroy the chunk and cleanup, out of memory
       
   521 		Kern::ChunkClose(chunk);
       
   522 		delete(surface);
       
   523 		TRACE(Kern::Printf("SM D %08x TSurface CreateSurface",surface);)
       
   524 		NKern::ThreadLeaveCS();
       
   525 		return KErrNoMemory;
       
   526 		}
       
   527 	
       
   528 	owner->iCount = 1;		//mark it as open in this process
       
   529 	owner->iOwningProcess =  &Kern::CurrentProcess();
       
   530 	owner->iNext = NULL;
       
   531 		
       
   532 	surface->iOwners = owner;	//only 1 owner at creation time
       
   533 
       
   534 	NKern::FMWait(&iMutex);
       
   535 	//at this point we have a fully constructed TSurface
       
   536 	//add surface to head of surfaces list
       
   537 
       
   538 	//Mask off the bottom log2(KMaxLists) bits of the first word of the surfaceID as an index
       
   539 	//add the new surface to the beginning of the list 
       
   540 	TInt index = SurfaceIdToIndex(sid);
       
   541 	surface->iNext = iSurfacesIndex[index];
       
   542 	iSurfacesIndex[index] = surface;
       
   543 	NKern::FMSignal(&iMutex);		
       
   544 	NKern::ThreadLeaveCS();
       
   545 	
       
   546 	//write surface id back to user side
       
   547 	kumemput(reinterpret_cast<TSurfaceId*>(param.iSurfaceId), &sid, sizeof (TSurfaceId));
       
   548 	return KErrNone;
       
   549 	}
       
   550 
       
   551 
       
   552 /**
       
   553 Opens a surface.  If the current process already is in the owners list, its usage count is
       
   554 incremented.  If this is an open from a different process, a new surface owner object is added
       
   555 to the surface's list of owners and its usage count is set to 1.
       
   556 @param aId  The surface id of the surface to be opened.
       
   557 @return KErrNone if successful, otherwise a system error code
       
   558 @internalTechnology
       
   559 */
       
   560 TInt DSurfaceManager::OpenSurface(const TSurfaceId* aId)
       
   561 	{
       
   562 	TSurfaceId sid;
       
   563 	//fetch surface id from user memory
       
   564 	kumemget(&sid, aId, sizeof (TSurfaceId));
       
   565 	NKern::ThreadEnterCS();
       
   566 	TProcessListItem* owner = new TProcessListItem;  //speculative creation
       
   567 	TRACE(Kern::Printf("SM A %08x TProcessListItem OpenSurface", owner);)
       
   568 	
       
   569 	NKern::FMWait(&iMutex);
       
   570 	//look it up
       
   571 	TSurface* surface = FindSurfaceById(sid);
       
   572 	if (!surface)	
       
   573 		{
       
   574 		NKern::FMSignal(&iMutex);
       
   575 		delete owner;		//free the memory just allocated
       
   576 		TRACE(Kern::Printf("SM D %08x TProcessListItem OpenSurface", owner);)
       
   577 		NKern::ThreadLeaveCS();
       
   578 		return KErrArgument;
       
   579 		}
       
   580 
       
   581 	//find the owner
       
   582 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
   583 	if (so)
       
   584 		{
       
   585 		//already an owner so inc the ref count
       
   586 		++so->iCount;
       
   587 		}
       
   588 	else
       
   589 		{
       
   590 		//new process trying to open it
       
   591 		if (!owner)
       
   592 			{
       
   593 			//the creation of the owner information object failed, out of memory
       
   594 			NKern::FMSignal(&iMutex);
       
   595 			NKern::ThreadLeaveCS();
       
   596 			return KErrNoMemory;
       
   597 			}
       
   598 			
       
   599 		owner->iCount = 1;		//mark it open in this process
       
   600 		owner->iOwningProcess =  &Kern::CurrentProcess();
       
   601 		
       
   602 		//add the owner to the list of owners
       
   603 		owner->iNext = surface->iOwners;
       
   604 		surface->iOwners = owner;
       
   605 		owner = NULL;
       
   606 		}
       
   607 	NKern::FMSignal(&iMutex);
       
   608 	delete owner;		//free if not used.
       
   609 	TRACE(Kern::Printf("SM D %08x TProcessListItem OpenSurface", owner);)
       
   610 	NKern::ThreadLeaveCS();
       
   611 	return KErrNone;
       
   612 	}
       
   613 
       
   614 
       
   615 
       
   616 /**
       
   617 Closes a surface.  Decrements the usage count in the surface owner object
       
   618 if the usage count is then zero, removes this surface owner from the surface.
       
   619 If this results in a surface with no owners, the surface is deleted and the 
       
   620 surface shared chunk is closed.
       
   621 @param aId  The id of the surface to be closed
       
   622 @return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface,
       
   623 KErrAccessDenied if the surface is not open in the current process, otherwise a system wide
       
   624 error code.
       
   625 @internalTechnology
       
   626 */
       
   627 TInt DSurfaceManager::CloseSurface(const TSurfaceId* aId)
       
   628 	{
       
   629 
       
   630 	TSurfaceId sid;
       
   631 	kumemget(&sid, aId, sizeof (TSurfaceId));	//fetch surface id from user memory
       
   632 	//look it up
       
   633 	NKern::ThreadEnterCS();
       
   634 	NKern::FMWait(&iMutex);
       
   635 	TSurface* surface = FindSurfaceById(sid);
       
   636 	if (!surface)	
       
   637 		{
       
   638 		NKern::FMSignal(&iMutex);
       
   639 		NKern::ThreadLeaveCS();
       
   640 		return KErrArgument;
       
   641 		}
       
   642 
       
   643 	//find the owner
       
   644 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
   645 	if (!so)
       
   646 		{
       
   647 		NKern::FMSignal(&iMutex);
       
   648 		NKern::ThreadLeaveCS();
       
   649 		return KErrAccessDenied;
       
   650 		}
       
   651 
       
   652 	//current process is a surface owner so decrement the open count
       
   653 	TSurface* surfaceToDelete = NULL;
       
   654 	TProcessListItem* ownerToDelete = NULL;
       
   655 	DChunk* chunkToClose = NULL;
       
   656 	if (--so->iCount == 0)
       
   657 		{
       
   658 		//if count is now zero remove the owner
       
   659 		//surface->RemoveOwner(so);
       
   660 		UnlinkListItem(&surface->iOwners, so);
       
   661 		ownerToDelete = so;
       
   662 
       
   663 		//check to see if the surface has any owners
       
   664 		if (!surface->iOwners)
       
   665 			{
       
   666 			//no more owners of the surface
       
   667 			chunkToClose = surface->iChunk;
       
   668 
       
   669 			//remove the surface from the list
       
   670 			UnlinkListItem(&(iSurfacesIndex[SurfaceIdToIndex(surface->iId)]), surface);
       
   671 			surfaceToDelete = surface;
       
   672 			}
       
   673 		}
       
   674 	
       
   675 	NKern::FMSignal(&iMutex);
       
   676 
       
   677 	if (chunkToClose)
       
   678 		{
       
   679 #ifdef GRAPHICS_SURFACEMANAGER_SYBORG
       
   680         TLinAddr kernelAddress;
       
   681         TUint32 mapAttr;
       
   682         TUint32 physicalAddress(0);
       
   683         if (KErrNone == Kern::ChunkPhysicalAddress(chunkToClose, 0, chunkToClose->Size(), kernelAddress, mapAttr, physicalAddress))
       
   684             {
       
   685             Kern::Printf("Closing chunk: deallocate %u",physicalAddress);
       
   686             iVHWMemoryManager->Deallocate(physicalAddress);
       
   687             }
       
   688 #endif // GRAPHICS_SURFACEMANAGER_SYBORG
       
   689 		//surface has no more owners so close the chunk
       
   690 		Kern::ChunkClose(chunkToClose);
       
   691 		}
       
   692 
       
   693 	delete surfaceToDelete;
       
   694 	TRACE(Kern::Printf("SM D %08x TSurface CloseSurface",surfaceToDelete);)
       
   695 	delete ownerToDelete;
       
   696 	TRACE(Kern::Printf("SM D %08x TProcessListItem CloseSurface",ownerToDelete);)
       
   697 	NKern::ThreadLeaveCS();
       
   698 
       
   699 	return KErrNone;
       
   700 	}
       
   701 
       
   702 
       
   703 /**
       
   704 Maps the surface memory into the process of the calling thread. This will fail if
       
   705 the surface is not open in this process, or if the handle to the chunk cannot be created.
       
   706 @param aId  The id of the surface to be mapped in.
       
   707 @return KErrNone if successful, KErrArgument if the surface ID does not refer to a
       
   708 surface, KErrAccessDenied if the surface is not open in the current process,
       
   709 KErrNotSupported if the surface is not mappable, KErrOverflow if the chunk limit has been
       
   710 exceeded in the moving memory model, otherwise a system wide error code.
       
   711 @internalTechnology
       
   712 */
       
   713 TInt DSurfaceManager::MapSurface(const TSurfaceId* aId)
       
   714 	{
       
   715 	TSurfaceId sid;
       
   716 	kumemget(&sid, aId, sizeof (TSurfaceId));	//fetch surface id from user memory
       
   717 
       
   718 	//look it up
       
   719 	NKern::ThreadEnterCS();
       
   720 	NKern::FMWait(&iMutex);
       
   721 	TSurface* surface = FindSurfaceById(sid);
       
   722 	if (!surface)	
       
   723 		{
       
   724 		NKern::FMSignal(&iMutex);
       
   725 		NKern::ThreadLeaveCS();
       
   726 		return KErrArgument;	//surface id is not valid or in the list of surfaces
       
   727 		}
       
   728 	if(!surface->iMappable)
       
   729 		{
       
   730 		NKern::FMSignal(&iMutex);
       
   731 		NKern::ThreadLeaveCS();		
       
   732 		return KErrNotSupported;
       
   733 		}
       
   734 
       
   735 	//find the owner
       
   736 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
   737 	if (!so)
       
   738 		{
       
   739 		NKern::FMSignal(&iMutex);
       
   740 		NKern::ThreadLeaveCS();
       
   741 		return KErrAccessDenied;	//can't map it in, it's not open in this process
       
   742 		}
       
   743 
       
   744 	DChunk* chunk = surface->iChunk;
       
   745 	TInt r = chunk->Open();
       
   746 	NKern::FMSignal(&iMutex);
       
   747 	TRACE(Kern::Printf("SM MapSurface chunk open r %d\n",r);)
       
   748 
       
   749 	if (r == KErrGeneral)
       
   750 		{
       
   751 		NKern::ThreadLeaveCS();
       
   752 		return KErrAccessDenied;
       
   753 		}
       
   754 
       
   755 	//if we are here, got the surface and we are the owner.
       
   756 	//if we are the owner we must have it open at least once
       
   757 
       
   758 	r = Kern::MakeHandleAndOpen(NULL, chunk);
       
   759 	chunk->Close(NULL);
       
   760 	TRACE(Kern::Printf("SM MapSurface handle open r: %d\n",r);)
       
   761 
       
   762 	NKern::ThreadLeaveCS();
       
   763 
       
   764 	return r;
       
   765 	}
       
   766 
       
   767 
       
   768 /**
       
   769 Record a new connection to the driver.
       
   770 Adds an element to the reference counted list of connected processes if the connection
       
   771 is from a new process, otherwise it increments the reference count.
       
   772 @param aProcess  The process which has opened a driver channel.
       
   773 @internalTechnology
       
   774 */
       
   775 TInt DSurfaceManager::AddConnection(const DProcess* aProcess)
       
   776 	{
       
   777 	TRACE(Kern::Printf("SM AddConnection process %08x\n", aProcess);)
       
   778 	NKern::ThreadEnterCS();
       
   779 	TProcessListItem* connectedProcess = new TProcessListItem;  //speculative creation
       
   780 	TRACE(Kern::Printf("SM A %08x TProcessListItem AddConnection", connectedProcess);)
       
   781 	NKern::FMWait(&iMutex);
       
   782 	TProcessListItem* p = FindConnectedProcess(aProcess);
       
   783 	if (p)	//already connected, found the process
       
   784 		{
       
   785 		++p->iCount;
       
   786 		}
       
   787 	else
       
   788 		{
       
   789 		//add a new connected process
       
   790 		if (!connectedProcess)
       
   791 			{
       
   792 			//the creation of the owner information object failed, out of memory
       
   793 			NKern::FMSignal(&iMutex);
       
   794 			NKern::ThreadLeaveCS();
       
   795 			return KErrNoMemory;
       
   796 			}
       
   797 		connectedProcess->iOwningProcess = (DProcess*)aProcess;
       
   798 		connectedProcess->iCount=1;
       
   799 		
       
   800 		connectedProcess->iNext = iConnectedProcesses;
       
   801 		iConnectedProcesses = connectedProcess;
       
   802 		connectedProcess = NULL;
       
   803 		}
       
   804 	NKern::FMSignal(&iMutex);
       
   805 	delete connectedProcess;
       
   806 	TRACE(Kern::Printf("SM D %08x TProcessListItem AddConnection", connectedProcess);)
       
   807 	NKern::ThreadLeaveCS();
       
   808 	return KErrNone;
       
   809 	}
       
   810 	
       
   811 	
       
   812 	
       
   813 /**
       
   814 Called when the driver channel is closed.
       
   815 Decrements the reference count for the connected process, if the last connection
       
   816 for this process is closed (reference count reaches 0) it removes the process from the list.
       
   817 @param aProcess  The process which has closed the driver channel.
       
   818 @internalTechnology
       
   819 */
       
   820 void DSurfaceManager::RemoveConnection(const DProcess* aProcess)
       
   821 	{
       
   822 	TRACE(Kern::Printf("SM RemoveConnection process %08x\n", aProcess);)
       
   823 	NKern::ThreadEnterCS();
       
   824 	NKern::FMWait(&iMutex);
       
   825 	TProcessListItem* p =FindConnectedProcess(aProcess);
       
   826 	TProcessListItem* toDelete = NULL;
       
   827 	if (p)	//already connected, found the process
       
   828 		{
       
   829 		if (--p->iCount == 0) //last connection in process has disconnected
       
   830 			{
       
   831 			//remove the process from the list and cleanup
       
   832 			UnlinkListItem(&iConnectedProcesses, p);
       
   833 			toDelete = p;
       
   834 			}
       
   835 		}
       
   836 	NKern::FMSignal(&iMutex);
       
   837 	delete toDelete;
       
   838 	TRACE(Kern::Printf("SM D %08x TProcessListItem RemoveConnection ", toDelete);)
       
   839 	
       
   840 	
       
   841 	if (toDelete)	// if a process has closed its last channel, remove process from the surface owners.
       
   842 		{
       
   843 		CloseSurfaceHandlesForProcess(aProcess);
       
   844 		}
       
   845 
       
   846 	NKern::ThreadLeaveCS();
       
   847 	}
       
   848 	
       
   849 
       
   850 
       
   851 
       
   852 /**
       
   853 Closes all the surfaces belonging to the process which has just terminated.
       
   854 If this is the only owner of a surface, delete the surface.
       
   855 @param aProcess  The process which has terminated.
       
   856 @pre must be called in critical section
       
   857 @internalTechnology
       
   858 */
       
   859 void DSurfaceManager::CloseSurfaceHandlesForProcess(const DProcess* aProcess)
       
   860 	{
       
   861 
       
   862 	NKern::FMWait(&iMutex);
       
   863 
       
   864 	TSurface* p = NULL;
       
   865 	TSurface* surfacesTodelete = NULL;
       
   866 	TProcessListItem* ownersTodelete = NULL;
       
   867 	TProcessListItem* so;
       
   868 	// There are 16 doubly linked lists managed by Surface Manager
       
   869 	for (TInt index = 0; index < KMaxLists; index++)
       
   870 		{
       
   871 		p = iSurfacesIndex[index];
       
   872 		while(p)
       
   873 			{
       
   874 			//see if the process which has just died is an owner of any surfaces
       
   875 			TSurface* surface = p;
       
   876 			p=p->iNext;
       
   877 			so = surface->ProcessOwnerInfo(aProcess);
       
   878 			if (so)
       
   879 				{
       
   880 				UnlinkListItem(&surface->iOwners, so);
       
   881 				so->iNext = ownersTodelete;	//add the owner to the list of owner objects to remove
       
   882 				ownersTodelete = so;
       
   883 
       
   884 				if (!surface->iOwners)	//if the surface hasn't any owners
       
   885 					{
       
   886 					//remove the surface from the list
       
   887 					UnlinkListItem(&iSurfacesIndex[index], surface);
       
   888 					surface->iNext = surfacesTodelete;	//add the surface to the list of surfaces to remove
       
   889 					surfacesTodelete = surface;
       
   890 					}
       
   891 				}
       
   892 			}
       
   893 		}
       
   894 	NKern::FMSignal(&iMutex);
       
   895 
       
   896 	while(surfacesTodelete)
       
   897 		{
       
   898 		p = surfacesTodelete->iNext;
       
   899 		Kern::ChunkClose(surfacesTodelete->iChunk);
       
   900 		TRACE(Kern::Printf("SM Close chunk %08x CloseSurfaceHandlesForProcess",surfacesTodelete->iChunk);)
       
   901 		delete surfacesTodelete;
       
   902 		TRACE(Kern::Printf("SM D %08x TSurface CloseSurfaceHandlesForProcess",surfacesTodelete);)
       
   903 		surfacesTodelete = p;
       
   904 		}
       
   905 
       
   906 	while(ownersTodelete)
       
   907 		{
       
   908 		so = ownersTodelete->iNext;
       
   909 		delete ownersTodelete;
       
   910 		TRACE(Kern::Printf("SM D %08x TProcessListItem CloseSurfaceHandlesForProcess",ownersTodelete);)
       
   911 		ownersTodelete = so;
       
   912 		}
       
   913 	}
       
   914 
       
   915 	
       
   916 /**
       
   917 Returns the metadata information about the specified surface.
       
   918 @param aId  The id of the surface.
       
   919 @param aInfo  Pointer to user side descriptor to receive the information.
       
   920 @return KErrNone if successful, KErrArgument if the surface ID does not refer to a surface,
       
   921 KErrAccessDenied if the surface is not open in the current process, otherwise a system wide
       
   922 error code.
       
   923 @internalTechnology
       
   924 */	
       
   925 TInt DSurfaceManager::SurfaceInfo(const TSurfaceId* aId, TDes8* aInfo)
       
   926 	{
       
   927 	TSurfaceId sid;
       
   928 	//fetch surface id from user memory
       
   929 	kumemget(&sid, aId, sizeof (TSurfaceId));
       
   930 
       
   931 	RSurfaceManager::TInfoBuf buf;
       
   932 	RSurfaceManager::TSurfaceInfoV01& info = buf();
       
   933 
       
   934 	NKern::FMWait(&iMutex);
       
   935 	//look it up
       
   936 	TSurface* surface = FindSurfaceById(sid);
       
   937 	if (!surface)	
       
   938 		{
       
   939 		NKern::FMSignal(&iMutex);
       
   940 		return KErrArgument;
       
   941 		}
       
   942 	
       
   943 	//find the owner
       
   944 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
   945 	if (!so)
       
   946 		{
       
   947 		NKern::FMSignal(&iMutex);
       
   948 		return KErrAccessDenied;	//can do this, not open
       
   949 		}
       
   950 	
       
   951 	//at this point, we have a surface, we are the owner and it's mapped in
       
   952 	info.iSize = surface->iSize; 									// Visible width/height in pixels
       
   953 	info.iBuffers = surface->iBuffers;								// Number of Buffers
       
   954 	info.iPixelFormat = surface->iPixelFormat;	      				// pixel format
       
   955 	info.iStride = surface->iStride;								// Number of bytes between start of one line and start of next
       
   956 	info.iContiguous = surface->iContiguous;						// is it physically contiguous
       
   957 	info.iCacheAttrib = surface->iCacheAttrib;						// Underlying chunk is CPU cached or not
       
   958 	info.iMappable = surface->iMappable;							// Is the surface Mappable
       
   959 	NKern::FMSignal(&iMutex);
       
   960 	
       
   961 	//copy it back to user side
       
   962 	Kern::InfoCopy(*aInfo, buf);
       
   963 	return KErrNone;
       
   964 	}
       
   965 
       
   966 
       
   967 
       
   968 /**
       
   969 Generates a unique surface id
       
   970 @param aId  Surface id reference to receive the generated id.
       
   971 @internalTechnology
       
   972 */	
       
   973 void DSurfaceManager::GenerateSurfaceId(TSurfaceId& aId)
       
   974 	{
       
   975 	TSurfaceId id;
       
   976 	
       
   977 	for (TInt x = 0; x < 4; ++x)
       
   978 		{
       
   979 		id.iInternal[x] = Kern::Random();
       
   980 		};
       
   981 	
       
   982 	//package up the handle,
       
   983 	//set the type identifier
       
   984 	id.iInternal[3] &= 0x00FFFFFF;
       
   985 	id.iInternal[3] |= TSurfaceTypes::ESurfaceManagerSurface << 24;
       
   986 	aId = id;
       
   987 	TRACE(Kern::Printf("SM GenerateSurfaceId id = %u %u %u %u\n",id.iInternal[0],id.iInternal[1],id.iInternal[2],id.iInternal[3]);)
       
   988 	};
       
   989 	
       
   990 
       
   991 
       
   992 /**
       
   993 Validates the surface creation attributes and calculates the size of the chunk required.
       
   994 @param aAttribs  The surface creation attributes used to specify the surface requirements.
       
   995 @param aOffset  Set to the offset between buffers on successfull return.
       
   996 @param aNewChunk  If this is true, surface is created in a new chunk otherwise the surface is created in an existing chunk
       
   997 @return The size of chunk required.  A size of 0 indicates a problem.
       
   998 */	
       
   999 TInt DSurfaceManager::ValidateAndCalculateChunkSize(RSurfaceManager::TSurfaceCreationAttributes& aAttribs, 
       
  1000 			TInt& aOffset, TUint &aActualBufferSize, const TBool aNewChunk)
       
  1001 	{
       
  1002 /*	
       
  1003 	TRACE(Kern::Printf("SM width = %d  height = %d\n", aAttribs.iSize.iWidth, aAttribs.iSize.iHeight);)
       
  1004 	TRACE(Kern::Printf("SM buffers = %d\n", aAttribs.iBuffers);)
       
  1005 	TRACE(Kern::Printf("SM format = %d\n", aAttribs.iPixelFormat);)
       
  1006 	TRACE(Kern::Printf("SM stride = %d\n", aAttribs.iStride);)
       
  1007 	TRACE(Kern::Printf("SM offset to first buffer = %d\n", aAttribs.iOffsetToFirstBuffer);)
       
  1008 	TRACE(Kern::Printf("SM offset between buffer = %d\n", aOffset);)
       
  1009 	TRACE(Kern::Printf("SM alignment = %d\n", aAttribs.iAlignment);)
       
  1010 	TRACE(Kern::Printf("SM contiguous = %d\n\n", aAttribs.iContiguous);)
       
  1011 	TRACE(Kern::Printf("SM cacheAttrib = %d\n\n", aAttribs.iCacheAttrib);)
       
  1012 */
       
  1013 	//check for negative values
       
  1014 	if(aAttribs.iOffsetToFirstBuffer < 0 || aOffset < 0 )
       
  1015 		{
       
  1016 		TRACE(Kern::Printf("SM Validate offset for negative value");)
       
  1017 		return 0;
       
  1018 		}
       
  1019 
       
  1020 	//check aligment is sensible
       
  1021 	TInt alignmentMask = 0;
       
  1022 	switch(aAttribs.iAlignment)
       
  1023 		{
       
  1024 		case 1:	
       
  1025 		case 2:	
       
  1026 		case 4: 
       
  1027 		case 8: 
       
  1028 		case 16: 
       
  1029 		case 32: 
       
  1030 			alignmentMask = 31; 
       
  1031 			break;
       
  1032 		case 64: 
       
  1033 			alignmentMask = 63; 
       
  1034 			break;
       
  1035 		case RSurfaceManager::EPageAligned:
       
  1036 			break;
       
  1037 		default:
       
  1038 			TRACE(Kern::Printf("SM Validate alignment");)
       
  1039 			return 0;
       
  1040 		}
       
  1041 	
       
  1042 	//check alignment issues.
       
  1043 	if(aAttribs.iAlignment != RSurfaceManager::EPageAligned)
       
  1044 		{
       
  1045 		if(aNewChunk)	
       
  1046 			{
       
  1047 			if(aAttribs.iCacheAttrib == RSurfaceManager::ECached)	// Surface is CPU cached, so the alignment will be based on either 32 or 64 byte 
       
  1048 				{
       
  1049 				//offset to first buffer needs to fit alignment
       
  1050 				aAttribs.iOffsetToFirstBuffer = aAttribs.iOffsetToFirstBuffer + alignmentMask & ~alignmentMask;
       
  1051 				//alignment with respect to offsetbetweenbuffers
       
  1052 				aOffset = aOffset + alignmentMask & ~alignmentMask;
       
  1053 				}
       
  1054 			else	// Surface is NOT CPU cached, so the alignment will be based on surface attribute alignment
       
  1055 				{
       
  1056 				TUint alignMask = aAttribs.iAlignment-1;
       
  1057 				//offset to first buffer needs to fit alignment
       
  1058 				aAttribs.iOffsetToFirstBuffer = aAttribs.iOffsetToFirstBuffer + alignMask & ~alignMask;
       
  1059 				//alignment with respect to offsetbetweenbuffers
       
  1060 				aOffset = aOffset + alignMask & ~alignMask;
       
  1061 				}
       
  1062 			}
       
  1063 		else	// existing chunk
       
  1064 			{
       
  1065 			TUint alignMask = aAttribs.iAlignment-1;
       
  1066 			//check alignment issues.  offset to first buffer needs to fit alignment
       
  1067 			if (aAttribs.iOffsetToFirstBuffer & alignMask)
       
  1068 				{
       
  1069 				TRACE(Kern::Printf("SM Validate offset to first pixel misaligned");)
       
  1070 				return 0;
       
  1071 				}
       
  1072 
       
  1073 			//check alignment for offsetbetweenbuffers.  offset between buffer needs to fit alignment for existing chunks
       
  1074 			if (aOffset & alignMask)
       
  1075 				{
       
  1076 				TRACE(Kern::Printf("SM Validate offset between buffers misaligned");)
       
  1077 				return 0;
       
  1078 				}
       
  1079 			}
       
  1080 		}
       
  1081 	else	//page aligned
       
  1082 		{
       
  1083 		if(aNewChunk)// if its a new chunks and doesn't match exact alignment then do the rounding
       
  1084 			{
       
  1085 			TUint32 pageSize = Kern::RoundToPageSize(1);
       
  1086 			//offset to first buffer needs to fit alignment
       
  1087 			aAttribs.iOffsetToFirstBuffer = (aAttribs.iOffsetToFirstBuffer + (pageSize - 1)) & ~(pageSize - 1);
       
  1088 			//alignment with respect to offsetbetweenbuffers
       
  1089 			aOffset = (aOffset + (pageSize - 1)) & ~((pageSize - 1));
       
  1090 			}
       
  1091 		else	// for existing chunks don't do any rounding operation
       
  1092 			{
       
  1093 			TUint32 pageSize = Kern::RoundToPageSize(1);
       
  1094 			TUint alignmask = aAttribs.iOffsetToFirstBuffer & (pageSize - 1);
       
  1095 			if (alignmask)
       
  1096 				{
       
  1097 				TRACE(Kern::Printf("SM Validate offset to first pixel misaligned");)
       
  1098 				return 0;
       
  1099 				}
       
  1100 			
       
  1101 			alignmask = aOffset & (pageSize - 1);
       
  1102 			if (alignmask)
       
  1103 				{
       
  1104 				TRACE(Kern::Printf("SM Validate offset between buffers misaligned");)
       
  1105 				return 0;
       
  1106 				}
       
  1107 			}
       
  1108 		}
       
  1109 
       
  1110 	//check width and height
       
  1111 	if(aAttribs.iSize.iWidth <= 0 || aAttribs.iSize.iHeight <= 0)
       
  1112 		{
       
  1113 		TRACE(Kern::Printf("SM Validate width/height");)
       
  1114 		return 0;
       
  1115 		}
       
  1116 	
       
  1117 	
       
  1118 	//check there is at least 1 buffer
       
  1119 	if (aAttribs.iBuffers <= 0)
       
  1120 		{
       
  1121 		TRACE(Kern::Printf("SM Validate buffers");)
       
  1122 		return 0;
       
  1123 		}
       
  1124 
       
  1125 	//Sort the array and also check for duplication
       
  1126 	if (!SortHints(aAttribs.iSurfaceHints,aAttribs.iHintCount)) 
       
  1127 		{
       
  1128 		TRACE(Kern::Printf("SM Validate Duplicate hint key");)
       
  1129 		return 0;
       
  1130 		}
       
  1131 
       
  1132 	TUint size = 0;
       
  1133 	//calculate buffer size and round it to alignment or to page size
       
  1134 	TInt64 bufferSize = aAttribs.iStride;
       
  1135 	bufferSize  *= aAttribs.iSize.iHeight;
       
  1136 
       
  1137 	if (I64HIGH(bufferSize) > 0) //too big
       
  1138 		{
       
  1139 		TRACE(Kern::Printf("SM Validate chunk buffer size is out of range");)
       
  1140 		return 0;
       
  1141 		}
       
  1142 	
       
  1143 	TUint bsize = I64LOW(bufferSize);
       
  1144 	if (bsize > KMaxTInt)
       
  1145 		{
       
  1146 		TRACE(Kern::Printf("SM Validate buffer size is out of range for TInt");)
       
  1147 		return 0;
       
  1148 		}
       
  1149 
       
  1150 	if(aAttribs.iAlignment == RSurfaceManager::EPageAligned)
       
  1151 		{
       
  1152 		bsize = Kern::RoundToPageSize(bsize);	//page alignment
       
  1153 		}
       
  1154 	else if(aAttribs.iCacheAttrib == RSurfaceManager::ECached)
       
  1155 		{
       
  1156 		bsize = bsize + alignmentMask & ~alignmentMask;	//CPU cached byte alignment, for minimum of the specified alignment(32 or 64)
       
  1157 		}
       
  1158 	else
       
  1159 		{
       
  1160 		bsize = bsize + (aAttribs.iAlignment-1) & ~(aAttribs.iAlignment-1);	//NON CPU cached byte alignment for 1, 2, 4, 8, 16, 32 and 64
       
  1161 		}
       
  1162 	
       
  1163 	bufferSize = bsize;
       
  1164 	// Remember the actual size. 
       
  1165 	aActualBufferSize = bsize;
       
  1166 
       
  1167 	//if offset between buffers is zero, then assign the calculated value as offset between buffers
       
  1168 	if(aOffset == 0)
       
  1169 		{
       
  1170 		//buffer size rounded to alignment as offset between buffers
       
  1171 		aOffset = I64INT(bufferSize);
       
  1172 		}
       
  1173 	else if(aOffset < I64INT(bufferSize))
       
  1174 		{
       
  1175 		TRACE(Kern::Printf("SM Offset between the buffer is less than the required size");)
       
  1176 		return 0;
       
  1177 		}
       
  1178 	else
       
  1179 		{
       
  1180 		//use the buffer size specified
       
  1181 		bufferSize = aOffset;
       
  1182 		}
       
  1183 	
       
  1184 	
       
  1185 	TInt64 totalSize = aAttribs.iOffsetToFirstBuffer + (aAttribs.iBuffers * bufferSize);
       
  1186 	
       
  1187 	if (I64HIGH(totalSize) > 0) //too big
       
  1188 		{
       
  1189 		TRACE(Kern::Printf("SM Validate chunk size is out of range for RoundToPageSize");)
       
  1190 		return 0;
       
  1191 		}
       
  1192 		
       
  1193 	size = I64LOW(totalSize);
       
  1194 	if (size > KMaxTInt)
       
  1195 		{
       
  1196 		TRACE(Kern::Printf("SM Validate size is out of range for TInt");)
       
  1197 		return 0;
       
  1198 		}
       
  1199 
       
  1200 	size = Kern::RoundToPageSize(size);
       
  1201 
       
  1202 	//check the size isn't greater than will fit in a TInt
       
  1203 	if (size > KMaxTInt)
       
  1204 		{
       
  1205 		TRACE(Kern::Printf("SM Rounded size is out of range for TInt");)
       
  1206 		return 0;
       
  1207 		}
       
  1208 	
       
  1209 	TRACE(Kern::Printf("SM After validate - offset to first buffer = %d\n", aAttribs.iOffsetToFirstBuffer);)
       
  1210 	TRACE(Kern::Printf("SM After validate - offset between buffer = %d\n", aOffset);)
       
  1211 	TRACE(Kern::Printf("SM CalculateChunkSize size = %d\n", size);)
       
  1212 	return size;
       
  1213 	}
       
  1214 
       
  1215 
       
  1216 /**
       
  1217 Find the surface in the list.   
       
  1218 @param aId  The surface id of the surface to find in the surface list
       
  1219 @return pointer to the surface object
       
  1220 @internalTechnology
       
  1221 */
       
  1222 TSurface* DSurfaceManager::FindSurfaceById(const TSurfaceId& aId)
       
  1223 	{
       
  1224 	TSurface *p = iSurfacesIndex[SurfaceIdToIndex(aId)];
       
  1225 	while (p)
       
  1226 		{
       
  1227 		if (aId == p->iId)
       
  1228 			{
       
  1229 			//found it
       
  1230 			return p;
       
  1231 			}
       
  1232 	
       
  1233 		p = p->iNext;
       
  1234 		}
       
  1235 	return NULL;
       
  1236 	}
       
  1237 
       
  1238 
       
  1239 /**
       
  1240 Find the index of the hint key from the surface list using binary search.   
       
  1241 @param aHintsArray  Pointer to the first element in the array of surface hints
       
  1242 @param aKey  The surface hint key uid value to search in the surface list
       
  1243 @return index of the hint pair key in the surface list, KErrNotFound if key not found
       
  1244 @internalTechnology
       
  1245 */
       
  1246 TInt DSurfaceManager::FindHintKey(const RSurfaceManager::THintPair* aHintsArray, TUint32 aKey) const
       
  1247 	{
       
  1248 	__ASSERT_DEBUG(aHintsArray != NULL, Kern::Fault("Surface Manager", __LINE__));
       
  1249 
       
  1250 	TInt bottom = 0;
       
  1251 	TInt top = KMaxHintsPerSurface - 1;
       
  1252 	TInt mid;
       
  1253 	while (bottom <= top)
       
  1254 		{
       
  1255 	    mid = (bottom + top) / 2;
       
  1256 	    if((TUint) aHintsArray[mid].iKey.iUid == aKey)
       
  1257 	    	{
       
  1258 	    	return mid;
       
  1259 	    	} 
       
  1260 	    else if ((TUint)aHintsArray[mid].iKey.iUid < aKey) 
       
  1261 	    	{
       
  1262 	    	top = mid - 1;
       
  1263 	    	}
       
  1264 	    else
       
  1265 	    	{
       
  1266 	    	bottom = mid + 1;
       
  1267 	    	}
       
  1268 	  }
       
  1269 	return KErrNotFound;	//Hint key not found
       
  1270     }
       
  1271 
       
  1272 TProcessListItem* DSurfaceManager::FindConnectedProcess(const DProcess* aProcess)
       
  1273 	{
       
  1274 	TProcessListItem * p = iConnectedProcesses;
       
  1275 	while (p)
       
  1276 		{
       
  1277 		if (aProcess == p->iOwningProcess)
       
  1278 			{
       
  1279 			//found it
       
  1280 			return p;
       
  1281 			}
       
  1282 		
       
  1283 		p = p->iNext;
       
  1284 		}
       
  1285 	return NULL;
       
  1286 	}
       
  1287 
       
  1288 /**
       
  1289 Searches for a right place to insert the new hint pair in a sorted array.
       
  1290 @param aHintsArray  Pointer to the first element in the sorted array
       
  1291 @param aKey  The surface hint key uid value to search in the surface list
       
  1292 @pre, there is at least one empty place in the array
       
  1293 @return KErrNone if a new hint pair key inserted in the surface list, KErrAlreadyExists if duplicated
       
  1294 @internalTechnology
       
  1295 */
       
  1296 TInt DSurfaceManager::InsertHintKey(RSurfaceManager::THintPair* aHintsArray, const RSurfaceManager::THintPair& aHintPair) const
       
  1297 	{
       
  1298 	__ASSERT_DEBUG(aHintsArray != NULL, Kern::Fault("Surface Manager", __LINE__));
       
  1299 	__ASSERT_DEBUG(aHintsArray[KMaxHintsPerSurface-1].iKey.iUid == NULL, Kern::Fault("Surface Manager", __LINE__));
       
  1300 
       
  1301 	TInt pos = 0;
       
  1302 	if (aHintsArray[pos].iKey.iUid != 0)
       
  1303 		{
       
  1304 		while((TUint)aHintsArray[pos].iKey.iUid>(TUint)aHintPair.iKey.iUid && pos < KMaxHintsPerSurface-1)
       
  1305 			{// find the right place to insert
       
  1306 			++pos;
       
  1307 			}
       
  1308 	
       
  1309 		if((TUint)aHintsArray[pos].iKey.iUid==(TUint)aHintPair.iKey.iUid)
       
  1310 			{
       
  1311 			//Duplicate key 
       
  1312 			return KErrAlreadyExists;
       
  1313 			}
       
  1314 		else
       
  1315 			{
       
  1316 			// Shift right
       
  1317 			memmove(aHintsArray+pos+1, aHintsArray+pos, (KMaxHintsPerSurface-pos-1)*sizeof(RSurfaceManager::THintPair));		
       
  1318 			}	
       
  1319 		}
       
  1320 	aHintsArray[pos] = aHintPair;
       
  1321 	return KErrNone;
       
  1322 	}
       
  1323 
       
  1324 /**
       
  1325 Sort the surface hint array in descending order.
       
  1326 @param aHintsArray  The surface hintpair in the surface list
       
  1327 @param aNumberOfHints The number of hints
       
  1328 @return ETrue if sorting is finished or it is an empty array, EFalse if key duplicated
       
  1329 @internalTechnology
       
  1330 */
       
  1331 TBool DSurfaceManager::SortHints(RSurfaceManager::THintPair* aHintsArray, TInt aNumberOfHints) const
       
  1332 	{
       
  1333 	TInt in = 0;
       
  1334 	TInt out = 0;
       
  1335 	RSurfaceManager::THintPair temp;
       
  1336 	if(!aHintsArray)
       
  1337 		{
       
  1338 		return ETrue;
       
  1339 		}
       
  1340 	for(out = 0; out < aNumberOfHints; ++out) 
       
  1341 		{
       
  1342 		if(aHintsArray[out].iKey.iUid != 0)
       
  1343 			{
       
  1344 			temp = aHintsArray[out];   
       
  1345 			in = out;          // start shifting at out
       
  1346 			while(in > 0 && (TUint)aHintsArray[in-1].iKey.iUid <= (TUint)temp.iKey.iUid)
       
  1347 				{
       
  1348 				if ((TUint)aHintsArray[in-1].iKey.iUid == (TUint)temp.iKey.iUid)
       
  1349 					{
       
  1350 					return EFalse;		//duplicate hint keys are not allowed
       
  1351 					}
       
  1352 				aHintsArray[in] = aHintsArray[in-1];     // shift item to the right
       
  1353 				--in;          // go left one position
       
  1354 				}
       
  1355 			aHintsArray[in] = temp;        // insert marked item
       
  1356 			}
       
  1357 		}
       
  1358 	return ETrue;
       
  1359 	}
       
  1360 
       
  1361 
       
  1362 /**
       
  1363 Ensures the memory is updated consistently before/after triggering non CPU hardware access. 
       
  1364 @param aParam  The suface id and buffer number (0 based).
       
  1365 @param aOperation  The type of the synchronize operation. 
       
  1366 @return KErrNone if successful, KErrArgument if the surface ID is invalid or
       
  1367 buffer number is invalid, KErrAccessDenied if the surface is not open in this
       
  1368 process, otherwise a system wide error code.
       
  1369 @see RSurfaceManager::TSyncOperation
       
  1370 @internalTechnology
       
  1371 */	
       
  1372 TInt DSurfaceManager::SynchronizeCache(RSurfaceManagerDriver::TDeviceParam* aParam, RSurfaceManager::TSyncOperation aOperation)
       
  1373 	{
       
  1374 	//Parse the parameters
       
  1375 	RSurfaceManagerDriver::TDeviceParam param;
       
  1376 	kumemget(&param, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
       
  1377 	TSurfaceId sid;
       
  1378 	kumemget(&sid, param.iSurfaceId, sizeof(TSurfaceId));
       
  1379 	TInt buffer = (TInt)param.iBuffer;
       
  1380 	
       
  1381 	NKern::ThreadEnterCS();
       
  1382 	NKern::FMWait(&iMutex);
       
  1383 	//look it up
       
  1384 	TSurface* surface = FindSurfaceById(sid);
       
  1385 	if (!surface)	
       
  1386 		{
       
  1387 		NKern::FMSignal(&iMutex);
       
  1388 		NKern::ThreadLeaveCS();
       
  1389 		return KErrArgument;
       
  1390 		}
       
  1391 	
       
  1392 	//find the owner
       
  1393 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
  1394 	if (!so)
       
  1395 		{
       
  1396 		NKern::FMSignal(&iMutex);
       
  1397 		NKern::ThreadLeaveCS();
       
  1398 		return KErrAccessDenied;
       
  1399 		}
       
  1400 
       
  1401 	// surfaces have to have at least one buffer
       
  1402 	__ASSERT_DEBUG(surface->iBuffers > 0, Kern::Fault("Surface Manager", __LINE__));
       
  1403 	
       
  1404 	//Validate the buffer number is within range
       
  1405 	if((buffer >= surface->iBuffers) || (buffer < 0))
       
  1406 		{
       
  1407 		NKern::FMSignal(&iMutex);
       
  1408 		NKern::ThreadLeaveCS();
       
  1409 		return KErrArgument;
       
  1410 		}
       
  1411 
       
  1412 	DChunk* chunk = surface->iChunk;
       
  1413 	TInt offsetBetweenBuffers = surface->iOffsetBetweenBuffers;
       
  1414 	NKern::FMSignal(&iMutex);
       
  1415 
       
  1416 	TUint32 kernAddr;
       
  1417 	TUint32 mapAttr;
       
  1418 	TUint32 physAddr;
       
  1419 	TInt pageList = chunk->iSize / Kern::RoundToPageSize(1) + 1;
       
  1420 	TUint32* physAddr2 = new TUint32[pageList];
       
  1421 	if(!physAddr2)
       
  1422 		{
       
  1423 		NKern::ThreadLeaveCS();
       
  1424 		return KErrNoMemory;
       
  1425 		}
       
  1426 	
       
  1427 	TRACE(Kern::Printf("SM %08x DChunk SynchronizeCache", chunk);)
       
  1428 	
       
  1429 	//Retrieve the kernel address and mapping attribute from the chunk
       
  1430 	TInt err = Kern::ChunkPhysicalAddress(chunk, surface->iOffsetToFirstBuffer + (buffer * offsetBetweenBuffers), offsetBetweenBuffers, kernAddr, mapAttr, physAddr, physAddr2);
       
  1431 	delete[] physAddr2;
       
  1432 	if(err >= KErrNone)
       
  1433 		{
       
  1434 		TRACE(Kern::Printf("SM %08x kernAddr SynchronizeCache", kernAddr);)
       
  1435 		TRACE(Kern::Printf("SM %08x mapAttr SynchronizeCache", mapAttr);)
       
  1436 		err = KErrNone;
       
  1437 
       
  1438 		// Do the sync operation
       
  1439 		switch(aOperation)
       
  1440 			{
       
  1441 			case RSurfaceManager::ESyncBeforeNonCPURead:
       
  1442 				Cache::SyncMemoryBeforeDmaWrite(kernAddr, offsetBetweenBuffers, mapAttr);
       
  1443 				break;
       
  1444 			case RSurfaceManager::ESyncBeforeNonCPUWrite:
       
  1445 				Cache::SyncMemoryBeforeDmaRead(kernAddr, offsetBetweenBuffers, mapAttr);
       
  1446 				break;
       
  1447 			case RSurfaceManager::ESyncAfterNonCPUWrite:
       
  1448 				Cache::SyncMemoryAfterDmaRead(kernAddr, offsetBetweenBuffers);
       
  1449 				break;
       
  1450 			default: 
       
  1451 				err = KErrArgument;
       
  1452 				break;
       
  1453 			}			
       
  1454 		}
       
  1455 	NKern::ThreadLeaveCS();
       
  1456 
       
  1457 	return err;
       
  1458 	}
       
  1459 
       
  1460 
       
  1461 /**
       
  1462 Get the surface hint value for the given surface ID and hint pair key.
       
  1463 @param aSurfaceId  The surface identifier originally returned when the surface was created.
       
  1464 @param aHintPair  The hint value for the requested hint pair key.
       
  1465 @return KErrNone if successful, KErrArgument if the surface ID is invalid or
       
  1466 invalid hint pair key used, KErrAccessDenied if the surface is not open in the
       
  1467 current process, otherwise a system wide error code.
       
  1468 @internalTechnology
       
  1469 */ 
       
  1470 TInt DSurfaceManager::GetSurfaceHint(const TSurfaceId* aSurfaceId, RSurfaceManager::THintPair* aHintPair)
       
  1471 	{
       
  1472 	RSurfaceManager::THintPair hintPair;
       
  1473 	kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
       
  1474 
       
  1475 	if (hintPair.iKey.iUid == 0)
       
  1476 		{
       
  1477 		TRACE(Kern::Printf("SM GetSurfaceHint Hint key is invalid");)
       
  1478 		return KErrArgument;	//Invalid Hint key
       
  1479 		}
       
  1480 	
       
  1481 	TSurfaceId sid;
       
  1482 	//fetch surface id from user memory
       
  1483 	kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
       
  1484 
       
  1485 	NKern::FMWait(&iMutex);
       
  1486 	//look it up
       
  1487 	TSurface* surface = FindSurfaceById(sid);
       
  1488 	if (!surface)	
       
  1489 		{
       
  1490 		NKern::FMSignal(&iMutex);
       
  1491 		return KErrArgument;
       
  1492 		}
       
  1493 	
       
  1494 	//find the owner
       
  1495 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
  1496 	if (!so)
       
  1497 		{
       
  1498 		NKern::FMSignal(&iMutex);
       
  1499 		return KErrAccessDenied;
       
  1500 		}
       
  1501 	
       
  1502 	//at this point, we have a surface, we have to find the hint value based on the hint pair key
       
  1503 	TInt index = FindHintKey(surface->iSurfaceHints, hintPair.iKey.iUid);
       
  1504 
       
  1505 	if (index == KErrNotFound)
       
  1506 		{
       
  1507 		TRACE(Kern::Printf("SM GetSurfaceHint Hint key not found");)
       
  1508 		NKern::FMSignal(&iMutex);
       
  1509 		return KErrArgument;	//Hint key not found
       
  1510 		}
       
  1511 
       
  1512 	RSurfaceManager::THintPair hint = surface->iSurfaceHints[index];
       
  1513 	NKern::FMSignal(&iMutex);
       
  1514 		
       
  1515 	TRACE(Kern::Printf("SM GetSurfaceHint Hint value %d", hint.iValue);)
       
  1516 	//write it back to user side
       
  1517 	kumemput(aHintPair, &hint, sizeof(RSurfaceManager::THintPair));
       
  1518 	return KErrNone;
       
  1519 	}
       
  1520 
       
  1521 
       
  1522 /**
       
  1523 Set the surface hint value for an existing surface hint key of the surface Id.
       
  1524 @param aSurfaceId  The surface identifier originally returned when the surface was created.
       
  1525 @param aHintPair  The value of the hint pair to set.
       
  1526 @return KErrNone if successful, KErrArgument if the surface ID is invalid or if invalid
       
  1527 hint key used, KErrAccessDenied if the hint pair is immutable or the surface is not open
       
  1528 in the current process, otherwise a system wide error code.
       
  1529 @internalTechnology
       
  1530 */ 
       
  1531 TInt DSurfaceManager::SetSurfaceHint(const TSurfaceId* aSurfaceId, const RSurfaceManager::THintPair* aHintPair)
       
  1532 	{
       
  1533 	RSurfaceManager::THintPair hintPair;
       
  1534 	kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
       
  1535 
       
  1536 	//Check for valid hint key
       
  1537 	if (!hintPair.iKey.iUid)
       
  1538 		{
       
  1539 		TRACE(Kern::Printf("SM SetSurfaceHint Hint key is invalid");)
       
  1540 		return KErrArgument;	//Invalid Hint key
       
  1541 		}
       
  1542 	
       
  1543 	TSurfaceId sid;
       
  1544 	//fetch surface id from user memory
       
  1545 	kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
       
  1546 
       
  1547 	NKern::ThreadEnterCS();
       
  1548 	NKern::FMWait(&iMutex);
       
  1549 	//look it up
       
  1550 	TSurface* surface = FindSurfaceById(sid);
       
  1551 	if (!surface)	
       
  1552 		{
       
  1553 		NKern::FMSignal(&iMutex);
       
  1554 		NKern::ThreadLeaveCS();
       
  1555 		return KErrArgument;
       
  1556 		}
       
  1557 	
       
  1558 	//find the owner
       
  1559 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
  1560 	if (!so)
       
  1561 		{
       
  1562 		NKern::FMSignal(&iMutex);
       
  1563 		NKern::ThreadLeaveCS();
       
  1564 		return KErrAccessDenied;
       
  1565 		}
       
  1566 	
       
  1567 	//at this point, we have a surface, we have to find the hint value based on the hint pair key
       
  1568 	TInt index = FindHintKey(surface->iSurfaceHints, hintPair.iKey.iUid);
       
  1569 	if (index == KErrNotFound)
       
  1570 		{
       
  1571 		TRACE(Kern::Printf("SM SetSurfaceHint Hint key not found or invalid");)
       
  1572 		NKern::FMSignal(&iMutex);
       
  1573 		NKern::ThreadLeaveCS();
       
  1574 		return KErrArgument;	//Hint key not found or invalid
       
  1575 		}
       
  1576 	
       
  1577 	//Check for mutability
       
  1578 	if(!surface->iSurfaceHints[index].iMutable)
       
  1579 		{
       
  1580 		TRACE(Kern::Printf("SM SetSurfaceHint Hint is immutable");)
       
  1581 		NKern::FMSignal(&iMutex);
       
  1582 		NKern::ThreadLeaveCS();
       
  1583 		return KErrAccessDenied;	//Hint pair is immutable
       
  1584 		}
       
  1585 	TRACE(Kern::Printf("SM SetSurfaceHint Hint key found and updated its value %d for the surface %08x \n", aHintPair->iValue, &sid);)
       
  1586 	
       
  1587 	//set the hint pair value now
       
  1588 	memcpy(&surface->iSurfaceHints[index], &hintPair, sizeof(RSurfaceManager::THintPair));
       
  1589 	NKern::FMSignal(&iMutex);
       
  1590 	NKern::ThreadLeaveCS();
       
  1591 
       
  1592 	return KErrNone;
       
  1593 	}
       
  1594 
       
  1595 /**
       
  1596 Add a new surface hint value for the surface Id.
       
  1597 @param aSurfaceId  The surface identifier originally returned when the surface was created.
       
  1598 @param aHintPair  The value of the hint pair to Add.
       
  1599 @return Returns KErrNone if successful, KErrArgument if the surface ID is invalid or the
       
  1600 hint pair has invalid key UID, KErrAccessDenied if the surface is not open in the current
       
  1601 process, KErrAlreadyExists if duplicate hint key used, KErrOverflow if no space to add new
       
  1602 pair, otherwise a system wide error code.
       
  1603 @internalTechnology
       
  1604 */ 
       
  1605 TInt DSurfaceManager::AddSurfaceHint(const TSurfaceId* aSurfaceId, const RSurfaceManager::THintPair* aHintPair)
       
  1606 	{
       
  1607 	RSurfaceManager::THintPair hintPair;
       
  1608 	kumemget(&hintPair, aHintPair, sizeof(RSurfaceManager::THintPair));
       
  1609 
       
  1610 	//Check for valid hint key
       
  1611 	if (hintPair.iKey.iUid == 0)
       
  1612 		{
       
  1613 		TRACE(Kern::Printf("SM AddSurfaceHint Hint key is invalid");)
       
  1614 		return KErrArgument;	//Invalid Hint key
       
  1615 		}
       
  1616 	
       
  1617 	TSurfaceId sid;
       
  1618 	//fetch surface id from user memory
       
  1619 	kumemget(&sid, aSurfaceId, sizeof (TSurfaceId));
       
  1620 
       
  1621 	NKern::ThreadEnterCS();
       
  1622 	NKern::FMWait(&iMutex);
       
  1623 	//look it up
       
  1624 	TSurface* surface = FindSurfaceById(sid);
       
  1625 	if (!surface)	
       
  1626 		{
       
  1627 		NKern::FMSignal(&iMutex);
       
  1628 		NKern::ThreadLeaveCS();
       
  1629 		return KErrArgument;
       
  1630 		}
       
  1631 	
       
  1632 	//find the owner
       
  1633 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
  1634 	if (!so)
       
  1635 		{
       
  1636 		NKern::FMSignal(&iMutex);
       
  1637 		NKern::ThreadLeaveCS();
       
  1638 		return KErrAccessDenied;
       
  1639 		}
       
  1640 	
       
  1641 
       
  1642 	//Check for empty hint pair
       
  1643 	if(surface->iSurfaceHints[KMaxHintsPerSurface - 1].iKey.iUid != 0)//at least end of sorted hint array should be 0 to add a new hint
       
  1644 		{
       
  1645 		TRACE(Kern::Printf("SM AddSurfaceHint there is no room to add the hint");)
       
  1646 		NKern::FMSignal(&iMutex);
       
  1647 		NKern::ThreadLeaveCS();
       
  1648 		return KErrOverflow;	//No room for new hint
       
  1649 		}
       
  1650 	//We found room for a new hint pair, so insert it in the array
       
  1651 	// Meanwhile, we check for duplication, if it is, return KErrAlreadyExists
       
  1652 	TInt err = InsertHintKey(surface->iSurfaceHints,hintPair);
       
  1653 	NKern::FMSignal(&iMutex);
       
  1654 	TRACE(Kern::Printf("SM AddSurfaceHint Added new key ");)
       
  1655 	NKern::ThreadLeaveCS();
       
  1656 	return err;
       
  1657 	}
       
  1658 
       
  1659 /**
       
  1660 Get the offset of the specified buffer from the base address of the underlying
       
  1661 chunk.
       
  1662 
       
  1663 To obtain the address of the buffer, the offset returned must be added onto the
       
  1664 base address of the RChunk returned in a call to MapSurface(). Note that
       
  1665 buffer offsets are immutable during the lifetime of the surface.
       
  1666 @param aParam The input parameters including the surface ID and buffer index.
       
  1667 @pre The surface is open in the calling process.
       
  1668 @return KErrNone if successful, KErrArgument if aSurfaceId or aBuffer are invalid,
       
  1669 KErrAccessDenied if the surface is not open in the current process, KErrNotSupported if
       
  1670 the surface is not mappable, otherwise a system wide error code.
       
  1671 */
       
  1672 TInt DSurfaceManager::GetBufferOffset(RSurfaceManagerDriver::TDeviceParam* aParam,TUint* aOffset)
       
  1673 	{
       
  1674 	//Get the input parameters
       
  1675 	RSurfaceManagerDriver::TDeviceParam param;
       
  1676 	kumemget(&param, aParam, sizeof(RSurfaceManagerDriver::TDeviceParam));
       
  1677 	TSurfaceId sid;
       
  1678 	//fetch surface id from user memory
       
  1679 	kumemget(&sid, param.iSurfaceId, sizeof(TSurfaceId));
       
  1680 	//(TAny*)iBuffer holds the buffer number in its value
       
  1681 	TInt bufferNumber = (TInt) param.iBuffer;
       
  1682 	
       
  1683 	TSurface* surface = NULL;
       
  1684 	NKern::FMWait(&iMutex);
       
  1685 	surface = FindSurfaceById(sid);
       
  1686 	if(NULL == surface || (bufferNumber >= surface->iBuffers))
       
  1687 		{
       
  1688 		NKern::FMSignal(&iMutex);
       
  1689 		return KErrArgument;
       
  1690 		}
       
  1691 	if(!surface->iMappable)
       
  1692 		{
       
  1693 		NKern::FMSignal(&iMutex);
       
  1694 		return KErrNotSupported;
       
  1695 		}
       
  1696 	//find the owner
       
  1697 	TProcessListItem* so = surface->ProcessOwnerInfo(&Kern::CurrentProcess());
       
  1698 	if (!so)
       
  1699 		{
       
  1700 		NKern::FMSignal(&iMutex);
       
  1701 		return KErrAccessDenied;		
       
  1702 		}
       
  1703 	TInt bufferOffset = surface->iOffsetToFirstBuffer + bufferNumber*surface->iOffsetBetweenBuffers;
       
  1704 	NKern::FMSignal(&iMutex);
       
  1705 	
       
  1706 	kumemput(aOffset, &bufferOffset, sizeof (TInt));
       
  1707 	return KErrNone;
       
  1708 	}
       
  1709 
       
  1710 /**
       
  1711 Returns information specific to the Surface Manager implementation.
       
  1712 @param aAttrib: Attribute to retrieve
       
  1713 @param aValue : Output parameter where we write the value for the specified attribute
       
  1714 @return KErrNone if successful or KErrArgument if the attribute UID is not recognized
       
  1715 @internalTechnology
       
  1716 */
       
  1717 TInt DSurfaceManager::GetSurfaceManagerAttrib(RSurfaceManager::TSurfaceManagerAttrib* aAttrib,TInt* aValue)
       
  1718 	{
       
  1719 	RSurfaceManager::TSurfaceManagerAttrib attrib;
       
  1720 	kumemget(&attrib, aAttrib, sizeof(RSurfaceManager::TSurfaceManagerAttrib));
       
  1721 	
       
  1722 	TInt out=KErrNone;
       
  1723 	TInt value;
       
  1724 	switch (attrib)
       
  1725 		{
       
  1726 		case RSurfaceManager::EMaxNumberOfHints:
       
  1727 			value=KMaxHintsPerSurface;
       
  1728 			break;		
       
  1729 		
       
  1730 		default:
       
  1731 			out=KErrArgument;
       
  1732 			break;			
       
  1733 		};
       
  1734 	
       
  1735 	if (out==KErrNone)
       
  1736 		{
       
  1737 		kumemput(aValue, &value, sizeof (TInt));
       
  1738 		}	
       
  1739 	return out;
       
  1740 	}
       
  1741 
       
  1742 #ifdef GRAPHICS_SURFACEMANAGER_SYBORG
       
  1743 TInt DSurfaceManager::CreateMemory()
       
  1744 	{
       
  1745 	Kern::Printf("DSurfaceManager::CreateMemory()>");
       
  1746 	TUint32 physicalAddress = DVirtualVideoHwInterface::GetFrameBase();
       
  1747 	Kern::Printf("DSurfaceManager::CreateMemory: 0x%08x",physicalAddress);
       
  1748 	if( physicalAddress != 0 )
       
  1749 		{
       
  1750 		iVHWMemoryManager = new DVirtualHWMemoryManager( physicalAddress, VVI_FRAMEBUFFER_MEMORY_SIZE );
       
  1751 		Kern::Printf("DSurfaceManager::CreateMemory: iVHWMemoryManager: 0x%08x",iVHWMemoryManager);
       
  1752 		}
       
  1753 	else
       
  1754 		{
       
  1755 		iVHWMemoryManager = NULL;
       
  1756 		}
       
  1757 	return 0;
       
  1758 	}
       
  1759 #endif // GRAPHICS_SURFACEMANAGER_SYBORG