graphicsdeviceinterface/screendriver/sbit/Cdsb.cpp
author Faisal Memon <faisal.memon@nokia.com>
Fri, 25 Jun 2010 17:49:58 +0100
branchEGL_MERGE
changeset 105 158b2308cc08
parent 0 5d03bc08d59c
child 26 15986eb6c500
child 45 36b2e23a8629
permissions -rw-r--r--
Fix def files so that the implementation agnostic interface definition has no non-standards defined entry points, and change the eglrefimpl specific implementation to place its private entry points high up in the ordinal order space in the implementation region, not the standards based entrypoints region.

// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//

#include <hal.h>
#include <cdsb.h>
#include <e32hal.h>


#ifdef SYMBIAN_GRAPHICS_GCE
#undef __WINS__
#include "../sgeneric/scdraw.h"
#elif defined(__WINS__)
#include "_WININC.H"
#endif


//
//	CGenericDirectScreenBitmap: Implementation of generic CDirectScreenBitmap class
//
NONSHARABLE_CLASS(CGenericDirectScreenBitmap) : public CDirectScreenBitmap
	{
public:
	 CGenericDirectScreenBitmap();
	 CGenericDirectScreenBitmap(TInt aScreenNo);
	~CGenericDirectScreenBitmap();

public:
	// Pure virtual from CDirectScreenBitmap
	virtual TInt Create(const TRect& aScreenRect, TSettingsFlags aSettingsFlags);
	virtual TInt BeginUpdate(TAcceleratedBitmapInfo& aBitmapInfo);
	virtual void EndUpdate(TRequestStatus& aComplete);
	virtual void EndUpdate(const TRect& aScreenRect, TRequestStatus& aComplete);
	virtual void Close();

public:
	enum TDsbPanic
		{
		EPanicAlreadyCreated = 1,
		EPanicNotCreated     = 2,
		EPanicInvalidMode    = 3,
		EPanicOutOfBounds	 = 4,
		EPanicNotWordAligned = 5,
		EPanicInvalidRect    = 6,
		EPanicIncompleteRequest = 7,
		EPanicHandleReturnedIncorrect = 8
		};
    static void Panic(TDsbPanic aPanic);

private:
	TInt DoCreate();

#ifdef __WINS__
	TRgb ExtractRgb(TUint8* aBuffer,TInt aPixelOffset) const;
	void WinsUpdate(const TRect& aScreenRect);
#endif

private:
#ifndef __WINS__
	TInt    iVideoAddress;
#endif
#ifdef SYMBIAN_GRAPHICS_GCE
    CScreenDeviceHelper iSurfaceUpdater;
    TUidPixelFormat iPixelFormat;
    TBool iDsaBufferIsBusy;
    TRequestStatus iDsaBufferAvailable;
#endif
	TAcceleratedBitmapInfo iBitmapInfo;
	TUint32 iSettingsFlags;
	TRect   iUpdateRect;
	TInt    iDisplayOffsetLines;
	TInt    iBytesPerPixel;
	TInt	iDisplayOffsetPixel;
	TBool   iCreated;
    TInt    iScreenNo;
    RChunk 	iChunk;
    TBool 	iHasChunk;
	};

//
// Create a new instance of a DSB
// The default screen (with number 0) will be used
EXPORT_C CDirectScreenBitmap* CDirectScreenBitmap::NewL()
	{
	CGenericDirectScreenBitmap* pDsb=new(ELeave) CGenericDirectScreenBitmap;
	return(pDsb);
	}

//
// Create a new instance of a DSB
// The screen with aScreenNo number will be used
EXPORT_C CDirectScreenBitmap* CDirectScreenBitmap::NewL(TInt aScreenNo)
    {
	CGenericDirectScreenBitmap* pDsb = new (ELeave) CGenericDirectScreenBitmap(aScreenNo);
	return pDsb;
    }

CGenericDirectScreenBitmap::CGenericDirectScreenBitmap() :
#ifndef __WINS__
	iVideoAddress(NULL),
#endif
#ifdef SYMBIAN_GRAPHICS_GCE
	iDsaBufferIsBusy(EFalse),
#endif
	iBitmapInfo(),
	iSettingsFlags(ENone),
	iUpdateRect(),
	iDisplayOffsetLines(0),
	iBytesPerPixel(0),
	iDisplayOffsetPixel(0),
	iHasChunk(EFalse)
	{
    }

