os/graphics/windowing/windowserver/nga/CLIENT/RBUFFER.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1994-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// RWsBuffer class, handles buffering and flushing of window server commands
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <e32std.h>
sl@0
    19
#include "../SERVER/w32cmd.h"
sl@0
    20
#include "CLIENT.H"
sl@0
    21
#include "w32comm.h"
sl@0
    22
sl@0
    23
// Global functions
sl@0
    24
sl@0
    25
GLDEF_C void Assert(TW32Assert aAssert)
sl@0
    26
	{
sl@0
    27
	_LIT(KW32AssertCategory,"W32 Assert");
sl@0
    28
	User::Panic(KW32AssertCategory,aAssert);
sl@0
    29
	}
sl@0
    30
sl@0
    31
GLDEF_C void Panic(TW32Panic aPanic)
sl@0
    32
	{
sl@0
    33
	_LIT(KW32PanicCategory,"W32");
sl@0
    34
	User::Panic(KW32PanicCategory,aPanic);
sl@0
    35
	}
sl@0
    36
sl@0
    37
// Public functions
sl@0
    38
sl@0
    39
RWsBuffer::RWsBuffer(RWsSession *aSession) : iSession(aSession), iManager(NULL),
sl@0
    40
	#if defined(__AUTO_FLUSH)
sl@0
    41
		iAutoFlush(ETrue),
sl@0
    42
	#else
sl@0
    43
		iAutoFlush(EFalse),
sl@0
    44
	#endif
sl@0
    45
	iBuf(NULL,0,0), iNext(NULL), iPreviousHandle(0), iBufSize(0), iMaxBufSize(EMinBufferSize),
sl@0
    46
	#if defined(_DEBUG)
sl@0
    47
	iAppendDataLength(0),
sl@0
    48
	#endif
sl@0
    49
	iDirectAcessCount(0), iInvalidBitmapArray(EFalse), iWindowSizeCache(NULL)
sl@0
    50
	{
sl@0
    51
	}
sl@0
    52
sl@0
    53
TInt WsFbsDestroyCallBack(TAny* aBitmapHandle)
sl@0
    54
	{
sl@0
    55
	TInt* bitmapHandle=static_cast<TInt*>(aBitmapHandle);
sl@0
    56
	RWsBuffer::FlushAllBuffers(aBitmapHandle ? *bitmapHandle : 0);
sl@0
    57
sl@0
    58
	return(0);
sl@0
    59
	}
sl@0
    60
sl@0
    61
void RWsBuffer::SetCallBack()
sl@0
    62
	{
sl@0
    63
	for(RWsBuffer *buffer=(RWsBuffer *)Dll::Tls();buffer;buffer=buffer->iNext)
sl@0
    64
		if (buffer==this)
sl@0
    65
			return;	// Already linked
sl@0
    66
	iNext=(RWsBuffer *)Dll::Tls();
sl@0
    67
	Dll::SetTls(this);
sl@0
    68
	if (iNext==NULL)	// First connection so set callback
sl@0
    69
		RFbsSession::GetSession()->SetCallBack(TCallBack(WsFbsDestroyCallBack,NULL));
sl@0
    70
	}
sl@0
    71
sl@0
    72
void RWsBuffer::CancelCallBack()
sl@0
    73
	{
sl@0
    74
	RWsBuffer *buffer=(RWsBuffer *)Dll::Tls();
sl@0
    75
	if (buffer==this)
sl@0
    76
		{
sl@0
    77
		Dll::SetTls(iNext);
sl@0
    78
		if (iNext==NULL)
sl@0
    79
			RFbsSession::GetSession()->ResetCallBack();	// Last connection closing so cancel the callback
sl@0
    80
		}
sl@0
    81
	else
sl@0
    82
		{
sl@0
    83
		RWsBuffer *prev;
sl@0
    84
		while(buffer)
sl@0
    85
			{
sl@0
    86
			prev=buffer;
sl@0
    87
			buffer=buffer->iNext;
sl@0
    88
			if (buffer==this)
sl@0
    89
				{
sl@0
    90
				prev->iNext=iNext;
sl@0
    91
				break;
sl@0
    92
				}
sl@0
    93
			}
sl@0
    94
		}
sl@0
    95
	}
