kerneltest/e32test/video/t_videomemory.cpp
changeset 0 a41df078684a
child 20 597aaf25e343
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/video/t_videomemory.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,279 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Overview:
+// Test the video driver kernel extension that provides chunk handle to access video memory. 
+// API Information:
+// HAL, UserSvr
+// Details:
+// - Check that the "old" GetMemoryAddress function still works, for legacy compatibility.
+// - Check that we can get a chunk and that we can read/write the memory belonging to that chunk. 
+// - Check that asking for a DisplayMemoryHandle twice gives the same piece of memory.  
+// - Test that the same memory is available to a second process, by starting second process and
+// the second process can write to memory. Validate by confirming that the value in the second process 
+// is changed.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+// 
+//
+
+#include <e32test.h>
+#include <videodriver.h>
+#include <hal.h>
+#include <e32svr.h>
+#include <dispchannel.h>
+#include "t_videomemory.h"
+
+LOCAL_D RTest test(_L("T_VIDEOMEMORY"));
+
+#ifndef __WINS__
+#define DUMP(x) test.Printf(_L(#x"= %d =0x%08x\n"), x, x)
+#endif
+
+
+LOCAL_C void RunTestsForScreen(TInt aScreenID)
+	{
+
+	TInt ret = KErrNone;
+
+#ifdef __WINS__
+	RDisplayChannel displayChannel;
+	
+	test.Next(_L("Open Display Driver"));
+	
+    _LIT(KDisplayDriver, "display0");
+    ret = User::LoadLogicalDevice(KDisplayDriver);
+    test(KErrNone == ret || KErrAlreadyExists == ret);
+	
+	ret = displayChannel.Open(aScreenID);
+    test(KErrNone == ret);
+		
+#endif
+
+	test.Next(_L("Checking Display Memory Address"));
+	
+	// This is the real basic form of test:
+	// Get the display memory address from the HAL.
+	// Check that it's not zero - that would be invalid memory.
+	// Try to write to the memory - it should not give a page-fault/crash.
+	// Try to read the memory - we should get the same value as we wrote. 
+	
+	TInt memoryAddress=0;
+	volatile TUint32 *pMemory = 0;
+	ret = HAL::Get(aScreenID, HAL::EDisplayMemoryAddress, memoryAddress);
+	test (KErrNone == ret || KErrNotSupported == ret);
+
+	if (KErrNone == ret)
+		{
+		test.Printf(_L("Display Memory Address = %08x\n"), memoryAddress);
+		// Now check that we can write to memoryAddress:
+		test (memoryAddress != 0);
+		pMemory = reinterpret_cast<TUint32 *>(memoryAddress);
+		*pMemory = KTestValue1;
+		test(KTestValue1 == *pMemory);
+		}
+	else
+		{
+		test.Printf(_L("Memory Address not available from HAL\n"));
+		}
+	
+	// Second basic test. Use the HAL to fetch a handle
+	// to the display memory. 
+	// Check that the handle is not zero. 
+	// Get the base-address of the chunk. 
+	// Write this base address with a new value.
+	// Read with the chunk base address to see that teh new value is there. 
+	// Read the memory address from the above test and check that it changed 
+	// to the new value.
+	// Note that the memory address from above test MAY NOT BE SET - so 
+	// check to see if it's non-zero first.
+		
+	test.Next(_L("Checking Display Handle"));
+	TInt handle = 0;
+	volatile TUint32 *pChunkBase = 0;
+	RChunk chunk;
+	ret = HAL::Get(aScreenID, HALData::EDisplayMemoryHandle, handle);
+	test ((KErrNone == ret || KErrNotSupported == ret));
+	if (KErrNone == ret)
+		{
+		// Handle should not be zero. 
+		test(0 != handle);
+		ret = chunk.SetReturnedHandle(handle);
+		test(KErrNone == ret);
+		
+		pChunkBase = reinterpret_cast<TUint32 *>(chunk.Base());
+		test.Printf(_L("Display Memory Address = %08x\n"), reinterpret_cast<TUint>(pChunkBase));
+		*pChunkBase = KTestValue2;
+		test(KTestValue2 == *pChunkBase);
+		// We should see the new value through the pMemory pointer!
+		if (pMemory)
+			{
+			test(KTestValue2 == *pMemory);
+			}
+	
+		}
+	else
+		{
+		test.Printf(_L("Memory Handle not available from HAL - no point in further testing\n"));
+		return;
+		}
+	
+
+	// Check that we can write to more than the first bit of memory. 
+	test.Next(_L("Check that we can write to \"all\" of the memory"));
+	// First, find the mode with the biggest number of bits per pixel:
+	TInt totalModes;
+	ret = HAL::Get(aScreenID, HAL::EDisplayNumModes, totalModes);
+	test (KErrNone == ret);
+	TInt biggestMode = 0;
+	TInt maxBitsPerPixel = 0;
+	for(TInt mode = 0; mode < totalModes; mode++)
+		{
+		TInt bitsPerPixel = mode;
+		ret = HAL::Get(aScreenID, HAL::EDisplayBitsPerPixel, bitsPerPixel);
+		test (KErrNone == ret);
+		if (bitsPerPixel > maxBitsPerPixel)
+			{
+			maxBitsPerPixel = bitsPerPixel;
+			biggestMode = mode;
+			}
+		}
+	
+	TInt offsetToFirstPixel = biggestMode;
+	ret = HAL::Get(aScreenID, HALData::EDisplayOffsetToFirstPixel, offsetToFirstPixel);
+	test(KErrNone == ret);
+	
+	TInt stride = biggestMode;
+	ret = HAL::Get(aScreenID, HALData::EDisplayOffsetBetweenLines, stride);
+	test(KErrNone == ret);
+	
+	TInt yPixels = biggestMode;
+	ret = HAL::Get(aScreenID, HALData::EDisplayYPixels, yPixels);
+	test(KErrNone == ret);
+	
+	// Note this is no attempt to be precise. xPixels is not 
+	TUint maxByte = offsetToFirstPixel + stride * yPixels - sizeof(TUint32);
+		
+	volatile TUint32 *memPtr = reinterpret_cast<volatile TUint32 *>(reinterpret_cast<volatile TUint8 *>(pChunkBase) + maxByte);
+	*memPtr = KTestValue1;
+	test(KTestValue1 == *memPtr);
+	
+
+	// Ask for a second handle and see that this also points to the same bit of memory.
+	test.Next(_L("Checking Display Handle second time"));
+	volatile TUint32 *pChunkBase2 = 0;
+	ret = HAL::Get(aScreenID, HALData::EDisplayMemoryHandle, handle);
+	test ((KErrNone == ret || KErrNotSupported == ret));
+	if (KErrNone == ret)
+		{
+		// Handle should not be zero!
+		test(0 != handle);
+		RChunk chunk2;
+		ret = chunk2.SetReturnedHandle(handle);
+		test(KErrNone == ret);
+		
+		pChunkBase2 = reinterpret_cast<TUint32 *>(chunk2.Base());
+		test.Printf(_L("Display Memory Address = %08x\n"), reinterpret_cast<TUint>(pChunkBase));
+		test(KTestValue2 == *pChunkBase2);
+		*pChunkBase2 = KTestValue3;
+		test(KTestValue3 == *pChunkBase2);
+		chunk2.Close();
+		}
+	
+	test.Next(_L("Checking Display Handle using second process"));
+	
+	// Create a process, let it find the handle of the memory, then read it, and write it.
+	// Check that the value we have is the new value: KTestValue3.
+	_LIT(KProcName, "t_videomemprocess.exe");
+	RProcess process;
+	
+	ret = process.Create(KProcName, KNullDesC);
+	test(KErrNone == ret);
+	
+	TRequestStatus procStatus;
+	process.Logon(procStatus);
+	process.SetParameter(12, aScreenID);
+	process.Resume();
+	User::WaitForRequest(procStatus);
+	
+	test.Next(_L("Checking that second process updated video memory"));
+	// Check that we got the new value. 
+	test(KTestValue4 == *pChunkBase);
+	
+	chunk.Close();
+	
+#ifdef __WINS__
+	displayChannel.Close();
+#endif
+	
+	// Now for some negative tests: Attempt to get a handle for a closes display.
+	test.Next(_L("Negative test: Check that we CAN NOT use closed screen"));
+	ret = HAL::Get(aScreenID, HALData::EDisplayMemoryHandle, handle);
+	test (KErrNone != ret);
+	}
+
+
+
+LOCAL_C void NegativeTests(TInt aMaxScreens)
+	{
+	TInt handle;
+	TInt ret;
+	// Another few negative tests: Try invalid screen numbers.
+	test.Next(_L("Negative tests: Invalid screen ID's"));
+	ret = HAL::Get(aMaxScreens, HALData::EDisplayMemoryHandle, handle);
+	test (KErrNone != ret);
+	
+	ret = HAL::Get(aMaxScreens+1, HALData::EDisplayMemoryHandle, handle);
+	test (KErrNone != ret);
+	
+	ret = HAL::Get(4718, HALData::EDisplayMemoryHandle, handle);
+	test (KErrNone != ret);
+	
+	ret = HAL::Get(-1, HALData::EDisplayMemoryHandle, handle);
+	test (KErrNone != ret);
+	}
+
+
+
+GLDEF_C TInt E32Main()
+//
+//
+    {
+
+	test.Title();
+//
+#if defined(__EPOC32__) && defined(__CPU_X86)
+	test.Printf(_L("Doesn't run on X86\n"));
+#else
+
+	test.Start(_L("Testing Video Memory HAL interfaces"));
+
+	TInt screens = 0;	
+	TInt ret=HAL::Get(HAL::EDisplayNumberOfScreens, screens);
+	test((KErrNone == ret));
+	// We expect that there is at least ONE screen. 
+	test((screens > 0));
+
+	for(TInt i=0;i<screens;i++)
+		{
+		RunTestsForScreen(i);
+		}
+	
+	NegativeTests(screens);
+#endif
+	
+	return KErrNone;
+}