CGenericDirectScreenBitmap::CGenericDirectScreenBitmap(TInt aScreenNo) :
    iScreenNo(aScreenNo)
    {
    }

CGenericDirectScreenBitmap::~CGenericDirectScreenBitmap()
	{
	Close();
	}

//
// Create a DSB object using a region of the screen previously
// 'claimed' via the Window Servers Direct Screen Acceass API
//
TInt CGenericDirectScreenBitmap::Create(const TRect& aScreenRect, TSettingsFlags aSettingsFlags)
	{
	__ASSERT_ALWAYS(!iCreated, Panic(EPanicAlreadyCreated));

	__ASSERT_ALWAYS((aSettingsFlags&(EDoubleBuffer|EIncrementalUpdate)) !=
					(EDoubleBuffer|EIncrementalUpdate), Panic(EPanicInvalidMode));

    //Initialize iScreenNo - its value occupies upper 5 bits of aSettingsFlags.
    //(32 - 1) is max allowed screen number
    iScreenNo = static_cast <TUint32> ((aSettingsFlags & 0xF8000000) >> 27);

	// Find the screen dimensions from the HAL and validate
	TInt screenWidth = 0;
	TInt screenHeight = 0;

	TInt r = HAL::Get(iScreenNo, HALData::EDisplayXPixels, screenWidth);
	if (r!=KErrNone)
		{
		return r;
		}

	r = HAL::Get(iScreenNo, HALData::EDisplayYPixels,screenHeight);
	if (r!=KErrNone)
		{
		return r;
		}

	__ASSERT_ALWAYS(aScreenRect.iTl.iX >= 0 &&
					aScreenRect.iTl.iY >= 0 &&
					aScreenRect.Width() <= screenWidth &&
					aScreenRect.Height() <= screenHeight, Panic(EPanicOutOfBounds));

	__ASSERT_ALWAYS(aScreenRect.Width() > 0 &&
					aScreenRect.Height() > 0, Panic(EPanicInvalidRect));

	iUpdateRect = aScreenRect;
	iSettingsFlags = aSettingsFlags;

	r = DoCreate();
	if(r != KErrNone)
		{
		return r;
		}

	// Check that LHS is word-aligned
	const TUint pixelStartInBytes = aScreenRect.iTl.iX*iBytesPerPixel;
	const TUint pixelEndInBytes = aScreenRect.iBr.iX*iBytesPerPixel;

	// Check the alignment
	__ASSERT_ALWAYS(!(pixelStartInBytes & 0x03), Panic(EPanicNotWordAligned));
	__ASSERT_ALWAYS(!(pixelEndInBytes & 0x03),	 Panic(EPanicNotWordAligned));

	const TUint scanlineBytes = pixelEndInBytes-pixelStartInBytes;

#ifndef __WINS__	
	iVideoAddress += pixelStartInBytes +						// X Offset
						 iUpdateRect.iTl.iY*iDisplayOffsetLines +	// Y Offset
						 iDisplayOffsetPixel;						 // Pixel (Palette) Offset
#endif 
	
	// Since this is a generic implementation, we only require one
	//  buffer for both incremental and double buffered mode
	iBitmapInfo.iAddress = (TUint8*)User::Alloc(scanlineBytes * iUpdateRect.Height());
	if(!iBitmapInfo.iAddress)
		return KErrNoMemory;

	iBitmapInfo.iSize			 = TSize(iUpdateRect.Width(), iUpdateRect.Height());
	iBitmapInfo.iLinePitch		 = scanlineBytes;
	iBitmapInfo.iPhysicalAddress = 0;

	// All done
	iCreated = ETrue;

	return KErrNone;
	}

