Browse Source

Working OS cursor in DX11
Fixed an important texture data locking issue with row/slice pitch

Marko Pintera 12 years ago
parent
commit
b0b6182dab

+ 10 - 2
CamelotClient/CamelotClient.cpp

@@ -64,7 +64,7 @@ int CALLBACK WinMain(
 	//CommandQueue::addBreakpoint(0, 12);
 
 	RenderSystem* renderSystem = RenderSystem::instancePtr();
-	RenderWindowPtr renderWindow = gApplication().getPrimaryRenderWindow();
+	RenderWindowPtr renderWindow = gApplication().getPrimaryWindow();
 
 	HSceneObject cameraGO = SceneObject::create("MainCamera");
 	HCamera camera = cameraGO->addComponent<Camera>();
@@ -273,7 +273,15 @@ int CALLBACK WinMain(
 	//// Set the new state for the flag
 	//_CrtSetDbgFlag( tmpFlag );
 	Cursor::hide();
-	
+
+	HTexture dbgCursor = static_resource_cast<Texture>(Importer::instance().import("C:\\CursorDbg.psd"));
+	PixelDataPtr cursorPixelData = dbgCursor->allocateSubresourceBuffer(0);
+
+	gMainSyncedRC().readSubresource(dbgCursor.getInternalPtr(), 0, *cursorPixelData);
+	gMainSyncedRC().submitToGpu(true);
+
+	Cursor::setCustomCursor(*cursorPixelData, Int2(0, 0));
+
 	EditorWindow* newWindow = new EditorWindow("Test window");
 
 	gBansheeApp().runMainLoop();

+ 1 - 1
CamelotClient/CmEditorWindow.cpp

@@ -26,7 +26,7 @@ namespace BansheeEditor
 		renderWindowDesc.border = WindowBorder::None;
 		renderWindowDesc.toolWindow = true;
 
-		mRenderWindow = RenderWindow::create(renderWindowDesc, gApplication().getPrimaryRenderWindow());
+		mRenderWindow = RenderWindow::create(renderWindowDesc, gApplication().getPrimaryWindow());
 
 		HSceneObject so = SceneObject::create("EditorWindow-" + name);
 		HGUIWidget gui = so->addComponent<GUIWidget>();

+ 2 - 2
CamelotCore/Include/CmApplication.h

@@ -61,7 +61,7 @@ namespace CamelotFramework
 
 			UINT64 getAppWindowId();
 
-			RenderWindowPtr getPrimaryRenderWindow() const { return mPrimaryRenderWindow; }
+			RenderWindowPtr getPrimaryWindow() const { return mPrimaryWindow; }
 
 			/**
 			 * @brief	Loads a plugin.
@@ -74,7 +74,7 @@ namespace CamelotFramework
 		friend CM_EXPORT RenderContext& gMainRC();
 		friend CM_EXPORT SyncedRenderContext& gMainSyncedRC();
 
-		RenderWindowPtr mPrimaryRenderWindow;
+		RenderWindowPtr mPrimaryWindow;
 		RenderContextPtr mPrimaryRenderContext;
 		SyncedRenderContext* mPrimarySyncedRenderContext;
 

+ 14 - 0
CamelotCore/Include/CmCursor.h

@@ -2,6 +2,20 @@
 
 #include "CmPrerequisites.h"
 
+enum class CursorType
+{
+	Arrow,
+	Wait,
+	IBeam,
+	Help,
+	Hand,
+	SizeAll,
+	SizeNESW,
+	SizeNS,
+	SizeNWSE,
+	SizeWE
+};
+
 //Bring in the specific platform's header file
 #if CM_PLATFORM == CM_PLATFORM_WIN32
 # include "Win32/CmCursorImpl.h"

+ 2 - 2
CamelotCore/Include/CmPixelData.h

@@ -215,14 +215,14 @@ namespace CamelotFramework
          * is only valid for cubemaps and volume textures. This uses the first (largest)
          * mipmap.
          */
-        Color getColourAt(UINT32 x, UINT32 y, UINT32 z);
+        Color getColorAt(UINT32 x, UINT32 y, UINT32 z = 0);
 
         /**
          * Set colour value at a certain location in the PixelBox. The z coordinate
          * is only valid for cubemaps and volume textures. This uses the first (largest)
          * mipmap.
          */
-        void setColourAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z);
+        void setColorAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z = 0);
 
 	private:
 		Box mExtents;