sl@0
    96
sl@0
    97
void RWsBuffer::Close()
sl@0
    98
	{
sl@0
    99
	User::Free((TAny *)iBuf.Ptr());
sl@0
   100
	if (iWindowSizeCache)
sl@0
   101
	    {
sl@0
   102
	    iWindowSizeCache->Close();
sl@0
   103
	    delete iWindowSizeCache;
sl@0
   104
	    iWindowSizeCache = NULL;
sl@0
   105
	    }
sl@0
   106
	}
sl@0
   107
sl@0
   108
void RWsBuffer::Destroy()
sl@0
   109
	{
sl@0
   110
	Flush();
sl@0
   111
	Close();
sl@0
   112
	delete this;
sl@0
   113
	}
sl@0
   114
sl@0
   115
sl@0
   116
TInt RWsBuffer::Flush(const TIpcArgs* aIpcArgs,TBool aRequestFinish)
sl@0
   117
	{
sl@0
   118
	iBitmapArray.Reset();
sl@0
   119
	iInvalidBitmapArray=EFalse;
sl@0
   120
	if (iBuf.Length()==0)
sl@0
   121
		{
sl@0
   122
		return(KErrNone);
sl@0
   123
		}
sl@0
   124
	TIpcArgs ipcArgs;
sl@0
   125
	if (aIpcArgs!=NULL)
sl@0
   126
		{
sl@0
   127
		ipcArgs=*aIpcArgs;
sl@0
   128
		// check that the caller hasn't used the first slot
sl@0
   129
		ipcArgs.Set(KBufferMessageSlot,TIpcArgs::ENothing);
sl@0
   130
		__ASSERT_ALWAYS(Mem::Compare(REINTERPRET_CAST(const TUint8*, &ipcArgs), sizeof(TIpcArgs), REINTERPRET_CAST(const TUint8*, aIpcArgs), sizeof(TIpcArgs))==0,Panic(EW32PanicUsingReservedIpcSlot));
sl@0
   131
		}
sl@0
   132
	ipcArgs.Set(KBufferMessageSlot,&iBuf);
sl@0
   133
	TInt ret;
sl@0
   134
	if(aRequestFinish)
sl@0
   135
		ret=iSession->DoFlush(ipcArgs);
sl@0
   136
	else
sl@0
   137
		ret=iSession->DoSyncMsgBuf(ipcArgs);
sl@0
   138
	iBuf.Zero();
sl@0
   139
	iPreviousHandle=0;
sl@0
   140
	return(ret);
sl@0
   141
	}
sl@0
   142
sl@0
   143
void RWsBuffer::FlushAllBuffers(TInt aBitmapHandle)
sl@0
   144
	{
sl@0
   145
	for(RWsBuffer *buffer=(RWsBuffer *)Dll::Tls();buffer;buffer=buffer->iNext)
sl@0
   146
		{
sl@0
   147
		if(!aBitmapHandle || buffer->iInvalidBitmapArray || (buffer->iBitmapArray.FindInOrder(aBitmapHandle)!=KErrNotFound))
sl@0
   148
sl@0
   149
			buffer->Flush();
sl@0
   150
		}
sl@0
   151
	}
sl@0
   152
sl@0
   153