#ifndef __WINS__
//
// Attempt to initialise using the HAL
//
TInt CGenericDirectScreenBitmap::DoCreate()
	{
    // For GCE, if multiple modes are supported, only one needs to be returned.
	// On the emulator, what is returned via EDisplayMode can be set via ColorDepth setting in epoc.ini
	// On the hardware, 24/32bpp color mode is returned via EDisplayMode as pre-defined. 
	TInt displayMode = 0;
	TInt r1 = HAL::Get(iScreenNo, HALData::EDisplayMode, displayMode);
	if (r1!=KErrNone)
		{
		return r1;
		}

	TInt bitsPerPixel = displayMode;

	r1 = HAL::Get(iScreenNo, HALData::EDisplayBitsPerPixel, bitsPerPixel);
	if (r1!=KErrNone)
		{
		return r1;
		}
	iBytesPerPixel = (bitsPerPixel+7) >> 3;

	// Store the important driver parameters to avoid HAL calls when drawing
	iDisplayOffsetPixel = displayMode;
	r1 = HAL::Get(iScreenNo, HALData::EDisplayOffsetToFirstPixel, iDisplayOffsetPixel);
	if (r1!=KErrNone)
		{
		return r1;
		}
	iDisplayOffsetLines = displayMode;
	r1 = HAL::Get(iScreenNo, HALData::EDisplayOffsetBetweenLines, iDisplayOffsetLines);
	if (r1!=KErrNone)
		{
		return r1;
		}
	
	TInt val = 0;
	r1 = HAL::Get(iScreenNo, HALData::EDisplayMemoryHandle,val);
	if (r1 == KErrNotSupported)
		{
		// EDisplayMemoryHandle is not supported, use the address instead
		r1 = HAL::Get(iScreenNo, HALData::EDisplayMemoryAddress, iVideoAddress);
		if (r1!=KErrNone)
			{
			return r1;
			}
		}
	else if (r1 == KErrNone)
		{
		// EDisplayMemoryHandle is supported, use the handle base address
		__ASSERT_ALWAYS(val != 0, Panic(EPanicHandleReturnedIncorrect));
		RChunk chunk;
		r1 = chunk.SetReturnedHandle(val);
		if (r1 != KErrNone)
			{
			return r1;
			}
		iChunk = chunk;
		r1 = iChunk.Duplicate(RThread(), EOwnerProcess);
		chunk.Close();
		if (r1 != KErrNone)
			{
			return r1;
			}
		iVideoAddress = (TInt)iChunk.Base();
		iHasChunk = ETrue;
		}
	else  
		{
		return r1;
		}

	// The HAL doesn't specify explicit dislpay modes, so we need
	// to calculate the mode using bitsPerPixel and isMono
	TBool isMono = displayMode;
	r1 = HAL::Get(iScreenNo, HALData::EDisplayIsMono, isMono);
	if (r1!=KErrNone)
		{
		return r1;   
		}
     switch(bitsPerPixel)
		{
		// EGray2, EGray4, EGray16, EColor16 not supported on the hardware
		// The generic scdv support EGray2, EGray4, EGray16, EColor16 on the emulator
		// However, the low display modes should not be used.
		case 1:
			iBitmapInfo.iPixelShift = 0;
			iBitmapInfo.iDisplayMode = EGray2;
			iBytesPerPixel = 2;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatUnknown;
#endif
			break;
		case 2:
			iBitmapInfo.iPixelShift = 1;
			iBitmapInfo.iDisplayMode = EGray4;
			iBytesPerPixel = 2;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatUnknown;
#endif
			break;
		case 4:
			iBitmapInfo.iPixelShift = 2;
			iBitmapInfo.iDisplayMode = isMono ? EGray16 : EColor16;
			iBytesPerPixel = 2;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatUnknown;
#endif
			break;	 
		case 8:
			iBitmapInfo.iPixelShift = 3;
			iBitmapInfo.iDisplayMode = isMono ? EGray256 : EColor256;
			iBytesPerPixel = 2;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatUnknown;
#endif
			break;
		case 12:
			iBitmapInfo.iPixelShift = 4;
			iBitmapInfo.iDisplayMode = EColor4K;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatXRGB_4444;
#endif
			break;
		case 16:
			iBitmapInfo.iPixelShift = 4;
			iBitmapInfo.iDisplayMode = EColor64K;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatRGB_565;
#endif
			break;
		case 24:
		case 32:
			iBitmapInfo.iPixelShift = 5;
			iBitmapInfo.iDisplayMode = EColor16MAP;
#ifdef SYMBIAN_GRAPHICS_GCE
			iPixelFormat = EUidPixelFormatARGB_8888_PRE;
			iBytesPerPixel = 4;
#endif
			break;
		default:
			return KErrNotSupported;
		}

#ifdef SYMBIAN_GRAPHICS_GCE
    TInt ret = iSurfaceUpdater.Construct(iScreenNo,iPixelFormat,displayMode);
 	if (ret != KErrNone)
 		{
 		return ret;
 		}
#endif

	return KErrNone;
	}