+ 2 - 1
CamelotCore/Include/CmWindowEventUtilities.h

@@ -40,7 +40,8 @@ THE SOFTWARE.
 #  include <Carbon/Carbon.h>
 #endif
 
-
+#define WM_CM_HIDECURSOR WM_USER + 101
+#define WM_CM_SHOWCURSOR WM_USER + 102
 
 namespace CamelotFramework
 {

+ 16 - 0
CamelotCore/Include/Win32/CmCursorImpl.h

@@ -2,6 +2,7 @@
 
 #include "CmPrerequisites.h"
 #include "CmInt2.h"
+#include "CmRect.h"
 #include <windows.h>
 
 namespace CamelotFramework
@@ -18,7 +19,22 @@ namespace CamelotFramework
 		static Int2 getWindowPosition(RenderWindow& window);
 		static void setWindowPosition(RenderWindow& window, const Int2& pos);
 
+		static void clipToWindow(RenderWindow& window);
+		static void clipToRect(const Rect& screenRect);
+		static void clipDisable();
+
 		static void hide();
 		static void show();
+
+		static bool isHidden() { return mIsHidden; }
+		
+		static void setCursor(CursorType type);
+		static void setCustomCursor(PixelData& pixelData, const Int2& hotSpot);
+		static HCURSOR getHCursor() { return mCursor; }
+
+	private:
+		static bool mIsHidden;
+		static HCURSOR mCursor;
+		static bool mUsingCustom;
 	};
 }

+ 9 - 6
CamelotCore/Source/CmApplication.cpp

@@ -30,13 +30,14 @@
 #include "CmShader.h"
 #include "CmTechnique.h"
 #include "CmPass.h"
+#include "CmCursor.h"
 
 #include "CmRendererManager.h"
 
 namespace CamelotFramework
 {
 	Application::Application()
-		:mPrimaryRenderWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false)
+		:mPrimaryWindow(nullptr), mIsFrameRenderingFinished(true), mRunMainLoop(false)
 	{ }
 
 	void Application::startUp(START_UP_DESC& desc)
@@ -49,7 +50,7 @@ namespace CamelotFramework
 		HighLevelGpuProgramManager::startUp(CM_NEW(HighLevelGpuProgramManager, GenAlloc) HighLevelGpuProgramManager());
 
 		RenderSystemManager::startUp(CM_NEW(RenderSystemManager, GenAlloc) RenderSystemManager());
-		mPrimaryRenderWindow = RenderSystemManager::instance().initialize(desc.renderSystem, desc.primaryWindowDesc);
+		mPrimaryWindow = RenderSystemManager::instance().initialize(desc.renderSystem, desc.primaryWindowDesc);
 
 		RendererManager::startUp(CM_NEW(RendererManager, GenAlloc) RendererManager());
 
@@ -73,6 +74,8 @@ namespace CamelotFramework
 			loadPlugin(importerName);
 
 		loadPlugin(desc.input);
+
+		Cursor::setCursor(CursorType::Arrow);
 	}
 
 	void Application::runMainLoop()
@@ -134,8 +137,8 @@ namespace CamelotFramework
 
 	void Application::shutDown()
 	{
-		mPrimaryRenderWindow->destroy();
-		mPrimaryRenderWindow = nullptr;
+		mPrimaryWindow->destroy();
+		mPrimaryWindow = nullptr;
 
 		Importer::shutDown();
 		FontManager::shutDown();
@@ -188,13 +191,13 @@ namespace CamelotFramework
 
 	UINT64 Application::getAppWindowId()
 	{
-		if(!mPrimaryRenderWindow)
+		if(!mPrimaryWindow)
 		{
 			CM_EXCEPT(InternalErrorException, "Unable to get window handle. No active window exists!");
 		}
 
 		UINT64 windowId = 0;
-		mPrimaryRenderWindow->getCustomAttribute("WINDOW", &windowId);
+		mPrimaryWindow->getCustomAttribute("WINDOW", &windowId);
 
 		return windowId;
 	}

+ 2 - 2
CamelotCore/Source/CmPixelUtil.cpp

@@ -1490,7 +1490,7 @@ namespace CamelotFramework {
 		}
 	}
 