inline void RWsBuffer::SetAndLimitMaxBufSize(TInt aMaxBufSize)
sl@0
   154
	{ // apply upper & lower limits to input buffer size
sl@0
   155
	if (aMaxBufSize < EMinBufferSize)
sl@0
   156
		{
sl@0
   157
		iMaxBufSize = EMinBufferSize;
sl@0
   158
		}
sl@0
   159
	else if	(aMaxBufSize > EMaxBufferSize)
sl@0
   160
		{
sl@0
   161
		iMaxBufSize = EMaxBufferSize;
sl@0
   162
		}
sl@0
   163
	else
sl@0
   164
		{
sl@0
   165
		iMaxBufSize = aMaxBufSize;
sl@0
   166
		}
sl@0
   167
	}
sl@0
   168
sl@0
   169
void RWsBuffer::SetBufferSizeL(TInt aBufSize)
sl@0
   170
	{
sl@0
   171
	SetAndLimitMaxBufSize(aBufSize);
sl@0
   172
	ReAllocBufferL(iMaxBufSize);
sl@0
   173
	}
sl@0
   174
sl@0
   175
void RWsBuffer::SetMaxBufferSizeL(TInt aMaxBufSize)
sl@0
   176
	{
sl@0
   177
	SetAndLimitMaxBufSize(aMaxBufSize);
sl@0
   178
sl@0
   179
	if (iMaxBufSize < iBufSize)
sl@0
   180
		{ // shrink to new maximum
sl@0
   181
		ReAllocBufferL(iMaxBufSize);
sl@0
   182
		}
sl@0
   183
	else
sl@0
   184
		{
sl@0
   185
		 // initial allocation should be (at least) a quarter of the requested size
sl@0
   186
		TInt minSize = Max( (iMaxBufSize + 3) >> 2, EMinBufferSize);
sl@0
   187
		if (minSize > iBufSize)
sl@0
   188
			{ // new or enlarged buffer
sl@0
   189
			ReAllocBufferL(minSize);
sl@0
   190
			}
sl@0
   191
		}
sl@0
   192
sl@0
   193
	__ASSERT_DEBUG((iBufSize >= EMinBufferSize) && (iBufSize <= iMaxBufSize), Assert(EW32AssertBufferLogic));
sl@0
   194
	}
sl@0
   195
sl@0
   196
// Flush() buffer, try to ReAlloc, Leave if the ReAlloc fails.
sl@0
   197
void RWsBuffer::ReAllocBufferL(TInt aNewSize)
sl@0
   198
	{
sl@0
   199
	if (aNewSize != iBufSize)
sl@0
   200
		{
sl@0
   201
		Flush();
sl@0
   202
		if (!ReAllocBuffer(aNewSize))
sl@0
   203
			{
sl@0
   204
			User::LeaveNoMemory();
sl@0
   205
			}
sl@0
   206
		}
sl@0
   207
	}
sl@0
   208
sl@0
   209
TBool RWsBuffer::ReAllocBuffer(TInt aNewSize)
sl@0
   210
	{
sl@0
   211
	TUint8* ptr = const_cast<TUint8*>(iBuf.Ptr());
sl@0
   212
	__ASSERT_DEBUG((iBufSize == 0) || (ptr != NULL), Assert(EW32AssertBufferLogic));
sl@0
   213
	const TInt len = iBuf.Length();
sl@0
   214
	TUint8* newPtr = static_cast<TUint8*>(User::ReAlloc(ptr, aNewSize));
sl@0
   215
	if (newPtr != NULL)
sl@0
   216
		{ // realloc was successful
sl@0
   217
		iBuf.Set(newPtr, len, aNewSize);
sl@0
   218
		iBufSize = aNewSize;
sl@0
   219
		return ETrue;
sl@0
   220
		}
sl@0
   221
	return EFalse;
sl@0
   222
	}
sl@0
   223
sl@0
   224
/* Expand the buffer, to allow new drawing command to fit.
sl@0
   225
 
sl@0
   226
 Called either when trying to store additional commands to queue for Wserv, or
sl@0
   227
 the trying to send a command bigger than the current buffer size.
sl@0
   228
sl@0
   229
 Failure to expand the buffer is a minor problem in the first case but a big 
sl@0
   230
 problem in the second.
sl@0
   231
sl@0
   232
 @param aRequiredSpace Size of buffer increase required.
sl@0
   233
 @param aMsgSize If expanding the buffer fails then needs this value to know whether Flush() is good enough.
sl@0
   234
 @return ETrue if there is enough space, EFalse if not.
sl@0
   235
 */
