Add SwiftShader source to repo

Oct 6 code drop from Transgaming
Review URL: https://chromereviews.googleplex.com/3846015
diff --git a/src/Main/FrameBufferDD.cpp b/src/Main/FrameBufferDD.cpp
new file mode 100644
index 0000000..0ec2d79
--- /dev/null
+++ b/src/Main/FrameBufferDD.cpp
@@ -0,0 +1,488 @@
+// SwiftShader Software Renderer
+//
+// Copyright(c) 2005-2011 TransGaming Inc.
+//
+// All rights reserved. No part of this software may be copied, distributed, transmitted,
+// transcribed, stored in a retrieval system, translated into any human or computer
+// language by any means, or disclosed to third parties without the explicit written
+// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
+// or implied, including but not limited to any patent rights, are granted to you.
+//
+
+#include "FrameBufferDD.hpp"
+
+#include "Debug.hpp"
+
+namespace sw
+{
+	extern bool forceWindowed;
+
+	GUID secondaryDisplay = {0};
+
+	int __stdcall enumDisplayCallback(GUID* guid, char *driverDescription, char *driverName, void *context, HMONITOR monitor)
+	{
+		if(strcmp(driverName, "\\\\.\\DISPLAY2") == 0)
+		{
+			secondaryDisplay = *guid;
+		}
+
+		return 1;
+	}
+
+	FrameBufferDD::FrameBufferDD(HWND windowHandle, int width, int height, bool fullscreen) : FrameBuffer(windowHandle, width, height, fullscreen)
+	{
+		directDraw = 0;
+		frontBuffer = 0;
+		backBuffer = 0;
+
+		locked = 0;
+
+		ddraw = LoadLibrary("ddraw.dll");
+		DirectDrawCreate = (DIRECTDRAWCREATE)GetProcAddress(ddraw, "DirectDrawCreate");
+		DirectDrawEnumerateExA = (DIRECTDRAWENUMERATEEXA)GetProcAddress(ddraw, "DirectDrawEnumerateExA");
+
+		if(!windowed)
+		{
+			initFullscreen();
+		}
+		else
+		{
+			initWindowed();
+		}
+	}
+
+	FrameBufferDD::~FrameBufferDD()
+	{
+		releaseAll();
+
+		FreeLibrary(ddraw);
+	}
+
+	void FrameBufferDD::createSurfaces()
+	{
+		if(backBuffer)
+		{
+			backBuffer->Release();
+			backBuffer = 0;
+		}
+
+		if(frontBuffer)
+		{
+			frontBuffer->Release();
+			frontBuffer = 0;
+		}
+
+		if(!windowed)
+		{
+			DDSURFACEDESC surfaceDescription = {0};
+			surfaceDescription.dwSize = sizeof(surfaceDescription);
+			surfaceDescription.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+			surfaceDescription.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+			surfaceDescription.dwBackBufferCount = 1;
+			long result = directDraw->CreateSurface(&surfaceDescription, &frontBuffer, 0);
+
+			if(frontBuffer)
+			{
+				DDSCAPS surfaceCapabilties = {0};
+				surfaceCapabilties.dwCaps = DDSCAPS_BACKBUFFER;
+				frontBuffer->GetAttachedSurface(&surfaceCapabilties, &backBuffer);
+				backBuffer->AddRef();
+			}
+		}
+		else
+		{
+			IDirectDrawClipper *clipper;
+			
+			DDSURFACEDESC ddsd = {0};
+			ddsd.dwSize = sizeof(ddsd);
+			ddsd.dwFlags = DDSD_CAPS;
+			ddsd.ddsCaps.dwCaps	= DDSCAPS_PRIMARYSURFACE;
+
+			long result = directDraw->CreateSurface(&ddsd, &frontBuffer, 0);
+			directDraw->GetDisplayMode(&ddsd);
+			bitDepth = ddsd.ddpfPixelFormat.dwRGBBitCount;
+
+			if((result != DD_OK && result != DDERR_PRIMARYSURFACEALREADYEXISTS) || (bitDepth != 32 && bitDepth != 24 && bitDepth != 16))
+			{
+				gracefulExit("Failed to initialize graphics: incompatible display mode. Aborting application.", result);
+			}
+
+			ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;	   
+			ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+			ddsd.dwWidth = width;
+			ddsd.dwHeight = height;
+
+			directDraw->CreateSurface(&ddsd, &backBuffer, 0);
+
+			directDraw->CreateClipper(0, &clipper, 0);
+			clipper->SetHWnd(0, windowHandle);
+			frontBuffer->SetClipper(clipper);
+			clipper->Release();
+		}
+	}
+
+	bool FrameBufferDD::readySurfaces()
+	{
+		if(!frontBuffer || !backBuffer)
+		{
+			createSurfaces();
+		}
+
+		if(frontBuffer && backBuffer)
+		{
+			if(frontBuffer->IsLost() || backBuffer->IsLost())
+			{
+				restoreSurfaces();
+			}
+
+			if(frontBuffer && backBuffer)
+			{
+				if(!frontBuffer->IsLost() && !backBuffer->IsLost())
+				{
+					return true;
+				}
+			}
+		}
+
+		return false;
+	}
+
+	void FrameBufferDD::updateClipper(HWND windowOverride)
+	{
+		if(windowed)
+		{
+			if(frontBuffer)
+			{
+				HWND window = windowOverride ? windowOverride : windowHandle;
+
+				IDirectDrawClipper *clipper;
+				frontBuffer->GetClipper(&clipper);
+				clipper->SetHWnd(0, window);
+				clipper->Release();
+			}
+		}
+	}
+
+	void FrameBufferDD::restoreSurfaces()
+	{
+		long result1 = frontBuffer->Restore();
+		long result2 = backBuffer->Restore();
+
+		if(result1 != DD_OK || result2 != DD_OK)   // Surfaces could not be restored; recreate them
+		{
+			createSurfaces();
+		}
+	}
+
+	void FrameBufferDD::initFullscreen()
+	{
+		releaseAll();
+
+		if(true)   // Render to primary display
+		{
+			DirectDrawCreate(0, &directDraw, 0);
+		}
+		else   // Render to secondary display
+		{
+			DirectDrawEnumerateEx(&enumDisplayCallback, 0, DDENUM_ATTACHEDSECONDARYDEVICES);
+			DirectDrawCreate(&secondaryDisplay, &directDraw, 0);
+		}
+
+		directDraw->SetCooperativeLevel(windowHandle, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+
+		long result;
+
+		do
+		{
+			bitDepth = 32;
+			result = directDraw->SetDisplayMode(width, height, bitDepth);
+
+			if(result == DDERR_INVALIDMODE)
+			{
+				bitDepth = 16;
+				result = directDraw->SetDisplayMode(width, height, bitDepth);
+
+				if(result == DDERR_INVALIDMODE)
+				{
+					bitDepth = 24;
+					result = directDraw->SetDisplayMode(width, height, bitDepth);
+
+					if(result == DDERR_INVALIDMODE)
+					{
+						gracefulExit("Failed to initialize graphics: display mode unsupported. Aborting application.", result);
+					}
+				}
+			}
+
+			if(result != DD_OK)
+			{
+				Sleep(1);
+			}
+		}
+		while(result != DD_OK);
+
+		createSurfaces();
+
+		updateBounds(windowHandle);
+	}
+
+	void FrameBufferDD::initWindowed()
+	{
+		releaseAll();
+
+		DirectDrawCreate(0, &directDraw, 0);
+		directDraw->SetCooperativeLevel(windowHandle, DDSCL_NORMAL);
+
+		createSurfaces();
+
+		updateBounds(windowHandle);
+	}
+
+	void FrameBufferDD::flip(HWND windowOverride, void *source, bool HDR)
+	{
+		updateClipper(windowOverride);
+
+		copy(windowOverride, source, HDR);
+
+		if(!readySurfaces())
+		{
+			return;
+		}
+
+		while(true)
+		{
+			long result;
+
+			if(windowed)
+			{
+				result = frontBuffer->Blt(&bounds, backBuffer, 0, DDBLT_WAIT, 0);
+			}
+			else
+			{
+				result = frontBuffer->Flip(0, DDFLIP_NOVSYNC);
+			}
+
+			if(result != DDERR_WASSTILLDRAWING)
+			{
+				break;
+			}
+
+			Sleep(0);
+		}
+	}
+
+	void FrameBufferDD::blit(HWND windowOverride, void *source, const Rect *sourceRect, const Rect *destRect, bool HDR)
+	{
+		updateClipper(windowOverride);
+
+		copy(windowOverride, source, HDR);
+
+		if(!readySurfaces())
+		{
+			return;
+		}
+
+		RECT dRect;
+
+		if(destRect)
+		{
+			dRect.bottom = bounds.top + destRect->bottom;
+			dRect.left = bounds.left + destRect->left;
+			dRect.right = bounds.left + destRect->right;
+			dRect.top = bounds.top + destRect->top;
+		}
+		else
+		{
+			dRect.bottom = bounds.top + height;
+			dRect.left = bounds.left + 0;
+			dRect.right = bounds.left + width;
+			dRect.top = bounds.top + 0;
+		}
+
+		while(true)
+		{
+			long result = frontBuffer->Blt(&dRect, backBuffer, (LPRECT)sourceRect, DDBLT_WAIT, 0);
+
+			if(result != DDERR_WASSTILLDRAWING)
+			{
+				break;
+			}
+
+			Sleep(0);
+		}
+	}
+
+	void FrameBufferDD::screenshot(void *destBuffer)
+	{
+		if(!readySurfaces())
+		{
+			return;
+		}
+
+		DDSURFACEDESC DDSD;
+		DDSD.dwSize = sizeof(DDSD);
+
+		long result = frontBuffer->Lock(0, &DDSD, DDLOCK_WAIT, 0);
+
+		if(result == DD_OK)
+		{
+			int width = DDSD.dwWidth;
+			int height = DDSD.dwHeight;
+			int bitDepth = DDSD.ddpfPixelFormat.dwRGBBitCount;
+			int stride = DDSD.lPitch;
+
+			void *sourceBuffer = DDSD.lpSurface;
+
+			for(int y = 0; y < height; y++)
+			{
+				memcpy(destBuffer, sourceBuffer, width * 4);   // FIXME: Assumes 32-bit buffer
+
+				(char*&)sourceBuffer += stride;
+				(char*&)destBuffer += 4 * width;
+			}
+
+			frontBuffer->Unlock(0);
+		}
+	}
+
+	void FrameBufferDD::setGammaRamp(GammaRamp *gammaRamp, bool calibrate)
+	{
+		IDirectDrawGammaControl *gammaControl = 0;
+
+		if(frontBuffer)
+		{
+			frontBuffer->QueryInterface(IID_IDirectDrawGammaControl, (void**)&gammaControl); 
+
+			if(gammaControl)
+			{
+				gammaControl->SetGammaRamp(calibrate ? DDSGR_CALIBRATE : 0, (DDGAMMARAMP*)gammaRamp);
+
+				gammaControl->Release();
+			}
+		}
+	}
+
+	void FrameBufferDD::getGammaRamp(GammaRamp *gammaRamp)
+	{
+		IDirectDrawGammaControl *gammaControl = 0;
+
+		if(frontBuffer)
+		{
+			frontBuffer->QueryInterface(IID_IDirectDrawGammaControl, (void**)&gammaControl); 
+
+			if(gammaControl)
+			{
+				gammaControl->GetGammaRamp(0, (DDGAMMARAMP*)gammaRamp);
+
+				gammaControl->Release();
+			}
+		}
+	}
+
+	void *FrameBufferDD::lock()
+	{
+		if(locked)
+		{
+			return locked;
+		}
+		
+		if(!readySurfaces())
+		{
+			return 0;
+		}
+
+		DDSURFACEDESC DDSD;
+		DDSD.dwSize = sizeof(DDSD);
+
+		long result = backBuffer->Lock(0, &DDSD, DDLOCK_WAIT, 0);
+
+		if(result == DD_OK)
+		{
+			width = DDSD.dwWidth;
+			height = DDSD.dwHeight;
+			int bitDepth = DDSD.ddpfPixelFormat.dwRGBBitCount;
+			stride = DDSD.lPitch;
+
+			locked = DDSD.lpSurface;
+
+			return locked;
+		}
+
+		return 0;
+	}
+
+	void FrameBufferDD::unlock()
+	{
+		if(!locked || !backBuffer) return;
+
+		backBuffer->Unlock(0);
+
+		locked = 0;
+	}
+
+	void FrameBufferDD::drawText(int x, int y, const char *string, ...)
+	{
+		char buffer[256];
+		va_list arglist;
+
+		va_start(arglist, string);
+		vsprintf(buffer, string, arglist);
+		va_end(arglist);
+
+		HDC hdc;
+
+		backBuffer->GetDC(&hdc);
+
+		SetBkColor(hdc, RGB(0, 0, 255));
+		SetTextColor(hdc, RGB(255, 255, 255));
+
+		TextOut(hdc, x, y, buffer, lstrlen(buffer));
+
+		backBuffer->ReleaseDC(hdc);
+	}
+
+	bool FrameBufferDD::getScanline(bool &inVerticalBlank, unsigned int &scanline)
+	{
+		HRESULT result = directDraw->GetScanLine((unsigned long*)&scanline);
+
+		if(result == DD_OK)
+		{
+			inVerticalBlank = false;
+		}
+		else if(result == DDERR_VERTICALBLANKINPROGRESS)
+		{
+			inVerticalBlank = true;
+		}
+		else if(result == DDERR_UNSUPPORTED)
+		{
+			return false;
+		}
+		else ASSERT(false);
+
+		return true;
+	}
+
+	void FrameBufferDD::releaseAll()
+	{
+		unlock();
+
+		if(backBuffer)
+		{
+			backBuffer->Release();
+			backBuffer = 0;
+		}
+
+		if(frontBuffer)
+		{
+			frontBuffer->Release();
+			frontBuffer = 0;
+		}
+
+		if(directDraw)
+		{
+			directDraw->SetCooperativeLevel(0, DDSCL_NORMAL);
+			directDraw->Release();
+			directDraw = 0;
+		}
+	}
+}