| // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #include "Direct3DDevice9.hpp" | 
 |  | 
 | #include "Direct3D9.hpp" | 
 | #include "Direct3DSurface9.hpp" | 
 | #include "Direct3DIndexBuffer9.hpp" | 
 | #include "Direct3DVertexBuffer9.hpp" | 
 | #include "Direct3DTexture9.hpp" | 
 | #include "Direct3DVolumeTexture9.hpp" | 
 | #include "Direct3DCubeTexture9.hpp" | 
 | #include "Direct3DVertexDeclaration9.hpp" | 
 | #include "Direct3DSwapChain9.hpp" | 
 | #include "Direct3DPixelShader9.hpp" | 
 | #include "Direct3DVertexShader9.hpp" | 
 | #include "Direct3DStateBlock9.hpp" | 
 | #include "Direct3DQuery9.hpp" | 
 | #include "Direct3DVolume9.hpp" | 
 |  | 
 | #include "Debug.hpp" | 
 | #include "Capabilities.hpp" | 
 | #include "Math.hpp" | 
 | #include "Renderer.hpp" | 
 | #include "Config.hpp" | 
 | #include "FrameBuffer.hpp" | 
 | #include "Clipper.hpp" | 
 | #include "Configurator.hpp" | 
 | #include "Timer.hpp" | 
 | #include "Resource.hpp" | 
 |  | 
 | #include <assert.h> | 
 |  | 
 | bool localShaderConstants = true; | 
 |  | 
 | namespace D3D9 | 
 | { | 
 | 	inline unsigned long FtoDW(float f) | 
 | 	{ | 
 | 		return (unsigned long&)f; | 
 | 	} | 
 |  | 
 | 	Direct3DDevice9::Direct3DDevice9(const HINSTANCE instance, Direct3D9 *d3d9, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), adapter(adapter), d3d9(d3d9), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags) | 
 | 	{ | 
 | 		InitializeCriticalSection(&criticalSection); | 
 |  | 
 | 		init = true; | 
 | 		stateRecorder = 0; | 
 |  | 
 | 		d3d9->AddRef(); | 
 |  | 
 | 		context = new sw::Context(); | 
 | 		renderer = new sw::Renderer(context, sw::Direct3D, false); | 
 |  | 
 | 		swapChain = 0; | 
 | 		depthStencil = 0; | 
 | 		autoDepthStencil = 0; | 
 | 		renderTarget[0] = 0; | 
 | 		renderTarget[1] = 0; | 
 | 		renderTarget[2] = 0; | 
 | 		renderTarget[3] = 0; | 
 |  | 
 | 		for(int i = 0; i < 16 + 4; i++) | 
 | 		{ | 
 | 			texture[i] = 0; | 
 | 		} | 
 |  | 
 | 		cursor = 0; | 
 |  | 
 | 		Reset(presentParameters); | 
 |  | 
 | 		pixelShader = 0; | 
 | 		vertexShader = 0; | 
 |  | 
 | 		lightsDirty = true; | 
 | 		pixelShaderDirty = true; | 
 | 		pixelShaderConstantsBDirty = 0; | 
 | 		pixelShaderConstantsFDirty = 0; | 
 | 		pixelShaderConstantsIDirty = 0; | 
 | 		vertexShaderDirty = true; | 
 | 		vertexShaderConstantsBDirty = 0; | 
 | 		vertexShaderConstantsFDirty = 0; | 
 | 		vertexShaderConstantsIDirty = 0; | 
 |  | 
 | 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++) | 
 | 		{ | 
 | 			dataStream[i] = 0; | 
 | 			streamStride[i] = 0; | 
 | 			streamOffset[i] = 0; | 
 |  | 
 | 			streamSourceFreq[i] = 1; | 
 | 		} | 
 |  | 
 | 		indexData = 0; | 
 | 		vertexDeclaration = 0; | 
 |  | 
 | 		D3DMATERIAL9 material; | 
 |  | 
 | 		material.Diffuse.r = 1.0f; | 
 | 		material.Diffuse.g = 1.0f; | 
 | 		material.Diffuse.b = 1.0f; | 
 | 		material.Diffuse.a = 0.0f; | 
 | 		material.Ambient.r = 0.0f; | 
 | 		material.Ambient.g = 0.0f; | 
 | 		material.Ambient.b = 0.0f; | 
 | 		material.Ambient.a = 0.0f; | 
 | 		material.Emissive.r = 0.0f; | 
 | 		material.Emissive.g = 0.0f; | 
 | 		material.Emissive.b = 0.0f; | 
 | 		material.Emissive.a = 0.0f; | 
 | 		material.Specular.r = 0.0f; | 
 | 		material.Specular.g = 0.0f; | 
 | 		material.Specular.b = 0.0f; | 
 | 		material.Specular.a = 0.0f; | 
 | 		material.Power = 0.0f; | 
 |  | 
 | 		SetMaterial(&material); | 
 |  | 
 | 		D3DMATRIX identity = {1, 0, 0, 0, | 
 | 		                      0, 1, 0, 0, | 
 | 		                      0, 0, 1, 0, | 
 | 		                      0, 0, 0, 1}; | 
 |  | 
 | 		SetTransform(D3DTS_VIEW, &identity); | 
 | 		SetTransform(D3DTS_PROJECTION, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE0, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE1, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE2, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE3, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE4, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE5, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE6, &identity); | 
 | 		SetTransform(D3DTS_TEXTURE7, &identity); | 
 |  | 
 | 		for(int i = 0; i < 12; i++) | 
 | 		{ | 
 | 			SetTransform(D3DTS_WORLDMATRIX(i), &identity); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++) | 
 | 		{ | 
 | 			float zero[4] = {0, 0, 0, 0}; | 
 |  | 
 | 			SetPixelShaderConstantF(i, zero, 1); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++) | 
 | 		{ | 
 | 			float zero[4] = {0, 0, 0, 0}; | 
 |  | 
 | 			SetVertexShaderConstantF(i, zero, 1); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < 16; i++) | 
 | 		{ | 
 | 			int zero[4] = {0, 0, 0, 0}; | 
 |  | 
 | 			SetPixelShaderConstantI(i, zero, 1); | 
 | 			SetVertexShaderConstantI(i, zero, 1); | 
 | 			SetPixelShaderConstantB(i, &zero[0], 1); | 
 | 			SetVertexShaderConstantB(i, &zero[0], 1); | 
 | 		} | 
 |  | 
 | 		init = false; | 
 |  | 
 | 		if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE)) | 
 | 		{ | 
 | 			configureFPU(); | 
 | 		} | 
 |  | 
 | 		instancingEnabled = pixelShaderVersionX >= D3DPS_VERSION(3, 0); | 
 | 	} | 
 |  | 
 | 	Direct3DDevice9::~Direct3DDevice9() | 
 | 	{ | 
 | 		delete renderer; | 
 | 		renderer = 0; | 
 | 		delete context; | 
 | 		context = 0; | 
 |  | 
 | 		d3d9->Release(); | 
 | 		d3d9 = 0; | 
 |  | 
 | 		swapChain->unbind(); | 
 | 		swapChain = 0; | 
 |  | 
 | 		if(depthStencil) | 
 | 		{ | 
 | 			depthStencil->unbind(); | 
 | 			depthStencil = 0; | 
 | 		} | 
 |  | 
 | 		if(autoDepthStencil) | 
 | 		{ | 
 | 			autoDepthStencil->unbind(); | 
 | 			autoDepthStencil = 0; | 
 | 		} | 
 |  | 
 | 		for(int index = 0; index < 4; index++) | 
 | 		{ | 
 | 			if(renderTarget[index]) | 
 | 			{ | 
 | 				renderTarget[index]->unbind(); | 
 | 				renderTarget[index] = 0; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(vertexDeclaration) | 
 | 		{ | 
 | 			vertexDeclaration->unbind(); | 
 | 			vertexDeclaration = 0; | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < 16 + 4; i++) | 
 | 		{ | 
 | 			if(texture[i]) | 
 | 			{ | 
 | 				texture[i]->unbind(); | 
 | 				texture[i] = 0; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++) | 
 | 		{ | 
 | 			if(dataStream[i]) | 
 | 			{ | 
 | 				dataStream[i]->unbind(); | 
 | 				dataStream[i] = 0; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(indexData) | 
 | 		{ | 
 | 			indexData->unbind(); | 
 | 			indexData = 0; | 
 | 		} | 
 |  | 
 | 		if(pixelShader) | 
 | 		{ | 
 | 			pixelShader->unbind(); | 
 | 			pixelShader = 0; | 
 | 		} | 
 |  | 
 | 		if(vertexShader) | 
 | 		{ | 
 | 			vertexShader->unbind(); | 
 | 			vertexShader = 0; | 
 | 		} | 
 |  | 
 | 		if(stateRecorder) | 
 | 		{ | 
 | 			stateRecorder->unbind(); | 
 | 			stateRecorder = 0; | 
 | 		} | 
 |  | 
 | 		palette.clear(); | 
 |  | 
 | 		delete cursor; | 
 |  | 
 | 		DeleteCriticalSection(&criticalSection); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::QueryInterface(const IID &iid, void **object) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const IID &iid = 0x%0.8p, void **object = 0x%0.8p", iid, object); | 
 |  | 
 | 		if(iid == IID_IDirect3DDevice9 || | 
 | 		   iid == IID_IUnknown) | 
 | 		{ | 
 | 			AddRef(); | 
 | 			*object = this; | 
 |  | 
 | 			return S_OK; | 
 | 		} | 
 |  | 
 | 		*object = 0; | 
 |  | 
 | 		return NOINTERFACE(iid); | 
 | 	} | 
 |  | 
 | 	unsigned long Direct3DDevice9::AddRef() | 
 | 	{ | 
 | 		TRACE("void"); | 
 |  | 
 | 		return Unknown::AddRef(); | 
 | 	} | 
 |  | 
 | 	unsigned long Direct3DDevice9::Release() | 
 | 	{ | 
 | 		TRACE("void"); | 
 |  | 
 | 		return Unknown::Release(); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::BeginScene() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::BeginStateBlock() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		if(stateRecorder) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		stateRecorder = new Direct3DStateBlock9(this, (D3DSTATEBLOCKTYPE)0); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		stateRecorder->bind(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long count = %d, const D3DRECT *rects = 0x%0.8p, unsigned long flags = 0x%0.8X, unsigned long color = 0x%0.8X, float z = %f, unsigned long stencil = %d", count, rects, flags, color, z, stencil); | 
 |  | 
 | 		if(!rects && count != 0) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(flags & D3DCLEAR_STENCIL)   // Check for stencil component | 
 | 		{ | 
 | 			D3DSURFACE_DESC description; | 
 | 			depthStencil->GetDesc(&description); | 
 |  | 
 | 			switch(description.Format) | 
 | 			{ | 
 | 			case D3DFMT_D15S1: | 
 | 			case D3DFMT_D24S8: | 
 | 			case D3DFMT_D24X8: | 
 | 			case D3DFMT_D24X4S4: | 
 | 			case D3DFMT_D24FS8: | 
 | 			case D3DFMT_S8_LOCKABLE:   // FIXME: INVALIDCALL when trying to clear depth? | 
 | 			case D3DFMT_DF24: | 
 | 			case D3DFMT_DF16: | 
 | 			case D3DFMT_INTZ: | 
 | 				break; | 
 | 			case D3DFMT_D16_LOCKABLE: | 
 | 			case D3DFMT_D32: | 
 | 			case D3DFMT_D16: | 
 | 			case D3DFMT_D32F_LOCKABLE: | 
 | 			case D3DFMT_D32_LOCKABLE: | 
 | 				return INVALIDCALL(); | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(!rects) | 
 | 		{ | 
 | 			count = 1; | 
 |  | 
 | 			D3DRECT rect; | 
 | 			rect.x1 = viewport.X; | 
 | 			rect.x2 = viewport.X + viewport.Width; | 
 | 			rect.y1 = viewport.Y; | 
 | 			rect.y2 = viewport.Y + viewport.Height; | 
 |  | 
 | 			rects = ▭ | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			sw::SliceRect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2, 0); | 
 |  | 
 | 			clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height); | 
 |  | 
 | 			if(scissorEnable) | 
 | 			{ | 
 | 				clearRect.clip(scissorRect.left, scissorRect.top, scissorRect.right, scissorRect.bottom); | 
 | 			} | 
 |  | 
 | 			if(flags & D3DCLEAR_TARGET) | 
 | 			{ | 
 | 				for(int index = 0; index < 4; index++) | 
 | 				{ | 
 | 					if(renderTarget[index]) | 
 | 					{ | 
 | 						D3DSURFACE_DESC description; | 
 | 						renderTarget[index]->GetDesc(&description); | 
 |  | 
 | 						float rgba[4]; | 
 | 						rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000; | 
 | 						rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00; | 
 | 						rgba[2] = (float)(color & 0x000000FF) / 0x000000FF; | 
 | 						rgba[3] = (float)(color & 0xFF000000) / 0xFF000000; | 
 |  | 
 | 						if(renderState[D3DRS_SRGBWRITEENABLE] != FALSE && index == 0 && Capabilities::isSRGBwritable(description.Format)) | 
 | 						{ | 
 | 							rgba[0] = sw::linearToSRGB(rgba[0]); | 
 | 							rgba[1] = sw::linearToSRGB(rgba[1]); | 
 | 							rgba[2] = sw::linearToSRGB(rgba[2]); | 
 | 						} | 
 |  | 
 | 						renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget[index], clearRect, 0xF); | 
 | 					} | 
 | 				} | 
 | 			} | 
 |  | 
 | 			if(flags & D3DCLEAR_ZBUFFER) | 
 | 			{ | 
 | 				z = sw::clamp01(z); | 
 | 				depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); | 
 | 			} | 
 |  | 
 | 			if(flags & D3DCLEAR_STENCIL) | 
 | 			{ | 
 | 				depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height()); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::ColorFill(IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 *surface = 0x%0.8p, const RECT *rect = 0x%0.8p, D3DCOLOR color = 0x%0.8X", surface, rect, color); | 
 |  | 
 | 		if(!surface) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DSURFACE_DESC description; | 
 |  | 
 | 		surface->GetDesc(&description); | 
 |  | 
 | 		if(description.Pool != D3DPOOL_DEFAULT) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!rect) | 
 | 		{ | 
 | 			RECT lock; | 
 |  | 
 | 			lock.left = 0; | 
 | 			lock.top = 0; | 
 | 			lock.right = description.Width; | 
 | 			lock.bottom = description.Height; | 
 |  | 
 | 			rect = &lock; | 
 | 		} | 
 |  | 
 | 		static_cast<Direct3DSurface9*>(surface)->fill(color, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain9 **swapChain) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p, IDirect3DSwapChain9 **swapChain = 0x%0.8p", presentParameters, swapChain); | 
 |  | 
 | 		if(!swapChain) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*swapChain = 0; | 
 |  | 
 | 		if(!presentParameters) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(presentParameters->BackBufferCount > 3) | 
 | 		{ | 
 | 			return INVALIDCALL();   // Maximum of three back buffers | 
 | 		} | 
 |  | 
 | 		*swapChain = new Direct3DSwapChain9(this, presentParameters); | 
 |  | 
 | 		if(!*swapChain) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *swapChain; | 
 | 			*swapChain = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*swapChain)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture9 **cubeTexture, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int edgeLength = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DCubeTexture9 **cubeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", edgeLength, levels, usage, format, pool, cubeTexture, sharedHandle); | 
 |  | 
 | 		*cubeTexture = 0; | 
 |  | 
 | 		if(edgeLength == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*cubeTexture = new Direct3DCubeTexture9(this, edgeLength, levels, usage, format, pool); | 
 |  | 
 | 		if(!*cubeTexture) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *cubeTexture; | 
 | 			*cubeTexture = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*cubeTexture)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int discard, IDirect3DSurface9 **surface, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int discard = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, discard, surface, sharedHandle); | 
 |  | 
 | 		*surface = 0; | 
 |  | 
 | 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		bool lockable = false; | 
 |  | 
 | 		switch(format) | 
 | 		{ | 
 | 		case D3DFMT_D15S1: | 
 | 		case D3DFMT_D24S8: | 
 | 		case D3DFMT_D24X8: | 
 | 		case D3DFMT_D24X4S4: | 
 | 		case D3DFMT_D24FS8: | 
 | 		case D3DFMT_D32: | 
 | 		case D3DFMT_D16: | 
 | 		case D3DFMT_DF24: | 
 | 		case D3DFMT_DF16: | 
 | 		case D3DFMT_INTZ: | 
 | 			lockable = false; | 
 | 			break; | 
 | 		case D3DFMT_S8_LOCKABLE: | 
 | 		case D3DFMT_D16_LOCKABLE: | 
 | 		case D3DFMT_D32F_LOCKABLE: | 
 | 		case D3DFMT_D32_LOCKABLE: | 
 | 			lockable = true; | 
 | 			break; | 
 | 		default: | 
 | 			ASSERT(false); | 
 | 		} | 
 |  | 
 | 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL); | 
 |  | 
 | 		if(!*surface) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *surface; | 
 | 			*surface = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*surface)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **indexBuffer, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int length = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DIndexBuffer9 **indexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, format, pool, indexBuffer, sharedHandle); | 
 |  | 
 | 		*indexBuffer = new Direct3DIndexBuffer9(this, length, usage, format, pool); | 
 |  | 
 | 		if(!*indexBuffer) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *indexBuffer; | 
 | 			*indexBuffer = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*indexBuffer)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateOffscreenPlainSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, pool, surface, sharedHandle); | 
 |  | 
 | 		*surface = 0; | 
 |  | 
 | 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK)   // FIXME: Allow all formats supported by runtime/REF | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(pool == D3DPOOL_MANAGED) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*surface = new Direct3DSurface9(this, this, width, height, format, pool, D3DMULTISAMPLE_NONE, 0, true, 0); | 
 |  | 
 | 		if(!*surface) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *surface; | 
 | 			*surface = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*surface)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreatePixelShader(const unsigned long *function, IDirect3DPixelShader9 **shader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DPixelShader9 **shader = 0x%0.8p", function, shader); | 
 |  | 
 | 		if(!shader) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*shader = 0; | 
 |  | 
 | 		if(!sw::PixelShader::validate(function) || function[0] > pixelShaderVersionX) | 
 | 		{ | 
 | 			return INVALIDCALL();   // Shader contains unsupported operations | 
 | 		} | 
 |  | 
 | 		*shader = new Direct3DPixelShader9(this, function); | 
 |  | 
 | 		if(!*shader) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*shader)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateQuery(D3DQUERYTYPE type, IDirect3DQuery9 **query) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DQUERYTYPE type = %d, IDirect3DQuery9 **query = 0x%0.8p", type, query); | 
 |  | 
 | 		if(query == 0)   // Support checked | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DQUERYTYPE_VCACHE:				return D3D_OK; | 
 | 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_EVENT:				return D3D_OK; | 
 | 			case D3DQUERYTYPE_OCCLUSION:			return D3D_OK; | 
 | 			case D3DQUERYTYPE_TIMESTAMP:			return D3D_OK; | 
 | 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	return D3D_OK; | 
 | 			case D3DQUERYTYPE_TIMESTAMPFREQ:		return D3D_OK; | 
 | 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE(); | 
 | 			default:								ASSERT(false);   return NOTAVAILABLE(); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DQUERYTYPE_VCACHE:				break; | 
 | 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_EVENT:				break; | 
 | 			case D3DQUERYTYPE_OCCLUSION:			break; | 
 | 			case D3DQUERYTYPE_TIMESTAMP:			break; | 
 | 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	break; | 
 | 			case D3DQUERYTYPE_TIMESTAMPFREQ:		break; | 
 | 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE(); | 
 | 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE(); | 
 | 			default:								ASSERT(false);   return NOTAVAILABLE(); | 
 | 			} | 
 |  | 
 | 			*query = new Direct3DQuery9(this, type); | 
 |  | 
 | 			if(!*query) | 
 | 			{ | 
 | 				return OUTOFMEMORY(); | 
 | 			} | 
 |  | 
 | 			(*query)->AddRef(); | 
 |  | 
 | 			return D3D_OK; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int lockable, IDirect3DSurface9 **surface, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int lockable = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, lockable, surface, sharedHandle); | 
 |  | 
 | 		*surface = 0; | 
 |  | 
 | 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable != FALSE, D3DUSAGE_RENDERTARGET); | 
 |  | 
 | 		if(!*surface) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *surface; | 
 | 			*surface = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*surface)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateStateBlock(D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateBlock) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DSTATEBLOCKTYPE type = %d, IDirect3DStateBlock9 **stateBlock = 0x%0.8p", type, stateBlock); | 
 |  | 
 | 		*stateBlock = new Direct3DStateBlock9(this, type); | 
 |  | 
 | 		if(!*stateBlock) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*stateBlock)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9 **texture, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DTexture9 **texture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, levels, usage, format, pool, texture, sharedHandle); | 
 |  | 
 | 		*texture = 0; | 
 |  | 
 | 		if(width == 0 || height == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*texture = new Direct3DTexture9(this, width, height, levels, usage, format, pool); | 
 |  | 
 | 		if(!*texture) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *texture; | 
 | 			*texture = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*texture)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer9 **vertexBuffer, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int length = %d, unsigned long usage = %d, unsigned long FVF = 0x%0.8X, D3DPOOL pool = %d, IDirect3DVertexBuffer9 **vertexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, FVF, pool, vertexBuffer, sharedHandle); | 
 |  | 
 | 		*vertexBuffer = new Direct3DVertexBuffer9(this, length, usage, FVF, pool); | 
 |  | 
 | 		if(!*vertexBuffer) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *vertexBuffer; | 
 | 			*vertexBuffer = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*vertexBuffer)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateVertexDeclaration(const D3DVERTEXELEMENT9 *vertexElements, IDirect3DVertexDeclaration9 **declaration) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const D3DVERTEXELEMENT9 *vertexElements = 0x%0.8p, IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", vertexElements, declaration); | 
 |  | 
 | 		if(!declaration) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		const D3DVERTEXELEMENT9 *element = vertexElements; | 
 |  | 
 | 		while(element->Stream != 0xFF) | 
 | 		{ | 
 | 			if(element->Type > D3DDECLTYPE_UNUSED)   // FIXME: Check other fields too | 
 | 			{ | 
 | 				return FAIL(); | 
 | 			} | 
 |  | 
 | 			element++; | 
 | 		} | 
 |  | 
 | 		*declaration = new Direct3DVertexDeclaration9(this, vertexElements); | 
 |  | 
 | 		if(!*declaration) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*declaration)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateVertexShader(const unsigned long *function, IDirect3DVertexShader9 **shader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DVertexShader9 **shader = 0x%0.8p", function, shader); | 
 |  | 
 | 		if(!shader) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*shader = 0; | 
 |  | 
 | 		if(!sw::VertexShader::validate(function) || function[0] > vertexShaderVersionX) | 
 | 		{ | 
 | 			return INVALIDCALL();   // Shader contains unsupported operations | 
 | 		} | 
 |  | 
 | 		*shader = new Direct3DVertexShader9(this, function); | 
 |  | 
 | 		if(!*shader) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*shader)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture9 **volumeTexture, void **sharedHandle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int depth = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DVolumeTexture9 **volumeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, depth, levels, usage, format, pool, volumeTexture, sharedHandle); | 
 |  | 
 | 		*volumeTexture = 0; | 
 |  | 
 | 		if(width == 0 || height == 0 || depth == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*volumeTexture = new Direct3DVolumeTexture9(this, width, height, depth, levels, usage, format, pool); | 
 |  | 
 | 		if(!*volumeTexture) | 
 | 		{ | 
 | 			return OUTOFMEMORY(); | 
 | 		} | 
 |  | 
 | 		if(GetAvailableTextureMem() == 0) | 
 | 		{ | 
 | 			delete *volumeTexture; | 
 | 			*volumeTexture = 0; | 
 |  | 
 | 			return OUTOFVIDEOMEMORY(); | 
 | 		} | 
 |  | 
 | 		(*volumeTexture)->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DeletePatch(unsigned int handle) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int handle = %d", handle); | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, int baseVertexIndex, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRIMITIVETYPE type = %d, int baseVertexIndex = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int startIndex = %d, unsigned int primitiveCount = %d", type, baseVertexIndex, minIndex, numVertices, startIndex, primitiveCount); | 
 |  | 
 | 		if(!indexData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!bindResources(indexData) || !primitiveCount) | 
 | 		{ | 
 | 			return D3D_OK; | 
 | 		} | 
 |  | 
 | 		unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account | 
 |  | 
 | 		sw::DrawType drawType; | 
 |  | 
 | 		if(indexData->is32Bit()) | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break; | 
 | 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break; | 
 | 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break; | 
 | 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break; | 
 | 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break; | 
 | 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break; | 
 | 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break; | 
 | 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break; | 
 | 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break; | 
 | 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break; | 
 | 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if((streamSourceFreq[0] & D3DSTREAMSOURCE_INDEXEDDATA) && instanceData()) | 
 | 		{ | 
 | 			int instanceCount = (streamSourceFreq[0] & ~D3DSTREAMSOURCE_INDEXEDDATA); | 
 |  | 
 | 			for(int instance = 0; instance < instanceCount; instance++) | 
 | 			{ | 
 | 				bindVertexStreams(baseVertexIndex, true, instance); | 
 | 				renderer->draw(drawType, indexOffset, primitiveCount, instance == 0); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			bindVertexStreams(baseVertexIndex, false, 0); | 
 | 			renderer->draw(drawType, indexOffset, primitiveCount); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRIMITIVETYPE type = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int primitiveCount = %d, const void *indexData = 0x%0.8p, D3DFORMAT indexDataFormat = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", type, minIndex, numVertices, primitiveCount, indexData, indexDataFormat, vertexStreamZeroData, vertexStreamZeroStride); | 
 |  | 
 | 		if(!vertexStreamZeroData || !indexData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		int length = (minIndex + numVertices) * vertexStreamZeroStride; | 
 |  | 
 | 		Direct3DVertexBuffer9 *vertexBuffer = new Direct3DVertexBuffer9(this, length, 0, 0, D3DPOOL_DEFAULT); | 
 |  | 
 | 		void *data; | 
 | 		vertexBuffer->Lock(0, 0, &data, 0); | 
 | 		memcpy(data, vertexStreamZeroData, length); | 
 | 		vertexBuffer->Unlock(); | 
 |  | 
 | 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride); | 
 |  | 
 | 		switch(type) | 
 | 		{ | 
 | 		case D3DPT_POINTLIST:		length = primitiveCount;		break; | 
 | 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break; | 
 | 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break; | 
 | 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break; | 
 | 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break; | 
 | 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break; | 
 | 		default: | 
 | 			ASSERT(false); | 
 | 		} | 
 |  | 
 | 		length *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2; | 
 |  | 
 | 		Direct3DIndexBuffer9 *indexBuffer = new Direct3DIndexBuffer9(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT); | 
 |  | 
 | 		indexBuffer->Lock(0, 0, &data, 0); | 
 | 		memcpy(data, indexData, length); | 
 | 		indexBuffer->Unlock(); | 
 |  | 
 | 		SetIndices(indexBuffer); | 
 |  | 
 | 		if(!bindResources(indexBuffer) || !primitiveCount) | 
 | 		{ | 
 | 			vertexBuffer->Release(); | 
 |  | 
 | 			return D3D_OK; | 
 | 		} | 
 |  | 
 | 		sw::DrawType drawType; | 
 |  | 
 | 		if(indexDataFormat == D3DFMT_INDEX32) | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break; | 
 | 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break; | 
 | 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break; | 
 | 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break; | 
 | 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break; | 
 | 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break; | 
 | 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break; | 
 | 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break; | 
 | 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break; | 
 | 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break; | 
 | 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		bindVertexStreams(0, false, 0); | 
 | 		renderer->draw(drawType, 0, primitiveCount); | 
 |  | 
 | 		SetStreamSource(0, 0, 0, 0); | 
 | 		SetIndices(0); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int startVertex = %d, unsigned int primitiveCount = %d", primitiveType, startVertex, primitiveCount); | 
 |  | 
 | 		if(!bindResources(0) || !primitiveCount) | 
 | 		{ | 
 | 			return D3D_OK; | 
 | 		} | 
 |  | 
 | 		sw::DrawType drawType; | 
 |  | 
 | 		switch(primitiveType) | 
 | 		{ | 
 | 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break; | 
 | 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break; | 
 | 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break; | 
 | 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break; | 
 | 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break; | 
 | 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break; | 
 | 		default: | 
 | 			ASSERT(false); | 
 | 		} | 
 |  | 
 | 		bindVertexStreams(startVertex, false, 0); | 
 | 		renderer->draw(drawType, 0, primitiveCount); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int primitiveCount = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", primitiveType, primitiveCount, vertexStreamZeroData, vertexStreamZeroStride); | 
 |  | 
 | 		if(!vertexStreamZeroData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		IDirect3DVertexBuffer9 *vertexBuffer = 0; | 
 | 		int length = 0; | 
 |  | 
 | 		switch(primitiveType) | 
 | 		{ | 
 | 		case D3DPT_POINTLIST:		length = primitiveCount;		break; | 
 | 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break; | 
 | 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break; | 
 | 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break; | 
 | 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break; | 
 | 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break; | 
 | 		default: | 
 | 			ASSERT(false); | 
 | 		} | 
 |  | 
 | 		length *= vertexStreamZeroStride; | 
 |  | 
 | 		CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer, 0); | 
 |  | 
 | 		void *data; | 
 | 		vertexBuffer->Lock(0, 0, &data, 0); | 
 | 		memcpy(data, vertexStreamZeroData, length); | 
 | 		vertexBuffer->Unlock(); | 
 |  | 
 | 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride); | 
 |  | 
 | 		if(!bindResources(0) || !primitiveCount) | 
 | 		{ | 
 | 			vertexBuffer->Release(); | 
 |  | 
 | 			return D3D_OK; | 
 | 		} | 
 |  | 
 | 		sw::DrawType drawType; | 
 |  | 
 | 		switch(primitiveType) | 
 | 		{ | 
 | 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break; | 
 | 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break; | 
 | 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break; | 
 | 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break; | 
 | 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break; | 
 | 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break; | 
 | 		default: | 
 | 			ASSERT(false); | 
 | 		} | 
 |  | 
 | 		bindVertexStreams(0, false, 0); | 
 | 		renderer->draw(drawType, 0, primitiveCount); | 
 |  | 
 | 		SetStreamSource(0, 0, 0, 0); | 
 | 		vertexBuffer->Release(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DRECTPATCH_INFO *rectPatchInfo = 0x%0.8p", handle, numSegs, rectPatchInfo); | 
 |  | 
 | 		if(!numSegs || !rectPatchInfo) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DTRIPATCH_INFO *triPatchInfo = 0x%0.8p", handle, numSegs, triPatchInfo); | 
 |  | 
 | 		if(!numSegs || !triPatchInfo) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::EndScene() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::EndStateBlock(IDirect3DStateBlock9 **stateBlock) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DStateBlock9 **stateBlock = 0x%0.8p", stateBlock); | 
 |  | 
 | 		if(!stateBlock) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*stateBlock = 0; | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*stateBlock = stateRecorder; | 
 | 		stateRecorder->AddRef(); | 
 | 		stateRecorder->unbind(); | 
 | 		stateRecorder = 0;   // Stop recording | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::EvictManagedResources() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		//	UNIMPLEMENTED();   // FIXME | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	unsigned int Direct3DDevice9::GetAvailableTextureMem() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		int availableMemory = textureMemory - Direct3DResource9::getMemoryUsage(); | 
 | 		if(availableMemory < 0) availableMemory = 0; | 
 |  | 
 | 		// Round to nearest MB | 
 | 		return (availableMemory + 0x80000) & 0xFFF00000; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetBackBuffer(unsigned int swapChainIndex, unsigned int backBufferIndex, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int swapChainIndex = %d, unsigned int backBufferIndex = %d, D3DBACKBUFFER_TYPE type = %d, IDirect3DSurface9 **backBuffer = 0x%0.8p", swapChainIndex, backBufferIndex, type, backBuffer); | 
 |  | 
 | 		if(swapChainIndex >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		return swapChain->GetBackBuffer(backBufferIndex, type, backBuffer); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetClipPlane(unsigned long index, float *plane) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, float *plane = 0x%0.8p", index, plane); | 
 |  | 
 | 		if(!plane || index >= 6) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		plane[0] = this->plane[index][0]; | 
 | 		plane[1] = this->plane[index][1]; | 
 | 		plane[2] = this->plane[index][2]; | 
 | 		plane[3] = this->plane[index][3]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetClipStatus(D3DCLIPSTATUS9 *clipStatus) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus); | 
 |  | 
 | 		if(!clipStatus) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*clipStatus = this->clipStatus; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DDEVICE_CREATION_PARAMETERS *parameters = 0x%0.8p", parameters); | 
 |  | 
 | 		if(!parameters) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		parameters->AdapterOrdinal = adapter; | 
 | 		parameters->BehaviorFlags = behaviourFlags; | 
 | 		parameters->DeviceType = deviceType; | 
 | 		parameters->hFocusWindow = focusWindow; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetCurrentTexturePalette(unsigned int *paletteNumber) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int *paletteNumber = 0x%0.8p", paletteNumber); | 
 |  | 
 | 		if(!paletteNumber) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*paletteNumber = currentPalette; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetDepthStencilSurface(IDirect3DSurface9 **depthStencilSurface) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 **depthStencilSurface = 0x%0.8p", depthStencilSurface); | 
 |  | 
 | 		if(!depthStencilSurface) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*depthStencilSurface = depthStencil; | 
 |  | 
 | 		if(depthStencil) | 
 | 		{ | 
 | 			depthStencil->AddRef(); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return NOTFOUND(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetDeviceCaps(D3DCAPS9 *caps) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DCAPS9 *caps = 0x%0.8p", caps); | 
 |  | 
 | 		return d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetDirect3D(IDirect3D9 **d3d9) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3D9 **d3d9 = 0x%0.8p", d3d9); | 
 |  | 
 | 		if(!d3d9) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*d3d9 = this->d3d9; | 
 | 		this->d3d9->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetDisplayMode(unsigned int index, D3DDISPLAYMODE *mode) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int index = %d, D3DDISPLAYMODE *mode = 0x%0.8p", index, mode); | 
 |  | 
 | 		if(index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		return swapChain->GetDisplayMode(mode); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetFrontBufferData(unsigned int index, IDirect3DSurface9 *destSurface) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int index = %d, IDirect3DSurface9 *destSurface = %p", index, destSurface); | 
 |  | 
 | 		if(index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		return swapChain->GetFrontBufferData(destSurface); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetFVF(unsigned long *FVF) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long *FVF = 0x%0.8p", FVF); | 
 |  | 
 | 		if(!FVF) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(vertexDeclaration) | 
 | 		{ | 
 | 			*FVF = vertexDeclaration->getFVF(); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			*FVF = 0; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::GetGammaRamp(unsigned int index, D3DGAMMARAMP *ramp) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int index = %d, D3DGAMMARAMP *ramp = 0x%0.8p", index, ramp); | 
 |  | 
 | 		if(!ramp || index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return; | 
 | 		} | 
 |  | 
 | 		swapChain->getGammaRamp((sw::GammaRamp*)ramp); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetIndices(IDirect3DIndexBuffer9 **indexData) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DIndexBuffer9 **indexData = 0x%0.8p", indexData); | 
 |  | 
 | 		if(!indexData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*indexData = this->indexData; | 
 |  | 
 | 		if(this->indexData) | 
 | 		{ | 
 | 			this->indexData->AddRef(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetLight(unsigned long index, D3DLIGHT9 *light) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, D3DLIGHT9 *light = 0x%0.8p", index, light); | 
 |  | 
 | 		if(!light) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!this->light.exists(index)) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*light = this->light[index]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetLightEnable(unsigned long index, int *enable) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, int *enable = 0x%0.8p", index, enable); | 
 |  | 
 | 		if(!enable) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!light.exists(index)) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*enable = light[index].enable ? 128 : 0; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetMaterial(D3DMATERIAL9 *material) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DMATERIAL9 *material = 0x%0.8p", material); | 
 |  | 
 | 		if(!material) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*material = this->material; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	float Direct3DDevice9::GetNPatchMode() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return 0.0f;   // FIXME: Unimplemented | 
 | 	} | 
 |  | 
 | 	unsigned int Direct3DDevice9::GetNumberOfSwapChains() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return 1; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int paletteNumber = %d, PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries); | 
 |  | 
 | 		if(paletteNumber > 0xFFFF || !entries) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < 256; i++) | 
 | 		{ | 
 | 			entries[i] = palette[paletteNumber].entry[i]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetPixelShader(IDirect3DPixelShader9 **shader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DPixelShader9 **shader = 0x%0.8p", shader); | 
 |  | 
 | 		if(!shader) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(pixelShader) | 
 | 		{ | 
 | 			pixelShader->AddRef(); | 
 | 		} | 
 |  | 
 | 		*shader = pixelShader; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetPixelShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i] = pixelShaderConstantB[startRegister + i]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetPixelShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i * 4 + 0] = pixelShaderConstantF[startRegister + i][0]; | 
 | 			constantData[i * 4 + 1] = pixelShaderConstantF[startRegister + i][1]; | 
 | 			constantData[i * 4 + 2] = pixelShaderConstantF[startRegister + i][2]; | 
 | 			constantData[i * 4 + 3] = pixelShaderConstantF[startRegister + i][3]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetPixelShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i * 4 + 0] = pixelShaderConstantI[startRegister + i][0]; | 
 | 			constantData[i * 4 + 1] = pixelShaderConstantI[startRegister + i][1]; | 
 | 			constantData[i * 4 + 2] = pixelShaderConstantI[startRegister + i][2]; | 
 | 			constantData[i * 4 + 3] = pixelShaderConstantI[startRegister + i][3]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetRasterStatus(unsigned int index, D3DRASTER_STATUS *rasterStatus) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int swapChain = %d, D3DRASTER_STATUS *rasterStatus = 0x%0.8p", index, rasterStatus); | 
 |  | 
 | 		if(index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		return swapChain->GetRasterStatus(rasterStatus); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long *value = 0x%0.8p", state, value); | 
 |  | 
 | 		if(!value) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*value = renderState[state]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetRenderTarget(unsigned long index, IDirect3DSurface9 **renderTarget) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, IDirect3DSurface9 **renderTarget = 0x%0.8p", index, renderTarget); | 
 |  | 
 | 		if(index >= 4 || !renderTarget) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*renderTarget = 0; | 
 |  | 
 | 		if(!this->renderTarget[index]) | 
 | 		{ | 
 | 			return NOTFOUND(); | 
 | 		} | 
 |  | 
 | 		*renderTarget = this->renderTarget[index]; | 
 | 		this->renderTarget[index]->AddRef(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetRenderTargetData(IDirect3DSurface9 *renderTarget, IDirect3DSurface9 *destSurface) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 *renderTarget = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p", renderTarget, destSurface); | 
 |  | 
 | 		if(!renderTarget || !destSurface) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DSURFACE_DESC sourceDescription; | 
 | 		D3DSURFACE_DESC destinationDescription; | 
 |  | 
 | 		renderTarget->GetDesc(&sourceDescription); | 
 | 		destSurface->GetDesc(&destinationDescription); | 
 |  | 
 | 		if(sourceDescription.Width  != destinationDescription.Width || | 
 | 		   sourceDescription.Height != destinationDescription.Height || | 
 | 		   sourceDescription.Format != destinationDescription.Format || | 
 | 		   sourceDescription.MultiSampleType != D3DMULTISAMPLE_NONE) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(sourceDescription.Format == D3DFMT_A8R8G8B8 || | 
 | 		   sourceDescription.Format == D3DFMT_X8R8G8B8) | 
 | 		{ | 
 | 			sw::Surface *source = static_cast<Direct3DSurface9*>(renderTarget); | 
 | 			sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface); | 
 |  | 
 | 			void *sourceBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 | 			void *destBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC); | 
 |  | 
 | 			static void (__cdecl *blitFunction)(void *dst, void *src); | 
 | 			static sw::Routine *blitRoutine; | 
 | 			static sw::BlitState blitState = {0}; | 
 |  | 
 | 			sw::BlitState update; | 
 | 			update.width = sourceDescription.Width; | 
 | 			update.height = sourceDescription.Height; | 
 | 			update.sourceFormat = sw::FORMAT_A8R8G8B8; | 
 | 			update.destFormat = sw::FORMAT_A8R8G8B8; | 
 | 			update.stride = dest->getExternalPitchB(); | 
 | 			update.cursorHeight = 0; | 
 | 			update.cursorWidth = 0; | 
 |  | 
 | 			if(memcmp(&blitState, &update, sizeof(sw::BlitState)) != 0) | 
 | 			{ | 
 | 				blitState = update; | 
 | 				delete blitRoutine; | 
 |  | 
 | 				blitRoutine = sw::FrameBuffer::copyRoutine(blitState); | 
 | 				blitFunction = (void(__cdecl*)(void*, void*))blitRoutine->getEntry(); | 
 | 			} | 
 |  | 
 | 			blitFunction(destBuffer, sourceBuffer); | 
 |  | 
 | 			dest->unlockExternal(); | 
 | 			source->unlockExternal(); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return UpdateSurface(renderTarget, 0, destSurface, 0); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long *value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE type = %d, unsigned long *value = 0x%0.8p", sampler, state, value); | 
 |  | 
 | 		if(!value || state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)   // FIXME: Set *value to 0? | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(sampler >= D3DVERTEXTEXTURESAMPLER0) | 
 | 		{ | 
 | 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0); | 
 | 		} | 
 |  | 
 | 		*value = samplerState[sampler][state]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetScissorRect(RECT *rect) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("RECT *rect = 0x%0.8p", rect); | 
 |  | 
 | 		if(!rect) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*rect = scissorRect; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	int Direct3DDevice9::GetSoftwareVertexProcessing() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return softwareVertexProcessing ? TRUE : FALSE; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer9 **streamData, unsigned int *offset, unsigned int *stride) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int streamNumber = %d, IDirect3DVertexBuffer9 **streamData = 0x%0.8p, unsigned int *offset = 0x%0.8p, unsigned int *stride = 0x%0.8p", streamNumber, streamData, offset, stride); | 
 |  | 
 | 		if(streamNumber >= 16 || !streamData || !offset || !stride) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*streamData = dataStream[streamNumber]; | 
 |  | 
 | 		if(dataStream[streamNumber]) | 
 | 		{ | 
 | 			dataStream[streamNumber]->AddRef(); | 
 | 		} | 
 |  | 
 | 		*offset = streamOffset[streamNumber]; | 
 | 		*stride = streamStride[streamNumber]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetStreamSourceFreq(unsigned int streamNumber, unsigned int *divider) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int streamNumber = %d, unsigned int *divider = 0x%0.8p", streamNumber, divider); | 
 |  | 
 | 		if(streamNumber >= 16 || !divider) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*divider = streamSourceFreq[streamNumber]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetSwapChain(unsigned int index, IDirect3DSwapChain9 **swapChain) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int index = %d, IDirect3DSwapChain9 **swapChain = 0x%0.8p", index, swapChain); | 
 |  | 
 | 		if(!swapChain || index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*swapChain = this->swapChain; | 
 |  | 
 | 		if(*swapChain) | 
 | 		{ | 
 | 			(*swapChain)->AddRef(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetTexture(unsigned long sampler, IDirect3DBaseTexture9 **texture) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 **texture = 0x%0.8p", sampler, texture); | 
 |  | 
 | 		if(!texture) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*texture = 0; | 
 |  | 
 | 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*texture = this->texture[sampler]; | 
 |  | 
 | 		if(this->texture[sampler]) | 
 | 		{ | 
 | 			this->texture[sampler]->AddRef(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long *value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long *value = 0x%0.8p", stage, type, value); | 
 |  | 
 | 		if(!value) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*value = textureStageState[stage][type]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DTRANSFORMSTATETYPE state = %d, D3DMATRIX *matrix = 0x%0.8p", state, matrix); | 
 |  | 
 | 		if(!matrix || state < 0 || state > 511) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*matrix = this->matrix[state]; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9 **declaration) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", declaration); | 
 |  | 
 | 		if(!declaration) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*declaration = vertexDeclaration; | 
 |  | 
 | 		if(vertexDeclaration) | 
 | 		{ | 
 | 			vertexDeclaration->AddRef(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetVertexShader(IDirect3DVertexShader9 **shader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DVertexShader9 **shader = 0x%0.8p", shader); | 
 |  | 
 | 		if(!shader) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*shader = vertexShader; | 
 |  | 
 | 		if(vertexShader) | 
 | 		{ | 
 | 			vertexShader->AddRef(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetVertexShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i] = vertexShaderConstantB[startRegister + i]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetVertexShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i * 4 + 0] = vertexShaderConstantF[startRegister + i][0]; | 
 | 			constantData[i * 4 + 1] = vertexShaderConstantF[startRegister + i][1]; | 
 | 			constantData[i * 4 + 2] = vertexShaderConstantF[startRegister + i][2]; | 
 | 			constantData[i * 4 + 3] = vertexShaderConstantF[startRegister + i][3]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetVertexShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(unsigned int i = 0; i < count; i++) | 
 | 		{ | 
 | 			constantData[i * 4 + 0] = vertexShaderConstantI[startRegister + i][0]; | 
 | 			constantData[i * 4 + 1] = vertexShaderConstantI[startRegister + i][1]; | 
 | 			constantData[i * 4 + 2] = vertexShaderConstantI[startRegister + i][2]; | 
 | 			constantData[i * 4 + 3] = vertexShaderConstantI[startRegister + i][3]; | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::GetViewport(D3DVIEWPORT9 *viewport) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DVIEWPORT9 *viewport = 0x%0.8p", viewport); | 
 |  | 
 | 		if(!viewport) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*viewport = this->viewport; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::LightEnable(unsigned long index, int enable) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, int enable = %d", index, enable); | 
 |  | 
 | 		if(!light.exists(index))   // Insert default light | 
 | 		{ | 
 | 			D3DLIGHT9 light; | 
 |  | 
 | 			light.Type = D3DLIGHT_DIRECTIONAL; | 
 | 			light.Diffuse.r = 1; | 
 | 			light.Diffuse.g = 1; | 
 | 			light.Diffuse.b = 1; | 
 | 			light.Diffuse.a = 0; | 
 | 			light.Specular.r = 0; | 
 | 			light.Specular.g = 0; | 
 | 			light.Specular.b = 0; | 
 | 			light.Specular.a = 0; | 
 | 			light.Ambient.r = 0; | 
 | 			light.Ambient.g = 0; | 
 | 			light.Ambient.b = 0; | 
 | 			light.Ambient.a = 0; | 
 | 			light.Position.x = 0; | 
 | 			light.Position.y = 0; | 
 | 			light.Position.z = 0; | 
 | 			light.Direction.x = 0; | 
 | 			light.Direction.y = 0; | 
 | 			light.Direction.z = 1; | 
 | 			light.Range = 0; | 
 | 			light.Falloff = 0; | 
 | 			light.Attenuation0 = 0; | 
 | 			light.Attenuation1 = 0; | 
 | 			light.Attenuation2 = 0; | 
 | 			light.Theta = 0; | 
 | 			light.Phi = 0; | 
 |  | 
 | 			this->light[index] = light; | 
 | 			this->light[index].enable = false; | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			light[index].enable = (enable != FALSE); | 
 |  | 
 | 			lightsDirty = true; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->lightEnable(index, enable); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix); | 
 |  | 
 | 		if(!matrix) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DMATRIX *current = &this->matrix[state]; | 
 |  | 
 | 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41, | 
 | 		             current->_12, current->_22, current->_32, current->_42, | 
 | 		             current->_13, current->_23, current->_33, current->_43, | 
 | 		             current->_14, current->_24, current->_34, current->_44); | 
 |  | 
 | 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41, | 
 | 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42, | 
 | 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43, | 
 | 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44); | 
 |  | 
 | 		switch(state) | 
 | 		{ | 
 | 		case D3DTS_WORLD: | 
 | 			renderer->setModelMatrix(C * M); | 
 | 			break; | 
 | 		case D3DTS_VIEW: | 
 | 			renderer->setViewMatrix(C * M); | 
 | 			break; | 
 | 		case D3DTS_PROJECTION: | 
 | 			renderer->setProjectionMatrix(C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE0: | 
 | 			renderer->setTextureMatrix(0, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE1: | 
 | 			renderer->setTextureMatrix(1, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE2: | 
 | 			renderer->setTextureMatrix(2, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE3: | 
 | 			renderer->setTextureMatrix(3, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE4: | 
 | 			renderer->setTextureMatrix(4, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE5: | 
 | 			renderer->setTextureMatrix(5, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE6: | 
 | 			renderer->setTextureMatrix(6, C * M); | 
 | 			break; | 
 | 		case D3DTS_TEXTURE7: | 
 | 			renderer->setTextureMatrix(7, C * M); | 
 | 			break; | 
 | 		default: | 
 | 			if(state > 256 && state < 512) | 
 | 			{ | 
 | 				renderer->setModelMatrix(C * M, state - 256); | 
 | 			} | 
 | 			else ASSERT(false); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const RECT *sourceRect = 0x%0.8p, const RECT *destRect = 0x%0.8p, HWND destWindowOverride = %d, const RGNDATA *dirtyRegion = 0x%0.8p", sourceRect, destRect, destWindowOverride, dirtyRegion); | 
 |  | 
 | 		return swapChain->Present(sourceRect, destRect, destWindowOverride, dirtyRegion, 0); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer9 *destBuffer, IDirect3DVertexDeclaration9 *vertexDeclaration, unsigned long flags) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int srcStartIndex = %d, unsigned int destIndex = %d, unsigned int vertexCount = %d, IDirect3DVertexBuffer9 *destBuffer = 0x%0.8p, IDirect3DVertexDeclaration9 *vertexDeclaration = 0x%0.8p, unsigned long flags = %d", srcStartIndex, destIndex, vertexCount, destBuffer, vertexDeclaration, flags); | 
 |  | 
 | 		if(!destBuffer) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::Reset(D3DPRESENT_PARAMETERS *presentParameters) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p", presentParameters); | 
 |  | 
 | 		if(!presentParameters) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		deviceWindow = presentParameters->hDeviceWindow; | 
 |  | 
 | 		if(depthStencil) | 
 | 		{ | 
 | 			depthStencil->unbind(); | 
 | 			depthStencil = 0; | 
 | 		} | 
 |  | 
 | 		if(autoDepthStencil) | 
 | 		{ | 
 | 			autoDepthStencil->unbind(); | 
 | 			autoDepthStencil = 0; | 
 | 		} | 
 |  | 
 | 		for(int index = 0; index < 4; index++) | 
 | 		{ | 
 | 			if(renderTarget[index]) | 
 | 			{ | 
 | 				renderTarget[index]->unbind(); | 
 | 				renderTarget[index] = 0; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		if(!swapChain) | 
 | 		{ | 
 | 			swapChain = new Direct3DSwapChain9(this, presentParameters); | 
 | 			swapChain->bind(); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			swapChain->reset(presentParameters); | 
 | 		} | 
 |  | 
 | 		if(presentParameters->EnableAutoDepthStencil != FALSE) | 
 | 		{ | 
 | 			bool lockable = false; | 
 |  | 
 | 			switch(presentParameters->AutoDepthStencilFormat) | 
 | 			{ | 
 | 			case D3DFMT_D15S1: | 
 | 			case D3DFMT_D24S8: | 
 | 			case D3DFMT_D24X8: | 
 | 			case D3DFMT_D24X4S4: | 
 | 			case D3DFMT_D24FS8: | 
 | 			case D3DFMT_D32: | 
 | 			case D3DFMT_D16: | 
 | 			case D3DFMT_DF24: | 
 | 			case D3DFMT_DF16: | 
 | 			case D3DFMT_INTZ: | 
 | 				lockable = false; | 
 | 				break; | 
 | 			case D3DFMT_S8_LOCKABLE: | 
 | 			case D3DFMT_D16_LOCKABLE: | 
 | 			case D3DFMT_D32F_LOCKABLE: | 
 | 			case D3DFMT_D32_LOCKABLE: | 
 | 				lockable = true; | 
 | 				break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 |  | 
 | 			autoDepthStencil = new Direct3DSurface9(this, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL); | 
 | 			autoDepthStencil->bind(); | 
 |  | 
 | 			SetDepthStencilSurface(autoDepthStencil); | 
 | 		} | 
 |  | 
 | 		IDirect3DSurface9 *renderTarget; | 
 | 		swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget); | 
 | 		SetRenderTarget(0, renderTarget); | 
 | 		renderTarget->Release(); | 
 |  | 
 | 		SetRenderTarget(1, 0); | 
 | 		SetRenderTarget(2, 0); | 
 | 		SetRenderTarget(3, 0); | 
 |  | 
 | 		softwareVertexProcessing = (behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == D3DCREATE_SOFTWARE_VERTEXPROCESSING; | 
 |  | 
 | 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE); | 
 | 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); | 
 | 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); | 
 | 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE); | 
 | 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_LASTPIXEL, TRUE); | 
 | 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); | 
 | 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); | 
 | 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); | 
 | 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); | 
 | 		SetRenderState(D3DRS_ALPHAREF, 0); | 
 | 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); | 
 | 		SetRenderState(D3DRS_DITHERENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_FOGENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_SPECULARENABLE, FALSE); | 
 | 	//	SetRenderState(D3DRS_ZVISIBLE, 0); | 
 | 		SetRenderState(D3DRS_FOGCOLOR, 0); | 
 | 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); | 
 | 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_STENCILENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); | 
 | 		SetRenderState(D3DRS_STENCILREF, 0); | 
 | 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF); | 
 | 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); | 
 | 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF); | 
 | 		SetRenderState(D3DRS_WRAP0, 0); | 
 | 		SetRenderState(D3DRS_WRAP1, 0); | 
 | 		SetRenderState(D3DRS_WRAP2, 0); | 
 | 		SetRenderState(D3DRS_WRAP3, 0); | 
 | 		SetRenderState(D3DRS_WRAP4, 0); | 
 | 		SetRenderState(D3DRS_WRAP5, 0); | 
 | 		SetRenderState(D3DRS_WRAP6, 0); | 
 | 		SetRenderState(D3DRS_WRAP7, 0); | 
 | 		SetRenderState(D3DRS_CLIPPING, TRUE); | 
 | 		SetRenderState(D3DRS_LIGHTING, TRUE); | 
 | 		SetRenderState(D3DRS_AMBIENT, 0); | 
 | 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE); | 
 | 		SetRenderState(D3DRS_COLORVERTEX, TRUE); | 
 | 		SetRenderState(D3DRS_LOCALVIEWER, TRUE); | 
 | 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); | 
 | 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); | 
 | 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2); | 
 | 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); | 
 | 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); | 
 | 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); | 
 | 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0); | 
 | 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); | 
 | 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); | 
 | 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE); | 
 | 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE); | 
 | 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f)); | 
 | 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F); | 
 | 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | 
 | 		SetRenderState(D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC); | 
 | 		SetRenderState(D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR); | 
 | 		SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_MINTESSELLATIONLEVEL, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_MAXTESSELLATIONLEVEL, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_ADAPTIVETESS_X, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_ADAPTIVETESS_Y, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_ADAPTIVETESS_Z, FtoDW(1.0f)); | 
 | 		SetRenderState(D3DRS_ADAPTIVETESS_W, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_ENABLEADAPTIVETESSELLATION, FALSE); | 
 | 		SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); | 
 | 		SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP); | 
 | 		SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS); | 
 | 		SetRenderState(D3DRS_COLORWRITEENABLE1, 0x0000000F); | 
 | 		SetRenderState(D3DRS_COLORWRITEENABLE2, 0x0000000F); | 
 | 		SetRenderState(D3DRS_COLORWRITEENABLE3, 0x0000000F); | 
 | 		SetRenderState(D3DRS_BLENDFACTOR, 0xFFFFFFFF); | 
 | 		SetRenderState(D3DRS_SRGBWRITEENABLE, 0); | 
 | 		SetRenderState(D3DRS_DEPTHBIAS, FtoDW(0.0f)); | 
 | 		SetRenderState(D3DRS_WRAP8, 0); | 
 | 		SetRenderState(D3DRS_WRAP9, 0); | 
 | 		SetRenderState(D3DRS_WRAP10, 0); | 
 | 		SetRenderState(D3DRS_WRAP11, 0); | 
 | 		SetRenderState(D3DRS_WRAP12, 0); | 
 | 		SetRenderState(D3DRS_WRAP13, 0); | 
 | 		SetRenderState(D3DRS_WRAP14, 0); | 
 | 		SetRenderState(D3DRS_WRAP15, 0); | 
 | 		SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); | 
 | 		SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); | 
 | 		SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO); | 
 | 		SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD); | 
 |  | 
 | 		for(int i = 0; i < 8; i++) | 
 | 		{ | 
 | 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE); | 
 | 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); | 
 | 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); | 
 | 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE); | 
 | 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); | 
 | 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f)); | 
 | 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); | 
 | 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT); | 
 | 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT); | 
 | 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT); | 
 | 			SetTextureStageState(i, D3DTSS_CONSTANT, 0x00000000); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i <= D3DVERTEXTEXTURESAMPLER3; i = (i != 15) ? (i + 1) : D3DVERTEXTEXTURESAMPLER0) | 
 | 		{ | 
 | 			SetTexture(i, 0); | 
 |  | 
 | 			SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); | 
 | 			SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); | 
 | 			SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP); | 
 | 			SetSamplerState(i, D3DSAMP_BORDERCOLOR, 0x00000000); | 
 | 			SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT); | 
 | 			SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT); | 
 | 			SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE); | 
 | 			SetSamplerState(i, D3DSAMP_MIPMAPLODBIAS, 0); | 
 | 			SetSamplerState(i, D3DSAMP_MAXMIPLEVEL, 0); | 
 | 			SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 1); | 
 | 			SetSamplerState(i, D3DSAMP_SRGBTEXTURE, 0); | 
 | 			SetSamplerState(i, D3DSAMP_ELEMENTINDEX, 0); | 
 | 			SetSamplerState(i, D3DSAMP_DMAPOFFSET, 0); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < 6; i++) | 
 | 		{ | 
 | 			float plane[4] = {0, 0, 0, 0}; | 
 |  | 
 | 			SetClipPlane(i, plane); | 
 | 		} | 
 |  | 
 | 		currentPalette = 0xFFFF; | 
 |  | 
 | 		ShowCursor(FALSE); | 
 | 		delete cursor; | 
 | 		cursor = 0; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetClipPlane(unsigned long index, const float *plane) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, const float *plane = 0x%0.8p", index, plane); | 
 |  | 
 | 		if(!plane || index >= 6) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			this->plane[index][0] = plane[0]; | 
 | 			this->plane[index][1] = plane[1]; | 
 | 			this->plane[index][2] = plane[2]; | 
 | 			this->plane[index][3] = plane[3]; | 
 |  | 
 | 			renderer->setClipPlane(index, plane); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setClipPlane(index, plane); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetClipStatus(const D3DCLIPSTATUS9 *clipStatus) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus); | 
 |  | 
 | 		if(!clipStatus) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		this->clipStatus = *clipStatus; | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetCurrentTexturePalette(unsigned int paletteNumber) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int paletteNumber = %d", paletteNumber); | 
 |  | 
 | 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			currentPalette = paletteNumber; | 
 |  | 
 | 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setCurrentTexturePalette(paletteNumber); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::SetCursorPosition(int x, int y, unsigned long flags) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("int x = %d, int y = %d, unsigned long flags = 0x%0.8X", x, y, flags); | 
 |  | 
 | 		POINT point = {x, y}; | 
 | 		HWND window = deviceWindow ? deviceWindow : focusWindow; | 
 | 		ScreenToClient(window, &point); | 
 |  | 
 | 		sw::FrameBuffer::setCursorPosition(point.x, point.y); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface9 *cursorBitmap) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int x0 = %d, unsigned int y0 = %d, IDirect3DSurface9 *cursorBitmap = 0x%0.8p", x0, y0, cursorBitmap); | 
 |  | 
 | 		if(!cursorBitmap) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		sw::Surface *cursorSurface = static_cast<Direct3DSurface9*>(cursorBitmap); | 
 |  | 
 | 		int width = cursorSurface->getWidth(); | 
 | 		int height = cursorSurface->getHeight(); | 
 | 		void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 |  | 
 | 		delete cursor; | 
 | 		cursor = new sw::Surface(0, width, height, 1, sw::FORMAT_A8R8G8B8, false, false); | 
 |  | 
 | 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC); | 
 | 		memcpy(buffer, bitmap, width * height * sizeof(unsigned int)); | 
 | 		cursor->unlockExternal(); | 
 |  | 
 | 		cursorSurface->unlockExternal(); | 
 |  | 
 | 		if(showCursor) | 
 | 		{ | 
 | 			sw::FrameBuffer::setCursorImage(cursor); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sw::FrameBuffer::setCursorImage(0); | 
 | 		} | 
 |  | 
 | 		sw::FrameBuffer::setCursorOrigin(x0, y0); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetDepthStencilSurface(IDirect3DSurface9 *iDepthStencil) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 *newDepthStencil = 0x%0.8p", iDepthStencil); | 
 |  | 
 | 		Direct3DSurface9 *depthStencil = static_cast<Direct3DSurface9*>(iDepthStencil); | 
 |  | 
 | 		if(this->depthStencil == depthStencil) | 
 | 		{ | 
 | 			return D3D_OK; | 
 | 		} | 
 |  | 
 | 		if(depthStencil) | 
 | 		{ | 
 | 			depthStencil->bind(); | 
 | 		} | 
 |  | 
 | 		if(this->depthStencil) | 
 | 		{ | 
 | 			this->depthStencil->unbind(); | 
 | 		} | 
 |  | 
 | 		this->depthStencil = depthStencil; | 
 |  | 
 | 		renderer->setDepthBuffer(depthStencil); | 
 | 		renderer->setStencilBuffer(depthStencil); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetDialogBoxMode(int enableDialogs) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("int enableDialogs = %d", enableDialogs); | 
 |  | 
 | 		UNIMPLEMENTED(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetFVF(unsigned long FVF) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long FVF = 0x%0.8X", FVF); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(FVF != 0 || !this->vertexDeclaration) | 
 | 			{ | 
 | 				Direct3DVertexDeclaration9 *vertexDeclaration = new Direct3DVertexDeclaration9(this, FVF); | 
 | 				vertexDeclaration->bind(); | 
 |  | 
 | 				if(this->vertexDeclaration) | 
 | 				{ | 
 | 					this->vertexDeclaration->unbind(); | 
 | 				} | 
 |  | 
 | 				this->vertexDeclaration = vertexDeclaration; | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setFVF(FVF); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::SetGammaRamp(unsigned int index, unsigned long flags, const D3DGAMMARAMP *ramp) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int index = %d, unsigned long flags = 0x%0.8X, const D3DGAMMARAMP *ramp = 0x%0.8p", index, flags, ramp); | 
 |  | 
 | 		if(!ramp || index >= GetNumberOfSwapChains()) | 
 | 		{ | 
 | 			return; | 
 | 		} | 
 |  | 
 | 		swapChain->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE); | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetIndices(IDirect3DIndexBuffer9* iIndexBuffer) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DIndexBuffer9* indexData = 0x%0.8p", iIndexBuffer); | 
 |  | 
 | 		Direct3DIndexBuffer9 *indexBuffer = static_cast<Direct3DIndexBuffer9*>(iIndexBuffer); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(this->indexData == indexBuffer) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(indexBuffer) | 
 | 			{ | 
 | 				indexBuffer->bind(); | 
 | 			} | 
 |  | 
 | 			if(this->indexData) | 
 | 			{ | 
 | 				this->indexData->unbind(); | 
 | 			} | 
 |  | 
 | 			this->indexData = indexBuffer; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setIndices(indexBuffer); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetLight(unsigned long index, const D3DLIGHT9 *light) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, const D3DLIGHT9 *light = 0x%0.8p", index, light); | 
 |  | 
 | 		if(!light) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			this->light[index] = *light; | 
 |  | 
 | 			lightsDirty = true; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setLight(index, light); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetMaterial(const D3DMATERIAL9 *material) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const D3DMATERIAL9 *material = 0x%0.8p", material); | 
 |  | 
 | 		if(!material) | 
 | 		{ | 
 | 			return INVALIDCALL();   // FIXME: Correct behaviour? | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			this->material = *material; | 
 |  | 
 | 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a)); | 
 | 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a)); | 
 | 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a)); | 
 | 			renderer->setMaterialShininess(material->Power); | 
 | 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a)); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setMaterial(material); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetNPatchMode(float segments) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("float segments = %f", segments); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(segments < 1) | 
 | 			{ | 
 | 				// NOTE: Disable | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				UNIMPLEMENTED(); | 
 | 			} | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setNPatchMode(segments); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int paletteNumber = %d, const PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries); | 
 |  | 
 | 		if(paletteNumber > 0xFFFF || !entries) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		for(int i = 0; i < 256; i++) | 
 | 		{ | 
 | 			palette[paletteNumber].entry[i] = entries[i]; | 
 | 		} | 
 |  | 
 | 		if(paletteNumber == currentPalette) | 
 | 		{ | 
 | 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetPixelShader(IDirect3DPixelShader9 *iPixelShader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DPixelShader9 *shader = 0x%0.8p", iPixelShader); | 
 |  | 
 | 		Direct3DPixelShader9 *pixelShader = static_cast<Direct3DPixelShader9*>(iPixelShader); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(this->pixelShader == pixelShader) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(pixelShader) | 
 | 			{ | 
 | 				pixelShader->bind(); | 
 | 			} | 
 |  | 
 | 			if(this->pixelShader) | 
 | 			{ | 
 | 				this->pixelShader->unbind(); | 
 | 			} | 
 |  | 
 | 			this->pixelShader = pixelShader; | 
 | 			pixelShaderDirty = true; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setPixelShader(pixelShader); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetPixelShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++) | 
 | 			{ | 
 | 				pixelShaderConstantB[startRegister + i] = constantData[i]; | 
 | 			} | 
 |  | 
 | 			pixelShaderConstantsBDirty = sw::max(startRegister + count, pixelShaderConstantsBDirty); | 
 | 			pixelShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setPixelShaderConstantB(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < MAX_PIXEL_SHADER_CONST; i++) | 
 | 			{ | 
 | 				pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; | 
 | 				pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; | 
 | 				pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; | 
 | 				pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; | 
 | 			} | 
 |  | 
 | 			pixelShaderConstantsFDirty = sw::max(startRegister + count, pixelShaderConstantsFDirty); | 
 | 			pixelShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setPixelShaderConstantF(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetPixelShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++) | 
 | 			{ | 
 | 				pixelShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0]; | 
 | 				pixelShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1]; | 
 | 				pixelShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2]; | 
 | 				pixelShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3]; | 
 | 			} | 
 |  | 
 | 			pixelShaderConstantsIDirty = sw::max(startRegister + count, pixelShaderConstantsIDirty); | 
 | 			pixelShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setPixelShaderConstantI(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value); | 
 |  | 
 | 		if(state < D3DRS_ZENABLE || state > D3DRS_BLENDOPALPHA) | 
 | 		{ | 
 | 			return D3D_OK;   // FIXME: Warning | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(!init && renderState[state] == value) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			renderState[state] = value; | 
 |  | 
 | 			switch(state) | 
 | 			{ | 
 | 			case D3DRS_ZENABLE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DZB_TRUE: | 
 | 				case D3DZB_USEW: | 
 | 					renderer->setDepthBufferEnable(true); | 
 | 					break; | 
 | 				case D3DZB_FALSE: | 
 | 					renderer->setDepthBufferEnable(false); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_FILLMODE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DFILL_POINT: | 
 | 					renderer->setFillMode(sw::FILL_VERTEX); | 
 | 					break; | 
 | 				case D3DFILL_WIREFRAME: | 
 | 					renderer->setFillMode(sw::FILL_WIREFRAME); | 
 | 					break; | 
 | 				case D3DFILL_SOLID: | 
 | 					renderer->setFillMode(sw::FILL_SOLID); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_SHADEMODE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSHADE_FLAT: | 
 | 					renderer->setShadingMode(sw::SHADING_FLAT); | 
 | 					break; | 
 | 				case D3DSHADE_GOURAUD: | 
 | 					renderer->setShadingMode(sw::SHADING_GOURAUD); | 
 | 					break; | 
 | 				case D3DSHADE_PHONG: | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_ZWRITEENABLE: | 
 | 				renderer->setDepthWriteEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_ALPHATESTENABLE: | 
 | 				renderer->setAlphaTestEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_LASTPIXEL: | 
 | 			//	if(!init) UNIMPLEMENTED();   // FIXME | 
 | 				break; | 
 | 			case D3DRS_SRCBLEND: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLEND_ZERO: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_ZERO); | 
 | 					break; | 
 | 				case D3DBLEND_ONE: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_ONE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCCOLOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCCOLOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTCOLOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_DEST); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTCOLOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHASAT: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHSRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHINVSRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BLENDFACTOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_CONSTANT); | 
 | 					break; | 
 | 				case D3DBLEND_INVBLENDFACTOR: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVCONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_DESTBLEND: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLEND_ZERO: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_ZERO); | 
 | 					break; | 
 | 				case D3DBLEND_ONE: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_ONE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCCOLOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_SOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCCOLOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHA: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCALPHA: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTALPHA: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTALPHA: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTCOLOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_DEST); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTCOLOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVDEST); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHASAT: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHSRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHINVSRCALPHA: | 
 | 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA); | 
 | 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BLENDFACTOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_CONSTANT); | 
 | 					break; | 
 | 				case D3DBLEND_INVBLENDFACTOR: | 
 | 					renderer->setDestBlendFactor(sw::BLEND_INVCONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_CULLMODE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DCULL_NONE: | 
 | 					renderer->setCullMode(sw::CULL_NONE); | 
 | 					break; | 
 | 				case D3DCULL_CCW: | 
 | 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE); | 
 | 					break; | 
 | 				case D3DCULL_CW: | 
 | 					renderer->setCullMode(sw::CULL_CLOCKWISE); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_ZFUNC: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DCMP_NEVER: | 
 | 					renderer->setDepthCompare(sw::DEPTH_NEVER); | 
 | 					break; | 
 | 				case D3DCMP_LESS: | 
 | 					renderer->setDepthCompare(sw::DEPTH_LESS); | 
 | 					break; | 
 | 				case D3DCMP_EQUAL: | 
 | 					renderer->setDepthCompare(sw::DEPTH_EQUAL); | 
 | 					break; | 
 | 				case D3DCMP_LESSEQUAL: | 
 | 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATER: | 
 | 					renderer->setDepthCompare(sw::DEPTH_GREATER); | 
 | 					break; | 
 | 				case D3DCMP_NOTEQUAL: | 
 | 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATEREQUAL: | 
 | 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL); | 
 | 					break; | 
 | 				case D3DCMP_ALWAYS: | 
 | 					renderer->setDepthCompare(sw::DEPTH_ALWAYS); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_ALPHAREF: | 
 | 				renderer->setAlphaReference(value & 0x000000FF); | 
 | 				break; | 
 | 			case D3DRS_ALPHAFUNC: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DCMP_NEVER: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_NEVER); | 
 | 					break; | 
 | 				case D3DCMP_LESS: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_LESS); | 
 | 					break; | 
 | 				case D3DCMP_EQUAL: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_EQUAL); | 
 | 					break; | 
 | 				case D3DCMP_LESSEQUAL: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATER: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_GREATER); | 
 | 					break; | 
 | 				case D3DCMP_NOTEQUAL: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATEREQUAL: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL); | 
 | 					break; | 
 | 				case D3DCMP_ALWAYS: | 
 | 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_DITHERENABLE: | 
 | 			//	if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_ALPHABLENDENABLE: | 
 | 				renderer->setAlphaBlendEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_FOGENABLE: | 
 | 				renderer->setFogEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_FOGCOLOR: | 
 | 				renderer->setFogColor(value); | 
 | 				break; | 
 | 			case D3DRS_FOGTABLEMODE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DFOG_NONE: | 
 | 					renderer->setPixelFogMode(sw::FOG_NONE); | 
 | 					break; | 
 | 				case D3DFOG_LINEAR: | 
 | 					renderer->setPixelFogMode(sw::FOG_LINEAR); | 
 | 					break; | 
 | 				case D3DFOG_EXP: | 
 | 					renderer->setPixelFogMode(sw::FOG_EXP); | 
 | 					break; | 
 | 				case D3DFOG_EXP2: | 
 | 					renderer->setPixelFogMode(sw::FOG_EXP2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_FOGSTART: | 
 | 				renderer->setFogStart((float&)value); | 
 | 				break; | 
 | 			case D3DRS_FOGEND: | 
 | 				renderer->setFogEnd((float&)value); | 
 | 				break; | 
 | 			case D3DRS_FOGDENSITY: | 
 | 				renderer->setFogDensity((float&)value); | 
 | 				break; | 
 | 			case D3DRS_RANGEFOGENABLE: | 
 | 				renderer->setRangeFogEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_SPECULARENABLE: | 
 | 				renderer->setSpecularEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_STENCILENABLE: | 
 | 				renderer->setStencilEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_STENCILFAIL: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilFailOperation(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_STENCILZFAIL: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilZFailOperation(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_STENCILPASS: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilPassOperation(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_STENCILFUNC: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DCMP_NEVER: | 
 | 					renderer->setStencilCompare(sw::STENCIL_NEVER); | 
 | 					break; | 
 | 				case D3DCMP_LESS: | 
 | 					renderer->setStencilCompare(sw::STENCIL_LESS); | 
 | 					break; | 
 | 				case D3DCMP_EQUAL: | 
 | 					renderer->setStencilCompare(sw::STENCIL_EQUAL); | 
 | 					break; | 
 | 				case D3DCMP_LESSEQUAL: | 
 | 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATER: | 
 | 					renderer->setStencilCompare(sw::STENCIL_GREATER); | 
 | 					break; | 
 | 				case D3DCMP_NOTEQUAL: | 
 | 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATEREQUAL: | 
 | 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL); | 
 | 					break; | 
 | 				case D3DCMP_ALWAYS: | 
 | 					renderer->setStencilCompare(sw::STENCIL_ALWAYS); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_STENCILREF: | 
 | 				renderer->setStencilReference(value); | 
 | 				renderer->setStencilReferenceCCW(value); | 
 | 				break; | 
 | 			case D3DRS_STENCILMASK: | 
 | 				renderer->setStencilMask(value); | 
 | 				renderer->setStencilMaskCCW(value); | 
 | 				break; | 
 | 			case D3DRS_STENCILWRITEMASK: | 
 | 				renderer->setStencilWriteMask(value); | 
 | 				renderer->setStencilWriteMaskCCW(value); | 
 | 				break; | 
 | 			case D3DRS_TEXTUREFACTOR: | 
 | 				renderer->setTextureFactor(value); | 
 | 				break; | 
 | 			case D3DRS_WRAP0: | 
 | 				renderer->setTextureWrap(0, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP1: | 
 | 				renderer->setTextureWrap(1, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP2: | 
 | 				renderer->setTextureWrap(2, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP3: | 
 | 				renderer->setTextureWrap(3, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP4: | 
 | 				renderer->setTextureWrap(4, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP5: | 
 | 				renderer->setTextureWrap(5, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP6: | 
 | 				renderer->setTextureWrap(6, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP7: | 
 | 				renderer->setTextureWrap(7, value); | 
 | 				break; | 
 | 			case D3DRS_CLIPPING: | 
 | 				// Ignored, clipping is always performed | 
 | 				break; | 
 | 			case D3DRS_LIGHTING: | 
 | 				renderer->setLightingEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_AMBIENT: | 
 | 				renderer->setGlobalAmbient(value); | 
 | 				break; | 
 | 			case D3DRS_FOGVERTEXMODE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DFOG_NONE: | 
 | 					renderer->setVertexFogMode(sw::FOG_NONE); | 
 | 					break; | 
 | 				case D3DFOG_LINEAR: | 
 | 					renderer->setVertexFogMode(sw::FOG_LINEAR); | 
 | 					break; | 
 | 				case D3DFOG_EXP: | 
 | 					renderer->setVertexFogMode(sw::FOG_EXP); | 
 | 					break; | 
 | 				case D3DFOG_EXP2: | 
 | 					renderer->setVertexFogMode(sw::FOG_EXP2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_COLORVERTEX: | 
 | 				renderer->setColorVertexEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_LOCALVIEWER: | 
 | 				renderer->setLocalViewer(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_NORMALIZENORMALS: | 
 | 				renderer->setNormalizeNormals(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_DIFFUSEMATERIALSOURCE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DMCS_MATERIAL: | 
 | 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL); | 
 | 					break; | 
 | 				case D3DMCS_COLOR1: | 
 | 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1); | 
 | 					break; | 
 | 				case D3DMCS_COLOR2: | 
 | 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_SPECULARMATERIALSOURCE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DMCS_MATERIAL: | 
 | 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL); | 
 | 					break; | 
 | 				case D3DMCS_COLOR1: | 
 | 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1); | 
 | 					break; | 
 | 				case D3DMCS_COLOR2: | 
 | 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_AMBIENTMATERIALSOURCE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DMCS_MATERIAL: | 
 | 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL); | 
 | 					break; | 
 | 				case D3DMCS_COLOR1: | 
 | 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1); | 
 | 					break; | 
 | 				case D3DMCS_COLOR2: | 
 | 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_EMISSIVEMATERIALSOURCE: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DMCS_MATERIAL: | 
 | 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL); | 
 | 					break; | 
 | 				case D3DMCS_COLOR1: | 
 | 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1); | 
 | 					break; | 
 | 				case D3DMCS_COLOR2: | 
 | 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_VERTEXBLEND: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DVBF_DISABLE: | 
 | 					renderer->setVertexBlendMatrixCount(0); | 
 | 					break; | 
 | 				case D3DVBF_1WEIGHTS: | 
 | 					renderer->setVertexBlendMatrixCount(2); | 
 | 					break; | 
 | 				case D3DVBF_2WEIGHTS: | 
 | 					renderer->setVertexBlendMatrixCount(3); | 
 | 					break; | 
 | 				case D3DVBF_3WEIGHTS: | 
 | 					renderer->setVertexBlendMatrixCount(4); | 
 | 					break; | 
 | 				case D3DVBF_TWEENING: | 
 | 					UNIMPLEMENTED(); | 
 | 					break; | 
 | 				case D3DVBF_0WEIGHTS: | 
 | 					renderer->setVertexBlendMatrixCount(1); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_CLIPPLANEENABLE: | 
 | 				renderer->setClipFlags(value); | 
 | 				break; | 
 | 			case D3DRS_POINTSIZE: | 
 | 				if(value == D3DFMT_INST && pixelShaderVersionX >= D3DPS_VERSION(2, 0))   // ATI hack to enable instancing on SM 2.0 hardware | 
 | 				{ | 
 | 					instancingEnabled = true; | 
 | 				} | 
 | 				else if(value == D3DFMT_A2M1)   // ATI hack to enable transparency anti-aliasing | 
 | 				{ | 
 | 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE); | 
 | 					renderer->setAlphaTestEnable(true); | 
 | 				} | 
 | 				else if(value == D3DFMT_A2M0)   // ATI hack to disable transparency anti-aliasing | 
 | 				{ | 
 | 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE); | 
 | 					renderer->setAlphaTestEnable(false); | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					renderer->setPointSize((float&)value); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_POINTSIZE_MIN: | 
 | 				renderer->setPointSizeMin((float&)value); | 
 | 				break; | 
 | 			case D3DRS_POINTSPRITEENABLE: | 
 | 				renderer->setPointSpriteEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_POINTSCALEENABLE: | 
 | 				renderer->setPointScaleEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_POINTSCALE_A: | 
 | 				renderer->setPointScaleA((float&)value); | 
 | 				break; | 
 | 			case D3DRS_POINTSCALE_B: | 
 | 				renderer->setPointScaleB((float&)value); | 
 | 				break; | 
 | 			case D3DRS_POINTSCALE_C: | 
 | 				renderer->setPointScaleC((float&)value); | 
 | 				break; | 
 | 			case D3DRS_MULTISAMPLEANTIALIAS: | 
 | 			//	if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_MULTISAMPLEMASK: | 
 | 				SetRenderTarget(0, renderTarget[0]);   // Sets the multi-sample mask, if maskable | 
 | 				break; | 
 | 			case D3DRS_PATCHEDGESTYLE: | 
 | 				if(!init) if(value != D3DPATCHEDGE_DISCRETE) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_DEBUGMONITORTOKEN: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_POINTSIZE_MAX: | 
 | 				renderer->setPointSizeMax((float&)value); | 
 | 				break; | 
 | 			case D3DRS_INDEXEDVERTEXBLENDENABLE: | 
 | 				renderer->setIndexedVertexBlendEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_COLORWRITEENABLE: | 
 | 				renderer->setColorWriteMask(0, value & 0x0000000F); | 
 | 				break; | 
 | 			case D3DRS_TWEENFACTOR: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_BLENDOP: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLENDOP_ADD: | 
 | 					renderer->setBlendOperation(sw::BLENDOP_ADD); | 
 | 					break; | 
 | 				case D3DBLENDOP_SUBTRACT: | 
 | 					renderer->setBlendOperation(sw::BLENDOP_SUB); | 
 | 					break; | 
 | 				case D3DBLENDOP_REVSUBTRACT: | 
 | 					renderer->setBlendOperation(sw::BLENDOP_INVSUB); | 
 | 					break; | 
 | 				case D3DBLENDOP_MIN: | 
 | 					renderer->setBlendOperation(sw::BLENDOP_MIN); | 
 | 					break; | 
 | 				case D3DBLENDOP_MAX: | 
 | 					renderer->setBlendOperation(sw::BLENDOP_MAX); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_POSITIONDEGREE: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_NORMALDEGREE: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_SCISSORTESTENABLE: | 
 | 				scissorEnable = (value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_SLOPESCALEDEPTHBIAS: | 
 | 				renderer->setSlopeDepthBias((float&)value); | 
 | 				break; | 
 | 			case D3DRS_ANTIALIASEDLINEENABLE: | 
 | 				if(!init) if(value != FALSE) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_MINTESSELLATIONLEVEL: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_MAXTESSELLATIONLEVEL: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_ADAPTIVETESS_X: | 
 | 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_ADAPTIVETESS_Y: | 
 | 				if(value == D3DFMT_ATOC)   // NVIDIA hack to enable transparency anti-aliasing | 
 | 				{ | 
 | 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE); | 
 | 				} | 
 | 				else if(value == D3DFMT_UNKNOWN)   // NVIDIA hack to disable transparency anti-aliasing | 
 | 				{ | 
 | 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE); | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					if(!init) if((float&)value != 0.0f) UNIMPLEMENTED(); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_ADAPTIVETESS_Z: | 
 | 				if(!init) if((float&)value != 1.0f) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_ADAPTIVETESS_W: | 
 | 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_ENABLEADAPTIVETESSELLATION: | 
 | 				if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			case D3DRS_TWOSIDEDSTENCILMODE: | 
 | 				renderer->setTwoSidedStencil(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_CCW_STENCILFAIL: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_CCW_STENCILZFAIL: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_CCW_STENCILPASS: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DSTENCILOP_KEEP: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_KEEP); | 
 | 					break; | 
 | 				case D3DSTENCILOP_ZERO: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_ZERO); | 
 | 					break; | 
 | 				case D3DSTENCILOP_REPLACE: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_REPLACE); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCRSAT: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECRSAT: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECRSAT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INVERT: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_INVERT); | 
 | 					break; | 
 | 				case D3DSTENCILOP_INCR: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCR); | 
 | 					break; | 
 | 				case D3DSTENCILOP_DECR: | 
 | 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_CCW_STENCILFUNC: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DCMP_NEVER: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_NEVER); | 
 | 					break; | 
 | 				case D3DCMP_LESS: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_LESS); | 
 | 					break; | 
 | 				case D3DCMP_EQUAL: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_EQUAL); | 
 | 					break; | 
 | 				case D3DCMP_LESSEQUAL: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_LESSEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATER: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_GREATER); | 
 | 					break; | 
 | 				case D3DCMP_NOTEQUAL: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_NOTEQUAL); | 
 | 					break; | 
 | 				case D3DCMP_GREATEREQUAL: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_GREATEREQUAL); | 
 | 					break; | 
 | 				case D3DCMP_ALWAYS: | 
 | 					renderer->setStencilCompareCCW(sw::STENCIL_ALWAYS); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_COLORWRITEENABLE1: | 
 | 				renderer->setColorWriteMask(1, value); | 
 | 				break; | 
 | 			case D3DRS_COLORWRITEENABLE2: | 
 | 				renderer->setColorWriteMask(2, value); | 
 | 				break; | 
 | 			case D3DRS_COLORWRITEENABLE3: | 
 | 				renderer->setColorWriteMask(3, value); | 
 | 				break; | 
 | 			case D3DRS_BLENDFACTOR: | 
 | 				renderer->setBlendConstant(sw::Color<float>(value)); | 
 | 				break; | 
 | 			case D3DRS_SRGBWRITEENABLE: | 
 | 				renderer->setWriteSRGB(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_DEPTHBIAS: | 
 | 				renderer->setDepthBias((float&)value); | 
 | 				break; | 
 | 			case D3DRS_WRAP8: | 
 | 				renderer->setTextureWrap(8, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP9: | 
 | 				renderer->setTextureWrap(9, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP10: | 
 | 				renderer->setTextureWrap(10, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP11: | 
 | 				renderer->setTextureWrap(11, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP12: | 
 | 				renderer->setTextureWrap(12, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP13: | 
 | 				renderer->setTextureWrap(13, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP14: | 
 | 				renderer->setTextureWrap(14, value); | 
 | 				break; | 
 | 			case D3DRS_WRAP15: | 
 | 				renderer->setTextureWrap(15, value); | 
 | 				break; | 
 | 			case D3DRS_SEPARATEALPHABLENDENABLE: | 
 | 				renderer->setSeparateAlphaBlendEnable(value != FALSE); | 
 | 				break; | 
 | 			case D3DRS_SRCBLENDALPHA: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLEND_ZERO: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ZERO); | 
 | 					break; | 
 | 				case D3DBLEND_ONE: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ONE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCCOLOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCCOLOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTCOLOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DEST); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTCOLOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDEST); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHASAT: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SRCALPHASAT); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHSRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHINVSRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BLENDFACTOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_CONSTANT); | 
 | 					break; | 
 | 				case D3DBLEND_INVBLENDFACTOR: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVCONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_DESTBLENDALPHA: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLEND_ZERO: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_ZERO); | 
 | 					break; | 
 | 				case D3DBLEND_ONE: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_ONE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCCOLOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCCOLOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCE); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHA: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVSRCALPHA: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTALPHA: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_DESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTALPHA: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDESTALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_DESTCOLOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_DEST); | 
 | 					break; | 
 | 				case D3DBLEND_INVDESTCOLOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDEST); | 
 | 					break; | 
 | 				case D3DBLEND_SRCALPHASAT: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_SRCALPHASAT); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHSRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BOTHINVSRCALPHA: | 
 | 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA); | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA); | 
 | 					break; | 
 | 				case D3DBLEND_BLENDFACTOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_CONSTANT); | 
 | 					break; | 
 | 				case D3DBLEND_INVBLENDFACTOR: | 
 | 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVCONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DRS_BLENDOPALPHA: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DBLENDOP_ADD: | 
 | 					renderer->setBlendOperationAlpha(sw::BLENDOP_ADD); | 
 | 					break; | 
 | 				case D3DBLENDOP_SUBTRACT: | 
 | 					renderer->setBlendOperationAlpha(sw::BLENDOP_SUB); | 
 | 					break; | 
 | 				case D3DBLENDOP_REVSUBTRACT: | 
 | 					renderer->setBlendOperationAlpha(sw::BLENDOP_INVSUB); | 
 | 					break; | 
 | 				case D3DBLENDOP_MIN: | 
 | 					renderer->setBlendOperationAlpha(sw::BLENDOP_MIN); | 
 | 					break; | 
 | 				case D3DBLENDOP_MAX: | 
 | 					renderer->setBlendOperationAlpha(sw::BLENDOP_MAX); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else   // stateRecorder | 
 | 		{ | 
 | 			stateRecorder->setRenderState(state, value); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetRenderTarget(unsigned long index, IDirect3DSurface9 *iRenderTarget) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long index = %d, IDirect3DSurface9 *newRenderTarget = 0x%0.8p", index, iRenderTarget); | 
 |  | 
 | 		// FIXME: Check for D3DUSAGE_RENDERTARGET | 
 |  | 
 | 		if(index >= 4 || (index == 0 && !iRenderTarget)) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		Direct3DSurface9 *renderTarget = static_cast<Direct3DSurface9*>(iRenderTarget); | 
 |  | 
 | 		if(renderTarget) | 
 | 		{ | 
 | 			renderTarget->bind(); | 
 | 		} | 
 |  | 
 | 		if(this->renderTarget[index]) | 
 | 		{ | 
 | 			this->renderTarget[index]->unbind(); | 
 | 		} | 
 |  | 
 | 		this->renderTarget[index] = renderTarget; | 
 |  | 
 | 		if(renderTarget && index == 0) | 
 | 		{ | 
 | 			D3DSURFACE_DESC renderTargetDesc; | 
 | 			renderTarget->GetDesc(&renderTargetDesc); | 
 |  | 
 | 			// Reset viewport to size of current render target | 
 | 			viewport.X = 0; | 
 | 			viewport.Y = 0; | 
 | 			viewport.Width = renderTargetDesc.Width; | 
 | 			viewport.Height = renderTargetDesc.Height; | 
 | 			viewport.MinZ = 0; | 
 | 			viewport.MaxZ = 1; | 
 |  | 
 | 			// Reset scissor rectangle to size of current render target | 
 | 			scissorRect.left = 0; | 
 | 			scissorRect.top = 0; | 
 | 			scissorRect.right = renderTargetDesc.Width; | 
 | 			scissorRect.bottom = renderTargetDesc.Height; | 
 |  | 
 | 			// Set the multi-sample mask, if maskable | 
 | 			if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE && | 
 | 			   renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONMASKABLE) | 
 | 			{ | 
 | 				renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				renderer->setMultiSampleMask(0xFFFFFFFF); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		renderer->setRenderTarget(index, renderTarget); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE state = %d, unsigned long value = %d", sampler, state, value); | 
 |  | 
 | 		if(state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(sampler >= D3DVERTEXTEXTURESAMPLER0) | 
 | 		{ | 
 | 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(!init && samplerState[sampler][state] == value) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			samplerState[sampler][state] = value; | 
 |  | 
 | 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX; | 
 | 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group | 
 |  | 
 | 			switch(state) | 
 | 			{ | 
 | 			case D3DSAMP_ADDRESSU: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTADDRESS_WRAP: | 
 | 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_WRAP); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRROR: | 
 | 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRROR); | 
 | 					break; | 
 | 				case D3DTADDRESS_CLAMP: | 
 | 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_CLAMP); | 
 | 					break; | 
 | 				case D3DTADDRESS_BORDER: | 
 | 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_BORDER); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRRORONCE: | 
 | 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRRORONCE); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DSAMP_ADDRESSV: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTADDRESS_WRAP: | 
 | 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_WRAP); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRROR: | 
 | 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRROR); | 
 | 					break; | 
 | 				case D3DTADDRESS_CLAMP: | 
 | 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_CLAMP); | 
 | 					break; | 
 | 				case D3DTADDRESS_BORDER: | 
 | 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_BORDER); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRRORONCE: | 
 | 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRRORONCE); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DSAMP_ADDRESSW: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTADDRESS_WRAP: | 
 | 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_WRAP); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRROR: | 
 | 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRROR); | 
 | 					break; | 
 | 				case D3DTADDRESS_CLAMP: | 
 | 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_CLAMP); | 
 | 					break; | 
 | 				case D3DTADDRESS_BORDER: | 
 | 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_BORDER); | 
 | 					break; | 
 | 				case D3DTADDRESS_MIRRORONCE: | 
 | 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRRORONCE); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DSAMP_BORDERCOLOR: | 
 | 				renderer->setBorderColor(type, index, value); | 
 | 				break; | 
 | 			case D3DSAMP_MAGFILTER: | 
 | 				// NOTE: SwiftShader does not differentiate between minification and magnification filter | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTEXF_NONE: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter | 
 | 					break; | 
 | 				case D3DTEXF_POINT: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_POINT); | 
 | 					break; | 
 | 				case D3DTEXF_LINEAR: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR); | 
 | 					break; | 
 | 				case D3DTEXF_ANISOTROPIC: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC); | 
 | 					break; | 
 | 				case D3DTEXF_PYRAMIDALQUAD: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently | 
 | 					break; | 
 | 				case D3DTEXF_GAUSSIANQUAD: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently | 
 | 					break; | 
 | 				default: | 
 | 					return INVALIDCALL(); | 
 | 				}; | 
 | 				break; | 
 | 			case D3DSAMP_MINFILTER: | 
 | 				// NOTE: SwiftShader does not differentiate between minification and magnification filter | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTEXF_NONE: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter | 
 | 					break; | 
 | 				case D3DTEXF_POINT: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_POINT); | 
 | 					break; | 
 | 				case D3DTEXF_LINEAR: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR); | 
 | 					break; | 
 | 				case D3DTEXF_ANISOTROPIC: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC); | 
 | 					break; | 
 | 				case D3DTEXF_PYRAMIDALQUAD: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently | 
 | 					break; | 
 | 				case D3DTEXF_GAUSSIANQUAD: | 
 | 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently | 
 | 					break; | 
 | 				default: | 
 | 					return INVALIDCALL(); | 
 | 				}; | 
 | 				break; | 
 | 			case D3DSAMP_MIPFILTER: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTEXF_NONE: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_NONE); | 
 | 					break; | 
 | 				case D3DTEXF_POINT: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_POINT); | 
 | 					break; | 
 | 				case D3DTEXF_LINEAR: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR); | 
 | 					break; | 
 | 				case D3DTEXF_ANISOTROPIC: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter | 
 | 					break; | 
 | 				case D3DTEXF_PYRAMIDALQUAD: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter | 
 | 					break; | 
 | 				case D3DTEXF_GAUSSIANQUAD: | 
 | 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter | 
 | 					break; | 
 | 				default: | 
 | 					return INVALIDCALL(); | 
 | 				}; | 
 | 				break; | 
 | 			case D3DSAMP_MIPMAPLODBIAS: | 
 | 				if(value == D3DFMT_GET4)   // ATI hack to enable Fetch4 | 
 | 				{ | 
 | 					renderer->setGatherEnable(type, index, true); | 
 | 				} | 
 | 				else if(value == D3DFMT_GET1)   // ATI hack to disable Fetch4 | 
 | 				{ | 
 | 					renderer->setGatherEnable(type, index, false); | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes | 
 | 					renderer->setMipmapLOD(type, index, LOD); | 
 | 				} | 
 | 				break; | 
 | 			case D3DSAMP_MAXMIPLEVEL: | 
 | 				break; | 
 | 			case D3DSAMP_MAXANISOTROPY: | 
 | 				renderer->setMaxAnisotropy(type, index, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy)); | 
 | 				break; | 
 | 			case D3DSAMP_SRGBTEXTURE: | 
 | 				renderer->setReadSRGB(type, index, value != FALSE); | 
 | 				break; | 
 | 			case D3DSAMP_ELEMENTINDEX: | 
 | 				if(!init) UNIMPLEMENTED();   // Multi-element textures deprecated in favor of multiple render targets | 
 | 				break; | 
 | 			case D3DSAMP_DMAPOFFSET: | 
 | 			//	if(!init) UNIMPLEMENTED(); | 
 | 				break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else   // stateRecorder | 
 | 		{ | 
 | 			stateRecorder->setSamplerState(sampler, state, value); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetScissorRect(const RECT *rect) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const RECT *rect = 0x%0.8p", rect); | 
 |  | 
 | 		if(!rect) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			scissorRect = *rect; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setScissorRect(rect); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetSoftwareVertexProcessing(int software) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("int software = %d", software); | 
 |  | 
 | 		if(behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING && software == FALSE) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(behaviourFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING && software == TRUE) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		softwareVertexProcessing = (software != FALSE); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer9 *iVertexBuffer, unsigned int offset, unsigned int stride) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int stream = %d, IDirect3DVertexBuffer9 *data = 0x%0.8p, unsigned int offset = %d, unsigned int stride = %d", stream, iVertexBuffer, offset, stride); | 
 |  | 
 | 		Direct3DVertexBuffer9 *vertexBuffer = static_cast<Direct3DVertexBuffer9*>(iVertexBuffer); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(dataStream[stream] == vertexBuffer && streamOffset[stream] == offset && streamStride[stream] == stride) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(vertexBuffer) | 
 | 			{ | 
 | 				vertexBuffer->bind(); | 
 | 			} | 
 |  | 
 | 			if(dataStream[stream]) | 
 | 			{ | 
 | 				dataStream[stream]->unbind(); | 
 | 			} | 
 |  | 
 | 			dataStream[stream] = vertexBuffer; | 
 | 			streamOffset[stream] = offset; | 
 | 			streamStride[stream] = stride; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setStreamSource(stream, vertexBuffer, offset, stride); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetStreamSourceFreq(unsigned int streamNumber, unsigned int divider) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int streamNumber = %d, unsigned int divider = %d", streamNumber, divider); | 
 |  | 
 | 		if(!instancingEnabled) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			streamSourceFreq[streamNumber] = divider; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setStreamSourceFreq(streamNumber, divider); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetTexture(unsigned long sampler, IDirect3DBaseTexture9 *iBaseTexture) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 *texture = 0x%0.8p", sampler, iBaseTexture); | 
 |  | 
 | 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(sampler >= D3DVERTEXTEXTURESAMPLER0) | 
 | 		{ | 
 | 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0); | 
 | 		} | 
 |  | 
 | 		Direct3DBaseTexture9 *baseTexture = dynamic_cast<Direct3DBaseTexture9*>(iBaseTexture); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(texture[sampler] == baseTexture) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(baseTexture) | 
 | 			{ | 
 | 				baseTexture->bind();   // FIXME: Bind individual sub-surfaces? | 
 | 			} | 
 |  | 
 | 			if(texture[sampler]) | 
 | 			{ | 
 | 				texture[sampler]->unbind(); | 
 | 			} | 
 |  | 
 | 			texture[sampler] = baseTexture; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setTexture(sampler, baseTexture); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value); | 
 |  | 
 | 		if(stage < 0 || stage >= 8 || type < D3DTSS_COLOROP || type > D3DTSS_CONSTANT) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(!init && textureStageState[stage][type] == value) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			textureStageState[stage][type] = value; | 
 |  | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DTSS_COLOROP: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTOP_DISABLE: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE); | 
 | 					break; | 
 | 				case D3DTOP_SELECTARG1: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1); | 
 | 					break; | 
 | 				case D3DTOP_SELECTARG2: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE2X: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE4X: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X); | 
 | 					break; | 
 | 				case D3DTOP_ADD: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD); | 
 | 					break; | 
 | 				case D3DTOP_ADDSIGNED: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED); | 
 | 					break; | 
 | 				case D3DTOP_ADDSIGNED2X: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X); | 
 | 					break; | 
 | 				case D3DTOP_SUBTRACT: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT); | 
 | 					break; | 
 | 				case D3DTOP_ADDSMOOTH: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH); | 
 | 					break; | 
 | 				case D3DTOP_BLENDDIFFUSEALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDTEXTUREALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDFACTORALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDTEXTUREALPHAPM: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM); | 
 | 					break; | 
 | 				case D3DTOP_BLENDCURRENTALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA); | 
 | 					break; | 
 | 				case D3DTOP_PREMODULATE: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEALPHA_ADDCOLOR: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR); | 
 | 					break; | 
 | 				case D3DTOP_MODULATECOLOR_ADDALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BUMPENVMAP: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP); | 
 | 					break; | 
 | 				case D3DTOP_BUMPENVMAPLUMINANCE: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE); | 
 | 					break; | 
 | 				case D3DTOP_DOTPRODUCT3: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3); | 
 | 					break; | 
 | 				case D3DTOP_MULTIPLYADD: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD); | 
 | 					break; | 
 | 				case D3DTOP_LERP: | 
 | 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_COLORARG1: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_CONSTANT: | 
 | 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_COLORARG2: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_CONSTANT: | 
 | 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_ALPHAOP: | 
 | 				switch(value) | 
 | 				{ | 
 | 				case D3DTOP_DISABLE: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE); | 
 | 					break; | 
 | 				case D3DTOP_SELECTARG1: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1); | 
 | 					break; | 
 | 				case D3DTOP_SELECTARG2: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE2X: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X); | 
 | 					break; | 
 | 				case D3DTOP_MODULATE4X: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X); | 
 | 					break; | 
 | 				case D3DTOP_ADD: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD); | 
 | 					break; | 
 | 				case D3DTOP_ADDSIGNED: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED); | 
 | 					break; | 
 | 				case D3DTOP_ADDSIGNED2X: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X); | 
 | 					break; | 
 | 				case D3DTOP_SUBTRACT: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT); | 
 | 					break; | 
 | 				case D3DTOP_ADDSMOOTH: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH); | 
 | 					break; | 
 | 				case D3DTOP_BLENDDIFFUSEALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDTEXTUREALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDFACTORALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BLENDTEXTUREALPHAPM: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM); | 
 | 					break; | 
 | 				case D3DTOP_BLENDCURRENTALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA); | 
 | 					break; | 
 | 				case D3DTOP_PREMODULATE: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEALPHA_ADDCOLOR: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR); | 
 | 					break; | 
 | 				case D3DTOP_MODULATECOLOR_ADDALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR); | 
 | 					break; | 
 | 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA); | 
 | 					break; | 
 | 				case D3DTOP_BUMPENVMAP: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP); | 
 | 					break; | 
 | 				case D3DTOP_BUMPENVMAPLUMINANCE: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE); | 
 | 					break; | 
 | 				case D3DTOP_DOTPRODUCT3: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3); | 
 | 					break; | 
 | 				case D3DTOP_MULTIPLYADD: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD); | 
 | 					break; | 
 | 				case D3DTOP_LERP: | 
 | 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_ALPHAARG1: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_CONSTANT: | 
 | 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_ALPHAARG2: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_CONSTANT: | 
 | 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVMAT00: | 
 | 				renderer->setBumpmapMatrix(stage, 0, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVMAT01: | 
 | 				renderer->setBumpmapMatrix(stage, 1, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVMAT10: | 
 | 				renderer->setBumpmapMatrix(stage, 2, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVMAT11: | 
 | 				renderer->setBumpmapMatrix(stage, 3, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_TEXCOORDINDEX: | 
 | 				renderer->setTexCoordIndex(stage, value & 0x0000FFFF); | 
 |  | 
 | 				switch(value & 0xFFFF0000) | 
 | 				{ | 
 | 				case D3DTSS_TCI_PASSTHRU: | 
 | 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU); | 
 | 					break; | 
 | 				case D3DTSS_TCI_CAMERASPACENORMAL: | 
 | 					renderer->setTexCoordIndex(stage, stage); | 
 | 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL); | 
 | 					break; | 
 | 				case D3DTSS_TCI_CAMERASPACEPOSITION: | 
 | 					renderer->setTexCoordIndex(stage, stage); | 
 | 					renderer->setTexGen(stage, sw::TEXGEN_POSITION); | 
 | 					break; | 
 | 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR: | 
 | 					renderer->setTexCoordIndex(stage, stage); | 
 | 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION); | 
 | 					break; | 
 | 				case D3DTSS_TCI_SPHEREMAP: | 
 | 					renderer->setTexCoordIndex(stage, stage); | 
 | 					renderer->setTexGen(stage, sw::TEXGEN_SPHEREMAP); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVLSCALE: | 
 | 				renderer->setLuminanceScale(stage, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_BUMPENVLOFFSET: | 
 | 				renderer->setLuminanceOffset(stage, (float&)value); | 
 | 				break; | 
 | 			case D3DTSS_TEXTURETRANSFORMFLAGS: | 
 | 				switch(value & ~D3DTTFF_PROJECTED) | 
 | 				{ | 
 | 				case D3DTTFF_DISABLE: | 
 | 					renderer->setTextureTransform(stage, 0, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
 | 					break; | 
 | 				case D3DTTFF_COUNT1: | 
 | 					renderer->setTextureTransform(stage, 1, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
 | 					break; | 
 | 				case D3DTTFF_COUNT2: | 
 | 					renderer->setTextureTransform(stage, 2, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
 | 					break; | 
 | 				case D3DTTFF_COUNT3: | 
 | 					renderer->setTextureTransform(stage, 3, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
 | 					break; | 
 | 				case D3DTTFF_COUNT4: | 
 | 					renderer->setTextureTransform(stage, 4, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_COLORARG0: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_ALPHAARG0: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_DIFFUSE: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE); | 
 | 					break; | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEXTURE: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE); | 
 | 					break; | 
 | 				case D3DTA_TFACTOR: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR); | 
 | 					break; | 
 | 				case D3DTA_SPECULAR: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP); | 
 | 					break; | 
 | 				case D3DTA_CONSTANT: | 
 | 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 |  | 
 | 				switch(value & ~D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case 0: | 
 | 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT: | 
 | 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR); | 
 | 					break; | 
 | 				case D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA); | 
 | 					break; | 
 | 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE: | 
 | 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_RESULTARG: | 
 | 				switch(value & D3DTA_SELECTMASK) | 
 | 				{ | 
 | 				case D3DTA_CURRENT: | 
 | 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT); | 
 | 					break; | 
 | 				case D3DTA_TEMP: | 
 | 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP); | 
 | 					break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 				break; | 
 | 			case D3DTSS_CONSTANT: | 
 | 				renderer->setConstantColor(stage, value); | 
 | 				break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else   // stateRecorder | 
 | 		{ | 
 | 			stateRecorder->setTextureStageState(stage, type, value); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix); | 
 |  | 
 | 		if(!matrix) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			this->matrix[state] = *matrix; | 
 |  | 
 | 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41, | 
 | 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42, | 
 | 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43, | 
 | 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44); | 
 |  | 
 | 			switch(state) | 
 | 			{ | 
 | 			case D3DTS_WORLD: | 
 | 				renderer->setModelMatrix(M); | 
 | 				break; | 
 | 			case D3DTS_VIEW: | 
 | 				renderer->setViewMatrix(M); | 
 | 				break; | 
 | 			case D3DTS_PROJECTION: | 
 | 				renderer->setProjectionMatrix(M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE0: | 
 | 				renderer->setTextureMatrix(0, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE1: | 
 | 				renderer->setTextureMatrix(1, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE2: | 
 | 				renderer->setTextureMatrix(2, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE3: | 
 | 				renderer->setTextureMatrix(3, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE4: | 
 | 				renderer->setTextureMatrix(4, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE5: | 
 | 				renderer->setTextureMatrix(5, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE6: | 
 | 				renderer->setTextureMatrix(6, M); | 
 | 				break; | 
 | 			case D3DTS_TEXTURE7: | 
 | 				renderer->setTextureMatrix(7, M); | 
 | 				break; | 
 | 			default: | 
 | 				if(state > 256 && state < 512) | 
 | 				{ | 
 | 					renderer->setModelMatrix(M, state - 256); | 
 | 				} | 
 | 				else ASSERT(false); | 
 | 			} | 
 | 		} | 
 | 		else   // stateRecorder | 
 | 		{ | 
 | 			stateRecorder->setTransform(state, matrix); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9 *iVertexDeclaration) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DVertexDeclaration9 *declaration = 0x%0.8p", iVertexDeclaration); | 
 |  | 
 | 		Direct3DVertexDeclaration9 *vertexDeclaration = static_cast<Direct3DVertexDeclaration9*>(iVertexDeclaration); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(this->vertexDeclaration == vertexDeclaration) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(vertexDeclaration) | 
 | 			{ | 
 | 				vertexDeclaration->bind(); | 
 | 			} | 
 |  | 
 | 			if(this->vertexDeclaration) | 
 | 			{ | 
 | 				this->vertexDeclaration->unbind(); | 
 | 			} | 
 |  | 
 | 			this->vertexDeclaration = vertexDeclaration; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setVertexDeclaration(vertexDeclaration); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetVertexShader(IDirect3DVertexShader9 *iVertexShader) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DVertexShader9 *shader = 0x%0.8p", iVertexShader); | 
 |  | 
 | 		Direct3DVertexShader9 *vertexShader = static_cast<Direct3DVertexShader9*>(iVertexShader); | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			if(this->vertexShader == vertexShader) | 
 | 			{ | 
 | 				return D3D_OK; | 
 | 			} | 
 |  | 
 | 			if(vertexShader) | 
 | 			{ | 
 | 				vertexShader->bind(); | 
 | 			} | 
 |  | 
 | 			if(this->vertexShader) | 
 | 			{ | 
 | 				this->vertexShader->unbind(); | 
 | 			} | 
 |  | 
 | 			this->vertexShader = vertexShader; | 
 | 			vertexShaderDirty = true; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setVertexShader(vertexShader); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetVertexShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++) | 
 | 			{ | 
 | 				vertexShaderConstantB[startRegister + i] = constantData[i]; | 
 | 			} | 
 |  | 
 | 			vertexShaderConstantsBDirty = sw::max(startRegister + count, vertexShaderConstantsBDirty); | 
 | 			vertexShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setVertexShaderConstantB(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < MAX_VERTEX_SHADER_CONST; i++) | 
 | 			{ | 
 | 				vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0]; | 
 | 				vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1]; | 
 | 				vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2]; | 
 | 				vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3]; | 
 | 			} | 
 |  | 
 | 			vertexShaderConstantsFDirty = sw::max(startRegister + count, vertexShaderConstantsFDirty); | 
 | 			vertexShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setVertexShaderConstantF(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetVertexShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count); | 
 |  | 
 | 		if(!constantData) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++) | 
 | 			{ | 
 | 				vertexShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0]; | 
 | 				vertexShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1]; | 
 | 				vertexShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2]; | 
 | 				vertexShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3]; | 
 | 			} | 
 |  | 
 | 			vertexShaderConstantsIDirty = sw::max(startRegister + count, vertexShaderConstantsIDirty); | 
 | 			vertexShaderDirty = true;   // Reload DEF constants | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setVertexShaderConstantI(startRegister, constantData, count); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::SetViewport(const D3DVIEWPORT9 *viewport) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("const D3DVIEWPORT9 *viewport = 0x%0.8p", viewport); | 
 |  | 
 | 		if(!viewport)   // FIXME: Check if valid | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		if(!stateRecorder) | 
 | 		{ | 
 | 			this->viewport = *viewport; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			stateRecorder->setViewport(viewport); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	int Direct3DDevice9::ShowCursor(int show) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("int show = %d", show); | 
 |  | 
 | 		int oldValue = showCursor ? TRUE : FALSE; | 
 | 		showCursor = show != FALSE; | 
 |  | 
 | 		if(showCursor) | 
 | 		{ | 
 | 			sw::FrameBuffer::setCursorImage(cursor); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sw::FrameBuffer::setCursorImage(0); | 
 | 		} | 
 |  | 
 | 		return oldValue; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::StretchRect(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destSurface, const RECT *destRect, D3DTEXTUREFILTERTYPE filter) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p, const RECT *destRect = 0x%0.8p, D3DTEXTUREFILTERTYPE filter = %d", sourceSurface, sourceRect, destSurface, destRect, filter); | 
 |  | 
 | 		if(!sourceSurface || !destSurface || !validRectangle(sourceRect, sourceSurface) || !validRectangle(destRect, destSurface)) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DSURFACE_DESC sourceDescription; | 
 | 		D3DSURFACE_DESC destDescription; | 
 |  | 
 | 		sourceSurface->GetDesc(&sourceDescription); | 
 | 		destSurface->GetDesc(&destDescription); | 
 |  | 
 | 		if(sourceDescription.Pool != D3DPOOL_DEFAULT || destDescription.Pool != D3DPOOL_DEFAULT) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		Direct3DSurface9 *source = static_cast<Direct3DSurface9*>(sourceSurface); | 
 | 		Direct3DSurface9 *dest = static_cast<Direct3DSurface9*>(destSurface); | 
 |  | 
 | 		stretchRect(source, sourceRect, dest, destRect, filter); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::TestCooperativeLevel() | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("void"); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::UpdateSurface(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destinationSurface, const POINT *destPoint) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint); | 
 |  | 
 | 		if(!sourceSurface || !destinationSurface) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DSURFACE_DESC sourceDescription; | 
 | 		D3DSURFACE_DESC destinationDescription; | 
 |  | 
 | 		sourceSurface->GetDesc(&sourceDescription); | 
 | 		destinationSurface->GetDesc(&destinationDescription); | 
 |  | 
 | 		RECT sRect; | 
 | 		RECT dRect; | 
 |  | 
 | 		if(sourceRect) | 
 | 		{ | 
 | 			sRect.left = sourceRect->left; | 
 | 			sRect.top = sourceRect->top; | 
 | 			sRect.right = sourceRect->right; | 
 | 			sRect.bottom = sourceRect->bottom; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sRect.left = 0; | 
 | 			sRect.top = 0; | 
 | 			sRect.right = sourceDescription.Width; | 
 | 			sRect.bottom = sourceDescription.Height; | 
 | 		} | 
 |  | 
 | 		if(destPoint) | 
 | 		{ | 
 | 			dRect.left = destPoint->x; | 
 | 			dRect.top = destPoint->y; | 
 | 			dRect.right = destPoint->x + sRect.right - sRect.left; | 
 | 			dRect.bottom = destPoint->y + sRect.bottom - sRect.top; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			dRect.left = 0; | 
 | 			dRect.top = 0; | 
 | 			dRect.right = sRect.right - sRect.left; | 
 | 			dRect.bottom = sRect.bottom - sRect.top; | 
 | 		} | 
 |  | 
 | 		if(!validRectangle(&sRect, sourceSurface) || !validRectangle(&dRect, destinationSurface)) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		int sWidth = sRect.right - sRect.left; | 
 | 		int sHeight = sRect.bottom - sRect.top; | 
 |  | 
 | 		int dWidth = dRect.right - dRect.left; | 
 | 		int dHeight = dRect.bottom - dRect.top; | 
 |  | 
 | 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE || | 
 | 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE || | 
 | 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags | 
 | 		// destinationDescription.Pool != D3DPOOL_DEFAULT || | 
 | 		   sourceDescription.Format != destinationDescription.Format) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		sw::Surface *source = static_cast<Direct3DSurface9*>(sourceSurface); | 
 | 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destinationSurface); | 
 |  | 
 | 		unsigned char *sBuffer = (unsigned char*)source->lockExternal(sRect.left, sRect.top, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 | 		unsigned char *dBuffer = (unsigned char*)dest->lockExternal(dRect.left, dRect.top, 0, sw::LOCK_WRITEONLY, sw::PUBLIC); | 
 | 		int sPitch = source->getExternalPitchB(); | 
 | 		int dPitch = dest->getExternalPitchB(); | 
 |  | 
 | 		unsigned int width; | 
 | 		unsigned int height; | 
 | 		unsigned int bytes; | 
 |  | 
 | 		switch(sourceDescription.Format) | 
 | 		{ | 
 | 		case D3DFMT_DXT1: | 
 | 		case D3DFMT_ATI1: | 
 | 			width = (dWidth + 3) / 4; | 
 | 			height = (dHeight + 3) / 4; | 
 | 			bytes = width * 8;   // 64 bit per 4x4 block | 
 | 			break; | 
 | 		case D3DFMT_DXT2: | 
 | 		case D3DFMT_DXT3: | 
 | 		case D3DFMT_DXT4: | 
 | 		case D3DFMT_DXT5: | 
 | 		case D3DFMT_ATI2: | 
 | 			width = (dWidth + 3) / 4; | 
 | 			height = (dHeight + 3) / 4; | 
 | 			bytes = width * 16;   // 128 bit per 4x4 block | 
 | 			break; | 
 | 		default: | 
 | 			width = dWidth; | 
 | 			height = dHeight; | 
 | 			bytes = width * Direct3DSurface9::bytes(sourceDescription.Format); | 
 | 		} | 
 |  | 
 | 		if(sourceDescription.Format == D3DFMT_ATI1 || sourceDescription.Format == D3DFMT_ATI2) | 
 | 		{ | 
 | 			// Make the pitch correspond to 4 rows | 
 | 			sPitch *= 4; | 
 | 			dPitch *= 4; | 
 | 		} | 
 |  | 
 | 		for(unsigned int y = 0; y < height; y++) | 
 | 		{ | 
 | 			memcpy(dBuffer, sBuffer, bytes); | 
 |  | 
 | 			sBuffer += sPitch; | 
 | 			dBuffer += dPitch; | 
 | 		} | 
 |  | 
 | 		source->unlockExternal(); | 
 | 		dest->unlockExternal(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::UpdateTexture(IDirect3DBaseTexture9 *sourceTexture, IDirect3DBaseTexture9 *destinationTexture) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("IDirect3DBaseTexture9 *sourceTexture = 0x%0.8p, IDirect3DBaseTexture9 *destinationTexture = 0x%0.8p", sourceTexture, destinationTexture); | 
 |  | 
 | 		if(!sourceTexture || !destinationTexture) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		// FIXME: Check memory pools | 
 |  | 
 | 		D3DRESOURCETYPE type = sourceTexture->GetType(); | 
 |  | 
 | 		if(type != destinationTexture->GetType()) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		switch(type) | 
 | 		{ | 
 | 		case D3DRTYPE_TEXTURE: | 
 | 			{ | 
 | 				IDirect3DTexture9 *source; | 
 | 				IDirect3DTexture9 *dest; | 
 |  | 
 | 				sourceTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&source); | 
 | 				destinationTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&dest); | 
 |  | 
 | 				ASSERT(source && dest); | 
 |  | 
 | 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination | 
 | 				{ | 
 | 					IDirect3DSurface9 *sourceSurface; | 
 | 					IDirect3DSurface9 *destinationSurface; | 
 |  | 
 | 					source->GetSurfaceLevel(level, &sourceSurface); | 
 | 					dest->GetSurfaceLevel(level, &destinationSurface); | 
 |  | 
 | 					UpdateSurface(sourceSurface, 0, destinationSurface, 0); | 
 |  | 
 | 					sourceSurface->Release(); | 
 | 					destinationSurface->Release(); | 
 | 				} | 
 |  | 
 | 				source->Release(); | 
 | 				dest->Release(); | 
 | 			} | 
 | 			break; | 
 | 		case D3DRTYPE_VOLUMETEXTURE: | 
 | 			{ | 
 | 				IDirect3DVolumeTexture9 *source; | 
 | 				IDirect3DVolumeTexture9 *dest; | 
 |  | 
 | 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&source); | 
 | 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&dest); | 
 |  | 
 | 				ASSERT(source && dest); | 
 |  | 
 | 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination | 
 | 				{ | 
 | 					IDirect3DVolume9 *sourceVolume; | 
 | 					IDirect3DVolume9 *destinationVolume; | 
 |  | 
 | 					source->GetVolumeLevel(level, &sourceVolume); | 
 | 					dest->GetVolumeLevel(level, &destinationVolume); | 
 |  | 
 | 					updateVolume(sourceVolume, destinationVolume); | 
 |  | 
 | 					sourceVolume->Release(); | 
 | 					destinationVolume->Release(); | 
 | 				} | 
 |  | 
 | 				source->Release(); | 
 | 				dest->Release(); | 
 | 			} | 
 | 			break; | 
 | 		case D3DRTYPE_CUBETEXTURE: | 
 | 			{ | 
 | 				IDirect3DCubeTexture9 *source; | 
 | 				IDirect3DCubeTexture9 *dest; | 
 |  | 
 | 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&source); | 
 | 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&dest); | 
 |  | 
 | 				ASSERT(source && dest); | 
 |  | 
 | 				for(int face = 0; face < 6; face++) | 
 | 				{ | 
 | 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination | 
 | 					{ | 
 | 						IDirect3DSurface9 *sourceSurface; | 
 | 						IDirect3DSurface9 *destinationSurface; | 
 |  | 
 | 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface); | 
 | 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface); | 
 |  | 
 | 						UpdateSurface(sourceSurface, 0, destinationSurface, 0); | 
 |  | 
 | 						sourceSurface->Release(); | 
 | 						destinationSurface->Release(); | 
 | 					} | 
 | 				} | 
 |  | 
 | 				source->Release(); | 
 | 				dest->Release(); | 
 | 			} | 
 | 			break; | 
 | 		default: | 
 | 			UNIMPLEMENTED(); | 
 | 		} | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::ValidateDevice(unsigned long *numPasses) | 
 | 	{ | 
 | 		CriticalSection cs(this); | 
 |  | 
 | 		TRACE("unsigned long *numPasses = 0x%0.8p", numPasses); | 
 |  | 
 | 		if(!numPasses) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		*numPasses = 1; | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::getAdapterDisplayMode(unsigned int adapter, D3DDISPLAYMODE *mode) | 
 | 	{ | 
 | 		return d3d9->GetAdapterDisplayMode(adapter, mode); | 
 | 	} | 
 |  | 
 | 	int Direct3DDevice9::typeStride(unsigned char streamType) | 
 | 	{ | 
 | 		static int LUT[] = | 
 | 		{ | 
 | 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.) | 
 | 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.) | 
 | 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.) | 
 | 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float | 
 | 			4,	// D3DDECLTYPE_D3DCOLOR  =  4,  // 4D packed unsigned bytes mapped to 0. to 1. range. Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A) | 
 | 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte | 
 | 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.) | 
 | 			8,	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short | 
 | 			4,	// D3DDECLTYPE_UBYTE4N   =  8,  // Each of 4 bytes is normalized by dividing to 255.0 | 
 | 			4,	// D3DDECLTYPE_SHORT2N   =  9,  // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1) | 
 | 			8,	// D3DDECLTYPE_SHORT4N   = 10,  // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0) | 
 | 			4,	// D3DDECLTYPE_USHORT2N  = 11,  // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1) | 
 | 			8,	// D3DDECLTYPE_USHORT4N  = 12,  // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0) | 
 | 			4,	// D3DDECLTYPE_UDEC3     = 13,  // 3D unsigned 10 10 10 format expanded to (value, value, value, 1) | 
 | 			4,	// D3DDECLTYPE_DEC3N     = 14,  // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1) | 
 | 			4,	// D3DDECLTYPE_FLOAT16_2 = 15,  // Two 16-bit floating point values, expanded to (value, value, 0, 1) | 
 | 			8,	// D3DDECLTYPE_FLOAT16_4 = 16,  // Four 16-bit floating point values | 
 | 			0,	// D3DDECLTYPE_UNUSED    = 17,  // When the type field in a decl is unused. | 
 | 		}; | 
 |  | 
 | 		return LUT[streamType]; | 
 | 	} | 
 |  | 
 | 	bool Direct3DDevice9::instanceData() | 
 | 	{ | 
 | 		ASSERT(vertexDeclaration); | 
 |  | 
 | 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1]; | 
 | 		unsigned int numElements; | 
 | 		vertexDeclaration->GetDeclaration(vertexElement, &numElements); | 
 |  | 
 | 		bool instanceData = false; | 
 |  | 
 | 		for(unsigned int i = 0; i < numElements - 1; i++) | 
 | 		{ | 
 | 			unsigned short stream = vertexElement[i].Stream; | 
 |  | 
 | 			if(stream != 0) | 
 | 			{ | 
 | 				instanceData = instanceData || (streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA) != 0; | 
 | 			} | 
 | 		} | 
 |  | 
 | 		return instanceData; | 
 | 	} | 
 |  | 
 | 	bool Direct3DDevice9::bindResources(Direct3DIndexBuffer9 *indexBuffer) | 
 | 	{ | 
 | 		if(!bindViewport()) | 
 | 		{ | 
 | 			return false;   // Zero-area target region | 
 | 		} | 
 |  | 
 | 		bindTextures(); | 
 | 		bindIndexBuffer(indexBuffer); | 
 | 		bindShaderConstants(); | 
 | 		bindLights(); | 
 |  | 
 | 		return true; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::bindVertexStreams(int base, bool instancing, int instance) | 
 | 	{ | 
 | 		ASSERT(vertexDeclaration); | 
 |  | 
 | 		renderer->resetInputStreams(vertexDeclaration->isPreTransformed()); | 
 |  | 
 | 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1]; | 
 | 		unsigned int numElements; | 
 | 		vertexDeclaration->GetDeclaration(vertexElement, &numElements); | 
 |  | 
 | 		// Bind vertex data streams | 
 | 		for(unsigned int i = 0; i < numElements - 1; i++) | 
 | 		{ | 
 | 			unsigned short stream = vertexElement[i].Stream; | 
 | 			unsigned short offset = vertexElement[i].Offset; | 
 | 			unsigned char type = vertexElement[i].Type; | 
 | 			unsigned char method = vertexElement[i].Method; | 
 | 			unsigned char usage = vertexElement[i].Usage; | 
 | 			unsigned char index = vertexElement[i].UsageIndex; | 
 |  | 
 | 			ASSERT(method == D3DDECLMETHOD_DEFAULT);	// FIXME: Unimplemented | 
 |  | 
 | 			if(!dataStream[stream]) | 
 | 			{ | 
 | 				continue; | 
 | 			} | 
 |  | 
 | 			Direct3DVertexBuffer9 *streamBuffer = dataStream[stream]; | 
 | 			sw::Resource *resource = streamBuffer->getResource(); | 
 | 			const void *buffer = ((char*)resource->data() + streamOffset[stream]) + offset; | 
 |  | 
 | 			int stride = streamStride[stream]; | 
 |  | 
 | 			if(instancing && streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA) | 
 | 			{ | 
 | 				int instanceFrequency = streamSourceFreq[stream] & ~D3DSTREAMSOURCE_INSTANCEDATA; | 
 | 				buffer = (char*)buffer + stride * (instance / instanceFrequency); | 
 |  | 
 | 				stride = 0; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				buffer = (char*)buffer + stride * base; | 
 | 			} | 
 |  | 
 | 			sw::Stream attribute(resource, buffer, stride); | 
 |  | 
 | 			switch(type) | 
 | 			{ | 
 | 			case D3DDECLTYPE_FLOAT1:    attribute.define(sw::STREAMTYPE_FLOAT, 1, false);  break; | 
 | 			case D3DDECLTYPE_FLOAT2:    attribute.define(sw::STREAMTYPE_FLOAT, 2, false);  break; | 
 | 			case D3DDECLTYPE_FLOAT3:    attribute.define(sw::STREAMTYPE_FLOAT, 3, false);  break; | 
 | 			case D3DDECLTYPE_FLOAT4:    attribute.define(sw::STREAMTYPE_FLOAT, 4, false);  break; | 
 | 			case D3DDECLTYPE_D3DCOLOR:  attribute.define(sw::STREAMTYPE_COLOR, 4, false);  break; | 
 | 			case D3DDECLTYPE_UBYTE4:    attribute.define(sw::STREAMTYPE_BYTE, 4, false);   break; | 
 | 			case D3DDECLTYPE_SHORT2:    attribute.define(sw::STREAMTYPE_SHORT, 2, false);  break; | 
 | 			case D3DDECLTYPE_SHORT4:    attribute.define(sw::STREAMTYPE_SHORT, 4, false);  break; | 
 | 			case D3DDECLTYPE_UBYTE4N:   attribute.define(sw::STREAMTYPE_BYTE, 4, true);    break; | 
 | 			case D3DDECLTYPE_SHORT2N:   attribute.define(sw::STREAMTYPE_SHORT, 2, true);   break; | 
 | 			case D3DDECLTYPE_SHORT4N:   attribute.define(sw::STREAMTYPE_SHORT, 4, true);   break; | 
 | 			case D3DDECLTYPE_USHORT2N:  attribute.define(sw::STREAMTYPE_USHORT, 2, true);  break; | 
 | 			case D3DDECLTYPE_USHORT4N:  attribute.define(sw::STREAMTYPE_USHORT, 4, true);  break; | 
 | 			case D3DDECLTYPE_UDEC3:     attribute.define(sw::STREAMTYPE_UDEC3, 3, false);  break; | 
 | 			case D3DDECLTYPE_DEC3N:     attribute.define(sw::STREAMTYPE_DEC3N, 3, true);   break; | 
 | 			case D3DDECLTYPE_FLOAT16_2: attribute.define(sw::STREAMTYPE_HALF, 2, false);   break; | 
 | 			case D3DDECLTYPE_FLOAT16_4: attribute.define(sw::STREAMTYPE_HALF, 4, false);   break; | 
 | 			case D3DDECLTYPE_UNUSED:    attribute.defaults();                              break; | 
 | 			default: | 
 | 				ASSERT(false); | 
 | 			} | 
 |  | 
 | 			if(vertexShader) | 
 | 			{ | 
 | 				const sw::VertexShader *shader = vertexShader->getVertexShader(); | 
 |  | 
 | 				if(!vertexDeclaration->isPreTransformed()) | 
 | 				{ | 
 | 					for(int i = 0; i < MAX_VERTEX_INPUTS; i++) | 
 | 					{ | 
 | 						const sw::Shader::Semantic& input = shader->getInput(i); | 
 | 						if((usage == input.usage) && (index == input.index)) | 
 | 						{ | 
 | 							renderer->setInputStream(i, attribute); | 
 |  | 
 | 							break; | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 				else   // Bind directly to the output | 
 | 				{ | 
 | 					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++) | 
 | 					{ | 
 | 						const sw::Shader::Semantic& output = shader->getOutput(i, 0); | 
 | 						if(((usage == output.usage) || (usage == D3DDECLUSAGE_POSITIONT && output.usage == D3DDECLUSAGE_POSITION)) && | 
 | 						   (index == output.index)) | 
 | 						{ | 
 | 							renderer->setInputStream(i, attribute); | 
 |  | 
 | 							break; | 
 | 						} | 
 | 					} | 
 | 				} | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				switch(usage) | 
 | 				{ | 
 | 				case D3DDECLUSAGE_POSITION:     renderer->setInputStream(sw::Position, attribute);                                       break; | 
 | 				case D3DDECLUSAGE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);                                    break; | 
 | 				case D3DDECLUSAGE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute.define(sw::STREAMTYPE_INDICES, 1)); break; | 
 | 				case D3DDECLUSAGE_NORMAL:       renderer->setInputStream(sw::Normal, attribute.define(sw::STREAMTYPE_FLOAT, 3));         break; | 
 | 				case D3DDECLUSAGE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute.define(sw::STREAMTYPE_FLOAT, 1));      break; | 
 | 				case D3DDECLUSAGE_TEXCOORD:     renderer->setInputStream(sw::TexCoord0 + index, attribute);                              break; | 
 | 				case D3DDECLUSAGE_TANGENT:      /* Ignored */                                                                            break; | 
 | 				case D3DDECLUSAGE_BINORMAL:     /* Ignored */                                                                            break; | 
 | 				case D3DDECLUSAGE_TESSFACTOR:   UNIMPLEMENTED();                                                                         break; | 
 | 				case D3DDECLUSAGE_POSITIONT:    renderer->setInputStream(sw::PositionT, attribute.define(sw::STREAMTYPE_FLOAT, 4));      break; | 
 | 				case D3DDECLUSAGE_COLOR:        renderer->setInputStream(sw::Color0 + index, attribute.define(sw::STREAMTYPE_COLOR, 4)); break; | 
 | 				case D3DDECLUSAGE_FOG:          /* Ignored */                                                                            break; | 
 | 				case D3DDECLUSAGE_DEPTH:        /* Ignored */                                                                            break; | 
 | 				case D3DDECLUSAGE_SAMPLE:       UNIMPLEMENTED();                                                                         break; | 
 | 				default: | 
 | 					ASSERT(false); | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::bindIndexBuffer(Direct3DIndexBuffer9 *indexBuffer) | 
 | 	{ | 
 | 		sw::Resource *resource = 0; | 
 |  | 
 | 		if(indexBuffer) | 
 | 		{ | 
 | 			resource = indexBuffer->getResource(); | 
 | 		} | 
 |  | 
 | 		renderer->setIndexBuffer(resource); | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::bindShaderConstants() | 
 | 	{ | 
 | 		if(pixelShaderDirty) | 
 | 		{ | 
 | 			if(pixelShader) | 
 | 			{ | 
 | 				if(pixelShaderConstantsBDirty) | 
 | 				{ | 
 | 					renderer->setPixelShaderConstantB(0, pixelShaderConstantB, pixelShaderConstantsBDirty); | 
 | 				} | 
 |  | 
 | 				if(pixelShaderConstantsFDirty) | 
 | 				{ | 
 | 					renderer->setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty); | 
 | 				} | 
 |  | 
 | 				if(pixelShaderConstantsIDirty) | 
 | 				{ | 
 | 					renderer->setPixelShaderConstantI(0, pixelShaderConstantI[0], pixelShaderConstantsIDirty); | 
 | 				} | 
 |  | 
 | 				renderer->setPixelShader(pixelShader->getPixelShader());   // Loads shader constants set with DEF | 
 | 				pixelShaderConstantsBDirty = pixelShader->getPixelShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty | 
 | 				pixelShaderConstantsFDirty = pixelShader->getPixelShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty | 
 | 				pixelShaderConstantsIDirty = pixelShader->getPixelShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				renderer->setPixelShader(0); | 
 | 			} | 
 |  | 
 | 			pixelShaderDirty = false; | 
 | 		} | 
 |  | 
 | 		if(vertexShaderDirty) | 
 | 		{ | 
 | 			if(vertexShader) | 
 | 			{ | 
 | 				if(vertexShaderConstantsBDirty) | 
 | 				{ | 
 | 					renderer->setVertexShaderConstantB(0, vertexShaderConstantB, vertexShaderConstantsBDirty); | 
 | 				} | 
 |  | 
 | 				if(vertexShaderConstantsFDirty) | 
 | 				{ | 
 | 					renderer->setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty); | 
 | 				} | 
 |  | 
 | 				if(vertexShaderConstantsIDirty) | 
 | 				{ | 
 | 					renderer->setVertexShaderConstantI(0, vertexShaderConstantI[0], vertexShaderConstantsIDirty); | 
 | 				} | 
 |  | 
 | 				renderer->setVertexShader(vertexShader->getVertexShader());   // Loads shader constants set with DEF | 
 | 				vertexShaderConstantsBDirty = vertexShader->getVertexShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty | 
 | 				vertexShaderConstantsFDirty = vertexShader->getVertexShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty | 
 | 				vertexShaderConstantsIDirty = vertexShader->getVertexShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				renderer->setVertexShader(0); | 
 | 			} | 
 |  | 
 | 			vertexShaderDirty = false; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::bindLights() | 
 | 	{ | 
 | 		if(!lightsDirty) return; | 
 |  | 
 | 		Lights::iterator i = light.begin(); | 
 | 		int active = 0; | 
 |  | 
 | 		// Set and enable renderer lights | 
 | 		while(active < 8) | 
 | 		{ | 
 | 			while(i != light.end() && !i->second.enable) | 
 | 			{ | 
 | 				i++; | 
 | 			} | 
 |  | 
 | 			if(i == light.end()) | 
 | 			{ | 
 | 				break; | 
 | 			} | 
 |  | 
 | 			const Light &l = i->second; | 
 |  | 
 | 			sw::Point position(l.Position.x, l.Position.y, l.Position.z); | 
 | 			sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a); | 
 | 			sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a); | 
 | 			sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a); | 
 | 			sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z); | 
 |  | 
 | 			renderer->setLightDiffuse(active, diffuse); | 
 | 			renderer->setLightSpecular(active, specular); | 
 | 			renderer->setLightAmbient(active, ambient); | 
 |  | 
 | 			if(l.Type == D3DLIGHT_DIRECTIONAL) | 
 | 			{ | 
 | 				// FIXME: Unsupported, make it a positional light far away without falloff | 
 | 				renderer->setLightPosition(active, -1e10f * direction); | 
 | 				renderer->setLightRange(active, l.Range); | 
 | 				renderer->setLightAttenuation(active, 1, 0, 0); | 
 | 			} | 
 | 			else if(l.Type == D3DLIGHT_SPOT) | 
 | 			{ | 
 | 				// FIXME: Unsupported, make it a positional light | 
 | 				renderer->setLightPosition(active, position); | 
 | 				renderer->setLightRange(active, l.Range); | 
 | 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				renderer->setLightPosition(active, position); | 
 | 				renderer->setLightRange(active, l.Range); | 
 | 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2); | 
 | 			} | 
 |  | 
 | 			renderer->setLightEnable(active, true); | 
 |  | 
 | 			active++; | 
 | 			i++; | 
 | 		} | 
 |  | 
 | 		// Remaining lights are disabled | 
 | 		while(active < 8) | 
 | 		{ | 
 | 			renderer->setLightEnable(active, false); | 
 |  | 
 | 			active++; | 
 | 		} | 
 |  | 
 | 		lightsDirty = false; | 
 | 	} | 
 |  | 
 | 	bool Direct3DDevice9::bindViewport() | 
 | 	{ | 
 | 		if(viewport.Width <= 0 || viewport.Height <= 0) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		if(scissorEnable) | 
 | 		{ | 
 | 			if(scissorRect.left >= scissorRect.right || scissorRect.top >= scissorRect.bottom) | 
 | 			{ | 
 | 				return false; | 
 | 			} | 
 |  | 
 | 			sw::Rect scissor; | 
 | 			scissor.x0 = scissorRect.left; | 
 | 			scissor.x1 = scissorRect.right; | 
 | 			scissor.y0 = scissorRect.top; | 
 | 			scissor.y1 = scissorRect.bottom; | 
 |  | 
 | 			renderer->setScissor(scissor); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			sw::Rect scissor; | 
 | 			scissor.x0 = viewport.X; | 
 | 			scissor.x1 = viewport.X + viewport.Width; | 
 | 			scissor.y0 = viewport.Y; | 
 | 			scissor.y1 = viewport.Y + viewport.Height; | 
 |  | 
 | 			renderer->setScissor(scissor); | 
 | 		} | 
 |  | 
 | 		sw::Viewport view; | 
 | 		view.x0 = (float)viewport.X; | 
 | 		view.y0 = (float)viewport.Y + viewport.Height; | 
 | 		view.width = (float)viewport.Width; | 
 | 		view.height = -(float)viewport.Height; | 
 | 		view.minZ = viewport.MinZ; | 
 | 		view.maxZ = viewport.MaxZ; | 
 |  | 
 | 		renderer->setViewport(view); | 
 |  | 
 | 		return true; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::bindTextures() | 
 | 	{ | 
 | 		for(int sampler = 0; sampler < 16 + 4; sampler++) | 
 | 		{ | 
 | 			Direct3DBaseTexture9 *baseTexture = texture[sampler]; | 
 |  | 
 | 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX; | 
 | 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group | 
 |  | 
 | 			bool textureUsed = false; | 
 |  | 
 | 			if(type == sw::SAMPLER_PIXEL && pixelShader) | 
 | 			{ | 
 | 				textureUsed = pixelShader->getPixelShader()->usesSampler(index); | 
 | 			} | 
 | 			else if(type == sw::SAMPLER_VERTEX && vertexShader) | 
 | 			{ | 
 | 				textureUsed = vertexShader->getVertexShader()->usesSampler(index); | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				textureUsed = true;   // FIXME: Check fixed-function use? | 
 | 			} | 
 |  | 
 | 			sw::Resource *resource = 0; | 
 |  | 
 | 			if(baseTexture && textureUsed) | 
 | 			{ | 
 | 				resource = baseTexture->getResource(); | 
 | 			} | 
 |  | 
 | 			renderer->setTextureResource(sampler, resource); | 
 |  | 
 | 			if(baseTexture && textureUsed) | 
 | 			{ | 
 | 				baseTexture->GenerateMipSubLevels(); | 
 | 			} | 
 |  | 
 | 			if(baseTexture && textureUsed) | 
 | 			{ | 
 | 				int levelCount = baseTexture->getInternalLevelCount(); | 
 |  | 
 | 				int textureLOD = baseTexture->GetLOD(); | 
 | 				int samplerLOD = samplerState[sampler][D3DSAMP_MAXMIPLEVEL]; | 
 | 				int LOD = textureLOD > samplerLOD ? textureLOD : samplerLOD; | 
 |  | 
 | 				if(samplerState[sampler][D3DSAMP_MIPFILTER] == D3DTEXF_NONE) | 
 | 				{ | 
 | 					LOD = 0; | 
 | 				} | 
 |  | 
 | 				switch(baseTexture->GetType()) | 
 | 				{ | 
 | 				case D3DRTYPE_TEXTURE: | 
 | 					{ | 
 | 						Direct3DTexture9 *texture = dynamic_cast<Direct3DTexture9*>(baseTexture); | 
 | 						Direct3DSurface9 *surface; | 
 |  | 
 | 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
 | 						{ | 
 | 							int surfaceLevel = mipmapLevel; | 
 |  | 
 | 							if(surfaceLevel < LOD) | 
 | 							{ | 
 | 								surfaceLevel = LOD; | 
 | 							} | 
 |  | 
 | 							if(surfaceLevel < 0) | 
 | 							{ | 
 | 								surfaceLevel = 0; | 
 | 							} | 
 | 							else if(surfaceLevel >= levelCount) | 
 | 							{ | 
 | 								surfaceLevel = levelCount - 1; | 
 | 							} | 
 |  | 
 | 							surface = texture->getInternalSurfaceLevel(surfaceLevel); | 
 | 							renderer->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D); | 
 | 						} | 
 | 					} | 
 | 					break; | 
 | 				case D3DRTYPE_CUBETEXTURE: | 
 | 					for(int face = 0; face < 6; face++) | 
 | 					{ | 
 | 						Direct3DCubeTexture9 *cubeTexture = dynamic_cast<Direct3DCubeTexture9*>(baseTexture); | 
 | 						Direct3DSurface9 *surface; | 
 |  | 
 | 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
 | 						{ | 
 | 							int surfaceLevel = mipmapLevel; | 
 |  | 
 | 							if(surfaceLevel < LOD) | 
 | 							{ | 
 | 								surfaceLevel = LOD; | 
 | 							} | 
 |  | 
 | 							if(surfaceLevel < 0) | 
 | 							{ | 
 | 								surfaceLevel = 0; | 
 | 							} | 
 | 							else if(surfaceLevel >= levelCount) | 
 | 							{ | 
 | 								surfaceLevel = levelCount - 1; | 
 | 							} | 
 |  | 
 | 							surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel); | 
 | 							renderer->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE); | 
 | 						} | 
 | 					} | 
 | 					break; | 
 | 				case D3DRTYPE_VOLUMETEXTURE: | 
 | 					{ | 
 | 						Direct3DVolumeTexture9 *volumeTexture = dynamic_cast<Direct3DVolumeTexture9*>(baseTexture); | 
 | 						Direct3DVolume9 *volume; | 
 |  | 
 | 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++) | 
 | 						{ | 
 | 							int surfaceLevel = mipmapLevel; | 
 |  | 
 | 							if(surfaceLevel < LOD) | 
 | 							{ | 
 | 								surfaceLevel = LOD; | 
 | 							} | 
 |  | 
 | 							if(surfaceLevel < 0) | 
 | 							{ | 
 | 								surfaceLevel = 0; | 
 | 							} | 
 | 							else if(surfaceLevel >= levelCount) | 
 | 							{ | 
 | 								surfaceLevel = levelCount - 1; | 
 | 							} | 
 |  | 
 | 							volume = volumeTexture->getInternalVolumeLevel(surfaceLevel); | 
 | 							renderer->setTextureLevel(sampler, 0, mipmapLevel, volume, sw::TEXTURE_3D); | 
 | 						} | 
 | 					} | 
 | 					break; | 
 | 				default: | 
 | 					UNIMPLEMENTED(); | 
 | 				} | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				renderer->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL); | 
 | 			} | 
 | 		} | 
 | 	} | 
 |  | 
 | 	bool Direct3DDevice9::isRecording() const | 
 | 	{ | 
 | 		return stateRecorder != 0; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::setOcclusionEnabled(bool enable) | 
 | 	{ | 
 | 		renderer->setOcclusionEnabled(enable); | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::removeQuery(sw::Query *query) | 
 | 	{ | 
 | 		renderer->removeQuery(query); | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::addQuery(sw::Query *query) | 
 | 	{ | 
 | 		renderer->addQuery(query); | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::stretchRect(Direct3DSurface9 *source, const RECT *sourceRect, Direct3DSurface9 *dest, const RECT *destRect, D3DTEXTUREFILTERTYPE filter) | 
 | 	{ | 
 | 		D3DSURFACE_DESC sourceDescription; | 
 | 		D3DSURFACE_DESC destDescription; | 
 |  | 
 | 		source->GetDesc(&sourceDescription); | 
 | 		dest->GetDesc(&destDescription); | 
 |  | 
 | 		int sWidth = source->getWidth(); | 
 | 		int sHeight = source->getHeight(); | 
 | 		int dWidth = dest->getWidth(); | 
 | 		int dHeight = dest->getHeight(); | 
 |  | 
 | 		sw::Rect sRect(0, 0, sWidth, sHeight); | 
 | 		sw::Rect dRect(0, 0, dWidth, dHeight); | 
 |  | 
 | 		if(sourceRect) | 
 | 		{ | 
 | 			sRect.x0 = sourceRect->left; | 
 | 			sRect.y0 = sourceRect->top; | 
 | 			sRect.x1 = sourceRect->right; | 
 | 			sRect.y1 = sourceRect->bottom; | 
 | 		} | 
 |  | 
 | 		if(destRect) | 
 | 		{ | 
 | 			dRect.x0 = destRect->left; | 
 | 			dRect.y0 = destRect->top; | 
 | 			dRect.x1 = destRect->right; | 
 | 			dRect.y1 = destRect->bottom; | 
 | 		} | 
 |  | 
 | 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0); | 
 | 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat(); | 
 | 		bool depthStencil = (sourceDescription.Usage & D3DUSAGE_DEPTHSTENCIL) == D3DUSAGE_DEPTHSTENCIL; | 
 | 		bool alpha0xFF = false; | 
 |  | 
 | 		if((sourceDescription.Format == D3DFMT_A8R8G8B8 && destDescription.Format == D3DFMT_X8R8G8B8) || | 
 | 		   (sourceDescription.Format == D3DFMT_X8R8G8B8 && destDescription.Format == D3DFMT_A8R8G8B8)) | 
 | 		{ | 
 | 			equalFormats = true; | 
 | 			alpha0xFF = true; | 
 | 		} | 
 |  | 
 | 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check | 
 | 		{ | 
 | 			if(source->hasDepth()) | 
 | 			{ | 
 | 				byte *sourceBuffer = (byte*)source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 | 				byte *destBuffer = (byte*)dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC); | 
 |  | 
 | 				unsigned int width = source->getWidth(); | 
 | 				unsigned int height = source->getHeight(); | 
 | 				unsigned int pitch = source->getInternalPitchB(); | 
 |  | 
 | 				for(unsigned int y = 0; y < height; y++) | 
 | 				{ | 
 | 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes | 
 |  | 
 | 					sourceBuffer += pitch; | 
 | 					destBuffer += pitch; | 
 | 				} | 
 |  | 
 | 				source->unlockInternal(); | 
 | 				dest->unlockInternal(); | 
 | 			} | 
 |  | 
 | 			if(source->hasStencil()) | 
 | 			{ | 
 | 				byte *sourceBuffer = (byte*)source->lockStencil(0, 0, 0, sw::PUBLIC); | 
 | 				byte *destBuffer = (byte*)dest->lockStencil(0, 0, 0, sw::PUBLIC); | 
 |  | 
 | 				unsigned int width = source->getWidth(); | 
 | 				unsigned int height = source->getHeight(); | 
 | 				unsigned int pitch = source->getStencilPitchB(); | 
 |  | 
 | 				for(unsigned int y = 0; y < height; y++) | 
 | 				{ | 
 | 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes | 
 |  | 
 | 					sourceBuffer += pitch; | 
 | 					destBuffer += pitch; | 
 | 				} | 
 |  | 
 | 				source->unlockStencil(); | 
 | 				dest->unlockStencil(); | 
 | 			} | 
 | 		} | 
 | 		else if(!scaling && equalFormats) | 
 | 		{ | 
 | 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 | 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, sw::LOCK_READWRITE, sw::PUBLIC); | 
 | 			unsigned int sourcePitch = source->getInternalPitchB(); | 
 | 			unsigned int destPitch = dest->getInternalPitchB(); | 
 |  | 
 | 			unsigned int width = dRect.x1 - dRect.x0; | 
 | 			unsigned int height = dRect.y1 - dRect.y0; | 
 | 			unsigned int bytes = width * sw::Surface::bytes(source->getInternalFormat()); | 
 |  | 
 | 			for(unsigned int y = 0; y < height; y++) | 
 | 			{ | 
 | 				memcpy(destBytes, sourceBytes, bytes); | 
 |  | 
 | 				if(alpha0xFF) | 
 | 				{ | 
 | 					for(unsigned int x = 0; x < width; x++) | 
 | 					{ | 
 | 						destBytes[4 * x + 3] = 0xFF; | 
 | 					} | 
 | 				} | 
 |  | 
 | 				sourceBytes += sourcePitch; | 
 | 				destBytes += destPitch; | 
 | 			} | 
 |  | 
 | 			source->unlockInternal(); | 
 | 			dest->unlockInternal(); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			renderer->blit(source, sRect, dest, dRect, filter >= D3DTEXF_LINEAR); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	long Direct3DDevice9::updateVolume(IDirect3DVolume9 *sourceVolume, IDirect3DVolume9 *destinationVolume) | 
 | 	{ | 
 | 		TRACE("IDirect3DVolume9 *sourceVolume = 0x%0.8p, IDirect3DVolume9 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume); | 
 |  | 
 | 		if(!sourceVolume || !destinationVolume) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		D3DVOLUME_DESC sourceDescription; | 
 | 		D3DVOLUME_DESC destinationDescription; | 
 |  | 
 | 		sourceVolume->GetDesc(&sourceDescription); | 
 | 		destinationVolume->GetDesc(&destinationDescription); | 
 |  | 
 | 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM || | 
 | 		   destinationDescription.Pool != D3DPOOL_DEFAULT || | 
 | 		   sourceDescription.Format != destinationDescription.Format || | 
 | 		   sourceDescription.Width  != destinationDescription.Width || | 
 | 		   sourceDescription.Height != destinationDescription.Height || | 
 | 		   sourceDescription.Depth  != destinationDescription.Depth) | 
 | 		{ | 
 | 			return INVALIDCALL(); | 
 | 		} | 
 |  | 
 | 		sw::Surface *source = static_cast<Direct3DVolume9*>(sourceVolume); | 
 | 		sw::Surface *dest = static_cast<Direct3DVolume9*>(destinationVolume); | 
 |  | 
 | 		if(source->getExternalPitchB() != dest->getExternalPitchB() || | 
 | 		   source->getExternalSliceB() != dest->getExternalSliceB()) | 
 | 		{ | 
 | 			UNIMPLEMENTED(); | 
 | 		} | 
 |  | 
 | 		void *sBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); | 
 | 		void *dBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC); | 
 |  | 
 | 		memcpy(dBuffer, sBuffer, source->getExternalSliceB() * sourceDescription.Depth); | 
 |  | 
 | 		source->unlockExternal(); | 
 | 		dest->unlockExternal(); | 
 |  | 
 | 		return D3D_OK; | 
 | 	} | 
 |  | 
 | 	bool Direct3DDevice9::validRectangle(const RECT *rect, IDirect3DSurface9 *surface) | 
 | 	{ | 
 | 		if(!rect) | 
 | 		{ | 
 | 			return true; | 
 | 		} | 
 |  | 
 | 		if(rect->right <= rect->left || rect->bottom <= rect->top) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		if(rect->left < 0 || rect->top < 0) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		D3DSURFACE_DESC description; | 
 | 		surface->GetDesc(&description); | 
 |  | 
 | 		if(rect->right > (int)description.Width || rect->bottom > (int)description.Height) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		return true; | 
 | 	} | 
 |  | 
 | 	void Direct3DDevice9::configureFPU() | 
 | 	{ | 
 | 	//	_controlfp(_PC_24, _MCW_PC);     // Single-precision | 
 | 		_controlfp(_MCW_EM, _MCW_EM);    // Mask all exceptions | 
 | 		_controlfp(_RC_NEAR, _MCW_RC);   // Round to nearest | 
 | 	} | 
 | } |