#endif

#ifdef __WINS__
//
// Attempt to initialise for WINS
// This is intended for use if HAL initialisation fails.
//
TInt CGenericDirectScreenBitmap::DoCreate()
	{
    RWindows* window = ::WindowHandler(iScreenNo);
    if(window)
		{
		iBitmapInfo.iDisplayMode = window->iDisplayMode;
		iDisplayOffsetLines		 = window->iEpocBitmapLinePitch;
		iDisplayOffsetPixel		 = 0;

		switch(iBitmapInfo.iDisplayMode)
			{
			case EGray2:
				iBitmapInfo.iPixelShift = 0;
				iBytesPerPixel = 1;
				break;
			case EGray4:
				iBitmapInfo.iPixelShift = 1;
				iBytesPerPixel = 1;
				break;
			case EGray16:
			case EColor16:
				iBitmapInfo.iPixelShift = 2;
				iBytesPerPixel = 1;
				break;
			case EGray256:
			case EColor256:
				iBitmapInfo.iPixelShift = 3;
				iBytesPerPixel = 1;
				break;
			case EColor4K:
			case EColor64K:
				iBitmapInfo.iPixelShift = 4;
				iBytesPerPixel = 2;
				break;
			case EColor16M:
				iBitmapInfo.iPixelShift = 5;
				iBytesPerPixel = 3;
				break;
			case ERgb:
			case EColor16MU:
			case EColor16MA:
			case EColor16MAP:
				iBitmapInfo.iPixelShift = 5;
				iBytesPerPixel = 4;
				break;
			default:
				return KErrNotSupported;
			}

		return KErrNone;
		}
	else
		{
		return KErrNoMemory;
		}
	}
#endif

//
// Begin update - aBitmapinfo returns the current bitmap
//
TInt CGenericDirectScreenBitmap::BeginUpdate(TAcceleratedBitmapInfo& aBitmapInfo)
	{
	__ASSERT_ALWAYS(iCreated, Panic(EPanicNotCreated));
	aBitmapInfo = iBitmapInfo;
	return KErrNone;
	}


#ifdef __WINS__

void CGenericDirectScreenBitmap::WinsUpdate(const TRect& aScreenRect)
	{
	const TUint dS = iBitmapInfo.iLinePitch;
	const TUint offY = aScreenRect.iTl.iY - iUpdateRect.iTl.iY;
	TUint8* pS = iBitmapInfo.iAddress + (offY*dS);
	RWindows* window = ::WindowHandler(iScreenNo);
	TInt orientation=window->Orientation();
	TRect orientedRect;
	TSize orientedSize;

	orientedSize = window->GetOrientedSize();
	orientedRect = window->GetOrientedRect(aScreenRect);

	TInt BrX = iUpdateRect.iBr.iX-1;
	TInt BrY = iUpdateRect.iBr.iY-1;

	for(TInt y=aScreenRect.iTl.iY; y < aScreenRect.iBr.iY; y++)
		{

		TRgb pixelColor;

		TInt xSource = aScreenRect.iTl.iX-iUpdateRect.iTl.iX;

		for(TInt x = aScreenRect.iTl.iX; x < aScreenRect.iBr.iX; x++)
			{
			TUint8* pD;

			switch(orientation)
				{
				case 0:
					pD = window->PixelAddress(x, y);
					break;
				case 1:
					pD = window->PixelAddress(y, BrX-x);
					break;
				case 2:
					pD = window->PixelAddress(BrX-x, BrY-y);
					break;
				case 3:
					pD = window->PixelAddress(BrY-y, x);
					break;
				default:
					break;
				}

			// Convert the user colour to RGB, as required by the WINS Emulator
			pixelColor = ExtractRgb(pS, xSource++);

			pD[0] = TUint8(pixelColor.Blue());
			pD[1] = TUint8(pixelColor.Green());
			pD[2] = TUint8(pixelColor.Red());

			}
		pS += dS;
		}

	RRegion region;
	region.AddRect(orientedRect);
	window->Update(region,orientedSize);
	region.Close();
	}

#endif