-    Color PixelData::getColourAt(UINT32 x, UINT32 y, UINT32 z)
+    Color PixelData::getColorAt(UINT32 x, UINT32 y, UINT32 z)
     {
         Color cv;
 
@@ -1501,7 +1501,7 @@ namespace CamelotFramework {
         return cv;
     }
 
-    void PixelData::setColourAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z)
+    void PixelData::setColorAt(Color const &cv, UINT32 x, UINT32 y, UINT32 z)
     {
         UINT32 pixelSize = PixelUtil::getNumElemBytes(mFormat);
         UINT32 pixelOffset = pixelSize * (z * mSlicePitch + y * mRowPitch + x);

+ 2 - 2
CamelotCore/Source/CmVertexDeclaration.cpp

@@ -159,12 +159,12 @@ namespace CamelotFramework
 		default:
 #endif
 		case VET_COLOR_ARGB:
-			return src.getAsARGB();
+			return src.getAsBGRA();
 #if CM_PLATFORM != CM_PLATFORM_WIN32
 		default:
 #endif
 		case VET_COLOR_ABGR: 
-			return src.getAsABGR();
+			return src.getAsRGBA();
 		};
 
 	}

+ 7 - 3
CamelotCore/Source/CmWindowEventUtilities.cpp

@@ -29,6 +29,8 @@ THE SOFTWARE.
 #include "CmRenderWindow.h"
 #include "CmApplication.h"
 #include "CmException.h"
+#include "CmCursor.h"
+
 #if CM_PLATFORM == CM_PLATFORM_LINUX
 #include <X11/Xlib.h>
 void GLXProc( CamelotFramework::RenderWindow *win, const XEvent &event );
@@ -225,9 +227,11 @@ LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wPa
 			(index->second)->windowResized(win);
 		break;
 	case WM_SETCURSOR:
-		 //SetCursor(0);
-		 //ShowCursor(FALSE);
-		 break;
+		if(Cursor::isHidden())
+			SetCursor(0);
+		else
+			SetCursor(Cursor::getHCursor());
+		return true;
 	case WM_GETMINMAXINFO:
 		// Prevent the window from going smaller than some minimu size
 		((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;

+ 243 - 22
CamelotCore/Source/Win32/CmCursorImpl.cpp

@@ -1,8 +1,15 @@
-#include "Win32/CmCursorImpl.h"
+#include "CmCursor.h"
 #include "CmRenderWindow.h"
+#include "CmWindowEventUtilities.h"
+#include "CmPixelUtil.h"
+#include "CmApplication.h"
 
 namespace CamelotFramework
 {
+	bool Cursor::mIsHidden = false;
+	HCURSOR Cursor::mCursor;
+	bool Cursor::mUsingCustom = false;
+
 	Int2 Cursor::getWindowPosition(RenderWindow& window)
 	{
 		POINT screenPos;
@@ -32,7 +39,7 @@ namespace CamelotFramework
 		SetCursorPos(screenPos.x, screenPos.y);
 	}
 
-	static Int2 getScreenPosition()
+	Int2 Cursor::getScreenPosition()
 	{
 		POINT screenPos;
 		GetCursorPos(&screenPos);
@@ -40,11 +47,10 @@ namespace CamelotFramework
 		return Int2(screenPos.x, screenPos.y);
 	}
 
-	static void setScreenPosition(const Int2& pos)
+	void Cursor::setScreenPosition(const Int2& pos)
 	{
 		POINT screenPos;
 
-		// Convert client coordinates to screen coordinates
 		screenPos.x = pos.x;
 		screenPos.y = pos.y;
 
@@ -53,33 +59,248 @@ namespace CamelotFramework
 
 	void Cursor::hide()
 	{
+		mIsHidden = true;
+
+		// ShowCursor(FALSE) doesn't work. Presumably because we're in the wrong thread, and using
+		// WM_SETCURSOR in message loop to hide the cursor is smarter solution anyway.
+
+		RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
+		HWND hwnd;
+		primaryWindow->getCustomAttribute("WINDOW", &hwnd);
+
+		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+	}
+
+	void Cursor::show()
+	{
+		mIsHidden = false;
+
+		// ShowCursor(FALSE) doesn't work. Presumably because we're in the wrong thread, and using
+		// WM_SETCURSOR in message loop to hide the cursor is smarter solution anyway.
+
+		RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
+		HWND hwnd;
+		primaryWindow->getCustomAttribute("WINDOW", &hwnd);
+
+		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+	}
+
+	void Cursor::clipToWindow(RenderWindow& window)
+	{
+		HWND hwnd;
+		window.getCustomAttribute("WINDOW", &hwnd);
+
+		// Clip cursor to the window
 		RECT clipWindowRect;
+		if(GetWindowRect(hwnd, &clipWindowRect))
+		{
+			ClipCursor(&clipWindowRect);
+		}
+	}
 
-		ShowCursor(FALSE);
-		SetCursor(0);
+	void Cursor::clipToRect(const Rect& screenRect)
+	{
+		RECT clipWindowRect;
+		clipWindowRect.left = screenRect.x;
+		clipWindowRect.top = screenRect.y;
+		clipWindowRect.right = screenRect.x + screenRect.width;
+		clipWindowRect.bottom = screenRect.y + screenRect.height;
 
-		//RenderWindowPtr primaryWindow = gApplication().getPrimaryRenderWindow();
-		//HWND hwnd;
-		//primaryWindow->getCustomAttribute("WINDOW", &hwnd);
+		ClipCursor(&clipWindowRect);
+	}
 
-		//// Clip cursor to the window
-		//if( GetWindowRect(hwnd, &clipWindowRect))
-		//{
-		//	ClipCursor(&clipWindowRect);
-		//}
+	void Cursor::clipDisable()
+	{
+		ClipCursor(NULL);
+	}
+
+	void Cursor::setCursor(CursorType type)
+	{
+		if(mUsingCustom)
+		{
+			SetCursor(0);
+			DestroyIcon(mCursor);
+			mUsingCustom = false;
+		}
+
+		switch(type)
+		{
+		case CursorType::Arrow:
+			mCursor = LoadCursor(0, IDC_ARROW);
+			break;
+		case CursorType::Wait:
+			mCursor = LoadCursor(0, IDC_WAIT);
+			break;
+		case CursorType::IBeam:
+			mCursor = LoadCursor(0, IDC_IBEAM);
+			break;
+		case CursorType::Help:
+			mCursor = LoadCursor(0, IDC_HELP);
+			break;
+		case CursorType::Hand:
+			mCursor = LoadCursor(0, IDC_HAND);
+			break;
+		case CursorType::SizeAll:
+			mCursor = LoadCursor(0, IDC_SIZEALL);
+			break;
+		case CursorType::SizeNESW:
+			mCursor = LoadCursor(0, IDC_SIZENESW);
+			break;
+		case CursorType::SizeNS:
+			mCursor = LoadCursor(0, IDC_SIZENS);
+			break;
+		case CursorType::SizeNWSE:
+			mCursor = LoadCursor(0, IDC_SIZENWSE);
+			break;
+		case CursorType::SizeWE:
+			mCursor = LoadCursor(0, IDC_SIZEWE);
+			break;
+		}
+
+		// Make sure we notify the message loop to perform the actual cursor update
+		RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
+		HWND hwnd;
+		primaryWindow->getCustomAttribute("WINDOW", &hwnd);
 
-		//// Capture cursor to user window
-		//SetCapture(hwnd);
+		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
 	}
 
-	void Cursor::show()
+	// TODO - Add support for animated custom cursor
+	void Cursor::setCustomCursor(PixelData& pixelData, const Int2& hotSpot)
 	{
-		//// Un-capture cursor
-		//ReleaseCapture();
+		if(mUsingCustom)
+		{
+			SetCursor(0);
+			DestroyIcon(mCursor);
+		}
+
+		mUsingCustom = true;
+
+		BITMAPV5HEADER bi;
+
+		ZeroMemory(&bi,sizeof(BITMAPV5HEADER));
+		bi.bV5Size = sizeof(BITMAPV5HEADER);
+		bi.bV5Width = pixelData.getWidth();
+		bi.bV5Height = pixelData.getHeight();
+		bi.bV5Planes = 1;
+		bi.bV5BitCount = 32;
+		bi.bV5Compression = BI_BITFIELDS;
+		bi.bV5RedMask   =  0x00FF0000;
+		bi.bV5GreenMask =  0x0000FF00;
+		bi.bV5BlueMask  =  0x000000FF;
+		bi.bV5AlphaMask =  0xFF000000; 
+
+		HDC hDC = GetDC(NULL);
+
+		void* data = nullptr;
+		HBITMAP hBitmap = CreateDIBSection(hDC, (BITMAPINFO *)&bi, DIB_RGB_COLORS, 
+			(void**)&data, NULL, (DWORD)0);
+
+		HDC hBitmapDC = CreateCompatibleDC(hDC); 
+		ReleaseDC(NULL, hDC);
+
+		// Create an empty mask bitmap.
+		HBITMAP hMonoBitmap = CreateBitmap(pixelData.getWidth(), pixelData.getHeight(), 1, 1, NULL);
+
+		//Select the bitmaps to DC
+		HBITMAP hOldBitmap  = (HBITMAP)SelectObject(hBitmapDC, hBitmap);
+
+		//Scan each pixel of the source bitmap and create the masks
+		Color pixel;
+		DWORD *dst = (DWORD*)data;
+		for(UINT32 y = 0; y < pixelData.getHeight(); ++y)
+		{
+			for(UINT32 x = 0; x < pixelData.getWidth(); ++x)
+			{
+				pixel = pixelData.getColorAt(x, pixelData.getHeight() - y - 1);
+				*dst = pixel.getAsBGRA();
+
+				dst++;
+			}
+		}
+
+		SelectObject(hBitmapDC, hOldBitmap);
+
+		DeleteDC(hBitmapDC);
+
+		ICONINFO iconinfo = {0};
+		iconinfo.fIcon = FALSE;
+		iconinfo.xHotspot = (DWORD)hotSpot.x;
+		iconinfo.yHotspot = (DWORD)hotSpot.y;
+		iconinfo.hbmMask = hMonoBitmap;
+		iconinfo.hbmColor = hBitmap;
+
+		mCursor = CreateIconIndirect(&iconinfo);
+
+		DeleteObject(hBitmap);          
+		DeleteObject(hMonoBitmap);
+
+		// Make sure we notify the message loop to perform the actual cursor update
+		RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
+		HWND hwnd;
+		primaryWindow->getCustomAttribute("WINDOW", &hwnd);
+
+		PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
+
+
+		//HDC hDC = GetDC(NULL);
+		//HDC hAndMaskDC = CreateCompatibleDC(hDC); 
+		//HDC hXorMaskDC = CreateCompatibleDC(hDC); 
+
+		////Get the dimensions of the source bitmap
+		//HBITMAP hAndMaskBitmap  = CreateCompatibleBitmap(hDC, pixelData.getWidth(), pixelData.getHeight());
+		//HBITMAP hXorMaskBitmap  = CreateCompatibleBitmap(hDC, pixelData.getWidth(), pixelData.getHeight());
 
-		//// Release the cursor from the window
-		//ClipCursor(NULL);
+		////Select the bitmaps to DC
+		//HBITMAP hOldAndMaskBitmap  = (HBITMAP)SelectObject(hAndMaskDC, hAndMaskBitmap);
+		//HBITMAP hOldXorMaskBitmap  = (HBITMAP)SelectObject(hXorMaskDC, hXorMaskBitmap);
+
+		////Scan each pixel of the souce bitmap and create the masks
+		//Color pixel;
+		//for(UINT32 x = 0; x < pixelData.getWidth(); ++x)
+		//{
+		//	for(UINT32 y = 0; y < pixelData.getHeight(); ++y)
+		//	{
+		//		pixel = pixelData.getColorAt(x, y);
+		//		DWORD pixel32 = pixel.getAsRGBA();
+
+		//		if(pixel.a < 1.0f)
+		//		{
+		//			SetPixel(hAndMaskDC, x, y, RGB(255,255,255));
+		//			/*SetPixel(hXorMaskDC, x, y, RGB(pixel32 & 0xFF, (pixel32 >> 8) & 0xFF, (pixel32 >> 16) & 0xFF));*/
+		//			SetPixel(hXorMaskDC, x, y, RGB(255,255,255));
+		//		}
+		//		else
+		//		{
+		//			SetPixel(hAndMaskDC, x, y, RGB(0,0,0));
+		//			//SetPixel(hXorMaskDC, x, y, RGB(pixel32 & 0xFF, (pixel32 >> 8) & 0xFF, (pixel32 >> 16) & 0xFF));
+		//			SetPixel(hXorMaskDC, x, y, RGB(255,255,255));
+		//		}
+		//	}
+		//}
+
+		//SelectObject(hAndMaskDC, hOldAndMaskBitmap);
+		//SelectObject(hXorMaskDC, hOldXorMaskBitmap);
+
+		//DeleteDC(hXorMaskDC);
+		//DeleteDC(hAndMaskDC);
+
+		//ReleaseDC(NULL, hDC);
+
+		//ICONINFO iconinfo = {0};
+		//iconinfo.fIcon = FALSE;
+		//iconinfo.xHotspot = (DWORD)hotSpot.x;
+		//iconinfo.yHotspot = (DWORD)hotSpot.y;
+		//iconinfo.hbmMask = hAndMaskBitmap;
+		//iconinfo.hbmColor = hXorMaskBitmap;
+
+		//mCursor = CreateIconIndirect(&iconinfo);
+
+		//// Make sure we notify the message loop to perform the actual cursor update
+		//RenderWindowPtr primaryWindow = gApplication().getPrimaryWindow();
+		//HWND hwnd;
+		//primaryWindow->getCustomAttribute("WINDOW", &hwnd);
 
-		//ShowCursor(TRUE);
+		//PostMessage(hwnd, WM_SETCURSOR, WPARAM(hwnd), (LPARAM)MAKELONG(HTCLIENT, WM_MOUSEMOVE));
 	}
 }

+ 2 - 2
CamelotD3D11RenderSystem/Include/CmD3D11Texture.h

@@ -59,10 +59,10 @@ namespace CamelotFramework
 
 		void _createStagingBuffer();
 
-		void* _map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face);
+		void* _map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
 		void _unmap(ID3D11Resource* res);
 
-		void* _mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face);
+		void* _mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
 		void _unmapstagingbuffer();
 		
 		void* _mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 slice);