sl@0
   236
void RWsBuffer::GrowBuffer(TInt aRequiredSpace, TInt aMsgSize)
sl@0
   237
	{
sl@0
   238
	__ASSERT_DEBUG(iBufSize < iMaxBufSize, Assert(EW32AssertBufferLogic));
sl@0
   239
	// maximum size will be big enough?
sl@0
   240
	__ASSERT_ALWAYS(aMsgSize <= iMaxBufSize, Panic(EW32PanicDataExceedsBufferLength));
sl@0
   241
	
sl@0
   242
	 // double or quad the current size, then limit it
sl@0
   243
	TInt newSize = Min((iBufSize >= aRequiredSpace) ? iBufSize << 1 : iBufSize << 2, iMaxBufSize);
sl@0
   244
sl@0
   245
	if (!ReAllocBuffer(newSize))
sl@0
   246
		{ // OOM error
sl@0
   247
		Flush();
sl@0
   248
		if (aMsgSize > iBufSize)
sl@0
   249
			{ // message is too big for buffer
sl@0
   250
			Panic(EW32PanicDataExceedsBufferLength);
sl@0
   251
			}
sl@0
   252
		}
sl@0
   253
	}
sl@0
   254
sl@0
   255
sl@0
   256
TBool RWsBuffer::SetAutoFlush(TBool aState)
sl@0
   257
	{
sl@0
   258
	TBool old;
sl@0
   259
sl@0
   260
	old=iAutoFlush;
sl@0
   261
#if defined(__AUTO_FLUSH)
sl@0
   262
	if (aState)
sl@0
   263
#else
sl@0
   264
	iAutoFlush=aState;
sl@0
   265
	if (iAutoFlush)
sl@0
   266
#endif
sl@0
   267
		Flush();
sl@0
   268
	return(old);
sl@0
   269
	}
sl@0
   270
sl@0
   271
