Home | History | Annotate | Download | only in D3D8
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "Direct3DDevice8.hpp"
     16 
     17 #include "Direct3D8.hpp"
     18 #include "Direct3DSurface8.hpp"
     19 #include "Direct3DIndexBuffer8.hpp"
     20 #include "Direct3DVertexBuffer8.hpp"
     21 #include "Direct3DTexture8.hpp"
     22 #include "Direct3DVolumeTexture8.hpp"
     23 #include "Direct3DCubeTexture8.hpp"
     24 #include "Direct3DSwapChain8.hpp"
     25 #include "Direct3DPixelShader8.hpp"
     26 #include "Direct3DVertexShader8.hpp"
     27 #include "Direct3DVolume8.hpp"
     28 
     29 #include "Debug.hpp"
     30 #include "Capabilities.hpp"
     31 #include "Renderer.hpp"
     32 #include "Config.hpp"
     33 #include "FrameBuffer.hpp"
     34 #include "Clipper.hpp"
     35 #include "Configurator.hpp"
     36 #include "Timer.hpp"
     37 #include "Resource.hpp"
     38 
     39 #include <assert.h>
     40 
     41 bool localShaderConstants = false;
     42 
     43 namespace D3D8
     44 {
     45 	inline unsigned long FtoDW(float f)   // FIXME: Deprecate
     46 	{
     47 		return (unsigned long&)f;
     48 	}
     49 
     50 	Direct3DDevice8::Direct3DDevice8(const HINSTANCE instance, Direct3D8 *d3d8, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), d3d8(d3d8), adapter(adapter), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags), presentParameters(*presentParameters)
     51 	{
     52 		init = true;
     53 		recordState = false;
     54 
     55 		d3d8->AddRef();
     56 
     57 		context = new sw::Context();
     58 		renderer = new sw::Renderer(context, sw::Direct3D, false);
     59 
     60 		swapChain.push_back(0);
     61 		depthStencil = 0;
     62 		renderTarget = 0;
     63 
     64 		for(int i = 0; i < 8; i++)
     65 		{
     66 			texture[i] = 0;
     67 		}
     68 
     69 		cursor = 0;
     70 		unsigned char one[32 * 32 / sizeof(unsigned char)];
     71 		memset(one, 0xFFFFFFFF, sizeof(one));
     72 		unsigned char zero[32 * 32 / sizeof(unsigned char)] = {0};
     73 		nullCursor = CreateCursor(instance, 0, 0, 32, 32, one, zero);
     74 		win32Cursor = GetCursor();
     75 
     76 		Reset(presentParameters);
     77 
     78 		pixelShader.push_back(0);   // pixelShader[0] = 0
     79 		vertexShader.push_back(0);   // vertexShader[0] = 0
     80 		vertexShaderHandle = 0;
     81 		pixelShaderHandle = 0;
     82 
     83 		lightsDirty = true;
     84 
     85 		for(int i = 0; i < 16; i++)
     86 		{
     87 			dataStream[i] = 0;
     88 			streamStride[i] = 0;
     89 		}
     90 
     91 		indexData = 0;
     92 		baseVertexIndex = 0;
     93 		declaration = 0;
     94 		FVF = 0;
     95 
     96 		D3DMATERIAL8 material;
     97 
     98 		material.Diffuse.r = 1.0f;
     99 		material.Diffuse.g = 1.0f;
    100 		material.Diffuse.b = 1.0f;
    101 		material.Diffuse.a = 0.0f;
    102 		material.Ambient.r = 0.0f;
    103 		material.Ambient.g = 0.0f;
    104 		material.Ambient.b = 0.0f;
    105 		material.Ambient.a = 0.0f;
    106 		material.Emissive.r = 0.0f;
    107 		material.Emissive.g = 0.0f;
    108 		material.Emissive.b = 0.0f;
    109 		material.Emissive.a = 0.0f;
    110 		material.Specular.r = 0.0f;
    111 		material.Specular.g = 0.0f;
    112 		material.Specular.b = 0.0f;
    113 		material.Specular.a = 0.0f;
    114 		material.Power = 0.0f;
    115 
    116 		SetMaterial(&material);
    117 
    118 		D3DMATRIX identity = {1, 0, 0, 0,
    119 			                  0, 1, 0, 0,
    120 							  0, 0, 1, 0,
    121 							  0, 0, 0, 1};
    122 
    123 		SetTransform(D3DTS_VIEW, &identity);
    124 		SetTransform(D3DTS_PROJECTION, &identity);
    125 		SetTransform(D3DTS_TEXTURE0, &identity);
    126 		SetTransform(D3DTS_TEXTURE1, &identity);
    127 		SetTransform(D3DTS_TEXTURE2, &identity);
    128 		SetTransform(D3DTS_TEXTURE3, &identity);
    129 		SetTransform(D3DTS_TEXTURE4, &identity);
    130 		SetTransform(D3DTS_TEXTURE5, &identity);
    131 		SetTransform(D3DTS_TEXTURE6, &identity);
    132 		SetTransform(D3DTS_TEXTURE7, &identity);
    133 
    134 		for(int i = 0; i < 12; i++)
    135 		{
    136 			SetTransform(D3DTS_WORLDMATRIX(i), &identity);
    137 		}
    138 
    139 		for(int i = 0; i < 8; i++)
    140 		{
    141 			float zero[4] = {0, 0, 0, 0};
    142 
    143 			SetPixelShaderConstant(i, zero, 1);
    144 		}
    145 
    146 		for(int i = 0; i < 256; i++)
    147 		{
    148 			float zero[4] = {0, 0, 0, 0};
    149 
    150 			SetVertexShaderConstant(i, zero, 1);
    151 		}
    152 
    153 		init = false;
    154 
    155 		if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE))
    156 		{
    157 			configureFPU();
    158 		}
    159 	}
    160 
    161 	Direct3DDevice8::~Direct3DDevice8()
    162 	{
    163 		delete renderer;
    164 		renderer = 0;
    165 		delete context;
    166 		context = 0;
    167 
    168 		d3d8->Release();
    169 		d3d8 = 0;
    170 
    171 		for(unsigned int i = 0; i < swapChain.size(); i++)
    172 		{
    173 			if(swapChain[i])
    174 			{
    175 				swapChain[i]->unbind();
    176 				swapChain[i] = 0;
    177 			}
    178 		}
    179 
    180 		if(depthStencil)
    181 		{
    182 			depthStencil->unbind();
    183 			depthStencil = 0;
    184 		}
    185 
    186 		if(renderTarget)
    187 		{
    188 			renderTarget->unbind();
    189 			renderTarget = 0;
    190 		}
    191 
    192 		for(int i = 0; i < 8; i++)
    193 		{
    194 			if(texture[i])
    195 			{
    196 				texture[i]->unbind();
    197 				texture[i] = 0;
    198 			}
    199 		}
    200 
    201 		for(int i = 0; i < 16; i++)
    202 		{
    203 			if(dataStream[i])
    204 			{
    205 				dataStream[i]->unbind();
    206 				dataStream[i] = 0;
    207 			}
    208 		}
    209 
    210 		if(indexData)
    211 		{
    212 			indexData->unbind();
    213 			indexData = 0;
    214 		}
    215 
    216 		for(unsigned int i = 0; i < pixelShader.size(); i++)
    217 		{
    218 			if(pixelShader[i])
    219 			{
    220 				pixelShader[i]->unbind();
    221 				pixelShader[i] = 0;
    222 			}
    223 		}
    224 
    225 		for(unsigned int i = 0; i < vertexShader.size(); i++)
    226 		{
    227 			if(vertexShader[i])
    228 			{
    229 				vertexShader[i]->unbind();
    230 				vertexShader[i] = 0;
    231 			}
    232 		}
    233 
    234 		for(unsigned int i = 0; i < stateRecorder.size(); i++)
    235 		{
    236 			if(stateRecorder[i])
    237 			{
    238 				stateRecorder[i]->unbind();
    239 				stateRecorder[i] = 0;
    240 			}
    241 		}
    242 
    243 		palette.clear();
    244 
    245 		delete cursor;
    246 		DestroyCursor(nullCursor);
    247 	}
    248 
    249 	long Direct3DDevice8::QueryInterface(const IID &iid, void **object)
    250 	{
    251 		TRACE("");
    252 
    253 		if(iid == IID_IDirect3DDevice8 ||
    254 		   iid == IID_IUnknown)
    255 		{
    256 			AddRef();
    257 			*object = this;
    258 
    259 			return S_OK;
    260 		}
    261 
    262 		*object = 0;
    263 
    264 		return NOINTERFACE(iid);
    265 	}
    266 
    267 	unsigned long Direct3DDevice8::AddRef()
    268 	{
    269 		TRACE("");
    270 
    271 		return Unknown::AddRef();
    272 	}
    273 
    274 	unsigned long Direct3DDevice8::Release()
    275 	{
    276 		TRACE("");
    277 
    278 		return Unknown::Release();
    279 	}
    280 
    281 	long Direct3DDevice8::ApplyStateBlock(unsigned long token)
    282 	{
    283 		TRACE("");
    284 
    285 		stateRecorder[token]->Apply();
    286 
    287 		return D3D_OK;
    288 	}
    289 
    290 	long Direct3DDevice8::BeginScene()
    291 	{
    292 		TRACE("");
    293 
    294 		return D3D_OK;
    295 	}
    296 
    297 	long Direct3DDevice8::BeginStateBlock()
    298 	{
    299 		TRACE("");
    300 
    301 		recordState = true;
    302 		Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, (D3DSTATEBLOCKTYPE)0);
    303 		stateBlock->bind();
    304 		stateRecorder.push_back(stateBlock);
    305 
    306 		return D3D_OK;
    307 	}
    308 
    309 	long Direct3DDevice8::CaptureStateBlock(unsigned long token)
    310 	{
    311 		TRACE("");
    312 
    313 		stateRecorder[token]->Capture();
    314 
    315 		return D3D_OK;
    316 	}
    317 
    318 	long Direct3DDevice8::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil)
    319 	{
    320 		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);
    321 
    322 		if(!rects && count != 0)
    323 		{
    324 			return INVALIDCALL();
    325 		}
    326 
    327 		if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil)
    328 		{
    329 			return INVALIDCALL();
    330 		}
    331 
    332 		if(flags & D3DCLEAR_STENCIL)   // Check for stencil component
    333 		{
    334 			D3DSURFACE_DESC description;
    335 			depthStencil->GetDesc(&description);
    336 
    337 			switch(description.Format)
    338 			{
    339 			case D3DFMT_D15S1:
    340 			case D3DFMT_D24S8:
    341 			case D3DFMT_D24X8:
    342 			case D3DFMT_D24X4S4:
    343 				break;
    344 			case D3DFMT_D16_LOCKABLE:
    345 			case D3DFMT_D32:
    346 			case D3DFMT_D16:
    347 				return INVALIDCALL();
    348 			default:
    349 				ASSERT(false);
    350 			}
    351 		}
    352 
    353 		if(!rects)
    354 		{
    355 			count = 1;
    356 
    357 			D3DRECT rect;
    358 			rect.x1 = viewport.X;
    359 			rect.x2 = viewport.X + viewport.Width;
    360 			rect.y1 = viewport.Y;
    361 			rect.y2 = viewport.Y + viewport.Height;
    362 
    363 			rects = &rect;
    364 		}
    365 
    366 		for(unsigned int i = 0; i < count; i++)
    367 		{
    368 			sw::Rect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
    369 
    370 			clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height);
    371 
    372 			if(flags & D3DCLEAR_TARGET)
    373 			{
    374 				if(renderTarget)
    375 				{
    376 					D3DSURFACE_DESC description;
    377 					renderTarget->GetDesc(&description);
    378 
    379 					float rgba[4];
    380 					rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000;
    381 					rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00;
    382 					rgba[2] = (float)(color & 0x000000FF) / 0x000000FF;
    383 					rgba[3] = (float)(color & 0xFF000000) / 0xFF000000;
    384 
    385 					renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget, clearRect, 0xF);
    386 				}
    387 			}
    388 
    389 			if(flags & D3DCLEAR_ZBUFFER)
    390 			{
    391 				z = sw::clamp01(z);
    392 				depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    393 			}
    394 
    395 			if(flags & D3DCLEAR_STENCIL)
    396 			{
    397 				depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
    398 			}
    399 		}
    400 
    401 		return D3D_OK;
    402 	}
    403 
    404 	long Direct3DDevice8::CopyRects(IDirect3DSurface8 *sourceSurface, const RECT *sourceRectsArray, unsigned int rects, IDirect3DSurface8 *destinationSurface, const POINT *destPointsArray)
    405 	{
    406 		TRACE("");
    407 
    408 		if(!sourceSurface || !destinationSurface)
    409 		{
    410 			return INVALIDCALL();
    411 		}
    412 
    413 		if(sourceRectsArray && rects == 0 || !sourceRectsArray && rects > 0)
    414 		{
    415 			return INVALIDCALL();   // FIXME: Verify REF behaviour
    416 		}
    417 
    418 		D3DSURFACE_DESC sourceDescription;
    419 		D3DSURFACE_DESC destDescription;
    420 
    421 		sourceSurface->GetDesc(&sourceDescription);
    422 		destinationSurface->GetDesc(&destDescription);
    423 
    424 		if(sourceDescription.Format != destDescription.Format)
    425 		{
    426 			return INVALIDCALL();
    427 		}
    428 
    429 		int sWidth = sourceDescription.Width;
    430 		int sHeight = sourceDescription.Height;
    431 		int dWidth = destDescription.Width;
    432 		int dHeight = destDescription.Height;
    433 
    434 		RECT sRect = {0, 0, sWidth, sHeight};
    435 		POINT dPoint = {0, 0};
    436 
    437 		if(!sourceRectsArray || !destPointsArray)
    438 		{
    439 			sourceRectsArray = &sRect;
    440 			destPointsArray = &dPoint;
    441 
    442 			rects = 1;
    443 		}
    444 
    445 		int bpp = 8 * Direct3DSurface8::bytes(sourceDescription.Format);
    446 
    447 		for(unsigned int i = 0; i < rects; i++)
    448 		{
    449 			const RECT &sRect = sourceRectsArray[i];
    450 			const POINT &dPoint = destPointsArray[i];
    451 
    452 			int rWidth = sRect.right - sRect.left;
    453 			int rHeight = sRect.bottom - sRect.top;
    454 
    455 			RECT dRect;
    456 
    457 			dRect.top = dPoint.y;
    458 			dRect.left = dPoint.x;
    459 			dRect.bottom = dPoint.y + rHeight;
    460 			dRect.right = dPoint.x + rWidth;
    461 
    462 			D3DLOCKED_RECT sourceLock;
    463 			D3DLOCKED_RECT destLock;
    464 
    465 			sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY);
    466 			destinationSurface->LockRect(&destLock, &dRect, D3DLOCK_DISCARD);
    467 
    468 			for(int y = 0; y < rHeight; y++)
    469 			{
    470 				switch(sourceDescription.Format)
    471 				{
    472 				case D3DFMT_DXT1:
    473 				case D3DFMT_DXT2:
    474 				case D3DFMT_DXT3:
    475 				case D3DFMT_DXT4:
    476 				case D3DFMT_DXT5:
    477 					memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8);
    478 					y += 3;   // Advance four lines at once
    479 					break;
    480 				default:
    481 					memcpy(destLock.pBits, sourceLock.pBits, rWidth * bpp / 8);
    482 				}
    483 
    484 				(char*&)sourceLock.pBits += sourceLock.Pitch;
    485 				(char*&)destLock.pBits += destLock.Pitch;
    486 			}
    487 
    488 			sourceSurface->UnlockRect();
    489 			destinationSurface->UnlockRect();
    490 		}
    491 
    492 		return D3D_OK;
    493 	}
    494 
    495 	long Direct3DDevice8::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain8 **swapChain)
    496 	{
    497 		TRACE("");
    498 
    499 		*swapChain = 0;
    500 
    501 		if(!presentParameters || !swapChain)
    502 		{
    503 			return INVALIDCALL();
    504 		}
    505 
    506 		if(presentParameters->BackBufferCount > 3)
    507 		{
    508 			return INVALIDCALL();   // Maximum of three back buffers
    509 		}
    510 
    511 		if(presentParameters->BackBufferCount == 0)
    512 		{
    513 			presentParameters->BackBufferCount = 1;
    514 		}
    515 
    516 		D3DPRESENT_PARAMETERS present = *presentParameters;
    517 
    518 		*swapChain = new Direct3DSwapChain8(this, &present);
    519 
    520 		if(!*swapChain)
    521 		{
    522 			return OUTOFMEMORY();
    523 		}
    524 
    525 		if(GetAvailableTextureMem() == 0)
    526 		{
    527 			delete *swapChain;
    528 
    529 			return OUTOFVIDEOMEMORY();
    530 		}
    531 
    532 		this->swapChain.push_back(static_cast<Direct3DSwapChain8*>(*swapChain));
    533 
    534 		(*swapChain)->AddRef();
    535 
    536 		return D3D_OK;
    537 	}
    538 
    539 	long Direct3DDevice8::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture8 **cubeTexture)
    540 	{
    541 		TRACE("");
    542 
    543 		*cubeTexture = 0;
    544 
    545 		if(edgeLength == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK)
    546 		{
    547 			return INVALIDCALL();
    548 		}
    549 
    550 		*cubeTexture = new Direct3DCubeTexture8(this, edgeLength, levels, usage, format, pool);
    551 
    552 		if(!*cubeTexture)
    553 		{
    554 			return OUTOFMEMORY();
    555 		}
    556 
    557 		if(GetAvailableTextureMem() == 0)
    558 		{
    559 			delete *cubeTexture;
    560 
    561 			return OUTOFVIDEOMEMORY();
    562 		}
    563 
    564 		(*cubeTexture)->AddRef();
    565 
    566 		return D3D_OK;
    567 	}
    568 
    569 	long Direct3DDevice8::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, IDirect3DSurface8 **surface)
    570 	{
    571 		TRACE("");
    572 
    573 		*surface = 0;
    574 
    575 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
    576 		{
    577 			return INVALIDCALL();
    578 		}
    579 
    580 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, format == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL);
    581 
    582 		if(!*surface)
    583 		{
    584 			return OUTOFMEMORY();
    585 		}
    586 
    587 		if(GetAvailableTextureMem() == 0)
    588 		{
    589 			delete *surface;
    590 
    591 			return OUTOFVIDEOMEMORY();
    592 		}
    593 
    594 		(*surface)->AddRef();
    595 
    596 		return D3D_OK;
    597 	}
    598 
    599 	long Direct3DDevice8::CreateImageSurface(unsigned int width, unsigned int height, D3DFORMAT format, IDirect3DSurface8 **surface)
    600 	{
    601 		TRACE("");
    602 
    603 		*surface = 0;
    604 
    605 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK)
    606 		{
    607 			return INVALIDCALL();
    608 		}
    609 
    610 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_SYSTEMMEM, D3DMULTISAMPLE_NONE, true, 0);
    611 
    612 		if(!*surface)
    613 		{
    614 			return OUTOFMEMORY();
    615 		}
    616 
    617 		if(GetAvailableTextureMem() == 0)
    618 		{
    619 			delete *surface;
    620 
    621 			return OUTOFVIDEOMEMORY();
    622 		}
    623 
    624 		(*surface)->AddRef();
    625 
    626 		return D3D_OK;
    627 	}
    628 
    629 	long Direct3DDevice8::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer8 **indexBuffer)
    630 	{
    631 		TRACE("");
    632 
    633 		*indexBuffer = new Direct3DIndexBuffer8(this, length, usage, format, pool);
    634 
    635 		if(!*indexBuffer)
    636 		{
    637 			return OUTOFMEMORY();
    638 		}
    639 
    640 		if(GetAvailableTextureMem() == 0)
    641 		{
    642 			delete *indexBuffer;
    643 
    644 			return OUTOFVIDEOMEMORY();
    645 		}
    646 
    647 		(*indexBuffer)->AddRef();
    648 
    649 		return D3D_OK;
    650 	}
    651 
    652 	long Direct3DDevice8::CreatePixelShader(const unsigned long *function, unsigned long *handle)
    653 	{
    654 		TRACE("");
    655 
    656 		if(!function || !handle || function[0] > pixelShaderVersion)
    657 		{
    658 			return INVALIDCALL();
    659 		}
    660 
    661 		unsigned int index;
    662 
    663 		for(index = 1; index < pixelShader.size(); index++)   // Skip NULL handle
    664 		{
    665 			if(pixelShader[index] == 0)
    666 			{
    667 				pixelShader[index] = new Direct3DPixelShader8(this, function);   // FIXME: Check for null
    668 
    669 				break;
    670 			}
    671 		}
    672 
    673 		if(index == pixelShader.size())
    674 		{
    675 			pixelShader.push_back(new Direct3DPixelShader8(this, function));
    676 		}
    677 
    678 		pixelShader[index]->AddRef();
    679 
    680 		*handle = index;
    681 
    682 		return D3D_OK;
    683 	}
    684 
    685 	long Direct3DDevice8::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, int lockable, IDirect3DSurface8 **surface)
    686 	{
    687 		TRACE("");
    688 
    689 		*surface = 0;
    690 
    691 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
    692 		{
    693 			return INVALIDCALL();
    694 		}
    695 
    696 		*surface = new Direct3DSurface8(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, lockable != FALSE, D3DUSAGE_RENDERTARGET);
    697 
    698 		if(!*surface)
    699 		{
    700 			return OUTOFMEMORY();
    701 		}
    702 
    703 		if(GetAvailableTextureMem() == 0)
    704 		{
    705 			delete *surface;
    706 
    707 			return OUTOFVIDEOMEMORY();
    708 		}
    709 
    710 		(*surface)->AddRef();
    711 
    712 		return D3D_OK;
    713 	}
    714 
    715 	long Direct3DDevice8::CreateStateBlock(D3DSTATEBLOCKTYPE type, unsigned long *token)
    716 	{
    717 		TRACE("");
    718 
    719 		if(!token)
    720 		{
    721 			return INVALIDCALL();
    722 		}
    723 
    724 		Direct3DStateBlock8 *stateBlock = new Direct3DStateBlock8(this, type);
    725 		stateBlock->bind();
    726 		stateRecorder.push_back(stateBlock);
    727 		*token = (unsigned long)(stateRecorder.size() - 1);
    728 
    729 		return D3D_OK;
    730 	}
    731 
    732 	long Direct3DDevice8::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture8 **texture)
    733 	{
    734 		TRACE("");
    735 
    736 		*texture = 0;
    737 
    738 		if(width == 0 || height == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK)
    739 		{
    740 			return INVALIDCALL();
    741 		}
    742 
    743 		*texture = new Direct3DTexture8(this, width, height, levels, usage, format, pool);
    744 
    745 		if(!*texture)
    746 		{
    747 			return OUTOFMEMORY();
    748 		}
    749 
    750 		if(GetAvailableTextureMem() == 0)
    751 		{
    752 			delete *texture;
    753 
    754 			return OUTOFVIDEOMEMORY();
    755 		}
    756 
    757 		(*texture)->AddRef();
    758 
    759 		return D3D_OK;
    760 	}
    761 
    762 	long Direct3DDevice8::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer8 **vertexBuffer)
    763 	{
    764 		TRACE("");
    765 
    766 		*vertexBuffer = new Direct3DVertexBuffer8(this, length, usage, FVF, pool);
    767 
    768 		if(!*vertexBuffer)
    769 		{
    770 			return OUTOFMEMORY();
    771 		}
    772 
    773 		if(GetAvailableTextureMem() == 0)
    774 		{
    775 			delete *vertexBuffer;
    776 
    777 			return OUTOFVIDEOMEMORY();
    778 		}
    779 
    780 		(*vertexBuffer)->AddRef();
    781 
    782 		return D3D_OK;
    783 	}
    784 
    785 	long Direct3DDevice8::CreateVertexShader(const unsigned long *declaration, const unsigned long *function, unsigned long *handle, unsigned long usage)
    786 	{
    787 		TRACE("const unsigned long *declaration = 0x%0.8p, const unsigned long *function = 0x%0.8p, unsigned long *handle = 0x%0.8p, unsigned long usage = %d", declaration, function, handle, usage);
    788 
    789 		if(!declaration || !handle || (function && function[0] > vertexShaderVersion))
    790 		{
    791 			return INVALIDCALL();
    792 		}
    793 
    794 		unsigned int index;
    795 
    796 		for(index = 1; index < vertexShader.size(); index++)   // NOTE: skip NULL handle
    797 		{
    798 			if(vertexShader[index] == 0)
    799 			{
    800 				vertexShader[index] = new Direct3DVertexShader8(this, declaration, function);   // FIXME: Check for null
    801 
    802 				break;
    803 			}
    804 		}
    805 
    806 		if(index == vertexShader.size())
    807 		{
    808 			vertexShader.push_back(new Direct3DVertexShader8(this, declaration, function));
    809 		}
    810 
    811 		vertexShader[index]->AddRef();
    812 
    813 		*handle = (index << 16) + 1;
    814 
    815 		return D3D_OK;
    816 	}
    817 
    818 	long Direct3DDevice8::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture8 **volumeTexture)
    819 	{
    820 		TRACE("");
    821 
    822 		*volumeTexture = 0;
    823 
    824 		if(width == 0 || height == 0 || depth == 0 || d3d8->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK)
    825 		{
    826 			return INVALIDCALL();
    827 		}
    828 
    829 		*volumeTexture = new Direct3DVolumeTexture8(this, width, height, depth, levels, usage, format, pool);
    830 
    831 		if(!*volumeTexture)
    832 		{
    833 			return OUTOFMEMORY();
    834 		}
    835 
    836 		if(GetAvailableTextureMem() == 0)
    837 		{
    838 			delete *volumeTexture;
    839 
    840 			return OUTOFVIDEOMEMORY();
    841 		}
    842 
    843 		(*volumeTexture)->AddRef();
    844 
    845 		return D3D_OK;
    846 	}
    847 
    848 	long Direct3DDevice8::DeletePatch(unsigned int handle)
    849 	{
    850 		TRACE("");
    851 
    852 		UNIMPLEMENTED();
    853 
    854 		return D3D_OK;
    855 	}
    856 
    857 	long Direct3DDevice8::DeleteStateBlock(unsigned long token)
    858 	{
    859 		TRACE("");
    860 
    861 		if(token >= stateRecorder.size() || !stateRecorder[token])
    862 		{
    863 			return INVALIDCALL();
    864 		}
    865 
    866 		stateRecorder[token]->unbind();
    867 		stateRecorder[token] = 0;
    868 
    869 		return D3D_OK;
    870 	}
    871 
    872 	long Direct3DDevice8::DeleteVertexShader(unsigned long handle)
    873 	{
    874 		TRACE("");
    875 
    876 		unsigned int index = handle >> 16;
    877 
    878 		if(index >= vertexShader.size() || !vertexShader[index])
    879 		{
    880 			return INVALIDCALL();
    881 		}
    882 
    883 		vertexShader[index]->Release();
    884 		vertexShader[index] = 0;
    885 
    886 		return D3D_OK;
    887 	}
    888 
    889 	long Direct3DDevice8::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount)
    890 	{
    891 		TRACE("");
    892 
    893 		if(!indexData)
    894 		{
    895 			return INVALIDCALL();
    896 		}
    897 
    898 		if(!bindData(indexData, baseVertexIndex) || !primitiveCount)
    899 		{
    900 			return D3D_OK;
    901 		}
    902 
    903 		unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account
    904 
    905 		sw::DrawType drawType;
    906 
    907 		if(indexData->is32Bit())
    908 		{
    909 			switch(type)
    910 			{
    911 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break;
    912 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break;
    913 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break;
    914 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break;
    915 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break;
    916 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break;
    917 			default:
    918 				ASSERT(false);
    919 			}
    920 		}
    921 		else
    922 		{
    923 			switch(type)
    924 			{
    925 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break;
    926 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break;
    927 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break;
    928 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break;
    929 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break;
    930 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break;
    931 			default:
    932 				ASSERT(false);
    933 			}
    934 		}
    935 
    936 		bindData(indexData, baseVertexIndex);
    937 
    938 		renderer->draw(drawType, indexOffset, primitiveCount);
    939 
    940 		return D3D_OK;
    941 	}
    942 
    943 	long Direct3DDevice8::DeletePixelShader(unsigned long handle)
    944 	{
    945 		TRACE("");
    946 
    947 		if(handle >= pixelShader.size() || !pixelShader[handle])
    948 		{
    949 			return INVALIDCALL();
    950 		}
    951 
    952 		pixelShader[handle]->Release();
    953 		pixelShader[handle] = 0;
    954 
    955 		return D3D_OK;
    956 	}
    957 
    958 	long Direct3DDevice8::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
    959 	{
    960 		TRACE("");
    961 
    962 		if(!vertexStreamZeroData || !indexData)
    963 		{
    964 			return INVALIDCALL();
    965 		}
    966 
    967 		int length = (minIndex + numVertices) * vertexStreamZeroStride;
    968 
    969 		Direct3DVertexBuffer8 *vertexBuffer = new Direct3DVertexBuffer8(this, length, 0, 0, D3DPOOL_DEFAULT);
    970 
    971 		unsigned char *data;
    972 		vertexBuffer->Lock(0, 0, &data, 0);
    973 		memcpy(data, vertexStreamZeroData, length);
    974 		vertexBuffer->Unlock();
    975 
    976 		SetStreamSource(0, vertexBuffer, vertexStreamZeroStride);
    977 
    978 		switch(type)
    979 		{
    980 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
    981 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
    982 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
    983 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
    984 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
    985 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
    986 		default:
    987 			ASSERT(false);
    988 		}
    989 
    990 		length *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2;
    991 
    992 		Direct3DIndexBuffer8 *indexBuffer = new Direct3DIndexBuffer8(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT);
    993 
    994 		indexBuffer->Lock(0, 0, &data, 0);
    995 		memcpy(data, indexData, length);
    996 		indexBuffer->Unlock();
    997 
    998 		SetIndices(indexBuffer, 0);
    999 
   1000 		if(!bindData(indexBuffer, 0) || !primitiveCount)
   1001 		{
   1002 			vertexBuffer->Release();
   1003 
   1004 			return D3D_OK;
   1005 		}
   1006 
   1007 		sw::DrawType drawType;
   1008 
   1009 		if(indexDataFormat == D3DFMT_INDEX32)
   1010 		{
   1011 			switch(type)
   1012 			{
   1013 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST32;		break;
   1014 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST32;			break;
   1015 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP32;		break;
   1016 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST32;		break;
   1017 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32;	break;
   1018 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;		break;
   1019 			default:
   1020 				ASSERT(false);
   1021 			}
   1022 		}
   1023 		else
   1024 		{
   1025 			switch(type)
   1026 			{
   1027 			case D3DPT_POINTLIST:		drawType = sw::DRAW_INDEXEDPOINTLIST16;		break;
   1028 			case D3DPT_LINELIST:		drawType = sw::DRAW_INDEXEDLINELIST16;			break;
   1029 			case D3DPT_LINESTRIP:		drawType = sw::DRAW_INDEXEDLINESTRIP16;		break;
   1030 			case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_INDEXEDTRIANGLELIST16;		break;
   1031 			case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16;	break;
   1032 			case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;		break;
   1033 			default:
   1034 				ASSERT(false);
   1035 			}
   1036 		}
   1037 
   1038 		renderer->draw(drawType, 0, primitiveCount);
   1039 
   1040 		SetStreamSource(0, 0, 0);
   1041 		SetIndices(0, 0);
   1042 
   1043 		return D3D_OK;
   1044 	}
   1045 
   1046 	long Direct3DDevice8::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount)
   1047 	{
   1048 		TRACE("");
   1049 
   1050 		if(!bindData(0, startVertex) || !primitiveCount)
   1051 		{
   1052 			return D3D_OK;
   1053 		}
   1054 
   1055 		sw::DrawType drawType;
   1056 
   1057 		switch(primitiveType)
   1058 		{
   1059 		case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break;
   1060 		case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break;
   1061 		case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break;
   1062 		case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break;
   1063 		case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break;
   1064 		case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break;
   1065 		default:
   1066 			ASSERT(false);
   1067 		}
   1068 
   1069 		renderer->draw(drawType, 0, primitiveCount);
   1070 
   1071 		return D3D_OK;
   1072 	}
   1073 
   1074 	long Direct3DDevice8::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
   1075 	{
   1076 		TRACE("");
   1077 
   1078 		if(!vertexStreamZeroData)
   1079 		{
   1080 			return INVALIDCALL();
   1081 		}
   1082 
   1083 		IDirect3DVertexBuffer8 *vertexBuffer = 0;
   1084 		int length = 0;
   1085 
   1086 		switch(primitiveType)
   1087 		{
   1088 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
   1089 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
   1090 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
   1091 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
   1092 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
   1093 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
   1094 		default:
   1095 			ASSERT(false);
   1096 		}
   1097 
   1098 		length *= vertexStreamZeroStride;
   1099 
   1100 		CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer);
   1101 
   1102 		unsigned char *data;
   1103 		vertexBuffer->Lock(0, 0, &data, 0);
   1104 		memcpy(data, vertexStreamZeroData, length);
   1105 		vertexBuffer->Unlock();
   1106 
   1107 		SetStreamSource(0, vertexBuffer, vertexStreamZeroStride);
   1108 
   1109 		if(!bindData(0, 0) || !primitiveCount)
   1110 		{
   1111 			vertexBuffer->Release();
   1112 
   1113 			return D3D_OK;
   1114 		}
   1115 
   1116 		sw::DrawType drawType;
   1117 
   1118 		switch(primitiveType)
   1119 		{
   1120 		case D3DPT_POINTLIST:		drawType = sw::DRAW_POINTLIST;		break;
   1121 		case D3DPT_LINELIST:		drawType = sw::DRAW_LINELIST;		break;
   1122 		case D3DPT_LINESTRIP:		drawType = sw::DRAW_LINESTRIP;		break;
   1123 		case D3DPT_TRIANGLELIST:	drawType = sw::DRAW_TRIANGLELIST;	break;
   1124 		case D3DPT_TRIANGLESTRIP:	drawType = sw::DRAW_TRIANGLESTRIP;	break;
   1125 		case D3DPT_TRIANGLEFAN:		drawType = sw::DRAW_TRIANGLEFAN;	break;
   1126 		default:
   1127 			ASSERT(false);
   1128 		}
   1129 
   1130 		renderer->draw(drawType, 0, primitiveCount);
   1131 
   1132 		SetStreamSource(0, 0, 0);
   1133 		vertexBuffer->Release();
   1134 
   1135 		return D3D_OK;
   1136 	}
   1137 
   1138 	long Direct3DDevice8::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo)
   1139 	{
   1140 		TRACE("");
   1141 
   1142 		if(!numSegs || !rectPatchInfo)
   1143 		{
   1144 			return INVALIDCALL();
   1145 		}
   1146 
   1147 		UNIMPLEMENTED();
   1148 
   1149 		return D3D_OK;
   1150 	}
   1151 
   1152 	long Direct3DDevice8::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo)
   1153 	{
   1154 		TRACE("");
   1155 
   1156 		if(!numSegs || !triPatchInfo)
   1157 		{
   1158 			return INVALIDCALL();
   1159 		}
   1160 
   1161 		UNIMPLEMENTED();
   1162 
   1163 		return D3D_OK;
   1164 	}
   1165 
   1166 	long Direct3DDevice8::EndScene()
   1167 	{
   1168 		TRACE("");
   1169 
   1170 		return D3D_OK;
   1171 	}
   1172 
   1173 	long Direct3DDevice8::EndStateBlock(unsigned long *token)
   1174 	{
   1175 		TRACE("");
   1176 
   1177 		if(!token)
   1178 		{
   1179 			return INVALIDCALL();
   1180 		}
   1181 
   1182 		recordState = false;
   1183 		*token = (unsigned long)(stateRecorder.size() - 1);
   1184 
   1185 		return D3D_OK;
   1186 	}
   1187 
   1188 	unsigned int Direct3DDevice8::GetAvailableTextureMem()
   1189 	{
   1190 		TRACE("");
   1191 
   1192 		int availableMemory = textureMemory - Direct3DResource8::getMemoryUsage();
   1193 		if(availableMemory < 0) availableMemory = 0;
   1194 
   1195 		// Round to nearest MB
   1196 		return (availableMemory + 0x80000) & 0xFFF00000;
   1197 	}
   1198 
   1199 	long Direct3DDevice8::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface8 **backBuffer)
   1200 	{
   1201 		TRACE("");
   1202 
   1203 		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
   1204 		{
   1205 			return INVALIDCALL();
   1206 		}
   1207 
   1208 		swapChain[index]->GetBackBuffer(index, type, backBuffer);
   1209 
   1210 		return D3D_OK;
   1211 	}
   1212 
   1213 	long Direct3DDevice8::GetClipPlane(unsigned long index, float *plane)
   1214 	{
   1215 		TRACE("");
   1216 
   1217 		if(!plane || index >= 6)
   1218 		{
   1219 			return INVALIDCALL();
   1220 		}
   1221 
   1222 		plane[0] = this->plane[index][0];
   1223 		plane[1] = this->plane[index][1];
   1224 		plane[2] = this->plane[index][2];
   1225 		plane[3] = this->plane[index][3];
   1226 
   1227 		return D3D_OK;
   1228 	}
   1229 
   1230 	long Direct3DDevice8::GetClipStatus(D3DCLIPSTATUS8 *clipStatus)
   1231 	{
   1232 		TRACE("");
   1233 
   1234 		if(!clipStatus)
   1235 		{
   1236 			return INVALIDCALL();
   1237 		}
   1238 
   1239 		*clipStatus = this->clipStatus;
   1240 
   1241 		return D3D_OK;
   1242 	}
   1243 
   1244 	long Direct3DDevice8::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters)
   1245 	{
   1246 		TRACE("");
   1247 
   1248 		if(!parameters)
   1249 		{
   1250 			return INVALIDCALL();
   1251 		}
   1252 
   1253 		parameters->AdapterOrdinal = adapter;
   1254 		parameters->BehaviorFlags = behaviourFlags;
   1255 		parameters->DeviceType = deviceType;
   1256 		parameters->hFocusWindow = focusWindow;
   1257 
   1258 		return D3D_OK;
   1259 	}
   1260 
   1261 	long Direct3DDevice8::GetCurrentTexturePalette(unsigned int *paletteNumber)
   1262 	{
   1263 		TRACE("");
   1264 
   1265 		if(!paletteNumber)
   1266 		{
   1267 			return INVALIDCALL();
   1268 		}
   1269 
   1270 		*paletteNumber = currentPalette;
   1271 
   1272 		return D3D_OK;
   1273 	}
   1274 
   1275 	long Direct3DDevice8::GetDepthStencilSurface(IDirect3DSurface8 **depthStencilSurface)
   1276 	{
   1277 		TRACE("");
   1278 
   1279 		if(!depthStencilSurface)
   1280 		{
   1281 			return INVALIDCALL();
   1282 		}
   1283 
   1284 		*depthStencilSurface = depthStencil;
   1285 
   1286 		if(depthStencil)
   1287 		{
   1288 			depthStencil->AddRef();
   1289 		}
   1290 
   1291 		return D3D_OK;   // FIXME: Return NOTFOUND() when no depthStencil?
   1292 	}
   1293 
   1294 	long Direct3DDevice8::GetDeviceCaps(D3DCAPS8 *caps)
   1295 	{
   1296 		TRACE("");
   1297 
   1298 		return d3d8->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps);
   1299 	}
   1300 
   1301 	long Direct3DDevice8::GetDirect3D(IDirect3D8 **d3d8)
   1302 	{
   1303 		TRACE("");
   1304 
   1305 		if(!d3d8)
   1306 		{
   1307 			return INVALIDCALL();
   1308 		}
   1309 
   1310 		ASSERT(this->d3d8);
   1311 
   1312 		*d3d8 = this->d3d8;
   1313 		this->d3d8->AddRef();
   1314 
   1315 		return D3D_OK;
   1316 	}
   1317 
   1318 	long Direct3DDevice8::GetDisplayMode(D3DDISPLAYMODE *mode)
   1319 	{
   1320 		TRACE("");
   1321 
   1322 		if(!mode)
   1323 		{
   1324 			return INVALIDCALL();
   1325 		}
   1326 
   1327 		d3d8->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, mode);
   1328 
   1329 		return D3D_OK;
   1330 	}
   1331 
   1332 	long Direct3DDevice8::GetFrontBuffer(IDirect3DSurface8 *destSurface)
   1333 	{
   1334 		TRACE("");
   1335 
   1336 		if(!destSurface)
   1337 		{
   1338 			return INVALIDCALL();
   1339 		}
   1340 
   1341 		D3DLOCKED_RECT description;
   1342 		destSurface->LockRect(&description, 0, 0);
   1343 
   1344 		swapChain[0]->screenshot(description.pBits);
   1345 
   1346 		destSurface->UnlockRect();
   1347 
   1348 		return D3D_OK;
   1349 	}
   1350 
   1351 	void Direct3DDevice8::GetGammaRamp(D3DGAMMARAMP *ramp)
   1352 	{
   1353 		TRACE("");
   1354 
   1355 		if(!ramp)
   1356 		{
   1357 			return;
   1358 		}
   1359 
   1360 		swapChain[0]->getGammaRamp((sw::GammaRamp*)ramp);
   1361 	}
   1362 
   1363 	long Direct3DDevice8::GetIndices(IDirect3DIndexBuffer8 **indexData, unsigned int *baseVertexIndex)
   1364 	{
   1365 		TRACE("");
   1366 
   1367 		if(!indexData || !baseVertexIndex)
   1368 		{
   1369 			return INVALIDCALL();
   1370 		}
   1371 
   1372 		*indexData = this->indexData;
   1373 
   1374 		if(this->indexData)
   1375 		{
   1376 			this->indexData->AddRef();
   1377 		}
   1378 
   1379 		*baseVertexIndex = this->baseVertexIndex;
   1380 
   1381 		return D3D_OK;
   1382 	}
   1383 
   1384 	long Direct3DDevice8::GetInfo(unsigned long devInfoID, void *devInfoStruct, unsigned long devInfoStructSize)
   1385 	{
   1386 		TRACE("");
   1387 
   1388 		if(!devInfoStruct || devInfoStructSize == 0)
   1389 		{
   1390 			return INVALIDCALL();
   1391 		}
   1392 
   1393 		switch(devInfoID)
   1394 		{
   1395 		case 0: return E_FAIL;
   1396 		case 1: return E_FAIL;
   1397 		case 2: return E_FAIL;
   1398 		case 3: return E_FAIL;
   1399 		case 4: return S_FALSE;
   1400 		case 5: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_RESOURCEMANAGER
   1401 		case 6: UNIMPLEMENTED();   // FIXME: D3DDEVINFOID_D3DVERTEXSTATS
   1402 		case 7: return E_FAIL;
   1403 		}
   1404 
   1405 		return D3D_OK;
   1406 	}
   1407 
   1408 	long Direct3DDevice8::GetLight(unsigned long index, D3DLIGHT8 *light)
   1409 	{
   1410 		TRACE("");
   1411 
   1412 		if(!light)
   1413 		{
   1414 			return INVALIDCALL();
   1415 		}
   1416 
   1417 		if(!this->light.exists(index))
   1418 		{
   1419 			return INVALIDCALL();
   1420 		}
   1421 
   1422 		*light = this->light[index];
   1423 
   1424 		return D3D_OK;
   1425 	}
   1426 
   1427 	long Direct3DDevice8::GetLightEnable(unsigned long index , int *enable)
   1428 	{
   1429 		TRACE("");
   1430 
   1431 		if(!enable)
   1432 		{
   1433 			return INVALIDCALL();
   1434 		}
   1435 
   1436 		if(!light.exists(index))
   1437 		{
   1438 			return INVALIDCALL();
   1439 		}
   1440 
   1441 		*enable = light[index].enable;
   1442 
   1443 		return D3D_OK;
   1444 	}
   1445 
   1446 	long Direct3DDevice8::GetMaterial(D3DMATERIAL8 *material)
   1447 	{
   1448 		TRACE("");
   1449 
   1450 		if(!material)
   1451 		{
   1452 			return INVALIDCALL();
   1453 		}
   1454 
   1455 		*material = this->material;
   1456 
   1457 		return D3D_OK;
   1458 	}
   1459 
   1460 	long Direct3DDevice8::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries)
   1461 	{
   1462 		TRACE("");
   1463 
   1464 		if(paletteNumber > 0xFFFF || !entries)
   1465 		{
   1466 			return INVALIDCALL();
   1467 		}
   1468 
   1469 		for(int i = 0; i < 256; i++)
   1470 		{
   1471 			entries[i] = palette[paletteNumber].entry[i];
   1472 		}
   1473 
   1474 		return D3D_OK;
   1475 	}
   1476 
   1477 	long Direct3DDevice8::GetPixelShader(unsigned long *handle)
   1478 	{
   1479 		TRACE("");
   1480 
   1481 		if(!handle)
   1482 		{
   1483 			return INVALIDCALL();
   1484 		}
   1485 
   1486 		*handle = pixelShaderHandle;
   1487 
   1488 		return D3D_OK;
   1489 	}
   1490 
   1491 	long Direct3DDevice8::GetPixelShaderFunction(unsigned long handle, void *data, unsigned long *size)
   1492 	{
   1493 		TRACE("");
   1494 
   1495 		if(!data)
   1496 		{
   1497 			return INVALIDCALL();
   1498 		}
   1499 
   1500 		UNIMPLEMENTED();
   1501 
   1502 		return D3D_OK;
   1503 	}
   1504 
   1505 	long Direct3DDevice8::GetPixelShaderConstant(unsigned long startRegister, void *constantData, unsigned long count)
   1506 	{
   1507 		TRACE("");
   1508 
   1509 		if(!constantData)
   1510 		{
   1511 			return INVALIDCALL();
   1512 		}
   1513 
   1514 		for(unsigned int i = 0; i < count; i++)
   1515 		{
   1516 			((float*)constantData)[i * 4 + 0] = pixelShaderConstant[startRegister + i][0];
   1517 			((float*)constantData)[i * 4 + 1] = pixelShaderConstant[startRegister + i][1];
   1518 			((float*)constantData)[i * 4 + 2] = pixelShaderConstant[startRegister + i][2];
   1519 			((float*)constantData)[i * 4 + 3] = pixelShaderConstant[startRegister + i][3];
   1520 		}
   1521 
   1522 		return D3D_OK;
   1523 	}
   1524 
   1525 	long Direct3DDevice8::GetRasterStatus(D3DRASTER_STATUS *rasterStatus)
   1526 	{
   1527 		TRACE("");
   1528 
   1529 		if(!rasterStatus)
   1530 		{
   1531 			return INVALIDCALL();
   1532 		}
   1533 
   1534 		UNIMPLEMENTED();
   1535 
   1536 		return D3D_OK;
   1537 	}
   1538 
   1539 	long Direct3DDevice8::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value)
   1540 	{
   1541 		TRACE("");
   1542 
   1543 		if(!value)
   1544 		{
   1545 			return INVALIDCALL();
   1546 		}
   1547 
   1548 		*value = renderState[state];
   1549 
   1550 		return D3D_OK;
   1551 	}
   1552 
   1553 	long Direct3DDevice8::GetRenderTarget(IDirect3DSurface8 **renderTarget)
   1554 	{
   1555 		TRACE("");
   1556 
   1557 		if(!renderTarget)
   1558 		{
   1559 			return INVALIDCALL();
   1560 		}
   1561 
   1562 		*renderTarget = this->renderTarget;
   1563 		this->renderTarget->AddRef();
   1564 
   1565 		return D3D_OK;
   1566 	}
   1567 
   1568 	long Direct3DDevice8::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer8 **streamData, unsigned int *stride)
   1569 	{
   1570 		TRACE("");
   1571 
   1572 		if(streamNumber >= 16 || !streamData || !stride)
   1573 		{
   1574 			return INVALIDCALL();
   1575 		}
   1576 
   1577 		*streamData = dataStream[streamNumber];
   1578 
   1579 		if(dataStream[streamNumber])
   1580 		{
   1581 			dataStream[streamNumber]->AddRef();
   1582 		}
   1583 
   1584 		*stride = 0;   // NOTE: Unimplemented
   1585 
   1586 		return D3D_OK;
   1587 	}
   1588 
   1589 	long Direct3DDevice8::GetTexture(unsigned long stage, IDirect3DBaseTexture8 **texture)
   1590 	{
   1591 		TRACE("");
   1592 
   1593 		if(!texture || stage >= 8)
   1594 		{
   1595 			return INVALIDCALL();
   1596 		}
   1597 
   1598 		*texture = this->texture[stage];
   1599 
   1600 		if(this->texture[stage])
   1601 		{
   1602 			this->texture[stage]->AddRef();
   1603 		}
   1604 
   1605 		return D3D_OK;
   1606 	}
   1607 
   1608 	long Direct3DDevice8::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE state, unsigned long *value)
   1609 	{
   1610 		TRACE("");
   1611 
   1612 		if(!value  || stage < 0 || stage >= 8 || state < 0 || state > D3DTSS_RESULTARG)   // FIXME: Set *value to 0?
   1613 		{
   1614 			return INVALIDCALL();
   1615 		}
   1616 
   1617 		*value = textureStageState[stage][state];
   1618 
   1619 		return D3D_OK;
   1620 	}
   1621 
   1622 	long Direct3DDevice8::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
   1623 	{
   1624 		TRACE("");
   1625 
   1626 		if(!matrix || state < 0 || state > 511)
   1627 		{
   1628 			return INVALIDCALL();
   1629 		}
   1630 
   1631 		*matrix = this->matrix[state];
   1632 
   1633 		return D3D_OK;
   1634 	}
   1635 
   1636 	long Direct3DDevice8::GetVertexShader(unsigned long *handle)
   1637 	{
   1638 		TRACE("");
   1639 
   1640 		if(!handle)
   1641 		{
   1642 			return INVALIDCALL();
   1643 		}
   1644 
   1645 		*handle = vertexShaderHandle;
   1646 
   1647 		return D3D_OK;
   1648 	}
   1649 
   1650 	long Direct3DDevice8::GetVertexShaderConstant(unsigned long startRegister, void *constantData, unsigned long count)
   1651 	{
   1652 		TRACE("");
   1653 
   1654 		if(!constantData)
   1655 		{
   1656 			return INVALIDCALL();
   1657 		}
   1658 
   1659 		for(unsigned int i = 0; i < count; i++)
   1660 		{
   1661 			((float*)constantData)[i * 4 + 0] = vertexShaderConstant[startRegister + i][0];
   1662 			((float*)constantData)[i * 4 + 1] = vertexShaderConstant[startRegister + i][1];
   1663 			((float*)constantData)[i * 4 + 2] = vertexShaderConstant[startRegister + i][2];
   1664 			((float*)constantData)[i * 4 + 3] = vertexShaderConstant[startRegister + i][3];
   1665 		}
   1666 
   1667 		return D3D_OK;
   1668 	}
   1669 
   1670 	long Direct3DDevice8::GetVertexShaderDeclaration(unsigned long handle, void *data, unsigned long *size)
   1671 	{
   1672 		TRACE("");
   1673 
   1674 		if(!data || !size)
   1675 		{
   1676 			return INVALIDCALL();
   1677 		}
   1678 
   1679 		UNIMPLEMENTED();
   1680 
   1681 		return D3D_OK;
   1682 	}
   1683 
   1684 	long Direct3DDevice8::GetVertexShaderFunction(unsigned long handle, void *data, unsigned long *size)
   1685 	{
   1686 		TRACE("");
   1687 
   1688 		if(!data || !size)
   1689 		{
   1690 			return INVALIDCALL();
   1691 		}
   1692 
   1693 		UNIMPLEMENTED();
   1694 
   1695 		return D3D_OK;
   1696 	}
   1697 
   1698 	long Direct3DDevice8::GetViewport(D3DVIEWPORT8 *viewport)
   1699 	{
   1700 		TRACE("");
   1701 
   1702 		if(!viewport)
   1703 		{
   1704 			return INVALIDCALL();
   1705 		}
   1706 
   1707 		*viewport = this->viewport;
   1708 
   1709 		return D3D_OK;
   1710 	}
   1711 
   1712 	long Direct3DDevice8::LightEnable(unsigned long index, int enable)
   1713 	{
   1714 		TRACE("");
   1715 
   1716 		if(!recordState)
   1717 		{
   1718 			if(!light.exists(index))   // Insert default light
   1719 			{
   1720 				D3DLIGHT8 light;
   1721 
   1722 				light.Type = D3DLIGHT_DIRECTIONAL;
   1723 				light.Diffuse.r = 1;
   1724 				light.Diffuse.g = 1;
   1725 				light.Diffuse.b = 1;
   1726 				light.Diffuse.a = 0;
   1727 				light.Specular.r = 0;
   1728 				light.Specular.g = 0;
   1729 				light.Specular.b = 0;
   1730 				light.Specular.a = 0;
   1731 				light.Ambient.r = 0;
   1732 				light.Ambient.g = 0;
   1733 				light.Ambient.b = 0;
   1734 				light.Ambient.a = 0;
   1735 				light.Position.x = 0;
   1736 				light.Position.y = 0;
   1737 				light.Position.z = 0;
   1738 				light.Direction.x = 0;
   1739 				light.Direction.y = 0;
   1740 				light.Direction.z = 1;
   1741 				light.Range = 0;
   1742 				light.Falloff = 0;
   1743 				light.Attenuation0 = 0;
   1744 				light.Attenuation1 = 0;
   1745 				light.Attenuation2 = 0;
   1746 				light.Theta = 0;
   1747 				light.Phi = 0;
   1748 
   1749 				SetLight(index, &light);
   1750 			}
   1751 
   1752 			light[index].enable = (enable != FALSE);
   1753 
   1754 			lightsDirty = true;
   1755 		}
   1756 		else
   1757 		{
   1758 			stateRecorder.back()->lightEnable(index, enable);
   1759 		}
   1760 
   1761 		return D3D_OK;
   1762 	}
   1763 
   1764 	long Direct3DDevice8::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
   1765 	{
   1766 		TRACE("");
   1767 
   1768 		if(!matrix)
   1769 		{
   1770 			return INVALIDCALL();
   1771 		}
   1772 
   1773 		D3DMATRIX *current = &this->matrix[state];
   1774 
   1775 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41,
   1776 		             current->_12, current->_22, current->_32, current->_42,
   1777 		             current->_13, current->_23, current->_33, current->_43,
   1778 		             current->_14, current->_24, current->_34, current->_44);
   1779 
   1780 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
   1781 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
   1782 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
   1783 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
   1784 
   1785 		switch(state)
   1786 		{
   1787 		case D3DTS_WORLD:
   1788 			renderer->setModelMatrix(C * M);
   1789 			break;
   1790 		case D3DTS_VIEW:
   1791 			renderer->setViewMatrix(C * M);
   1792 			break;
   1793 		case D3DTS_PROJECTION:
   1794 			renderer->setProjectionMatrix(C * M);
   1795 			break;
   1796 		case D3DTS_TEXTURE0:
   1797 			renderer->setTextureMatrix(0, C * M);
   1798 			break;
   1799 		case D3DTS_TEXTURE1:
   1800 			renderer->setTextureMatrix(1, C * M);
   1801 			break;
   1802 		case D3DTS_TEXTURE2:
   1803 			renderer->setTextureMatrix(2, C * M);
   1804 			break;
   1805 		case D3DTS_TEXTURE3:
   1806 			renderer->setTextureMatrix(3, C * M);
   1807 			break;
   1808 		case D3DTS_TEXTURE4:
   1809 			renderer->setTextureMatrix(4, C * M);
   1810 			break;
   1811 		case D3DTS_TEXTURE5:
   1812 			renderer->setTextureMatrix(5, C * M);
   1813 			break;
   1814 		case D3DTS_TEXTURE6:
   1815 			renderer->setTextureMatrix(6, C * M);
   1816 			break;
   1817 		case D3DTS_TEXTURE7:
   1818 			renderer->setTextureMatrix(7, C * M);
   1819 			break;
   1820 		default:
   1821 			if(state > 256 && state < 512)
   1822 			{
   1823 				renderer->setModelMatrix(C * M, state - 256);
   1824 			}
   1825 			else ASSERT(false);
   1826 		}
   1827 
   1828 		return D3D_OK;
   1829 	}
   1830 
   1831 	long Direct3DDevice8::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
   1832 	{
   1833 		TRACE("");
   1834 
   1835 		// NOTE: sourceRect and destRect can be null, dirtyRegion has to be null
   1836 
   1837 		HWND windowHandle = presentParameters.hDeviceWindow ? presentParameters.hDeviceWindow : focusWindow;
   1838 
   1839 		if(destWindowOverride && destWindowOverride != windowHandle)
   1840 		{
   1841 			UNIMPLEMENTED();
   1842 		}
   1843 
   1844 		if(dirtyRegion)
   1845 		{
   1846 			return INVALIDCALL();
   1847 		}
   1848 
   1849 		swapChain[0]->Present(sourceRect, destRect, destWindowOverride, dirtyRegion);
   1850 
   1851 		return D3D_OK;
   1852 	}
   1853 
   1854 	long Direct3DDevice8::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer8 *destBuffer, unsigned long flags)
   1855 	{
   1856 		TRACE("");
   1857 
   1858 		if(!destBuffer)
   1859 		{
   1860 			return INVALIDCALL();
   1861 		}
   1862 
   1863 		UNIMPLEMENTED();
   1864 
   1865 		return D3D_OK;
   1866 	}
   1867 
   1868 	long Direct3DDevice8::Reset(D3DPRESENT_PARAMETERS *presentParameters)
   1869 	{
   1870 		TRACE("");
   1871 
   1872 		if(!presentParameters)
   1873 		{
   1874 			return INVALIDCALL();
   1875 		}
   1876 
   1877 		if(swapChain[0])
   1878 		{
   1879 			swapChain[0]->unbind();
   1880 			swapChain[0] = 0;
   1881 		}
   1882 
   1883 		if(depthStencil)
   1884 		{
   1885 			depthStencil->unbind();
   1886 			depthStencil = 0;
   1887 		}
   1888 
   1889 		if(renderTarget)
   1890 		{
   1891 			renderTarget->unbind();
   1892 			renderTarget = 0;
   1893 		}
   1894 
   1895 		D3DPRESENT_PARAMETERS present = *presentParameters;
   1896 
   1897 		if(!swapChain[0])
   1898 		{
   1899 			swapChain[0] = new Direct3DSwapChain8(this, &present);
   1900 			swapChain[0]->bind();
   1901 		}
   1902 		else
   1903 		{
   1904 			swapChain[0]->reset(&present);
   1905 		}
   1906 
   1907 		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : focusWindow;
   1908 
   1909 		int width = 0;
   1910 		int height = 0;
   1911 
   1912 		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
   1913 		{
   1914 			RECT rectangle;
   1915 			GetClientRect(windowHandle, &rectangle);
   1916 
   1917 			width = rectangle.right - rectangle.left;
   1918 			height = rectangle.bottom - rectangle.top;
   1919 		}
   1920 		else
   1921 		{
   1922 			width = presentParameters->BackBufferWidth;
   1923 			height = presentParameters->BackBufferHeight;
   1924 		}
   1925 
   1926 		if(presentParameters->EnableAutoDepthStencil != FALSE)
   1927 		{
   1928 			depthStencil = new Direct3DSurface8(this, this, width, height, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->AutoDepthStencilFormat == D3DFMT_D16_LOCKABLE, D3DUSAGE_DEPTHSTENCIL);
   1929 			depthStencil->bind();
   1930 		}
   1931 
   1932 		IDirect3DSurface8 *renderTarget;
   1933 		swapChain[0]->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget);
   1934 		SetRenderTarget(renderTarget, depthStencil);
   1935 		renderTarget->Release();
   1936 
   1937 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE);
   1938 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   1939 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
   1940 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
   1941 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
   1942 		SetRenderState(D3DRS_LASTPIXEL, TRUE);
   1943 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
   1944 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
   1945 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
   1946 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
   1947 		SetRenderState(D3DRS_ALPHAREF, 0);
   1948 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
   1949 		SetRenderState(D3DRS_DITHERENABLE, FALSE);
   1950 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   1951 		SetRenderState(D3DRS_FOGENABLE, FALSE);
   1952 		SetRenderState(D3DRS_SPECULARENABLE, FALSE);
   1953 	//	SetRenderState(D3DRS_ZVISIBLE, 0);
   1954 		SetRenderState(D3DRS_FOGCOLOR, 0);
   1955 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
   1956 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f));
   1957 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f));
   1958 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f));
   1959 		SetRenderState(D3DRS_EDGEANTIALIAS, FALSE);
   1960 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
   1961 		SetRenderState(D3DRS_ZBIAS, 0);
   1962 		SetRenderState(D3DRS_STENCILENABLE, FALSE);
   1963 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
   1964 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
   1965 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
   1966 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
   1967 		SetRenderState(D3DRS_STENCILREF, 0);
   1968 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
   1969 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
   1970 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
   1971 		SetRenderState(D3DRS_WRAP0, 0);
   1972 		SetRenderState(D3DRS_WRAP1, 0);
   1973 		SetRenderState(D3DRS_WRAP2, 0);
   1974 		SetRenderState(D3DRS_WRAP3, 0);
   1975 		SetRenderState(D3DRS_WRAP4, 0);
   1976 		SetRenderState(D3DRS_WRAP5, 0);
   1977 		SetRenderState(D3DRS_WRAP6, 0);
   1978 		SetRenderState(D3DRS_WRAP7, 0);
   1979 		SetRenderState(D3DRS_CLIPPING, TRUE);
   1980 		SetRenderState(D3DRS_LIGHTING, TRUE);
   1981 		SetRenderState(D3DRS_AMBIENT, 0);
   1982 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
   1983 		SetRenderState(D3DRS_COLORVERTEX, TRUE);
   1984 		SetRenderState(D3DRS_LOCALVIEWER, TRUE);
   1985 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
   1986 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
   1987 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
   1988 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
   1989 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
   1990 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
   1991 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
   1992 		SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
   1993 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f));
   1994 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(0.0f));
   1995 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
   1996 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
   1997 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f));
   1998 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
   1999 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
   2000 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
   2001 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
   2002 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
   2003 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
   2004 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f));
   2005 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
   2006 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F);
   2007 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f));
   2008 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
   2009 		SetRenderState(D3DRS_POSITIONORDER, D3DORDER_CUBIC);
   2010 		SetRenderState(D3DRS_NORMALORDER, D3DORDER_LINEAR);
   2011 
   2012 		for(int i = 0; i < 8; i++)
   2013 		{
   2014 			SetTexture(i, 0);
   2015 
   2016 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE);
   2017 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned
   2018 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
   2019 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE);
   2020 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);   // TODO: D3DTA_DIFFUSE when no texture assigned
   2021 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
   2022 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f));
   2023 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f));
   2024 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f));
   2025 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f));
   2026 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
   2027 			SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
   2028 			SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
   2029 			SetTextureStageState(i, D3DTSS_ADDRESSW, D3DTADDRESS_WRAP);
   2030 			SetTextureStageState(i, D3DTSS_BORDERCOLOR, 0x00000000);
   2031 			SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT);
   2032 			SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT);
   2033 			SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE);
   2034 			SetTextureStageState(i, D3DTSS_MIPMAPLODBIAS, 0);
   2035 			SetTextureStageState(i, D3DTSS_MAXMIPLEVEL, 0);
   2036 			SetTextureStageState(i, D3DTSS_MAXANISOTROPY, 1);
   2037 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f));
   2038 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f));
   2039 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
   2040 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
   2041 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
   2042 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
   2043 		}
   2044 
   2045 		currentPalette = 0xFFFF;
   2046 
   2047 		delete cursor;
   2048 		showCursor = false;
   2049 
   2050 		return D3D_OK;
   2051 	}
   2052 
   2053 	long Direct3DDevice8::ResourceManagerDiscardBytes(unsigned long bytes)
   2054 	{
   2055 		TRACE("");
   2056 
   2057 		return D3D_OK;
   2058 	}
   2059 
   2060 	long Direct3DDevice8::SetClipPlane(unsigned long index, const float *plane)
   2061 	{
   2062 		TRACE("");
   2063 
   2064 		if(!plane || index > 6)
   2065 		{
   2066 			return INVALIDCALL();
   2067 		}
   2068 
   2069 		if(!recordState)
   2070 		{
   2071 			this->plane[index][0] = plane[0];
   2072 			this->plane[index][1] = plane[1];
   2073 			this->plane[index][2] = plane[2];
   2074 			this->plane[index][3] = plane[3];
   2075 
   2076 			renderer->setClipPlane(index, plane);
   2077 		}
   2078 		else
   2079 		{
   2080 			stateRecorder.back()->setClipPlane(index, plane);
   2081 		}
   2082 
   2083 		return D3D_OK;
   2084 	}
   2085 
   2086 	long Direct3DDevice8::SetClipStatus(const D3DCLIPSTATUS8 *clipStatus)
   2087 	{
   2088 		TRACE("");
   2089 
   2090 		if(!clipStatus)
   2091 		{
   2092 			return INVALIDCALL();
   2093 		}
   2094 
   2095 		this->clipStatus = *clipStatus;
   2096 
   2097 		UNIMPLEMENTED();
   2098 
   2099 		return D3D_OK;
   2100 	}
   2101 
   2102 	long Direct3DDevice8::SetCurrentTexturePalette(unsigned int paletteNumber)
   2103 	{
   2104 		TRACE("");
   2105 
   2106 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end())
   2107 		{
   2108 			return INVALIDCALL();
   2109 		}
   2110 
   2111 		if(!recordState)
   2112 		{
   2113 			currentPalette = paletteNumber;
   2114 
   2115 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
   2116 		}
   2117 		else
   2118 		{
   2119 			stateRecorder.back()->setCurrentTexturePalette(paletteNumber);
   2120 		}
   2121 
   2122 		return D3D_OK;
   2123 	}
   2124 
   2125 	void Direct3DDevice8::SetCursorPosition(int x, int y, unsigned long flags)
   2126 	{
   2127 		TRACE("");
   2128 
   2129 		POINT point = {x, y};
   2130 		HWND window = focusWindow ? focusWindow : presentParameters.hDeviceWindow;
   2131 		ScreenToClient(window, &point);
   2132 
   2133 		sw::FrameBuffer::setCursorPosition(point.x, point.y);
   2134 	}
   2135 
   2136 	long Direct3DDevice8::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface8 *cursorBitmap)
   2137 	{
   2138 		TRACE("");
   2139 
   2140 		if(!cursorBitmap)
   2141 		{
   2142 			return INVALIDCALL();
   2143 		}
   2144 
   2145 		D3DSURFACE_DESC desc;
   2146 		D3DLOCKED_RECT lock;
   2147 
   2148 		cursorBitmap->GetDesc(&desc);
   2149 		cursorBitmap->LockRect(&lock, 0, 0);
   2150 
   2151 		delete cursor;
   2152 		cursor = sw::Surface::create(0, desc.Width, desc.Height, 1, 0, 1, sw::FORMAT_A8R8G8B8, false, false);
   2153 
   2154 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
   2155 		memcpy(buffer, lock.pBits, desc.Width * desc.Height * sizeof(unsigned int));
   2156 		cursor->unlockExternal();
   2157 
   2158 		cursorBitmap->UnlockRect();
   2159 
   2160 		sw::FrameBuffer::setCursorOrigin(x0, y0);
   2161 
   2162 		bindCursor();
   2163 
   2164 		return D3D_OK;
   2165 	}
   2166 
   2167 	void Direct3DDevice8::SetGammaRamp(unsigned long flags, const D3DGAMMARAMP *ramp)
   2168 	{
   2169 		TRACE("");
   2170 
   2171 		if(!ramp)
   2172 		{
   2173 			return;
   2174 		}
   2175 
   2176 		swapChain[0]->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE);
   2177 
   2178 		return;
   2179 	}
   2180 
   2181 	long Direct3DDevice8::SetLight(unsigned long index, const D3DLIGHT8 *light)
   2182 	{
   2183 		TRACE("");
   2184 
   2185 		if(!light)
   2186 		{
   2187 			return INVALIDCALL();
   2188 		}
   2189 
   2190 		if(!recordState)
   2191 		{
   2192 			this->light[index] = *light;
   2193 
   2194 			lightsDirty = true;
   2195 		}
   2196 		else
   2197 		{
   2198 			stateRecorder.back()->setLight(index, light);
   2199 		}
   2200 
   2201 		return D3D_OK;
   2202 	}
   2203 
   2204 	long Direct3DDevice8::SetMaterial(const D3DMATERIAL8 *material)
   2205 	{
   2206 		TRACE("");
   2207 
   2208 		if(!material)
   2209 		{
   2210 			return INVALIDCALL();   // FIXME: Correct behaviour?
   2211 		}
   2212 
   2213 		if(!recordState)
   2214 		{
   2215 			this->material = *material;
   2216 
   2217 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a));
   2218 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a));
   2219 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a));
   2220 			renderer->setMaterialShininess(material->Power);
   2221 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a));
   2222 		}
   2223 		else
   2224 		{
   2225 			stateRecorder.back()->setMaterial(material);
   2226 		}
   2227 
   2228 		return D3D_OK;
   2229 	}
   2230 
   2231 	long Direct3DDevice8::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries)
   2232 	{
   2233 		TRACE("");
   2234 
   2235 		if(paletteNumber > 0xFFFF || !entries)
   2236 		{
   2237 			return INVALIDCALL();
   2238 		}
   2239 
   2240 		for(int i = 0; i < 256; i++)
   2241 		{
   2242 			palette[paletteNumber].entry[i] = entries[i];
   2243 		}
   2244 
   2245 		if(paletteNumber == currentPalette)
   2246 		{
   2247 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
   2248 		}
   2249 
   2250 		return D3D_OK;
   2251 	}
   2252 
   2253 	long Direct3DDevice8::SetPixelShader(unsigned long handle)
   2254 	{
   2255 		TRACE("");
   2256 
   2257 		if(!recordState)
   2258 		{
   2259 			if(pixelShader[handle])
   2260 			{
   2261 				pixelShader[handle]->bind();
   2262 			}
   2263 
   2264 			if(pixelShader[pixelShaderHandle])
   2265 			{
   2266 				pixelShader[pixelShaderHandle]->unbind();
   2267 			}
   2268 
   2269 			pixelShaderHandle = handle;
   2270 
   2271 			if(handle != 0)
   2272 			{
   2273 				renderer->setPixelShader(pixelShader[handle]->getPixelShader());
   2274 			}
   2275 			else
   2276 			{
   2277 				renderer->setPixelShader(0);
   2278 			}
   2279 		}
   2280 		else
   2281 		{
   2282 			stateRecorder.back()->setPixelShader(handle);
   2283 		}
   2284 
   2285 		return D3D_OK;
   2286 	}
   2287 
   2288 	long Direct3DDevice8::SetPixelShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count)
   2289 	{
   2290 		TRACE("");
   2291 
   2292 		if(!recordState)
   2293 		{
   2294 			for(unsigned int i = 0; i < count; i++)
   2295 			{
   2296 				pixelShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0];
   2297 				pixelShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1];
   2298 				pixelShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2];
   2299 				pixelShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3];
   2300 			}
   2301 
   2302 			renderer->setPixelShaderConstantF(startRegister, (const float*)constantData, count);
   2303 		}
   2304 		else
   2305 		{
   2306 			stateRecorder.back()->setPixelShaderConstant(startRegister, constantData, count);
   2307 		}
   2308 
   2309 		return D3D_OK;
   2310 	}
   2311 
   2312 	long Direct3DDevice8::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value)
   2313 	{
   2314 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value);
   2315 
   2316 		if(state < D3DRS_ZENABLE || state > D3DRS_NORMALORDER)
   2317 		{
   2318 			return D3D_OK;   // FIXME: Warning
   2319 		}
   2320 
   2321 		if(!recordState)
   2322 		{
   2323 			if(!init && renderState[state] == value)
   2324 			{
   2325 				return D3D_OK;
   2326 			}
   2327 
   2328 			renderState[state] = value;
   2329 
   2330 			switch(state)
   2331 			{
   2332 			case D3DRS_ZENABLE:
   2333 				switch(value)
   2334 				{
   2335 				case D3DZB_TRUE:
   2336 				case D3DZB_USEW:
   2337 					renderer->setDepthBufferEnable(true);
   2338 					break;
   2339 				case D3DZB_FALSE:
   2340 					renderer->setDepthBufferEnable(false);
   2341 					break;
   2342 				default:
   2343 					ASSERT(false);
   2344 				}
   2345 				break;
   2346 			case D3DRS_FILLMODE:
   2347 				switch(value)
   2348 				{
   2349 				case D3DFILL_POINT:
   2350 					renderer->setFillMode(sw::FILL_VERTEX);
   2351 					break;
   2352 				case D3DFILL_WIREFRAME:
   2353 					renderer->setFillMode(sw::FILL_WIREFRAME);
   2354 					break;
   2355 				case D3DFILL_SOLID:
   2356 					renderer->setFillMode(sw::FILL_SOLID);
   2357 					break;
   2358 				default:
   2359 					ASSERT(false);
   2360 				}
   2361 				break;
   2362 			case D3DRS_SHADEMODE:
   2363 				switch(value)
   2364 				{
   2365 				case D3DSHADE_FLAT:
   2366 					renderer->setShadingMode(sw::SHADING_FLAT);
   2367 					break;
   2368 				case D3DSHADE_GOURAUD:
   2369 					renderer->setShadingMode(sw::SHADING_GOURAUD);
   2370 					break;
   2371 				case D3DSHADE_PHONG:
   2372 					// FIXME: Unimplemented (should set gouraud)?
   2373 					break;
   2374 				default:
   2375 					ASSERT(false);
   2376 				}
   2377 				break;
   2378 			case D3DRS_LINEPATTERN:
   2379 				if(!init) UNIMPLEMENTED();
   2380 				break;
   2381 			case D3DRS_ZWRITEENABLE:
   2382 				renderer->setDepthWriteEnable(value != FALSE);
   2383 				break;
   2384 			case D3DRS_ALPHATESTENABLE:
   2385 				renderer->setAlphaTestEnable(value != FALSE);
   2386 				break;
   2387 			case D3DRS_LASTPIXEL:
   2388 				if(!init) UNIMPLEMENTED();
   2389 				break;
   2390 			case D3DRS_SRCBLEND:
   2391 				switch(value)
   2392 				{
   2393 				case D3DBLEND_ZERO:
   2394 					renderer->setSourceBlendFactor(sw::BLEND_ZERO);
   2395 					break;
   2396 				case D3DBLEND_ONE:
   2397 					renderer->setSourceBlendFactor(sw::BLEND_ONE);
   2398 					break;
   2399 				case D3DBLEND_SRCCOLOR:
   2400 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE);
   2401 					break;
   2402 				case D3DBLEND_INVSRCCOLOR:
   2403 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE);
   2404 					break;
   2405 				case D3DBLEND_SRCALPHA:
   2406 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
   2407 					break;
   2408 				case D3DBLEND_INVSRCALPHA:
   2409 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2410 					break;
   2411 				case D3DBLEND_DESTALPHA:
   2412 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA);
   2413 					break;
   2414 				case D3DBLEND_INVDESTALPHA:
   2415 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA);
   2416 					break;
   2417 				case D3DBLEND_DESTCOLOR:
   2418 					renderer->setSourceBlendFactor(sw::BLEND_DEST);
   2419 					break;
   2420 				case D3DBLEND_INVDESTCOLOR:
   2421 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST);
   2422 					break;
   2423 				case D3DBLEND_SRCALPHASAT:
   2424 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT);
   2425 					break;
   2426 				case D3DBLEND_BOTHSRCALPHA:
   2427 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
   2428 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2429 					break;
   2430 				case D3DBLEND_BOTHINVSRCALPHA:
   2431 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2432 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
   2433 					break;
   2434 				default:
   2435 					ASSERT(false);
   2436 				}
   2437 				break;
   2438 			case D3DRS_DESTBLEND:
   2439 				switch(value)
   2440 				{
   2441 				case D3DBLEND_ZERO:
   2442 					renderer->setDestBlendFactor(sw::BLEND_ZERO);
   2443 					break;
   2444 				case D3DBLEND_ONE:
   2445 					renderer->setDestBlendFactor(sw::BLEND_ONE);
   2446 					break;
   2447 				case D3DBLEND_SRCCOLOR:
   2448 					renderer->setDestBlendFactor(sw::BLEND_SOURCE);
   2449 					break;
   2450 				case D3DBLEND_INVSRCCOLOR:
   2451 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE);
   2452 					break;
   2453 				case D3DBLEND_SRCALPHA:
   2454 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
   2455 					break;
   2456 				case D3DBLEND_INVSRCALPHA:
   2457 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2458 					break;
   2459 				case D3DBLEND_DESTALPHA:
   2460 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA);
   2461 					break;
   2462 				case D3DBLEND_INVDESTALPHA:
   2463 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA);
   2464 					break;
   2465 				case D3DBLEND_DESTCOLOR:
   2466 					renderer->setDestBlendFactor(sw::BLEND_DEST);
   2467 					break;
   2468 				case D3DBLEND_INVDESTCOLOR:
   2469 					renderer->setDestBlendFactor(sw::BLEND_INVDEST);
   2470 					break;
   2471 				case D3DBLEND_SRCALPHASAT:
   2472 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT);
   2473 					break;
   2474 				case D3DBLEND_BOTHSRCALPHA:
   2475 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
   2476 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2477 					break;
   2478 				case D3DBLEND_BOTHINVSRCALPHA:
   2479 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
   2480 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
   2481 					break;
   2482 				default:
   2483 					ASSERT(false);
   2484 				}
   2485 				break;
   2486 			case D3DRS_CULLMODE:
   2487 				switch(value)
   2488 				{
   2489 				case D3DCULL_NONE:
   2490 					renderer->setCullMode(sw::CULL_NONE);
   2491 					break;
   2492 				case D3DCULL_CCW:
   2493 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE);
   2494 					break;
   2495 				case D3DCULL_CW:
   2496 					renderer->setCullMode(sw::CULL_CLOCKWISE);
   2497 					break;
   2498 				default:
   2499 					ASSERT(false);
   2500 				}
   2501 				break;
   2502 			case D3DRS_ZFUNC:
   2503 				switch(value)
   2504 				{
   2505 				case D3DCMP_NEVER:
   2506 					renderer->setDepthCompare(sw::DEPTH_NEVER);
   2507 					break;
   2508 				case D3DCMP_LESS:
   2509 					renderer->setDepthCompare(sw::DEPTH_LESS);
   2510 					break;
   2511 				case D3DCMP_EQUAL:
   2512 					renderer->setDepthCompare(sw::DEPTH_EQUAL);
   2513 					break;
   2514 				case D3DCMP_LESSEQUAL:
   2515 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL);
   2516 					break;
   2517 				case D3DCMP_GREATER:
   2518 					renderer->setDepthCompare(sw::DEPTH_GREATER);
   2519 					break;
   2520 				case D3DCMP_NOTEQUAL:
   2521 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL);
   2522 					break;
   2523 				case D3DCMP_GREATEREQUAL:
   2524 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL);
   2525 					break;
   2526 				case D3DCMP_ALWAYS:
   2527 					renderer->setDepthCompare(sw::DEPTH_ALWAYS);
   2528 					break;
   2529 				default:
   2530 					ASSERT(false);
   2531 				}
   2532 				break;
   2533 			case D3DRS_ALPHAREF:
   2534 				renderer->setAlphaReference(value & 0x000000FF);
   2535 				break;
   2536 			case D3DRS_ALPHAFUNC:
   2537 				switch(value)
   2538 				{
   2539 				case D3DCMP_NEVER:
   2540 					renderer->setAlphaCompare(sw::ALPHA_NEVER);
   2541 					break;
   2542 				case D3DCMP_LESS:
   2543 					renderer->setAlphaCompare(sw::ALPHA_LESS);
   2544 					break;
   2545 				case D3DCMP_EQUAL:
   2546 					renderer->setAlphaCompare(sw::ALPHA_EQUAL);
   2547 					break;
   2548 				case D3DCMP_LESSEQUAL:
   2549 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL);
   2550 					break;
   2551 				case D3DCMP_GREATER:
   2552 					renderer->setAlphaCompare(sw::ALPHA_GREATER);
   2553 					break;
   2554 				case D3DCMP_NOTEQUAL:
   2555 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL);
   2556 					break;
   2557 				case D3DCMP_GREATEREQUAL:
   2558 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL);
   2559 					break;
   2560 				case D3DCMP_ALWAYS:
   2561 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS);
   2562 					break;
   2563 				default:
   2564 					ASSERT(false);
   2565 				}
   2566 				break;
   2567 			case D3DRS_DITHERENABLE:
   2568 			//	if(!init && value == 1) UNIMPLEMENTED();   // FIXME: Unimplemented
   2569 				break;
   2570 			case D3DRS_ALPHABLENDENABLE:
   2571 				renderer->setAlphaBlendEnable(value != FALSE);
   2572 				break;
   2573 			case D3DRS_FOGENABLE:
   2574 				renderer->setFogEnable(value != FALSE);
   2575 				break;
   2576 			case D3DRS_ZVISIBLE:
   2577 				break;   // Not supported
   2578 			case D3DRS_FOGCOLOR:
   2579 				renderer->setFogColor(value);
   2580 				break;
   2581 			case D3DRS_FOGTABLEMODE:
   2582 				switch(value)
   2583 				{
   2584 				case D3DFOG_NONE:
   2585 					renderer->setPixelFogMode(sw::FOG_NONE);
   2586 					break;
   2587 				case D3DFOG_LINEAR:
   2588 					renderer->setPixelFogMode(sw::FOG_LINEAR);
   2589 					break;
   2590 				case D3DFOG_EXP:
   2591 					renderer->setPixelFogMode(sw::FOG_EXP);
   2592 					break;
   2593 				case D3DFOG_EXP2:
   2594 					renderer->setPixelFogMode(sw::FOG_EXP2);
   2595 					break;
   2596 				default:
   2597 					ASSERT(false);
   2598 				}
   2599 				break;
   2600 			case D3DRS_FOGSTART:
   2601 				renderer->setFogStart((float&)value);
   2602 				break;
   2603 			case D3DRS_FOGEND:
   2604 				renderer->setFogEnd((float&)value);
   2605 				break;
   2606 			case D3DRS_FOGDENSITY:
   2607 				renderer->setFogDensity((float&)value);
   2608 				break;
   2609 			case D3DRS_EDGEANTIALIAS:
   2610 				if(!init) if(value != FALSE) UNIMPLEMENTED();
   2611 				break;
   2612 			case D3DRS_ZBIAS:
   2613 				renderer->setDepthBias(-2.0e-6f * value);
   2614 				renderer->setSlopeDepthBias(0.0f);
   2615 				break;
   2616 			case D3DRS_RANGEFOGENABLE:
   2617 				renderer->setRangeFogEnable(value != FALSE);
   2618 				break;
   2619 			case D3DRS_SPECULARENABLE:
   2620 				renderer->setSpecularEnable(value != FALSE);
   2621 				break;
   2622 			case D3DRS_STENCILENABLE:
   2623 				renderer->setStencilEnable(value != FALSE);
   2624 				break;
   2625 			case D3DRS_STENCILFAIL:
   2626 				switch(value)
   2627 				{
   2628 				case D3DSTENCILOP_KEEP:
   2629 					renderer->setStencilFailOperation(sw::OPERATION_KEEP);
   2630 					break;
   2631 				case D3DSTENCILOP_ZERO:
   2632 					renderer->setStencilFailOperation(sw::OPERATION_ZERO);
   2633 					break;
   2634 				case D3DSTENCILOP_REPLACE:
   2635 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE);
   2636 					break;
   2637 				case D3DSTENCILOP_INCRSAT:
   2638 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT);
   2639 					break;
   2640 				case D3DSTENCILOP_DECRSAT:
   2641 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT);
   2642 					break;
   2643 				case D3DSTENCILOP_INVERT:
   2644 					renderer->setStencilFailOperation(sw::OPERATION_INVERT);
   2645 					break;
   2646 				case D3DSTENCILOP_INCR:
   2647 					renderer->setStencilFailOperation(sw::OPERATION_INCR);
   2648 					break;
   2649 				case D3DSTENCILOP_DECR:
   2650 					renderer->setStencilFailOperation(sw::OPERATION_DECR);
   2651 					break;
   2652 				default:
   2653 					ASSERT(false);
   2654 				}
   2655 				break;
   2656 			case D3DRS_STENCILZFAIL:
   2657 				switch(value)
   2658 				{
   2659 				case D3DSTENCILOP_KEEP:
   2660 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP);
   2661 					break;
   2662 				case D3DSTENCILOP_ZERO:
   2663 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO);
   2664 					break;
   2665 				case D3DSTENCILOP_REPLACE:
   2666 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE);
   2667 					break;
   2668 				case D3DSTENCILOP_INCRSAT:
   2669 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT);
   2670 					break;
   2671 				case D3DSTENCILOP_DECRSAT:
   2672 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT);
   2673 					break;
   2674 				case D3DSTENCILOP_INVERT:
   2675 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT);
   2676 					break;
   2677 				case D3DSTENCILOP_INCR:
   2678 					renderer->setStencilZFailOperation(sw::OPERATION_INCR);
   2679 					break;
   2680 				case D3DSTENCILOP_DECR:
   2681 					renderer->setStencilZFailOperation(sw::OPERATION_DECR);
   2682 					break;
   2683 				default:
   2684 					ASSERT(false);
   2685 				}
   2686 				break;
   2687 			case D3DRS_STENCILPASS:
   2688 				switch(value)
   2689 				{
   2690 				case D3DSTENCILOP_KEEP:
   2691 					renderer->setStencilPassOperation(sw::OPERATION_KEEP);
   2692 					break;
   2693 				case D3DSTENCILOP_ZERO:
   2694 					renderer->setStencilPassOperation(sw::OPERATION_ZERO);
   2695 					break;
   2696 				case D3DSTENCILOP_REPLACE:
   2697 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE);
   2698 					break;
   2699 				case D3DSTENCILOP_INCRSAT:
   2700 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT);
   2701 					break;
   2702 				case D3DSTENCILOP_DECRSAT:
   2703 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT);
   2704 					break;
   2705 				case D3DSTENCILOP_INVERT:
   2706 					renderer->setStencilPassOperation(sw::OPERATION_INVERT);
   2707 					break;
   2708 				case D3DSTENCILOP_INCR:
   2709 					renderer->setStencilPassOperation(sw::OPERATION_INCR);
   2710 					break;
   2711 				case D3DSTENCILOP_DECR:
   2712 					renderer->setStencilPassOperation(sw::OPERATION_DECR);
   2713 					break;
   2714 				default:
   2715 					ASSERT(false);
   2716 				}
   2717 				break;
   2718 			case D3DRS_STENCILFUNC:
   2719 				switch(value)
   2720 				{
   2721 				case D3DCMP_NEVER:
   2722 					renderer->setStencilCompare(sw::STENCIL_NEVER);
   2723 					break;
   2724 				case D3DCMP_LESS:
   2725 					renderer->setStencilCompare(sw::STENCIL_LESS);
   2726 					break;
   2727 				case D3DCMP_EQUAL:
   2728 					renderer->setStencilCompare(sw::STENCIL_EQUAL);
   2729 					break;
   2730 				case D3DCMP_LESSEQUAL:
   2731 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL);
   2732 					break;
   2733 				case D3DCMP_GREATER:
   2734 					renderer->setStencilCompare(sw::STENCIL_GREATER);
   2735 					break;
   2736 				case D3DCMP_NOTEQUAL:
   2737 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL);
   2738 					break;
   2739 				case D3DCMP_GREATEREQUAL:
   2740 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL);
   2741 					break;
   2742 				case D3DCMP_ALWAYS:
   2743 					renderer->setStencilCompare(sw::STENCIL_ALWAYS);
   2744 					break;
   2745 				default:
   2746 					ASSERT(false);
   2747 				}
   2748 				break;
   2749 			case D3DRS_STENCILREF:
   2750 				renderer->setStencilReference(value);
   2751 				renderer->setStencilReferenceCCW(value);
   2752 				break;
   2753 			case D3DRS_STENCILMASK:
   2754 				renderer->setStencilMask(value);
   2755 				renderer->setStencilMaskCCW(value);
   2756 				break;
   2757 			case D3DRS_STENCILWRITEMASK:
   2758 				renderer->setStencilWriteMask(value);
   2759 				renderer->setStencilWriteMaskCCW(value);
   2760 				break;
   2761 			case D3DRS_TEXTUREFACTOR:
   2762 				renderer->setTextureFactor(value);
   2763 				break;
   2764 			case D3DRS_WRAP0:
   2765 				renderer->setTextureWrap(0, value);
   2766 				break;
   2767 			case D3DRS_WRAP1:
   2768 				renderer->setTextureWrap(1, value);
   2769 				break;
   2770 			case D3DRS_WRAP2:
   2771 				renderer->setTextureWrap(2, value);
   2772 				break;
   2773 			case D3DRS_WRAP3:
   2774 				renderer->setTextureWrap(3, value);
   2775 				break;
   2776 			case D3DRS_WRAP4:
   2777 				renderer->setTextureWrap(4, value);
   2778 				break;
   2779 			case D3DRS_WRAP5:
   2780 				renderer->setTextureWrap(5, value);
   2781 				break;
   2782 			case D3DRS_WRAP6:
   2783 				renderer->setTextureWrap(6, value);
   2784 				break;
   2785 			case D3DRS_WRAP7:
   2786 				renderer->setTextureWrap(7, value);
   2787 				break;
   2788 			case D3DRS_CLIPPING:
   2789 				// Ignored, clipping is always performed
   2790 				break;
   2791 			case D3DRS_LIGHTING:
   2792 				renderer->setLightingEnable(value != FALSE);
   2793 				break;
   2794 			case D3DRS_AMBIENT:
   2795 				renderer->setGlobalAmbient(value);
   2796 				break;
   2797 			case D3DRS_FOGVERTEXMODE:
   2798 				switch(value)
   2799 				{
   2800 				case D3DFOG_NONE:
   2801 					renderer->setVertexFogMode(sw::FOG_NONE);
   2802 					break;
   2803 				case D3DFOG_LINEAR:
   2804 					renderer->setVertexFogMode(sw::FOG_LINEAR);
   2805 					break;
   2806 				case D3DFOG_EXP:
   2807 					renderer->setVertexFogMode(sw::FOG_EXP);
   2808 					break;
   2809 				case D3DFOG_EXP2:
   2810 					renderer->setVertexFogMode(sw::FOG_EXP2);
   2811 					break;
   2812 				default:
   2813 					ASSERT(false);
   2814 				}
   2815 				break;
   2816 			case D3DRS_COLORVERTEX:
   2817 				renderer->setColorVertexEnable(value != FALSE);
   2818 				break;
   2819 			case D3DRS_LOCALVIEWER:
   2820 				renderer->setLocalViewer(value != FALSE);
   2821 				break;
   2822 			case D3DRS_NORMALIZENORMALS:
   2823 				renderer->setNormalizeNormals(value != FALSE);
   2824 				break;
   2825 			case D3DRS_DIFFUSEMATERIALSOURCE:
   2826 				switch(value)
   2827 				{
   2828 				case D3DMCS_MATERIAL:
   2829 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);
   2830 					break;
   2831 				case D3DMCS_COLOR1:
   2832 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
   2833 					break;
   2834 				case D3DMCS_COLOR2:
   2835 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2);
   2836 					break;
   2837 				default:
   2838 					ASSERT(false);
   2839 				}
   2840 				break;
   2841 			case D3DRS_SPECULARMATERIALSOURCE:
   2842 				switch(value)
   2843 				{
   2844 				case D3DMCS_MATERIAL:
   2845 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
   2846 					break;
   2847 				case D3DMCS_COLOR1:
   2848 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1);
   2849 					break;
   2850 				case D3DMCS_COLOR2:
   2851 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2);
   2852 					break;
   2853 				default:
   2854 					ASSERT(false);
   2855 				}
   2856 				break;
   2857 			case D3DRS_AMBIENTMATERIALSOURCE:
   2858 				switch(value)
   2859 				{
   2860 				case D3DMCS_MATERIAL:
   2861 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
   2862 					break;
   2863 				case D3DMCS_COLOR1:
   2864 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1);
   2865 					break;
   2866 				case D3DMCS_COLOR2:
   2867 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2);
   2868 					break;
   2869 				default:
   2870 					ASSERT(false);
   2871 				}
   2872 				break;
   2873 			case D3DRS_EMISSIVEMATERIALSOURCE:
   2874 				switch(value)
   2875 				{
   2876 				case D3DMCS_MATERIAL:
   2877 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
   2878 					break;
   2879 				case D3DMCS_COLOR1:
   2880 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1);
   2881 					break;
   2882 				case D3DMCS_COLOR2:
   2883 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2);
   2884 					break;
   2885 				default:
   2886 					ASSERT(false);
   2887 				}
   2888 				break;
   2889 			case D3DRS_VERTEXBLEND:
   2890 				switch(value)
   2891 				{
   2892 				case D3DVBF_DISABLE:
   2893 					renderer->setVertexBlendMatrixCount(0);
   2894 					break;
   2895 				case D3DVBF_1WEIGHTS:
   2896 					renderer->setVertexBlendMatrixCount(2);
   2897 					break;
   2898 				case D3DVBF_2WEIGHTS:
   2899 					renderer->setVertexBlendMatrixCount(3);
   2900 					break;
   2901 				case D3DVBF_3WEIGHTS:
   2902 					renderer->setVertexBlendMatrixCount(4);
   2903 					break;
   2904 				case D3DVBF_TWEENING:
   2905 					UNIMPLEMENTED();
   2906 					break;
   2907 				case D3DVBF_0WEIGHTS:
   2908 					renderer->setVertexBlendMatrixCount(1);
   2909 					break;
   2910 				default:
   2911 					ASSERT(false);
   2912 				}
   2913 				break;
   2914 			case D3DRS_CLIPPLANEENABLE:
   2915 				renderer->setClipFlags(value);
   2916 				break;
   2917 			case D3DRS_SOFTWAREVERTEXPROCESSING:
   2918 				break;
   2919 			case D3DRS_POINTSIZE:
   2920 				renderer->setPointSize((float&)value);
   2921 				break;
   2922 			case D3DRS_POINTSIZE_MIN:
   2923 				renderer->setPointSizeMin((float&)value);
   2924 				break;
   2925 			case D3DRS_POINTSPRITEENABLE:
   2926 				renderer->setPointSpriteEnable(value != FALSE);
   2927 				break;
   2928 			case D3DRS_POINTSCALEENABLE:
   2929 				renderer->setPointScaleEnable(value != FALSE);
   2930 				break;
   2931 			case D3DRS_POINTSCALE_A:
   2932 				renderer->setPointScaleA((float&)value);
   2933 				break;
   2934 			case D3DRS_POINTSCALE_B:
   2935 				renderer->setPointScaleB((float&)value);
   2936 				break;
   2937 			case D3DRS_POINTSCALE_C:
   2938 				renderer->setPointScaleC((float&)value);
   2939 				break;
   2940 			case D3DRS_MULTISAMPLEANTIALIAS:
   2941 			//	if(!init) UNIMPLEMENTED();
   2942 				break;
   2943 			case D3DRS_MULTISAMPLEMASK:
   2944 				SetRenderTarget(renderTarget, depthStencil);   // Sets the multi-sample mask, if maskable
   2945 				break;
   2946 			case D3DRS_PATCHEDGESTYLE:
   2947 			//	if(!init) UNIMPLEMENTED();
   2948 				break;
   2949 			case D3DRS_PATCHSEGMENTS:
   2950 			//	UNIMPLEMENTED();   // FIXME
   2951 				break;
   2952 			case D3DRS_DEBUGMONITORTOKEN:
   2953 				if(!init) UNIMPLEMENTED();
   2954 				break;
   2955 			case D3DRS_POINTSIZE_MAX:
   2956 				renderer->setPointSizeMax((float&)value);
   2957 				break;
   2958 			case D3DRS_INDEXEDVERTEXBLENDENABLE:
   2959 				renderer->setIndexedVertexBlendEnable(value != FALSE);
   2960 				break;
   2961 			case D3DRS_COLORWRITEENABLE:
   2962 				renderer->setColorWriteMask(0, value);
   2963 				break;
   2964 			case D3DRS_TWEENFACTOR:
   2965 				if(!init) UNIMPLEMENTED();
   2966 				break;
   2967 			case D3DRS_BLENDOP:
   2968 				switch(value)
   2969 				{
   2970 				case D3DBLENDOP_ADD:
   2971 					renderer->setBlendOperation(sw::BLENDOP_ADD);
   2972 					break;
   2973 				case D3DBLENDOP_SUBTRACT:
   2974 					renderer->setBlendOperation(sw::BLENDOP_SUB);
   2975 					break;
   2976 				case D3DBLENDOP_REVSUBTRACT:
   2977 					renderer->setBlendOperation(sw::BLENDOP_INVSUB);
   2978 					break;
   2979 				case D3DBLENDOP_MIN:
   2980 					renderer->setBlendOperation(sw::BLENDOP_MIN);
   2981 					break;
   2982 				case D3DBLENDOP_MAX:
   2983 					renderer->setBlendOperation(sw::BLENDOP_MAX);
   2984 					break;
   2985 				default:
   2986 					ASSERT(false);
   2987 				}
   2988 				break;
   2989 			case D3DRS_POSITIONORDER:
   2990 				if(!init) UNIMPLEMENTED();
   2991 				break;
   2992 			case D3DRS_NORMALORDER:
   2993 				if(!init) UNIMPLEMENTED();
   2994 				break;
   2995 			default:
   2996 				ASSERT(false);
   2997 			}
   2998 		}
   2999 		else   // stateRecorder
   3000 		{
   3001 			stateRecorder.back()->setRenderState(state, value);
   3002 		}
   3003 
   3004 		return D3D_OK;
   3005 	}
   3006 
   3007 	long Direct3DDevice8::SetRenderTarget(IDirect3DSurface8 *newRenderTarget, IDirect3DSurface8 *newDepthStencil)
   3008 	{
   3009 		TRACE("");
   3010 
   3011 		Direct3DSurface8 *renderTarget = static_cast<Direct3DSurface8*>(newRenderTarget);
   3012 
   3013 		if(renderTarget)   // FIXME: Check for D3DUSAGE_RENDERTARGET
   3014 		{
   3015 			renderTarget->bind();
   3016 		}
   3017 
   3018 		if(this->renderTarget)
   3019 		{
   3020 			this->renderTarget->unbind();
   3021 		}
   3022 
   3023 		this->renderTarget = renderTarget;
   3024 
   3025 		Direct3DSurface8 *depthStencil = static_cast<Direct3DSurface8*>(newDepthStencil);
   3026 
   3027 		if(depthStencil)   // FIXME: Check for D3DUSAGE_DEPTHSTENCIL and D3DPOOL_DEFAULT
   3028 		{
   3029 			depthStencil->bind();
   3030 		}
   3031 
   3032 		if(this->depthStencil)
   3033 		{
   3034 			this->depthStencil->unbind();
   3035 		}
   3036 
   3037 		this->depthStencil = depthStencil;
   3038 
   3039 		// Reset viewport to size of current render target
   3040 		D3DSURFACE_DESC renderTargetDesc;
   3041 		renderTarget->GetDesc(&renderTargetDesc);
   3042 
   3043 		D3DVIEWPORT8 viewport;
   3044 		viewport.X = 0;
   3045 		viewport.Y = 0;
   3046 		viewport.Width = renderTargetDesc.Width;
   3047 		viewport.Height = renderTargetDesc.Height;
   3048 		viewport.MinZ = 0;
   3049 		viewport.MaxZ = 1;
   3050 
   3051 		SetViewport(&viewport);
   3052 
   3053 		// Set the multi-sample mask, if maskable
   3054 		if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE)
   3055 		{
   3056 			renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]);
   3057 		}
   3058 		else
   3059 		{
   3060 			renderer->setMultiSampleMask(0xFFFFFFFF);
   3061 		}
   3062 
   3063 		renderer->setRenderTarget(0, renderTarget);
   3064 		renderer->setDepthBuffer(depthStencil);
   3065 		renderer->setStencilBuffer(depthStencil);
   3066 
   3067 		return D3D_OK;
   3068 	}
   3069 
   3070 	long Direct3DDevice8::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer8 *iVertexBuffer, unsigned int stride)
   3071 	{
   3072 		TRACE("");
   3073 
   3074 		Direct3DVertexBuffer8 *vertexBuffer = static_cast<Direct3DVertexBuffer8*>(iVertexBuffer);
   3075 
   3076 		if(!recordState)
   3077 		{
   3078 			if(vertexBuffer)
   3079 			{
   3080 				vertexBuffer->bind();
   3081 			}
   3082 
   3083 			if(dataStream[stream])
   3084 			{
   3085 				dataStream[stream]->unbind();
   3086 				streamStride[stream] = 0;
   3087 			}
   3088 
   3089 			dataStream[stream] = vertexBuffer;
   3090 			streamStride[stream] = stride;
   3091 		}
   3092 		else
   3093 		{
   3094 			stateRecorder.back()->setStreamSource(stream, vertexBuffer, stride);
   3095 		}
   3096 
   3097 		return D3D_OK;
   3098 	}
   3099 
   3100 	long Direct3DDevice8::SetTexture(unsigned long stage, IDirect3DBaseTexture8 *iBaseTexture)
   3101 	{
   3102 		TRACE("");
   3103 
   3104 		if(stage >= 8)
   3105 		{
   3106 			return INVALIDCALL();
   3107 		}
   3108 
   3109 		Direct3DBaseTexture8 *baseTexture = dynamic_cast<Direct3DBaseTexture8*>(iBaseTexture);
   3110 
   3111 		if(!recordState)
   3112 		{
   3113 			if(texture[stage] == baseTexture)
   3114 			{
   3115 				return D3D_OK;
   3116 			}
   3117 
   3118 			if(baseTexture)
   3119 			{
   3120 				baseTexture->bind();
   3121 			}
   3122 
   3123 			if(texture[stage])
   3124 			{
   3125 				texture[stage]->unbind();
   3126 			}
   3127 
   3128 			texture[stage] = baseTexture;
   3129 		}
   3130 		else
   3131 		{
   3132 			stateRecorder.back()->setTexture(stage, baseTexture);
   3133 		}
   3134 
   3135 		return D3D_OK;
   3136 	}
   3137 
   3138 	long Direct3DDevice8::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value)
   3139 	{
   3140 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value);
   3141 
   3142 		if(stage >= 8 || type < 0 || type > D3DTSS_RESULTARG)
   3143 		{
   3144 			return INVALIDCALL();
   3145 		}
   3146 
   3147 		if(!recordState)
   3148 		{
   3149 			if(!init && textureStageState[stage][type] == value)
   3150 			{
   3151 				return D3D_OK;
   3152 			}
   3153 
   3154 			textureStageState[stage][type] = value;
   3155 
   3156 			switch(type)
   3157 			{
   3158 			case D3DTSS_COLOROP:
   3159 				switch(value)
   3160 				{
   3161 				case D3DTOP_DISABLE:
   3162 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE);
   3163 					break;
   3164 				case D3DTOP_SELECTARG1:
   3165 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1);
   3166 					break;
   3167 				case D3DTOP_SELECTARG2:
   3168 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2);
   3169 					break;
   3170 				case D3DTOP_MODULATE:
   3171 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE);
   3172 					break;
   3173 				case D3DTOP_MODULATE2X:
   3174 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X);
   3175 					break;
   3176 				case D3DTOP_MODULATE4X:
   3177 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X);
   3178 					break;
   3179 				case D3DTOP_ADD:
   3180 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD);
   3181 					break;
   3182 				case D3DTOP_ADDSIGNED:
   3183 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED);
   3184 					break;
   3185 				case D3DTOP_ADDSIGNED2X:
   3186 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
   3187 					break;
   3188 				case D3DTOP_SUBTRACT:
   3189 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT);
   3190 					break;
   3191 				case D3DTOP_ADDSMOOTH:
   3192 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH);
   3193 					break;
   3194 				case D3DTOP_BLENDDIFFUSEALPHA:
   3195 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
   3196 					break;
   3197 				case D3DTOP_BLENDTEXTUREALPHA:
   3198 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
   3199 					break;
   3200 				case D3DTOP_BLENDFACTORALPHA:
   3201 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
   3202 					break;
   3203 				case D3DTOP_BLENDTEXTUREALPHAPM:
   3204 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
   3205 					break;
   3206 				case D3DTOP_BLENDCURRENTALPHA:
   3207 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
   3208 					break;
   3209 				case D3DTOP_PREMODULATE:
   3210 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE);
   3211 					break;
   3212 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
   3213 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
   3214 					break;
   3215 				case D3DTOP_MODULATECOLOR_ADDALPHA:
   3216 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
   3217 					break;
   3218 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
   3219 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
   3220 					break;
   3221 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
   3222 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
   3223 					break;
   3224 				case D3DTOP_BUMPENVMAP:
   3225 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP);
   3226 					break;
   3227 				case D3DTOP_BUMPENVMAPLUMINANCE:
   3228 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
   3229 					break;
   3230 				case D3DTOP_DOTPRODUCT3:
   3231 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3);
   3232 					break;
   3233 				case D3DTOP_MULTIPLYADD:
   3234 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD);
   3235 					break;
   3236 				case D3DTOP_LERP:
   3237 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP);
   3238 					break;
   3239 				default:
   3240 					ASSERT(false);
   3241 				}
   3242 				break;
   3243 			case D3DTSS_COLORARG1:
   3244 				switch(value & D3DTA_SELECTMASK)
   3245 				{
   3246 				case D3DTA_DIFFUSE:
   3247 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3248 					break;
   3249 				case D3DTA_CURRENT:
   3250 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT);
   3251 					break;
   3252 				case D3DTA_TEXTURE:
   3253 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
   3254 					break;
   3255 				case D3DTA_TFACTOR:
   3256 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
   3257 					break;
   3258 				case D3DTA_SPECULAR:
   3259 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
   3260 					break;
   3261 				case D3DTA_TEMP:
   3262 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP);
   3263 					break;
   3264 				default:
   3265 					ASSERT(false);
   3266 				}
   3267 
   3268 				switch(value & ~D3DTA_SELECTMASK)
   3269 				{
   3270 				case 0:
   3271 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR);
   3272 					break;
   3273 				case D3DTA_COMPLEMENT:
   3274 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3275 					break;
   3276 				case D3DTA_ALPHAREPLICATE:
   3277 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
   3278 					break;
   3279 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3280 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3281 					break;
   3282 				default:
   3283 					ASSERT(false);
   3284 				}
   3285 				break;
   3286 			case D3DTSS_COLORARG2:
   3287 				switch(value & D3DTA_SELECTMASK)
   3288 				{
   3289 				case D3DTA_DIFFUSE:
   3290 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3291 					break;
   3292 				case D3DTA_CURRENT:
   3293 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT);
   3294 					break;
   3295 				case D3DTA_TEXTURE:
   3296 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
   3297 					break;
   3298 				case D3DTA_TFACTOR:
   3299 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
   3300 					break;
   3301 				case D3DTA_SPECULAR:
   3302 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
   3303 					break;
   3304 				case D3DTA_TEMP:
   3305 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP);
   3306 					break;
   3307 				default:
   3308 					ASSERT(false);
   3309 				}
   3310 
   3311 				switch(value & ~D3DTA_SELECTMASK)
   3312 				{
   3313 				case 0:
   3314 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR);
   3315 					break;
   3316 				case D3DTA_COMPLEMENT:
   3317 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3318 					break;
   3319 				case D3DTA_ALPHAREPLICATE:
   3320 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
   3321 					break;
   3322 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3323 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3324 					break;
   3325 				default:
   3326 					ASSERT(false);
   3327 				}
   3328 				break;
   3329 			case D3DTSS_ALPHAOP:
   3330 				switch(value)
   3331 				{
   3332 				case D3DTOP_DISABLE:
   3333 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE);
   3334 					break;
   3335 				case D3DTOP_SELECTARG1:
   3336 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1);
   3337 					break;
   3338 				case D3DTOP_SELECTARG2:
   3339 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2);
   3340 					break;
   3341 				case D3DTOP_MODULATE:
   3342 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE);
   3343 					break;
   3344 				case D3DTOP_MODULATE2X:
   3345 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X);
   3346 					break;
   3347 				case D3DTOP_MODULATE4X:
   3348 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X);
   3349 					break;
   3350 				case D3DTOP_ADD:
   3351 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD);
   3352 					break;
   3353 				case D3DTOP_ADDSIGNED:
   3354 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED);
   3355 					break;
   3356 				case D3DTOP_ADDSIGNED2X:
   3357 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
   3358 					break;
   3359 				case D3DTOP_SUBTRACT:
   3360 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT);
   3361 					break;
   3362 				case D3DTOP_ADDSMOOTH:
   3363 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH);
   3364 					break;
   3365 				case D3DTOP_BLENDDIFFUSEALPHA:
   3366 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
   3367 					break;
   3368 				case D3DTOP_BLENDTEXTUREALPHA:
   3369 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
   3370 					break;
   3371 				case D3DTOP_BLENDFACTORALPHA:
   3372 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
   3373 					break;
   3374 				case D3DTOP_BLENDTEXTUREALPHAPM:
   3375 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
   3376 					break;
   3377 				case D3DTOP_BLENDCURRENTALPHA:
   3378 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
   3379 					break;
   3380 				case D3DTOP_PREMODULATE:
   3381 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE);
   3382 					break;
   3383 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
   3384 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
   3385 					break;
   3386 				case D3DTOP_MODULATECOLOR_ADDALPHA:
   3387 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
   3388 					break;
   3389 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
   3390 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
   3391 					break;
   3392 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
   3393 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
   3394 					break;
   3395 				case D3DTOP_BUMPENVMAP:
   3396 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP);
   3397 					break;
   3398 				case D3DTOP_BUMPENVMAPLUMINANCE:
   3399 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
   3400 					break;
   3401 				case D3DTOP_DOTPRODUCT3:
   3402 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3);
   3403 					break;
   3404 				case D3DTOP_MULTIPLYADD:
   3405 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD);
   3406 					break;
   3407 				case D3DTOP_LERP:
   3408 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP);
   3409 					break;
   3410 				default:
   3411 					ASSERT(false);
   3412 				}
   3413 				break;
   3414 			case D3DTSS_ALPHAARG1:
   3415 				switch(value & D3DTA_SELECTMASK)
   3416 				{
   3417 				case D3DTA_DIFFUSE:
   3418 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3419 					break;
   3420 				case D3DTA_CURRENT:
   3421 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
   3422 					break;
   3423 				case D3DTA_TEXTURE:
   3424 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
   3425 					break;
   3426 				case D3DTA_TFACTOR:
   3427 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
   3428 					break;
   3429 				case D3DTA_SPECULAR:
   3430 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
   3431 					break;
   3432 				case D3DTA_TEMP:
   3433 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
   3434 					break;
   3435 				default:
   3436 					ASSERT(false);
   3437 				}
   3438 
   3439 				switch(value & ~D3DTA_SELECTMASK)
   3440 				{
   3441 				case 0:
   3442 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
   3443 					break;
   3444 				case D3DTA_COMPLEMENT:
   3445 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3446 					break;
   3447 				case D3DTA_ALPHAREPLICATE:
   3448 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
   3449 					break;
   3450 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3451 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3452 					break;
   3453 				default:
   3454 					ASSERT(false);
   3455 				}
   3456 				break;
   3457 			case D3DTSS_ALPHAARG2:
   3458 				switch(value & D3DTA_SELECTMASK)
   3459 				{
   3460 				case D3DTA_DIFFUSE:
   3461 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3462 					break;
   3463 				case D3DTA_CURRENT:
   3464 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
   3465 					break;
   3466 				case D3DTA_TEXTURE:
   3467 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
   3468 					break;
   3469 				case D3DTA_TFACTOR:
   3470 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
   3471 					break;
   3472 				case D3DTA_SPECULAR:
   3473 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
   3474 					break;
   3475 				case D3DTA_TEMP:
   3476 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
   3477 					break;
   3478 				default:
   3479 					ASSERT(false);
   3480 				}
   3481 
   3482 				switch(value & ~D3DTA_SELECTMASK)
   3483 				{
   3484 				case 0:
   3485 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
   3486 					break;
   3487 				case D3DTA_COMPLEMENT:
   3488 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3489 					break;
   3490 				case D3DTA_ALPHAREPLICATE:
   3491 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
   3492 					break;
   3493 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3494 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3495 					break;
   3496 				default:
   3497 					ASSERT(false);
   3498 				}
   3499 				break;
   3500 			case D3DTSS_BUMPENVMAT00:
   3501 				renderer->setBumpmapMatrix(stage, 0, (float&)value);
   3502 				break;
   3503 			case D3DTSS_BUMPENVMAT01:
   3504 				renderer->setBumpmapMatrix(stage, 1, (float&)value);
   3505 				break;
   3506 			case D3DTSS_BUMPENVMAT10:
   3507 				renderer->setBumpmapMatrix(stage, 2, (float&)value);
   3508 				break;
   3509 			case D3DTSS_BUMPENVMAT11:
   3510 				renderer->setBumpmapMatrix(stage, 3, (float&)value);
   3511 				break;
   3512 			case D3DTSS_TEXCOORDINDEX:
   3513 				renderer->setTexCoordIndex(stage, value & 0xFFFF);
   3514 
   3515 				switch(value & 0xFFFF0000)
   3516 				{
   3517 				case D3DTSS_TCI_PASSTHRU:
   3518 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU);
   3519 					break;
   3520 				case D3DTSS_TCI_CAMERASPACENORMAL:
   3521 					renderer->setTexCoordIndex(stage, stage);
   3522 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL);
   3523 					break;
   3524 				case D3DTSS_TCI_CAMERASPACEPOSITION:
   3525 					renderer->setTexCoordIndex(stage, stage);
   3526 					renderer->setTexGen(stage, sw::TEXGEN_POSITION);
   3527 					break;
   3528 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
   3529 					renderer->setTexCoordIndex(stage, stage);
   3530 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION);
   3531 					break;
   3532 				default:
   3533 					ASSERT(false);
   3534 				}
   3535 				break;
   3536 			case D3DTSS_ADDRESSU:
   3537 				switch(value)
   3538 				{
   3539 				case D3DTADDRESS_WRAP:
   3540 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
   3541 					break;
   3542 				case D3DTADDRESS_MIRROR:
   3543 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
   3544 					break;
   3545 				case D3DTADDRESS_CLAMP:
   3546 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
   3547 					break;
   3548 				case D3DTADDRESS_BORDER:
   3549 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
   3550 					break;
   3551 				case D3DTADDRESS_MIRRORONCE:
   3552 					renderer->setAddressingModeU(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
   3553 					break;
   3554 				default:
   3555 					ASSERT(false);
   3556 				}
   3557 				break;
   3558 			case D3DTSS_ADDRESSV:
   3559 				switch(value)
   3560 				{
   3561 				case D3DTADDRESS_WRAP:
   3562 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
   3563 					break;
   3564 				case D3DTADDRESS_MIRROR:
   3565 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
   3566 					break;
   3567 				case D3DTADDRESS_CLAMP:
   3568 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
   3569 					break;
   3570 				case D3DTADDRESS_BORDER:
   3571 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
   3572 					break;
   3573 				case D3DTADDRESS_MIRRORONCE:
   3574 					renderer->setAddressingModeV(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
   3575 					break;
   3576 				default:
   3577 					ASSERT(false);
   3578 				}
   3579 				break;
   3580 			case D3DTSS_BORDERCOLOR:
   3581 				renderer->setBorderColor(sw::SAMPLER_PIXEL, stage, value);
   3582 				break;
   3583 			case D3DTSS_MAGFILTER:
   3584 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
   3585 				switch(value)
   3586 				{
   3587 				case D3DTEXF_NONE:
   3588 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
   3589 					break;
   3590 				case D3DTEXF_POINT:
   3591 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
   3592 					break;
   3593 				case D3DTEXF_LINEAR:
   3594 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);
   3595 					break;
   3596 				case D3DTEXF_ANISOTROPIC:
   3597 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC);
   3598 					break;
   3599 				case D3DTEXF_FLATCUBIC:
   3600 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
   3601 					break;
   3602 				case D3DTEXF_GAUSSIANCUBIC:
   3603 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
   3604 					break;
   3605 				default:
   3606 					return INVALIDCALL();
   3607 				};
   3608 				break;
   3609 			case D3DTSS_MINFILTER:
   3610 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
   3611 				switch(value)
   3612 				{
   3613 				case D3DTEXF_NONE:
   3614 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
   3615 					break;
   3616 				case D3DTEXF_POINT:
   3617 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_POINT);
   3618 					break;
   3619 				case D3DTEXF_LINEAR:
   3620 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);
   3621 					break;
   3622 				case D3DTEXF_ANISOTROPIC:
   3623 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_ANISOTROPIC);
   3624 					break;
   3625 				case D3DTEXF_FLATCUBIC:
   3626 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
   3627 					break;
   3628 				case D3DTEXF_GAUSSIANCUBIC:
   3629 					renderer->setTextureFilter(sw::SAMPLER_PIXEL, stage, sw::FILTER_LINEAR);   // NOTE: Unimplemented, fail silently
   3630 					break;
   3631 				default:
   3632 					return INVALIDCALL();
   3633 				};
   3634 				break;
   3635 			case D3DTSS_MIPFILTER:
   3636 				switch(value)
   3637 				{
   3638 				case D3DTEXF_NONE:
   3639 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_NONE);
   3640 					break;
   3641 				case D3DTEXF_POINT:
   3642 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_POINT);
   3643 					break;
   3644 				case D3DTEXF_LINEAR:
   3645 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);
   3646 					break;
   3647 				case D3DTEXF_ANISOTROPIC:
   3648 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
   3649 					break;
   3650 				case D3DTEXF_FLATCUBIC:
   3651 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
   3652 					break;
   3653 				case D3DTEXF_GAUSSIANCUBIC:
   3654 					renderer->setMipmapFilter(sw::SAMPLER_PIXEL, stage, sw::MIPMAP_LINEAR);   // NOTE: Unimplemented, fail silently
   3655 					break;
   3656 				default:
   3657 					return INVALIDCALL();
   3658 				};
   3659 				break;
   3660 			case D3DTSS_MIPMAPLODBIAS:
   3661 				{
   3662 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes
   3663 					renderer->setMipmapLOD(sw::SAMPLER_PIXEL, stage, LOD);
   3664 				}
   3665 				break;
   3666 			case D3DTSS_MAXMIPLEVEL:
   3667 				break;
   3668 			case D3DTSS_MAXANISOTROPY:
   3669 				renderer->setMaxAnisotropy(sw::SAMPLER_PIXEL, stage, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy));
   3670 				break;
   3671 			case D3DTSS_BUMPENVLSCALE:
   3672 				renderer->setLuminanceScale(stage, (float&)value);
   3673 				break;
   3674 			case D3DTSS_BUMPENVLOFFSET:
   3675 				renderer->setLuminanceOffset(stage, (float&)value);
   3676 				break;
   3677 			case D3DTSS_TEXTURETRANSFORMFLAGS:
   3678 				switch(value & ~D3DTTFF_PROJECTED)
   3679 				{
   3680 				case D3DTTFF_DISABLE:
   3681 					renderer->setTextureTransform(stage, 0, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
   3682 					break;
   3683 				case D3DTTFF_COUNT1:
   3684 					renderer->setTextureTransform(stage, 1, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
   3685 					break;
   3686 				case D3DTTFF_COUNT2:
   3687 					renderer->setTextureTransform(stage, 2, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
   3688 					break;
   3689 				case D3DTTFF_COUNT3:
   3690 					renderer->setTextureTransform(stage, 3, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
   3691 					break;
   3692 				case D3DTTFF_COUNT4:
   3693 					renderer->setTextureTransform(stage, 4, (value &  D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
   3694 					break;
   3695 				default:
   3696 					ASSERT(false);
   3697 				}
   3698 				break;
   3699 			case D3DTSS_ADDRESSW:
   3700 				switch(value)
   3701 				{
   3702 				case D3DTADDRESS_WRAP:
   3703 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_WRAP);
   3704 					break;
   3705 				case D3DTADDRESS_MIRROR:
   3706 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRROR);
   3707 					break;
   3708 				case D3DTADDRESS_CLAMP:
   3709 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_CLAMP);
   3710 					break;
   3711 				case D3DTADDRESS_BORDER:
   3712 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_BORDER);
   3713 					break;
   3714 				case D3DTADDRESS_MIRRORONCE:
   3715 					renderer->setAddressingModeW(sw::SAMPLER_PIXEL, stage, sw::ADDRESSING_MIRRORONCE);
   3716 					break;
   3717 				default:
   3718 					ASSERT(false);
   3719 				}
   3720 				break;
   3721 			case D3DTSS_COLORARG0:
   3722 				switch(value & D3DTA_SELECTMASK)
   3723 				{
   3724 				case D3DTA_CURRENT:
   3725 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT);
   3726 					break;
   3727 				case D3DTA_DIFFUSE:
   3728 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3729 					break;
   3730 				case D3DTA_SPECULAR:
   3731 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
   3732 					break;
   3733 				case D3DTA_TEMP:
   3734 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP);
   3735 					break;
   3736 				case D3DTA_TEXTURE:
   3737 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
   3738 					break;
   3739 				case D3DTA_TFACTOR:
   3740 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
   3741 					break;
   3742 				default:
   3743 					ASSERT(false);
   3744 				}
   3745 
   3746 				switch(value & ~D3DTA_SELECTMASK)
   3747 				{
   3748 				case 0:
   3749 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR);
   3750 					break;
   3751 				case D3DTA_COMPLEMENT:
   3752 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3753 					break;
   3754 				case D3DTA_ALPHAREPLICATE:
   3755 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
   3756 					break;
   3757 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3758 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3759 					break;
   3760 				default:
   3761 					ASSERT(false);
   3762 				}
   3763 				break;
   3764 			case D3DTSS_ALPHAARG0:
   3765 				switch(value & D3DTA_SELECTMASK)
   3766 				{
   3767 				case D3DTA_DIFFUSE:
   3768 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
   3769 					break;
   3770 				case D3DTA_CURRENT:
   3771 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
   3772 					break;
   3773 				case D3DTA_TEXTURE:
   3774 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
   3775 					break;
   3776 				case D3DTA_TFACTOR:
   3777 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
   3778 					break;
   3779 				case D3DTA_SPECULAR:
   3780 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
   3781 					break;
   3782 				case D3DTA_TEMP:
   3783 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
   3784 					break;
   3785 				default:
   3786 					ASSERT(false);
   3787 				}
   3788 
   3789 				switch(value & ~D3DTA_SELECTMASK)
   3790 				{
   3791 				case 0:
   3792 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
   3793 					break;
   3794 				case D3DTA_COMPLEMENT:
   3795 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
   3796 					break;
   3797 				case D3DTA_ALPHAREPLICATE:
   3798 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
   3799 					break;
   3800 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
   3801 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
   3802 					break;
   3803 				default:
   3804 					ASSERT(false);
   3805 				}
   3806 				break;
   3807 			case D3DTSS_RESULTARG:
   3808 				switch(value & D3DTA_SELECTMASK)
   3809 				{
   3810 				case D3DTA_CURRENT:
   3811 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT);
   3812 					break;
   3813 				case D3DTA_TEMP:
   3814 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP);
   3815 					break;
   3816 				default:
   3817 					ASSERT(false);
   3818 				}
   3819 				break;
   3820 			default:
   3821 				ASSERT(false);
   3822 			}
   3823 		}
   3824 		else   // stateRecorder
   3825 		{
   3826 			stateRecorder.back()->setTextureStageState(stage, type, value);
   3827 		}
   3828 
   3829 		return D3D_OK;
   3830 	}
   3831 
   3832 	long Direct3DDevice8::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
   3833 	{
   3834 		TRACE("");
   3835 
   3836 		if(!matrix || state < 0 || state > 511)
   3837 		{
   3838 			return INVALIDCALL();
   3839 		}
   3840 
   3841 		if(!recordState)
   3842 		{
   3843 			this->matrix[state] = *matrix;
   3844 
   3845 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
   3846 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
   3847 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
   3848 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
   3849 
   3850 			switch(state)
   3851 			{
   3852 			case D3DTS_WORLD:
   3853 				renderer->setModelMatrix(M);
   3854 				break;
   3855 			case D3DTS_VIEW:
   3856 				renderer->setViewMatrix(M);
   3857 				break;
   3858 			case D3DTS_PROJECTION:
   3859 				renderer->setProjectionMatrix(M);
   3860 				break;
   3861 			case D3DTS_TEXTURE0:
   3862 				renderer->setTextureMatrix(0, M);
   3863 				break;
   3864 			case D3DTS_TEXTURE1:
   3865 				renderer->setTextureMatrix(1, M);
   3866 				break;
   3867 			case D3DTS_TEXTURE2:
   3868 				renderer->setTextureMatrix(2, M);
   3869 				break;
   3870 			case D3DTS_TEXTURE3:
   3871 				renderer->setTextureMatrix(3, M);
   3872 				break;
   3873 			case D3DTS_TEXTURE4:
   3874 				renderer->setTextureMatrix(4, M);
   3875 				break;
   3876 			case D3DTS_TEXTURE5:
   3877 				renderer->setTextureMatrix(5, M);
   3878 				break;
   3879 			case D3DTS_TEXTURE6:
   3880 				renderer->setTextureMatrix(6, M);
   3881 				break;
   3882 			case D3DTS_TEXTURE7:
   3883 				renderer->setTextureMatrix(7, M);
   3884 				break;
   3885 			default:
   3886 				if(state > 256 && state < 512)
   3887 				{
   3888 					renderer->setModelMatrix(M, state - 256);
   3889 				}
   3890 				else ASSERT(false);
   3891 			}
   3892 		}
   3893 		else   // stateRecorder
   3894 		{
   3895 			stateRecorder.back()->setTransform(state, matrix);
   3896 		}
   3897 
   3898 		return D3D_OK;
   3899 	}
   3900 
   3901 	long Direct3DDevice8::SetVertexShader(unsigned long handle)
   3902 	{
   3903 		TRACE("");
   3904 
   3905 		if(!recordState)
   3906 		{
   3907 			if(handle & 0x00000001)
   3908 			{
   3909 				unsigned int index = handle >> 16;
   3910 
   3911 				if(vertexShader[index])
   3912 				{
   3913 					vertexShader[index]->bind();
   3914 				}
   3915 
   3916 				if(vertexShader[vertexShaderHandle >> 16])
   3917 				{
   3918 					vertexShader[vertexShaderHandle >> 16]->unbind();
   3919 				}
   3920 
   3921 				vertexShaderHandle = handle;
   3922 
   3923 				Direct3DVertexShader8 *shader = vertexShader[index];
   3924 				renderer->setVertexShader(shader->getVertexShader());
   3925 				declaration = shader->getDeclaration();
   3926 
   3927 				FVF = 0;
   3928 			}
   3929 			else
   3930 			{
   3931 				renderer->setVertexShader(0);
   3932 				declaration = 0;
   3933 
   3934 				FVF = handle;
   3935 			}
   3936 		}
   3937 		else
   3938 		{
   3939 			stateRecorder.back()->setVertexShader(handle);
   3940 		}
   3941 
   3942 		return D3D_OK;
   3943 	}
   3944 
   3945 	long Direct3DDevice8::SetVertexShaderConstant(unsigned long startRegister, const void *constantData, unsigned long count)
   3946 	{
   3947 		TRACE("");
   3948 
   3949 		if(!constantData)
   3950 		{
   3951 			return INVALIDCALL();
   3952 		}
   3953 
   3954 		if(!recordState)
   3955 		{
   3956 			for(unsigned int i = 0; i < count; i++)
   3957 			{
   3958 				vertexShaderConstant[startRegister + i][0] = ((float*)constantData)[i * 4 + 0];
   3959 				vertexShaderConstant[startRegister + i][1] = ((float*)constantData)[i * 4 + 1];
   3960 				vertexShaderConstant[startRegister + i][2] = ((float*)constantData)[i * 4 + 2];
   3961 				vertexShaderConstant[startRegister + i][3] = ((float*)constantData)[i * 4 + 3];
   3962 			}
   3963 
   3964 			renderer->setVertexShaderConstantF(startRegister, (const float*)constantData, count);
   3965 		}
   3966 		else
   3967 		{
   3968 			stateRecorder.back()->setVertexShaderConstant(startRegister, constantData, count);
   3969 		}
   3970 
   3971 		return D3D_OK;
   3972 	}
   3973 
   3974 	long Direct3DDevice8::SetViewport(const D3DVIEWPORT8 *viewport)
   3975 	{
   3976 		TRACE("");
   3977 
   3978 		if(!viewport)
   3979 		{
   3980 			return INVALIDCALL();
   3981 		}
   3982 
   3983 		if(!recordState)
   3984 		{
   3985 			this->viewport = *viewport;
   3986 		}
   3987 		else
   3988 		{
   3989 			stateRecorder.back()->setViewport(viewport);
   3990 		}
   3991 
   3992 		return D3D_OK;
   3993 	}
   3994 
   3995 	int Direct3DDevice8::ShowCursor(int show)
   3996 	{
   3997 		TRACE("");
   3998 
   3999 		int oldValue = showCursor ? TRUE : FALSE;
   4000 
   4001 		showCursor = show != FALSE && cursor;
   4002 
   4003 		bindCursor();
   4004 
   4005 		return oldValue;
   4006 	}
   4007 
   4008 	long Direct3DDevice8::TestCooperativeLevel()
   4009 	{
   4010 		TRACE("");
   4011 
   4012 		return D3D_OK;
   4013 	}
   4014 
   4015 	long Direct3DDevice8::UpdateTexture(IDirect3DBaseTexture8 *sourceTexture, IDirect3DBaseTexture8 *destinationTexture)
   4016 	{
   4017 		TRACE("");
   4018 
   4019 		if(!sourceTexture || !destinationTexture)
   4020 		{
   4021 			return INVALIDCALL();
   4022 		}
   4023 
   4024 		D3DRESOURCETYPE type = sourceTexture->GetType();
   4025 
   4026 		if(type != destinationTexture->GetType())
   4027 		{
   4028 			return INVALIDCALL();
   4029 		}
   4030 
   4031 		switch(type)
   4032 		{
   4033 		case D3DRTYPE_TEXTURE:
   4034 			{
   4035 				IDirect3DTexture8 *source;
   4036 				IDirect3DTexture8 *dest;
   4037 
   4038 				sourceTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&source);
   4039 				destinationTexture->QueryInterface(IID_IDirect3DTexture8, (void**)&dest);
   4040 
   4041 				ASSERT(source && dest);
   4042 
   4043 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)
   4044 				{
   4045 					IDirect3DSurface8 *sourceSurface;
   4046 					IDirect3DSurface8 *destinationSurface;
   4047 
   4048 					source->GetSurfaceLevel(level, &sourceSurface);
   4049 					dest->GetSurfaceLevel(level, &destinationSurface);
   4050 
   4051 					updateSurface(sourceSurface, 0, destinationSurface, 0);
   4052 
   4053 					sourceSurface->Release();
   4054 					destinationSurface->Release();
   4055 				}
   4056 
   4057 				source->Release();
   4058 				dest->Release();
   4059 			}
   4060 			break;
   4061 		case D3DRTYPE_VOLUMETEXTURE:
   4062 			{
   4063 				IDirect3DVolumeTexture8 *source;
   4064 				IDirect3DVolumeTexture8 *dest;
   4065 
   4066 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&source);
   4067 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture8, (void**)&dest);
   4068 
   4069 				ASSERT(source && dest);
   4070 
   4071 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
   4072 				{
   4073 					IDirect3DVolume8 *sourceVolume;
   4074 					IDirect3DVolume8 *destinationVolume;
   4075 
   4076 					source->GetVolumeLevel(level, &sourceVolume);
   4077 					dest->GetVolumeLevel(level, &destinationVolume);
   4078 
   4079 					updateVolume(sourceVolume, destinationVolume);
   4080 
   4081 					sourceVolume->Release();
   4082 					destinationVolume->Release();
   4083 				}
   4084 
   4085 				source->Release();
   4086 				dest->Release();
   4087 			}
   4088 			break;
   4089 		case D3DRTYPE_CUBETEXTURE:
   4090 			{
   4091 				IDirect3DCubeTexture8 *source;
   4092 				IDirect3DCubeTexture8 *dest;
   4093 
   4094 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&source);
   4095 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture8, (void**)&dest);
   4096 
   4097 				ASSERT(source && dest);
   4098 
   4099 				for(int face = 0; face < 6; face++)
   4100 				{
   4101 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)
   4102 					{
   4103 						IDirect3DSurface8 *sourceSurface;
   4104 						IDirect3DSurface8 *destinationSurface;
   4105 
   4106 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface);
   4107 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface);
   4108 
   4109 						updateSurface(sourceSurface, 0, destinationSurface, 0);
   4110 
   4111 						sourceSurface->Release();
   4112 						destinationSurface->Release();
   4113 					}
   4114 				}
   4115 
   4116 				source->Release();
   4117 				dest->Release();
   4118 			}
   4119 			break;
   4120 		default:
   4121 			ASSERT(false);
   4122 		}
   4123 
   4124 		return D3D_OK;
   4125 	}
   4126 
   4127 	long Direct3DDevice8::ValidateDevice(unsigned long *numPasses)
   4128 	{
   4129 		TRACE("");
   4130 
   4131 		if(!numPasses)
   4132 		{
   4133 			return INVALIDCALL();
   4134 		}
   4135 
   4136 		*numPasses = 1;
   4137 
   4138 		return D3D_OK;
   4139 	}
   4140 
   4141 	long Direct3DDevice8::updateSurface(IDirect3DSurface8 *sourceSurface, const RECT *sourceRect, IDirect3DSurface8 *destinationSurface, const POINT *destPoint)
   4142 	{
   4143 		TRACE("IDirect3DSurface8 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface8 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint);
   4144 
   4145 		if(!sourceSurface || !destinationSurface)
   4146 		{
   4147 			return INVALIDCALL();
   4148 		}
   4149 
   4150 		D3DSURFACE_DESC sourceDescription;
   4151 		D3DSURFACE_DESC destinationDescription;
   4152 
   4153 		sourceSurface->GetDesc(&sourceDescription);
   4154 		destinationSurface->GetDesc(&destinationDescription);
   4155 
   4156 		RECT sRect;
   4157 		RECT dRect;
   4158 
   4159 		if(sourceRect && destPoint)
   4160 		{
   4161 			sRect.left = sourceRect->left;
   4162 			sRect.top = sourceRect->top;
   4163 			sRect.right = sourceRect->right;
   4164 			sRect.bottom = sourceRect->bottom;
   4165 
   4166 			dRect.left = destPoint->x;
   4167 			dRect.top = destPoint->y;
   4168 			dRect.right = destPoint->x + sourceRect->right - sourceRect->left;
   4169 			dRect.bottom = destPoint->y + sourceRect->bottom - sourceRect->top;
   4170 		}
   4171 		else
   4172 		{
   4173 			sRect.left = 0;
   4174 			sRect.top = 0;
   4175 			sRect.right = sourceDescription.Width;
   4176 			sRect.bottom = sourceDescription.Height;
   4177 
   4178 			dRect.left = 0;
   4179 			dRect.top = 0;
   4180 			dRect.right = destinationDescription.Width;
   4181 			dRect.bottom = destinationDescription.Height;
   4182 		}
   4183 
   4184 		int sWidth = sRect.right - sRect.left;
   4185 		int sHeight = sRect.bottom - sRect.top;
   4186 
   4187 		int dWidth = dRect.right - dRect.left;
   4188 		int dHeight = dRect.bottom - dRect.top;
   4189 
   4190 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE ||
   4191 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE ||
   4192 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags
   4193 		// destinationDescription.Pool != D3DPOOL_DEFAULT ||
   4194 		   sourceDescription.Format != destinationDescription.Format ||
   4195 		   sWidth  != dWidth ||
   4196 		   sHeight != dHeight)
   4197 		{
   4198 			return INVALIDCALL();
   4199 		}
   4200 
   4201 		D3DLOCKED_RECT sourceLock;
   4202 		D3DLOCKED_RECT destinationLock;
   4203 
   4204 		sourceSurface->LockRect(&sourceLock, &sRect, D3DLOCK_READONLY);
   4205 		destinationSurface->LockRect(&destinationLock, &dRect, 0);
   4206 
   4207 		unsigned int width;
   4208 		unsigned int height;
   4209 		unsigned int bytes;
   4210 
   4211 		switch(sourceDescription.Format)
   4212 		{
   4213 		case D3DFMT_DXT1:
   4214 			width = (dWidth + 3) / 4;
   4215 			height = (dHeight + 3) / 4;
   4216 			bytes = width * 8;   // 64 bit per 4x4 block
   4217 			break;
   4218 		case D3DFMT_DXT2:
   4219 		case D3DFMT_DXT3:
   4220 		case D3DFMT_DXT4:
   4221 		case D3DFMT_DXT5:
   4222 			width = (dWidth + 3) / 4;
   4223 			height = (dHeight + 3) / 4;
   4224 			bytes = width * 16;   // 128 bit per 4x4 block
   4225 			break;
   4226 		default:
   4227 			width = dWidth;
   4228 			height = dHeight;
   4229 			bytes = width * Direct3DSurface8::bytes(sourceDescription.Format);
   4230 		}
   4231 
   4232 		for(unsigned int y = 0; y < height; y++)
   4233 		{
   4234 			memcpy(destinationLock.pBits, sourceLock.pBits, bytes);
   4235 
   4236 			(byte*&)sourceLock.pBits += sourceLock.Pitch;
   4237 			(byte*&)destinationLock.pBits += destinationLock.Pitch;
   4238 		}
   4239 
   4240 		sourceSurface->UnlockRect();
   4241 		destinationSurface->UnlockRect();
   4242 
   4243 		return D3D_OK;
   4244 	}
   4245 
   4246 	long Direct3DDevice8::SetIndices(IDirect3DIndexBuffer8 *iIndexBuffer, unsigned int baseVertexIndex)
   4247 	{
   4248 		TRACE("");
   4249 
   4250 		Direct3DIndexBuffer8 *indexBuffer = static_cast<Direct3DIndexBuffer8*>(iIndexBuffer);
   4251 
   4252 		if(!recordState)
   4253 		{
   4254 			if(indexBuffer)
   4255 			{
   4256 				indexBuffer->bind();
   4257 			}
   4258 
   4259 			if(this->indexData)
   4260 			{
   4261 				this->indexData->unbind();
   4262 			}
   4263 
   4264 			this->indexData = indexBuffer;
   4265 			this->baseVertexIndex = baseVertexIndex;
   4266 		}
   4267 		else
   4268 		{
   4269 			stateRecorder.back()->setIndices(indexBuffer, baseVertexIndex);
   4270 		}
   4271 
   4272 		return D3D_OK;
   4273 	}
   4274 
   4275 	int Direct3DDevice8::FVFStride(unsigned long FVF)
   4276 	{
   4277 		int stride = 0;
   4278 
   4279 		switch(FVF & D3DFVF_POSITION_MASK)
   4280 		{
   4281 		case D3DFVF_XYZ:	stride += 12;	break;
   4282 		case D3DFVF_XYZRHW:	stride += 16;	break;
   4283 		case D3DFVF_XYZB1:	stride += 16;	break;
   4284 		case D3DFVF_XYZB2:	stride += 20;	break;
   4285 		case D3DFVF_XYZB3:	stride += 24;	break;
   4286 		case D3DFVF_XYZB4:	stride += 28;	break;
   4287 		case D3DFVF_XYZB5:	stride += 32;	break;
   4288 		}
   4289 
   4290 		if(FVF & D3DFVF_NORMAL)		stride += 12;
   4291 		if(FVF & D3DFVF_PSIZE)		stride += 4;
   4292 		if(FVF & D3DFVF_DIFFUSE)	stride += 4;
   4293 		if(FVF & D3DFVF_SPECULAR)	stride += 4;
   4294 
   4295 		switch((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT)
   4296 		{
   4297 		case 8: stride += 4 + 4 * ((1 + (FVF >> 30)) % 4);
   4298 		case 7: stride += 4 + 4 * ((1 + (FVF >> 28)) % 4);
   4299 		case 6: stride += 4 + 4 * ((1 + (FVF >> 26)) % 4);
   4300 		case 5: stride += 4 + 4 * ((1 + (FVF >> 24)) % 4);
   4301 		case 4: stride += 4 + 4 * ((1 + (FVF >> 22)) % 4);
   4302 		case 3: stride += 4 + 4 * ((1 + (FVF >> 20)) % 4);
   4303 		case 2: stride += 4 + 4 * ((1 + (FVF >> 18)) % 4);
   4304 		case 1: stride += 4 + 4 * ((1 + (FVF >> 16)) % 4);
   4305 		case 0: break;
   4306 		default:
   4307 			ASSERT(false);
   4308 		}
   4309 
   4310 		return stride;
   4311 	}
   4312 
   4313 	int Direct3DDevice8::typeStride(unsigned char type)
   4314 	{
   4315 		static const int LUT[] =
   4316 		{
   4317 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.)
   4318 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.)
   4319 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.)
   4320 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float
   4321 			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)
   4322 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte
   4323 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.)
   4324 			8 	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short
   4325 		};
   4326 
   4327 		if(type <= 7)
   4328 		{
   4329 			return LUT[type];
   4330 		}
   4331 		else ASSERT(false);
   4332 
   4333 		return 0;
   4334 	}
   4335 
   4336 	bool Direct3DDevice8::bindData(Direct3DIndexBuffer8 *indexBuffer, int base)
   4337 	{
   4338 		if(!bindViewport())
   4339 		{
   4340 			return false;   // Zero-area target region
   4341 		}
   4342 
   4343 		bindTextures();
   4344 		bindStreams(base);
   4345 		bindIndexBuffer(indexBuffer);
   4346 		bindLights();
   4347 
   4348 		return true;
   4349 	}
   4350 
   4351 	void Direct3DDevice8::bindStreams(int base)
   4352 	{
   4353 		renderer->resetInputStreams((FVF & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW);
   4354 
   4355 		int stride;
   4356 
   4357 		if(!declaration)   // Fixed-function vertex pipeline
   4358 		{
   4359 			const void *buffer = 0;
   4360 
   4361 			ASSERT(dataStream[0]);
   4362 
   4363 			Direct3DVertexBuffer8 *stream = dataStream[0];
   4364 			sw::Resource *resource = stream->getResource();
   4365 			buffer = (char*)resource->data();
   4366 			stride = FVFStride(FVF);
   4367 
   4368 			ASSERT(stride == streamStride[0]);   // FIXME
   4369 			ASSERT(buffer && stride);
   4370 
   4371 			(char*&)buffer += stride * base;
   4372 
   4373 			sw::Stream attribute(resource, buffer, stride);
   4374 
   4375 			switch(FVF & D3DFVF_POSITION_MASK)
   4376 			{
   4377 			case D3DFVF_XYZ:
   4378 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4379 				(char*&)buffer += 12;
   4380 				break;
   4381 			case D3DFVF_XYZRHW:
   4382 				renderer->setInputStream(sw::PositionT, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4));
   4383 				(char*&)buffer += 16;
   4384 				break;
   4385 			case D3DFVF_XYZB1:
   4386 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4387 				(char*&)buffer += 12;
   4388 
   4389 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active?
   4390 				(char*&)buffer += 4;
   4391 				break;
   4392 			case D3DFVF_XYZB2:
   4393 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4394 				(char*&)buffer += 12;
   4395 
   4396 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));   // FIXME: Stream type depends on indexed blending active?
   4397 				(char*&)buffer += 8;
   4398 				break;
   4399 			case D3DFVF_XYZB3:
   4400 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4401 				(char*&)buffer += 12;
   4402 
   4403 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 2));   // FIXME: Stream type depends on indexed blending active?
   4404 				(char*&)buffer += 12;
   4405 				break;
   4406 			case D3DFVF_XYZB4:
   4407 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4408 				(char*&)buffer += 12;
   4409 
   4410 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));   // FIXME: Stream type depends on indexed blending active?
   4411 				(char*&)buffer += 16;
   4412 				break;
   4413 			case D3DFVF_XYZB5:
   4414 				renderer->setInputStream(sw::Position, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4415 				(char*&)buffer += 12;
   4416 
   4417 				renderer->setInputStream(sw::BlendWeight, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 4));   // FIXME: Stream type depends on indexed blending active?
   4418 				(char*&)buffer += 20;
   4419 				break;
   4420 			}
   4421 
   4422 			if(FVF & D3DFVF_LASTBETA_UBYTE4)
   4423 			{
   4424 				renderer->setInputStream(sw::BlendIndices, attribute.define((char*&)buffer - 4, sw::STREAMTYPE_INDICES, 1));
   4425 			}
   4426 
   4427 			if(FVF & D3DFVF_NORMAL)
   4428 			{
   4429 				renderer->setInputStream(sw::Normal, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 3));
   4430 				(char*&)buffer += 12;
   4431 			}
   4432 
   4433 			if(FVF & D3DFVF_PSIZE)
   4434 			{
   4435 				renderer->setInputStream(sw::PointSize, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1));
   4436 				(char*&)buffer += 4;
   4437 			}
   4438 
   4439 			if(FVF & D3DFVF_DIFFUSE)
   4440 			{
   4441 				renderer->setInputStream(sw::Color0, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4));
   4442 				(char*&)buffer += 4;
   4443 			}
   4444 
   4445 			if(FVF & D3DFVF_SPECULAR)
   4446 			{
   4447 				renderer->setInputStream(sw::Color1, attribute.define(buffer, sw::STREAMTYPE_COLOR, 4));
   4448 				(char*&)buffer += 4;
   4449 			}
   4450 
   4451 			for(unsigned int i = 0; i < 8; i++)
   4452 			{
   4453 				if((FVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT >= i + 1)
   4454 				{
   4455 					renderer->setInputStream(sw::TexCoord0 + i, attribute.define(buffer, sw::STREAMTYPE_FLOAT, 1 + (1 + (FVF >> (16 + i * 2))) % 4));
   4456 					(char*&)buffer += 4 + 4 * ((1 + (FVF >> (16 + i * 2))) % 4);
   4457 				}
   4458 			}
   4459 		}
   4460 		else
   4461 		{
   4462 			const unsigned long *element = declaration;
   4463 			int stream = 0;
   4464 			sw::Resource *resource;
   4465 			const void *buffer = 0;
   4466 
   4467 			while(*element != 0xFFFFFFFF)
   4468 			{
   4469 				switch((*element & 0xE0000000) >> 29)
   4470 				{
   4471 				case 0:   // NOP
   4472 					if(*element != 0x00000000)
   4473 					{
   4474 						ASSERT(false);
   4475 					}
   4476 					break;
   4477 				case 1:   // Stream selector
   4478 					stream = *element & 0x0000000F;
   4479 					{
   4480 						ASSERT(dataStream[stream]);   // Expected a stream
   4481 
   4482 						Direct3DVertexBuffer8 *streamBuffer = (Direct3DVertexBuffer8*)dataStream[stream];
   4483 						resource = streamBuffer->getResource();
   4484 						buffer = (char*)resource->data();
   4485 
   4486 						const unsigned long *streamElement = element + 1;
   4487 						stride = 0;
   4488 
   4489 						while((*streamElement & 0xE0000000) >> 29 == 2)   // Data definition
   4490 						{
   4491 							if(*streamElement & 0x10000000)   // Data skip
   4492 							{
   4493 								int skip = (*streamElement & 0x000F0000) >> 16;
   4494 
   4495 								stride += 4 * skip;
   4496 							}
   4497 							else
   4498 							{
   4499 								stride += typeStride((unsigned char)((*streamElement & 0x000F0000) >> 16));
   4500 							}
   4501 
   4502 							streamElement++;
   4503 						}
   4504 
   4505 					//	ASSERT(stride == streamStride[stream]);   // FIXME: Probably just ignore
   4506 
   4507 						(char*&)buffer += stride * base;
   4508 					}
   4509 					break;
   4510 				case 2:   // Data definition
   4511 					if(*element & 0x10000000)   // Data skip
   4512 					{
   4513 						int skip = (*element & 0x000F0000) >> 16;
   4514 
   4515 						(char*&)buffer += 4 * skip;
   4516 					}
   4517 					else
   4518 					{
   4519 						int type = (*element & 0x000F0000) >> 16;
   4520 						int index = (*element & 0x0000000F) >> 0;
   4521 
   4522 						sw::Stream attribute(resource, buffer, stride);
   4523 
   4524 						switch(type)
   4525 						{
   4526 						case D3DVSDT_FLOAT1:   attribute.define(sw::STREAMTYPE_FLOAT, 1); break;
   4527 						case D3DVSDT_FLOAT2:   attribute.define(sw::STREAMTYPE_FLOAT, 2); break;
   4528 						case D3DVSDT_FLOAT3:   attribute.define(sw::STREAMTYPE_FLOAT, 3); break;
   4529 						case D3DVSDT_FLOAT4:   attribute.define(sw::STREAMTYPE_FLOAT, 4); break;
   4530 						case D3DVSDT_D3DCOLOR: attribute.define(sw::STREAMTYPE_COLOR, 4); break;
   4531 						case D3DVSDT_UBYTE4:   attribute.define(sw::STREAMTYPE_BYTE, 4);  break;
   4532 						case D3DVSDT_SHORT2:   attribute.define(sw::STREAMTYPE_SHORT, 2); break;
   4533 						case D3DVSDT_SHORT4:   attribute.define(sw::STREAMTYPE_SHORT, 4); break;
   4534 						default:               attribute.define(sw::STREAMTYPE_FLOAT, 0); ASSERT(false);
   4535 						}
   4536 
   4537 						switch(index)
   4538 						{
   4539 						case D3DVSDE_POSITION:     renderer->setInputStream(sw::Position, attribute);     break;
   4540 						case D3DVSDE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);  break;
   4541 						case D3DVSDE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute); break;
   4542 						case D3DVSDE_NORMAL:       renderer->setInputStream(sw::Normal, attribute);       break;
   4543 						case D3DVSDE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute);    break;
   4544 						case D3DVSDE_DIFFUSE:      renderer->setInputStream(sw::Color0, attribute);       break;
   4545 						case D3DVSDE_SPECULAR:     renderer->setInputStream(sw::Color1, attribute);       break;
   4546 						case D3DVSDE_TEXCOORD0:    renderer->setInputStream(sw::TexCoord0, attribute);    break;
   4547 						case D3DVSDE_TEXCOORD1:    renderer->setInputStream(sw::TexCoord1, attribute);    break;
   4548 						case D3DVSDE_TEXCOORD2:    renderer->setInputStream(sw::TexCoord2, attribute);    break;
   4549 						case D3DVSDE_TEXCOORD3:    renderer->setInputStream(sw::TexCoord3, attribute);    break;
   4550 						case D3DVSDE_TEXCOORD4:    renderer->setInputStream(sw::TexCoord4, attribute);    break;
   4551 						case D3DVSDE_TEXCOORD5:    renderer->setInputStream(sw::TexCoord5, attribute);    break;
   4552 						case D3DVSDE_TEXCOORD6:    renderer->setInputStream(sw::TexCoord6, attribute);    break;
   4553 						case D3DVSDE_TEXCOORD7:    renderer->setInputStream(sw::TexCoord7, attribute);    break;
   4554 					//	case D3DVSDE_POSITION2:    renderer->setInputStream(sw::Position1, attribute);    break;
   4555 					//	case D3DVSDE_NORMAL2:      renderer->setInputStream(sw::Normal1, attribute);      break;
   4556 						default:
   4557 							ASSERT(false);
   4558 						}
   4559 
   4560 						(char*&)buffer += typeStride(type);
   4561 					}
   4562 					break;
   4563 				case 3:   // Tesselator data
   4564 					UNIMPLEMENTED();
   4565 					break;
   4566 				case 4:   // Constant data
   4567 					{
   4568 						int count = (*element & 0x1E000000) >> 25;
   4569 						int index = (*element & 0x0000007F) >> 0;
   4570 
   4571 						SetVertexShaderConstant(index, element + 1, count);
   4572 
   4573 						element += 4 * count;
   4574 					}
   4575 					break;
   4576 				case 5:   // Extension
   4577 					UNIMPLEMENTED();
   4578 					break;
   4579 				default:
   4580 					ASSERT(false);
   4581 				}
   4582 
   4583 				element++;
   4584 			}
   4585 		}
   4586 	}
   4587 
   4588 	void Direct3DDevice8::bindIndexBuffer(Direct3DIndexBuffer8 *indexBuffer)
   4589 	{
   4590 		sw::Resource *resource = 0;
   4591 
   4592 		if(indexBuffer)
   4593 		{
   4594 			resource = indexBuffer->getResource();
   4595 		}
   4596 
   4597 		renderer->setIndexBuffer(resource);
   4598 	}
   4599 
   4600 	void Direct3DDevice8::bindLights()
   4601 	{
   4602 		if(!lightsDirty) return;
   4603 
   4604 		Lights::iterator i = light.begin();
   4605 		int active = 0;
   4606 
   4607 		// Set and enable renderer lights
   4608 		while(active < 8)
   4609 		{
   4610 			while(i != light.end() && !i->second.enable)
   4611 			{
   4612 				i++;
   4613 			}
   4614 
   4615 			if(i == light.end())
   4616 			{
   4617 				break;
   4618 			}
   4619 
   4620 			const Light &l = i->second;
   4621 
   4622 			sw::Point position(l.Position.x, l.Position.y, l.Position.z);
   4623 			sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a);
   4624 			sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a);
   4625 			sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a);
   4626 			sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z);
   4627 
   4628 			renderer->setLightDiffuse(active, diffuse);
   4629 			renderer->setLightSpecular(active, specular);
   4630 			renderer->setLightAmbient(active, ambient);
   4631 
   4632 			if(l.Type == D3DLIGHT_DIRECTIONAL)
   4633 			{
   4634 			//	goto next;   // FIXME
   4635 
   4636 				// FIXME: Unsupported, make it a positional light far away without falloff
   4637 				renderer->setLightPosition(active, -1000 * direction);
   4638 				renderer->setLightRange(active, l.Range);
   4639 				renderer->setLightAttenuation(active, 1, 0, 0);
   4640 			}
   4641 			else if(l.Type == D3DLIGHT_SPOT)
   4642 			{
   4643 			//	goto next;   // FIXME
   4644 
   4645 				// FIXME: Unsupported, make it a positional light
   4646 				renderer->setLightPosition(active, position);
   4647 				renderer->setLightRange(active, l.Range);
   4648 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
   4649 			}
   4650 			else
   4651 			{
   4652 				renderer->setLightPosition(active, position);
   4653 				renderer->setLightRange(active, l.Range);
   4654 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
   4655 			}
   4656 
   4657 			renderer->setLightEnable(active, true);
   4658 
   4659 			active++;
   4660 
   4661 	//	next:   // FIXME
   4662 			i++;
   4663 		}
   4664 
   4665 		// Remaining lights are disabled
   4666 		while(active < 8)
   4667 		{
   4668 			renderer->setLightEnable(active, false);
   4669 
   4670 			active++;
   4671 		}
   4672 
   4673 		lightsDirty= false;
   4674 	}
   4675 
   4676 	bool Direct3DDevice8::bindViewport()
   4677 	{
   4678 		if(viewport.Width == 0 || viewport.Height == 0)
   4679 		{
   4680 			return false;
   4681 		}
   4682 
   4683 		sw::Viewport view;
   4684 		view.x0 = (float)viewport.X;
   4685 		view.y0 = (float)viewport.Y + viewport.Height;
   4686 		view.width = (float)viewport.Width;
   4687 		view.height = -(float)viewport.Height;
   4688 		view.minZ = viewport.MinZ;
   4689 		view.maxZ = viewport.MaxZ;
   4690 
   4691 		renderer->setViewport(view);
   4692 
   4693 		sw::Rect scissor;
   4694 		scissor.x0 = viewport.X;
   4695 		scissor.x1 = viewport.X + viewport.Width;
   4696 		scissor.y0 = viewport.Y;
   4697 		scissor.y1 = viewport.Y + viewport.Height;
   4698 
   4699 		renderer->setScissor(scissor);
   4700 
   4701 		return true;
   4702 	}
   4703 
   4704 	void Direct3DDevice8::bindTextures()
   4705 	{
   4706 		for(int stage = 0; stage < 8; stage++)
   4707 		{
   4708 			Direct3DBaseTexture8 *baseTexture = texture[stage];
   4709 			sw::Resource *resource = 0;
   4710 
   4711 			bool textureUsed = false;
   4712 
   4713 			if(pixelShader[pixelShaderHandle])
   4714 			{
   4715 				textureUsed = pixelShader[pixelShaderHandle]->getPixelShader()->usesSampler(stage);
   4716 			}
   4717 			else
   4718 			{
   4719 				textureUsed = true;   // FIXME: Check fixed-function use?
   4720 			}
   4721 
   4722 			if(baseTexture && textureUsed)
   4723 			{
   4724 				resource = baseTexture->getResource();
   4725 			}
   4726 
   4727 			renderer->setTextureResource(stage, resource);
   4728 
   4729 			if(baseTexture && textureUsed)
   4730 			{
   4731 				int levelCount = baseTexture->getInternalLevelCount();
   4732 
   4733 				int textureLOD = baseTexture->GetLOD();
   4734 				int stageLOD = textureStageState[stage][D3DTSS_MAXMIPLEVEL];
   4735 				int LOD = textureLOD > stageLOD ? textureLOD : stageLOD;
   4736 
   4737 				if(textureStageState[stage][D3DTSS_MIPFILTER] == D3DTEXF_NONE)
   4738 				{
   4739 					LOD = 0;
   4740 				}
   4741 
   4742 				switch(baseTexture->GetType())
   4743 				{
   4744 				case D3DRTYPE_TEXTURE:
   4745 					{
   4746 						Direct3DTexture8 *texture = dynamic_cast<Direct3DTexture8*>(baseTexture);
   4747 						Direct3DSurface8 *surface;
   4748 
   4749 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
   4750 						{
   4751 							int surfaceLevel = mipmapLevel;
   4752 
   4753 							if(surfaceLevel < LOD)
   4754 							{
   4755 								surfaceLevel = LOD;
   4756 							}
   4757 
   4758 							if(surfaceLevel < 0)
   4759 							{
   4760 								surfaceLevel = 0;
   4761 							}
   4762 							else if(surfaceLevel >= levelCount)
   4763 							{
   4764 								surfaceLevel = levelCount - 1;
   4765 							}
   4766 
   4767 							surface = texture->getInternalSurfaceLevel(surfaceLevel);
   4768 							renderer->setTextureLevel(stage, 0, mipmapLevel, surface, sw::TEXTURE_2D);
   4769 						}
   4770 					}
   4771 					break;
   4772 				case D3DRTYPE_CUBETEXTURE:
   4773 					for(int face = 0; face < 6; face++)
   4774 					{
   4775 						Direct3DCubeTexture8 *cubeTexture = dynamic_cast<Direct3DCubeTexture8*>(baseTexture);
   4776 						Direct3DSurface8 *surface;
   4777 
   4778 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
   4779 						{
   4780 							int surfaceLevel = mipmapLevel;
   4781 
   4782 							if(surfaceLevel < LOD)
   4783 							{
   4784 								surfaceLevel = LOD;
   4785 							}
   4786 
   4787 							if(surfaceLevel < 0)
   4788 							{
   4789 								surfaceLevel = 0;
   4790 							}
   4791 							else if(surfaceLevel >= levelCount)
   4792 							{
   4793 								surfaceLevel = levelCount - 1;
   4794 							}
   4795 
   4796 							surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel);
   4797 							renderer->setTextureLevel(stage, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
   4798 						}
   4799 					}
   4800 					break;
   4801 				case D3DRTYPE_VOLUMETEXTURE:
   4802 					{
   4803 						Direct3DVolumeTexture8 *volumeTexture = dynamic_cast<Direct3DVolumeTexture8*>(baseTexture);
   4804 						Direct3DVolume8 *volume;
   4805 
   4806 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
   4807 						{
   4808 							int surfaceLevel = mipmapLevel;
   4809 
   4810 							if(surfaceLevel < LOD)
   4811 							{
   4812 								surfaceLevel = LOD;
   4813 							}
   4814 
   4815 							if(surfaceLevel < 0)
   4816 							{
   4817 								surfaceLevel = 0;
   4818 							}
   4819 							else if(surfaceLevel >= levelCount)
   4820 							{
   4821 								surfaceLevel = levelCount - 1;
   4822 							}
   4823 
   4824 							volume = volumeTexture->getInternalVolumeLevel(surfaceLevel);
   4825 							renderer->setTextureLevel(stage, 0, mipmapLevel, volume, sw::TEXTURE_3D);
   4826 						}
   4827 					}
   4828 					break;
   4829 				default:
   4830 					UNIMPLEMENTED();
   4831 				}
   4832 			}
   4833 			else
   4834 			{
   4835 				renderer->setTextureLevel(stage, 0, 0, 0, sw::TEXTURE_NULL);
   4836 			}
   4837 		}
   4838 	}
   4839 
   4840 	void Direct3DDevice8::bindCursor()
   4841 	{
   4842 		if(showCursor)
   4843 		{
   4844 			sw::FrameBuffer::setCursorImage(cursor);
   4845 
   4846 			HCURSOR oldCursor = SetCursor(nullCursor);
   4847 
   4848 			if(oldCursor != nullCursor)
   4849 			{
   4850 				win32Cursor = oldCursor;
   4851 			}
   4852 		}
   4853 		else
   4854 		{
   4855 			sw::FrameBuffer::setCursorImage(0);
   4856 
   4857 			if(GetCursor() == nullCursor)
   4858 			{
   4859 				SetCursor(win32Cursor);
   4860 			}
   4861 		}
   4862 	}
   4863 
   4864 	long Direct3DDevice8::updateVolume(IDirect3DVolume8 *sourceVolume, IDirect3DVolume8 *destinationVolume)
   4865 	{
   4866 		TRACE("IDirect3DVolume8 *sourceVolume = 0x%0.8p, IDirect3DVolume8 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume);
   4867 
   4868 		if(!sourceVolume || !destinationVolume)
   4869 		{
   4870 			return INVALIDCALL();
   4871 		}
   4872 
   4873 		D3DVOLUME_DESC sourceDescription;
   4874 		D3DVOLUME_DESC destinationDescription;
   4875 
   4876 		sourceVolume->GetDesc(&sourceDescription);
   4877 		destinationVolume->GetDesc(&destinationDescription);
   4878 
   4879 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||
   4880 		   destinationDescription.Pool != D3DPOOL_DEFAULT ||
   4881 		   sourceDescription.Format != destinationDescription.Format ||
   4882 		   sourceDescription.Width  != destinationDescription.Width ||
   4883 		   sourceDescription.Height != destinationDescription.Height)
   4884 		{
   4885 			return INVALIDCALL();
   4886 		}
   4887 
   4888 		D3DLOCKED_BOX sourceLock;
   4889 		D3DLOCKED_BOX destinationLock;
   4890 
   4891 		sourceVolume->LockBox(&sourceLock, 0, 0);
   4892 		destinationVolume->LockBox(&destinationLock, 0, 0);
   4893 
   4894 		if(sourceLock.RowPitch != destinationLock.RowPitch ||
   4895 		   sourceLock.SlicePitch != destinationLock.SlicePitch)
   4896 		{
   4897 			UNIMPLEMENTED();
   4898 		}
   4899 
   4900 		memcpy(destinationLock.pBits, sourceLock.pBits, sourceLock.SlicePitch * sourceDescription.Depth);
   4901 
   4902 		sourceVolume->UnlockBox();
   4903 		destinationVolume->UnlockBox();
   4904 
   4905 		return D3D_OK;
   4906 	}
   4907 
   4908 	void Direct3DDevice8::configureFPU()
   4909 	{
   4910 		unsigned short cw;
   4911 
   4912 		__asm
   4913 		{
   4914 			fstcw cw
   4915 			and cw, 0xFCFC   // Single-precision
   4916 			or cw, 0x003F    // Mask all exceptions
   4917 			and cw, 0xF3FF   // Round to nearest
   4918 			fldcw cw
   4919 		}
   4920 	}
   4921 }
   4922