+ 19 - 5
CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp

@@ -59,15 +59,25 @@ namespace CamelotFramework
 
 		D3D11_MAP flags = D3D11Mappings::getLockOptions(options);
 
+		UINT32 rowPitch, slicePitch;
+
 		if(flags == D3D11_MAP_READ || flags == D3D11_MAP_READ_WRITE)
 		{
-			lockedArea.setExternalBuffer((UINT8*)_mapstagingbuffer(flags, face, mipLevel));
+			UINT8* data = (UINT8*)_mapstagingbuffer(flags, face, mipLevel, rowPitch, slicePitch);
+			lockedArea.setExternalBuffer(data);
+			lockedArea.setRowPitch(rowPitch);
+			lockedArea.setSlicePitch(slicePitch);
 			mLockedForReading = true;
 		}
 		else
 		{
 			if(mUsage == TU_DYNAMIC)
-				lockedArea.setExternalBuffer((UINT8*)_map(mTex, flags, face, mipLevel));
+			{
+				UINT8* data = (UINT8*)_map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
+				lockedArea.setExternalBuffer(data);
+				lockedArea.setRowPitch(rowPitch);
+				lockedArea.setSlicePitch(slicePitch);
+			}
 			else
 				lockedArea.setExternalBuffer((UINT8*)_mapstaticbuffer(lockedArea, mipLevel, face));
 
@@ -457,7 +467,7 @@ namespace CamelotFramework
 		}
 	}
 