TInt RWsBuffer::DoWrite(TInt aHandle, TUint aOpcode, TBool aFlush, const TIpcArgs* aIpcArgs, const TAny* aData, TInt aLength, const TAny* aData2, TInt aLength2)
sl@0
   272
	{
sl@0
   273
	__ASSERT_DEBUG(((TUint32) aOpcode) < 0x8000, Assert(EW32AssertIllegalOpcode));
sl@0
   274
	__ASSERT_DEBUG((aLength&0x3) == 0, Assert(EW32AssertOddLengthData));
sl@0
   275
	TInt xtra(0);
sl@0
   276
	if (aLength2>0)
sl@0
   277
		xtra = PadValue(aLength2);		// Round data upto a multiple of 4
sl@0
   278
sl@0
   279
	const TInt msgSize = aLength + aLength2 + xtra + static_cast<TInt>(sizeof(TWsCmdHeader));
sl@0
   280
	TInt available = iBuf.MaxLength() - iBuf.Length();
sl@0
   281
	if (msgSize > available)
sl@0
   282
		{
sl@0
   283
		if (iBufSize >= iMaxBufSize)
sl@0
   284
			{ // buffer is maximum size already
sl@0
   285
			Flush();
sl@0
   286
			}
sl@0
   287
		else
sl@0
   288
			{ // try to grow buffer
sl@0
   289
			 if ( (iBuf.Length() + msgSize) > iMaxBufSize)
sl@0
   290
				{ // growing alone will not make enough extra space
sl@0
   291
				Flush();
sl@0
   292
				available = iBufSize;
sl@0
   293
				}
sl@0
   294
sl@0
   295
			const TInt requiredSpace = msgSize - available;
sl@0
   296
			if (requiredSpace > 0)
sl@0
   297
				{
sl@0
   298
				GrowBuffer(requiredSpace, msgSize);
sl@0
   299
				}
sl@0
   300
			}
sl@0
   301
		}
sl@0
   302
sl@0
   303
	TWsCmdHeader cmdHeader;
sl@0
   304
	cmdHeader.iBase.iOpcode = (TInt16)aOpcode;
sl@0
   305
	cmdHeader.iBase.iCmdLength = (TInt16)(aLength + aLength2 + xtra);
sl@0
   306
sl@0
   307
	// For performance reasons we only pass in the handle if it is different
sl@0
   308
	// from the previous command
sl@0
   309
	if (aHandle == iPreviousHandle)
sl@0
   310
		{
sl@0
   311
		iBuf.Append((TUint8 *)&cmdHeader.iBase,sizeof(cmdHeader.iBase));
sl@0
   312
		}
sl@0
   313
	else
sl@0
   314
		{
sl@0
   315
		iPreviousHandle = aHandle;
sl@0
   316
		cmdHeader.iBase.iOpcode|=EWsOpcodeHandle;
sl@0
   317
		cmdHeader.iDestHandle = aHandle;
sl@0
   318
		iBuf.Append((TUint8 *)&cmdHeader,sizeof(cmdHeader));
sl@0
   319
		}
sl@0
   320
sl@0
   321
	if (aLength)
sl@0
   322
		{
sl@0
   323
		iBuf.Append((TUint8 *)aData, aLength);
sl@0
   324
		}
sl@0
   325
	if (aLength2>0 && aData2!=NULL)
sl@0
   326
		{
sl@0
   327
		iBuf.Append((TUint8 *)aData2, aLength2);
sl@0
   328
		iBuf.AppendFill(0,xtra);
sl@0
   329
		}
sl@0
   330
#if defined(_DEBUG)
sl@0
   331
	else if (aLength2>0 && aData2==NULL)
sl@0
   332
		{
sl@0
   333
		iAppendDataLength = aLength2;
sl@0
   334
		}
sl@0
   335
#endif
sl@0
   336
	if (aFlush)
sl@0
   337
		{
sl@0
   338
		return Flush(aIpcArgs);
sl@0
   339
		}
sl@0
   340
	return KErrNone;
sl@0
   341
	}
sl@0
   342
sl@0
   343
void RWsBuffer::Write(TInt handle,TUint opcode)
sl@0
   344
	{
sl@0
   345
	DoWrite(handle, opcode, iAutoFlush, NULL);
sl@0
   346
	}
sl@0
   347
sl@0
   348
/**
sl@0
   349
Writes data sent in aData of length aLength1 for the specifed aOpcode
sl@0
   350
into wserv buffer. It also takes an TIpcArgs by which you can send additional 
sl@0
   351
data. But one thing needs to be noted that if aIpcArgs has some content then 
sl@0
   352
this function flushes the wserv buffer.
sl@0
   353
sl@0
   354
@param aHandle aHandle of class derived from MWsClientClass
sl@0
   355
@param aOpcode Opcode for the current command
sl@0
   356
@param aData Data to be added to the buffer
sl@0
   357
@param aLength Length of the data to be added to buffer
sl@0
   358
@param aIpcArgs Additional data sent from client to server. It has default argument NULL.
sl@0
   359
				And if some data is sent in aIpcArgs, it flushes wserv buffer
sl@0
   360
*/
sl@0
   361
void RWsBuffer::Write(TInt aHandle, TUint aOpcode, const TAny *aData, TInt aLength, const TIpcArgs* aIpcArgs/*=NULL*/)
sl@0
   362
	{
sl@0
   363
	TBool flush = (aIpcArgs != NULL ? ETrue : iAutoFlush);	// If aIpcArgs contains data then we do explicit flush
sl@0
   364
	DoWrite(aHandle, aOpcode, flush, aIpcArgs, aData, aLength);
sl@0
   365
	}