//
// End Update - Commit changes to the Frame Buffer
//
void CGenericDirectScreenBitmap::EndUpdate(TRequestStatus& aComplete)
	{
	__ASSERT_ALWAYS(iCreated, Panic(EPanicNotCreated));

	TUint8* pS = iBitmapInfo.iAddress;
	const TUint dS = iBitmapInfo.iLinePitch;
	
#ifdef __WINS__

	WinsUpdate(iUpdateRect);

#else
	TUint8* pD = (TUint8*)iVideoAddress;
	const TUint dD = iDisplayOffsetLines;
#ifdef SYMBIAN_GRAPHICS_GCE
	if (iDsaBufferIsBusy)
		{
		User::WaitForRequest(iDsaBufferAvailable);
		__ASSERT_DEBUG(iDsaBufferAvailable != KRequestPending, Panic(EPanicIncompleteRequest));
		iDsaBufferIsBusy=EFalse;
		}
#endif	
	for(TInt y=iUpdateRect.Height(); y>0; y--)
		{
		Mem::Move((void *)pD, (void *)pS, dS);
		pS += dS;
		pD += dD;
		}
#endif
	
#ifdef SYMBIAN_GRAPHICS_GCE
	iDsaBufferIsBusy=ETrue;
	iSurfaceUpdater.UpdateRegion(iUpdateRect);
	iDsaBufferAvailable = KRequestPending;
	iSurfaceUpdater.NotifyWhenAvailable(iDsaBufferAvailable);
	iSurfaceUpdater.Update();
#endif
	// In the generic implementation, complete the request immediately to allow the client
    // to render to the back buffer
	TRequestStatus* pComplete=&aComplete;

    User::RequestComplete(pComplete,KErrNone);
 	}

//
// End Update - Commit changes within the given area to the Frame Buffer
//
void CGenericDirectScreenBitmap::EndUpdate(const TRect& aScreenRect, TRequestStatus& aComplete)
	{
	__ASSERT_ALWAYS(iCreated, Panic(EPanicNotCreated));

	__ASSERT_ALWAYS(aScreenRect.iTl.iX >= iUpdateRect.iTl.iX &&
					aScreenRect.iTl.iY >= iUpdateRect.iTl.iY &&
					aScreenRect.iBr.iX <= iUpdateRect.iBr.iX &&
					aScreenRect.iBr.iY <= iUpdateRect.iBr.iY, Panic(EPanicOutOfBounds));

	__ASSERT_ALWAYS(aScreenRect.Width() > 0 &&
					aScreenRect.Height() > 0, Panic(EPanicInvalidRect));

	// We can only use this functionality in Incremental Update mode
	__ASSERT_ALWAYS(iSettingsFlags == CDirectScreenBitmap::EIncrementalUpdate, Panic(EPanicInvalidMode));

	const TUint offY = aScreenRect.iTl.iY - iUpdateRect.iTl.iY;

	const TUint dS = iBitmapInfo.iLinePitch;

#ifdef __WINS__

	WinsUpdate(aScreenRect);

#else
	
	TInt xLeft  = aScreenRect.iTl.iX*iBytesPerPixel;
	TInt xRight = aScreenRect.iBr.iX*iBytesPerPixel;

	// We have already tested the limits against iUpdateRect, which is
	// word aligned, so we are safe to perform a round up/down here
	// without fear of overrunning the buffer.

	xLeft &= ~0x03;
	xRight = (xRight+0x03)&~0x03;

	const TUint offX = xLeft - iUpdateRect.iTl.iX*iBytesPerPixel;

	const TUint bytesToCopy = xRight-xLeft;

	const TUint dD = iDisplayOffsetLines;

	TUint8* pS = iBitmapInfo.iAddress + offX + (offY*dS);
	TUint8* pD = (TUint8*)iVideoAddress + offX + (offY*dD);

#ifdef SYMBIAN_GRAPHICS_GCE
	if (iDsaBufferIsBusy)
		{
		User::WaitForRequest(iDsaBufferAvailable);
		__ASSERT_DEBUG(iDsaBufferAvailable != KRequestPending, Panic(EPanicIncompleteRequest));
		iDsaBufferIsBusy=EFalse;
		}
#endif	
	
	for(TInt y=aScreenRect.Height(); y>0; y--)
		{
		Mem::Move((void *)pD, (void *)pS, bytesToCopy);
		pS += dS;
		pD += dD;
		}
#endif

#ifdef SYMBIAN_GRAPHICS_GCE
	iDsaBufferIsBusy=ETrue;
	iSurfaceUpdater.UpdateRegion(iUpdateRect);
	iDsaBufferAvailable = KRequestPending;
	iSurfaceUpdater.NotifyWhenAvailable(iDsaBufferAvailable);
	iSurfaceUpdater.Update();
#endif	
	// In the generic implementation, complete the request immediately.
	TRequestStatus* pComplete=&aComplete;

	User::RequestComplete(pComplete,KErrNone);
	}