-	void* D3D11Texture::_map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face)
+	void* D3D11Texture::_map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 		D3D11_MAPPED_SUBRESOURCE pMappedResource;
 		pMappedResource.pData = nullptr;
@@ -480,6 +490,10 @@ namespace CamelotFramework
 			CM_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
 		}
 
+		UINT32 bytesPerPixel = PixelUtil::getNumElemBytes(getFormat());
+		rowPitch = pMappedResource.RowPitch / bytesPerPixel;
+		slicePitch = pMappedResource.DepthPitch / bytesPerPixel;
+
 		return pMappedResource.pData;
 	}
 
@@ -496,7 +510,7 @@ namespace CamelotFramework
 		}
 	}
 
-	void* D3D11Texture::_mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face)
+	void* D3D11Texture::_mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 		if(!mStagingBuffer)
 			_createStagingBuffer();
@@ -505,7 +519,7 @@ namespace CamelotFramework
 		D3D11Device& device = rs->getPrimaryDevice();
 		device.getImmediateContext()->CopyResource(mStagingBuffer, mTex);
 
-		return _map(mStagingBuffer, flags, face, mipLevel);
+		return _map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
 	}
 
 	void D3D11Texture::_unmapstagingbuffer()

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -707,7 +707,7 @@ namespace CamelotFramework
 		THROW_IF_NOT_RENDER_THREAD;
 
 		HRESULT hr;