sl@0
   366
sl@0
   367
/**
sl@0
   368
Writes data sent in aData and aData2 of lengths aLength1 and aLength2 
sl@0
   369
for the specifed aOpcode into wserv buffer. It also takes an TIpcArgs by which 
sl@0
   370
you can send additional data. But one thing needs to be noted that if aIpcArgs 
sl@0
   371
has some content then this function flushes the wserv buffer.
sl@0
   372
sl@0
   373
@param aHandle Handle of class derived from MWsClientClass
sl@0
   374
@param aOpcode Opcode for the current command
sl@0
   375
@param aData Data to be added to the buffer
sl@0
   376
@param aLength Length of the data to be added to buffer
sl@0
   377
@param aData2 second Data to be added to the buffer
sl@0
   378
@param aLength2 Length of the second data to be added to buffer
sl@0
   379
@param aIpcArgs Additional data sent from client to server. It has default argument NULL.
sl@0
   380
				And if some data is sent in aIpcArgs, it flushes wserv buffer
sl@0
   381
*/
sl@0
   382
void RWsBuffer::Write(TInt aHandle, TUint aOpcode, const TAny *aData, TInt aLength, const TAny *aData2, TInt aLength2, const TIpcArgs* aIpcArgs/*=NULL*/)
sl@0
   383
	{
sl@0
   384
	__ASSERT_DEBUG(!((aIpcArgs != NULL) &&  (aLength2 > 0 && aData2 == NULL)), Assert(EW32AssertBufferLogic));
sl@0
   385
	TBool flush = iAutoFlush;
sl@0
   386
	if (aLength2 > 0 && aData2 == NULL)
sl@0
   387
		{
sl@0
   388
		flush = EFalse;		// if just length2 is sent then we should not flush
sl@0
   389
		}
sl@0
   390
	else if (aIpcArgs != NULL)
sl@0
   391
		{
sl@0
   392
		flush = ETrue;		// If aIpcArgs contains data then we do explicit flush
sl@0
   393
		}
sl@0
   394
	DoWrite(aHandle, aOpcode, flush, aIpcArgs, aData, aLength, aData2, aLength2);
sl@0
   395
	}
sl@0
   396
sl@0
   397
/**
sl@0
   398
Appends data directly to wserv buffer for the current command. So this function 
sl@0
   399
should be used after adding the current command. 
sl@0
   400
sl@0
   401
@param aData Data to be added to the buffer
sl@0
   402
@param aLength Length of the data to be added to buffer. Make sure that its length
sl@0
   403
		is less than availabe buffer.
sl@0
   404
@param aFinished EFalse, adds data to buffer and disables flushing even if auto flush is on, 
sl@0
   405
				 basically this notfies that more data is pending to be added.
sl@0
   406
				 ETrue, adds data to buffer and resume normal service for flushing
sl@0
   407
				 ie. Signals that this is the last bit of data to be added
sl@0
   408
sl@0
   409
Note: When data is added using this API, it pads out buffer to multiple of 4 bytes  
sl@0
   410
*/
sl@0
   411
void RWsBuffer::AppendData(const TAny *aData,TInt aLength,TBool aFinished)
sl@0
   412
	{
sl@0
   413
	__ASSERT_ALWAYS(iBuf.MaxLength()-iBuf.Length()>=PaddedValue(aLength),Assert(EW32AssertBufferLogic));
sl@0
   414
#if defined(_DEBUG)
sl@0
   415
	// Check if this function is called only after setting iAppendDataLength
sl@0
   416
	__ASSERT_DEBUG(iAppendDataLength > 0, Assert(EW32AssertBufferLogic));
sl@0
   417
	// Check if length passed in is less then iAppendDataLength
sl@0
   418
	__ASSERT_DEBUG(iAppendDataLength >= aLength, Assert(EW32AssertBufferLogic));
sl@0
   419
	if (aFinished)
sl@0
   420
		iAppendDataLength = 0; 
sl@0
   421
	else
sl@0
   422
		iAppendDataLength -= aLength;
sl@0
   423
#endif
sl@0
   424
	iBuf.Append((TUint8*)(aData),aLength);
sl@0
   425
	iBuf.AppendFill(0,PadValue(iBuf.Length()));		// Padout out buffer to multiple of 4 bytes
sl@0
   426
	if (aFinished && iAutoFlush)
sl@0
   427
		Flush(NULL);
sl@0
   428
	}