#ifdef __WINS__
//
// Extracts the RGB value of the specidied pixel from the buffer
//
TRgb CGenericDirectScreenBitmap::ExtractRgb(TUint8* aBuffer,TInt aPixelOffset) const
	{
	switch (iBitmapInfo.iDisplayMode)
		{
	case EGray2:
		{
		TUint8 byte = *(aBuffer + (aPixelOffset >> 3));
		if (byte & (1 << (aPixelOffset & 7)))
			return KRgbWhite;
		return KRgbBlack;
		}
	case EGray4:
		{
		TUint8 byte = *(aBuffer + (aPixelOffset >> 2));
		byte >>= ((aPixelOffset & 3) << 1);
		return TRgb::_Gray4(byte & 3);
		}
	case EGray16:
		{
		TUint8 byte = *(aBuffer + (aPixelOffset >> 1));
		if (aPixelOffset & 1)
			byte >>= 4;
		return TRgb::_Gray16(byte & 0xf);
		}
	case EGray256:
		return TRgb::_Gray256(*(aBuffer + aPixelOffset));
	case EColor16:
		{
		TUint8 byte = *(aBuffer + (aPixelOffset >> 1));
		if (aPixelOffset & 1)
			byte >>= 4;
		return TRgb::Color16(byte & 0xf);
		}
	case EColor256:
		return TRgb::Color256(*(aBuffer + aPixelOffset));
	case EColor4K:
		{
		TUint16 doubleByte = *(((TUint16*)aBuffer) + aPixelOffset);
		return TRgb::_Color4K(doubleByte & 0xfff);
		}
	case EColor64K:
		{
		TUint16 doubleByte = *(((TUint16*)aBuffer) + aPixelOffset);
		return TRgb::_Color64K(doubleByte);
		}
	case EColor16M:
		{
		aBuffer += aPixelOffset * 3;
		TInt value = *aBuffer++;
		value |= *aBuffer++ << 8;
		value |= *aBuffer << 16;
		return TRgb::_Color16M(value);
		}
	case ERgb:
		return *(((TRgb*)aBuffer) + aPixelOffset);
	case EColor16MU:
		{
		aBuffer += aPixelOffset * 4;
		TInt value = *aBuffer++;
		value |= *aBuffer++ << 8;
		value |= *aBuffer << 16;
		return TRgb::_Color16MU(value);
		}
	case EColor16MA:
		{
		aBuffer += aPixelOffset * 4;
		TInt value = *aBuffer++;
		value |= *aBuffer++ << 8;
		value |= *aBuffer++ << 16;
		value |= *aBuffer << 24;
		return TRgb::_Color16MA(value);
		}
	case EColor16MAP:
		{
		aBuffer += aPixelOffset * 4;
		TInt value = *aBuffer++;
		value |= *aBuffer++ << 8;
		value |= *aBuffer++ << 16;
		value |= *aBuffer << 24;
		return TRgb::_Color16MAP(value);
		}	
	default:
		break;
		};
	return KRgbBlack;
	}
#endif

//
// Close - Deallocate resources and cancel outstanding updates
//
void CGenericDirectScreenBitmap::Close()
	{
	if(iCreated)
		{
		User::Free(iBitmapInfo.iAddress);
		iBitmapInfo.iAddress = NULL;
		iCreated = EFalse;
		}
	if (iHasChunk)
		{
		iChunk.Close();
		}
	}

//
// Panic the user if a serious error occurs
//
void CGenericDirectScreenBitmap::Panic(TDsbPanic aPanic)
	{
	_LIT( KPanicString, "CGenericDirectScreenBitmap" );
	User::Panic( KPanicString, aPanic );
	}