-		if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsARGB()) ) )
+		if( FAILED( hr = __SetSamplerState( static_cast<DWORD>(stage), D3DSAMP_BORDERCOLOR, colour.getAsBGRA()) ) )
 			CM_EXCEPT(RenderingAPIException, "Failed to set texture border colour");
 	}
 	//---------------------------------------------------------------------
@@ -1404,7 +1404,7 @@ namespace CamelotFramework
 			0, 
 			NULL, 
 			flags,
-			colour.getAsARGB(), 
+			colour.getAsBGRA(), 
 			depth, 
 			stencil ) ) )
 		{

+ 0 - 32
CamelotUtility/Source/CmColor.cpp

@@ -39,11 +39,7 @@ namespace CamelotFramework {
     const Color Color::Blue = Color(0.0,0.0,1.0);
 
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     ABGR Color::getAsABGR(void) const
-#else
-    RGBA Color::getAsRGBA(void) const
-#endif
     {
         UINT8 val8;
         UINT32 val32 = 0;
@@ -70,11 +66,7 @@ namespace CamelotFramework {
         return val32;
     }
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     BGRA Color::getAsBGRA(void) const
-#else
-    ARGB Color::getAsARGB(void) const
-#endif
     {
         UINT8 val8;
         UINT32 val32 = 0;
@@ -102,11 +94,7 @@ namespace CamelotFramework {
         return val32;
     }
 	//---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
 	ARGB Color::getAsARGB(void) const
-#else
-	BGRA Color::getAsBGRA(void) const
-#endif
 	{
 		UINT8 val8;
 		UINT32 val32 = 0;
@@ -134,11 +122,7 @@ namespace CamelotFramework {
 		return val32;
 	}
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     RGBA Color::getAsRGBA(void) const
-#else
-    ABGR Color::getAsABGR(void) const
-#endif
     {
         UINT8 val8;
         UINT32 val32 = 0;
@@ -166,11 +150,7 @@ namespace CamelotFramework {
         return val32;
     }
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     void Color::setAsABGR(const ABGR val)
-#else
-    void Color::setAsRGBA(const RGBA val)
-#endif
     {
         UINT32 val32 = val;
 
@@ -190,11 +170,7 @@ namespace CamelotFramework {
         a = (val32 & 0xFF) / 255.0f;
     }
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     void Color::setAsBGRA(const BGRA val)
-#else
-    void Color::setAsARGB(const ARGB val)
-#endif
     {
         UINT32 val32 = val;
 
@@ -214,11 +190,7 @@ namespace CamelotFramework {
         b = (val32 & 0xFF) / 255.0f;
     }
 	//---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
 	void Color::setAsARGB(const ARGB val)
-#else
-	void Color::setAsBGRA(const BGRA val)
-#endif
 	{
 		UINT32 val32 = val;
 
@@ -238,11 +210,7 @@ namespace CamelotFramework {
 		a = (val32 & 0xFF) / 255.0f;
 	}
     //---------------------------------------------------------------------
-#if CM_ENDIAN == CM_ENDIAN_BIG
     void Color::setAsRGBA(const RGBA val)
-#else
-    void Color::setAsABGR(const ABGR val)
-#endif
     {
         UINT32 val32 = val;
 

+ 6 - 0
TODO.txt

@@ -10,6 +10,12 @@ When I'm canceling command queue commands I might be canceling important user co
 
 --------
 
+Avoid updating GUI every frame. Instead remember processed events and only update then.
+I still re-create GUIWidget mesh every frame instead of just updating it.
+Make it so that widgets can be batched together. Probably means GUIWidget::updateMesh methods needs to move up to GUIManager or similar.
+MAJOR ISSUE: writeSubresource/readSubresoure doesn't require a shared ptr to GpuResourceData which means it could get destroyed while still in command queue. Right now it only works because I block right after I call those methods, which ensures nothing is destroyed.
+GUIWidget::updateMeshes leaks. If I leave the game running I can see memory continously going up
+
  - My test model is rendering back faces. I need to flip them.
   - Although more than likely I am loading the model incorrectly since it works in Unity?
   - I probably want to determine front faces based on normals