sl@0
   429
sl@0
   430
TInt RWsBuffer::WriteReply(TInt handle,TUint opcode,const TIpcArgs* aIpcArgs)
sl@0
   431
	{
sl@0
   432
	return DoWrite(handle, opcode, ETrue, aIpcArgs);
sl@0
   433
	}
sl@0
   434
sl@0
   435
TInt RWsBuffer::WriteReply(TInt handle,TUint opcode,const TAny *pData, TInt length,const TIpcArgs* aIpcArgs)
sl@0
   436
	{
sl@0
   437
	return DoWrite(handle, opcode, ETrue, aIpcArgs, pData, length);
sl@0
   438
	}
sl@0
   439
	
sl@0
   440
TInt RWsBuffer::WriteReply(TInt handle,TUint opcode,const TAny *pData,TInt length,const TAny *pData2,TInt length2,const TIpcArgs* aIpcArgs)
sl@0
   441
	{
sl@0
   442
	return DoWrite(handle, opcode, ETrue, aIpcArgs, pData, length, pData2, length2);
sl@0
   443
	}
sl@0
   444
sl@0
   445
TInt RWsBuffer::WriteReplyP(TInt aHandle, TUint aOpcode, const TWriteDescriptorType& aReplyBuffer)
sl@0
   446
	{
sl@0
   447
	TIpcArgs ipcArgs;
sl@0
   448
	aReplyBuffer.SetDescriptorOnIpcArgs(ipcArgs);
sl@0
   449
	return DoWrite(aHandle, aOpcode, ETrue, &ipcArgs);
sl@0
   450
	}
sl@0
   451
sl@0
   452
TInt RWsBuffer::WriteReplyP(TInt aHandle,TUint aOpcode,const TAny *aData,TInt aLength,const TWriteDescriptorType& aReplyBuffer)
sl@0
   453
	{
sl@0
   454
	TIpcArgs ipcArgs;
sl@0
   455
	aReplyBuffer.SetDescriptorOnIpcArgs(ipcArgs);
sl@0
   456
	return DoWrite(aHandle, aOpcode, ETrue, &ipcArgs, aData, aLength);
sl@0
   457
	}
sl@0
   458
sl@0
   459
TInt RWsBuffer::WriteReplyP(TInt aHandle,TUint aOpcode,const TAny *aData1,TInt aLengthData1,const TAny *aData2,TInt aLengthData2,const TWriteDescriptorType& aReplyBuffer)
sl@0
   460
	{
sl@0
   461
	TIpcArgs ipcArgs;
sl@0
   462
	aReplyBuffer.SetDescriptorOnIpcArgs(ipcArgs);
sl@0
   463
	return DoWrite(aHandle, aOpcode, ETrue, &ipcArgs, aData1, aLengthData1, aData2, aLengthData2);
sl@0
   464
	}
sl@0
   465
sl@0
   466
TInt RWsBuffer::WriteReplyWs(TUint opcode)
sl@0
   467
//
sl@0
   468
// Do a WriteReply using the sessions handle
sl@0
   469
//
sl@0
   470
	{
sl@0
   471
	return(iSession->WriteReply(opcode));
sl@0
   472
	}
sl@0
   473
sl@0
   474
TInt RWsBuffer::WriteReplyWs(const TAny *pData, TInt aLength, TUint aOpcode)
sl@0
   475
//
sl@0
   476
// Do a WriteReply using the sessions handle
sl@0
   477
//
sl@0
   478
	{
sl@0
   479
	return(iSession->WriteReply(pData,aLength,aOpcode));
sl@0
   480
	}
sl@0
   481
sl@0
   482
TInt RWsBuffer::WriteReplyWs(const TAny *pData, TInt aLength, const TAny *pData2, TInt aLength2, TUint aOpcode)
sl@0
   483
//
sl@0
   484
// Do a WriteReply using the sessions handle
sl@0
   485
//
sl@0
   486
	{
sl@0
   487
	return(iSession->WriteReply(pData,aLength,pData2,aLength2,aOpcode));
sl@0
   488
	}
sl@0
   489
sl@0
   490
TInt RWsBuffer::WriteReplyByProvidingRemoteReadAccess(TInt aHandle,TUint aOpcode,const TAny *aData, TInt aLength,const TReadDescriptorType& aRemoteReadBuffer)
sl@0
   491
	{
sl@0
   492
	TIpcArgs ipcArgs;
sl@0
   493
	aRemoteReadBuffer.SetDescriptorOnIpcArgs(ipcArgs);
sl@0
   494
	return DoWrite(aHandle, aOpcode, ETrue, &ipcArgs, aData, aLength);
sl@0
   495
	}
sl@0
   496
sl@0
   497
void RWsBuffer::AddToBitmapArray(TInt aBitmapHandle)
sl@0
   498
	{
sl@0
   499
	if(aBitmapHandle && !iInvalidBitmapArray)
sl@0
   500
		{
sl@0
   501
		if(iBitmapArray.InsertInOrder(aBitmapHandle)==KErrNoMemory)
sl@0
   502
sl@0
   503
			iInvalidBitmapArray=ETrue;
sl@0
   504
		}
sl@0
   505
	}
sl@0
   506
	
sl@0
   507
void RWsBuffer::SetWsGraphicManager(CWsGraphic::CManager* aManager)
sl@0
   508
	{
sl@0
   509
	__ASSERT_DEBUG(!WsGraphicManager(),Panic(EW32PanicGraphicInternal));
sl@0
   510
	iManager = aManager;
sl@0
   511
	}
sl@0
   512
sl@0
   513
CWsGraphic::CManager* RWsBuffer::WsGraphicManager()
sl@0
   514
	{
sl@0
   515
	for(RWsBuffer *buffer=(RWsBuffer *)Dll::Tls();buffer;buffer=buffer->iNext)
sl@0
   516
		if (buffer->iManager)
sl@0
   517
			return buffer->iManager;	
sl@0
   518
	return NULL; // does not yet exist
sl@0
   519
	}
sl@0
   520
sl@0
   521
void RWsBuffer::AsyncRequest(TInt aHandle, TUint aOpcode, TRequestStatus& aStatus)
sl@0
   522
	{
sl@0
   523
	aStatus = KRequestPending;
sl@0
   524
	__ASSERT_DEBUG((aOpcode&EWservMessAsynchronousService)==0, Assert(EW32AssertIllegalOpcode));
sl@0
   525
	Flush(); 
sl@0
   526
sl@0
   527
	const TInt function = EWservMessAsynchronousService | aOpcode;
sl@0
   528
	TIpcArgs ipcArgs(aHandle);
sl@0
   529
sl@0
   530
	iSession->SendReceive(function, ipcArgs, aStatus);
sl@0
   531
	}
sl@0
   532
sl@0
   533
void RWsBuffer::EnableWindowSizeCacheL()
sl@0
   534
    {
sl@0
   535
    if (iWindowSizeCache == NULL)
sl@0
   536
        {
sl@0
   537
        iWindowSizeCache = new (ELeave) RHashMap<TInt, TWindowSizeCacheEntry>();        
sl@0
   538
        }
sl@0
   539
    }