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 "Direct3DDevice9.hpp"
16 
17 #include "Direct3D9.hpp"
18 #include "Direct3DSurface9.hpp"
19 #include "Direct3DIndexBuffer9.hpp"
20 #include "Direct3DVertexBuffer9.hpp"
21 #include "Direct3DTexture9.hpp"
22 #include "Direct3DVolumeTexture9.hpp"
23 #include "Direct3DCubeTexture9.hpp"
24 #include "Direct3DVertexDeclaration9.hpp"
25 #include "Direct3DSwapChain9.hpp"
26 #include "Direct3DPixelShader9.hpp"
27 #include "Direct3DVertexShader9.hpp"
28 #include "Direct3DStateBlock9.hpp"
29 #include "Direct3DQuery9.hpp"
30 #include "Direct3DVolume9.hpp"
31 
32 #include "Debug.hpp"
33 #include "Capabilities.hpp"
34 #include "Math.hpp"
35 #include "Renderer.hpp"
36 #include "Config.hpp"
37 #include "FrameBuffer.hpp"
38 #include "Clipper.hpp"
39 #include "Configurator.hpp"
40 #include "Timer.hpp"
41 #include "Resource.hpp"
42 
43 #include <assert.h>
44 
45 bool localShaderConstants = true;
46 
47 namespace D3D9
48 {
FtoDW(float f)49 	inline unsigned long FtoDW(float f)
50 	{
51 		return (unsigned long&)f;
52 	}
53 
Direct3DDevice9(const HINSTANCE instance,Direct3D9 * d3d9,unsigned int adapter,D3DDEVTYPE deviceType,HWND focusWindow,unsigned long behaviourFlags,D3DPRESENT_PARAMETERS * presentParameters)54 	Direct3DDevice9::Direct3DDevice9(const HINSTANCE instance, Direct3D9 *d3d9, unsigned int adapter, D3DDEVTYPE deviceType, HWND focusWindow, unsigned long behaviourFlags, D3DPRESENT_PARAMETERS *presentParameters) : instance(instance), adapter(adapter), d3d9(d3d9), deviceType(deviceType), focusWindow(focusWindow), behaviourFlags(behaviourFlags)
55 	{
56 		InitializeCriticalSection(&criticalSection);
57 
58 		init = true;
59 		stateRecorder = 0;
60 
61 		d3d9->AddRef();
62 
63 		context = new sw::Context();
64 		renderer = new sw::Renderer(context, sw::Direct3D, false);
65 
66 		swapChain = 0;
67 		depthStencil = 0;
68 		autoDepthStencil = 0;
69 		renderTarget[0] = 0;
70 		renderTarget[1] = 0;
71 		renderTarget[2] = 0;
72 		renderTarget[3] = 0;
73 
74 		for(int i = 0; i < 16 + 4; i++)
75 		{
76 			texture[i] = 0;
77 		}
78 
79 		cursor = 0;
80 
81 		Reset(presentParameters);
82 
83 		pixelShader = 0;
84 		vertexShader = 0;
85 
86 		lightsDirty = true;
87 		pixelShaderDirty = true;
88 		pixelShaderConstantsBDirty = 0;
89 		pixelShaderConstantsFDirty = 0;
90 		pixelShaderConstantsIDirty = 0;
91 		vertexShaderDirty = true;
92 		vertexShaderConstantsBDirty = 0;
93 		vertexShaderConstantsFDirty = 0;
94 		vertexShaderConstantsIDirty = 0;
95 
96 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
97 		{
98 			dataStream[i] = 0;
99 			streamStride[i] = 0;
100 			streamOffset[i] = 0;
101 
102 			streamSourceFreq[i] = 1;
103 		}
104 
105 		indexData = 0;
106 		vertexDeclaration = 0;
107 
108 		D3DMATERIAL9 material;
109 
110 		material.Diffuse.r = 1.0f;
111 		material.Diffuse.g = 1.0f;
112 		material.Diffuse.b = 1.0f;
113 		material.Diffuse.a = 0.0f;
114 		material.Ambient.r = 0.0f;
115 		material.Ambient.g = 0.0f;
116 		material.Ambient.b = 0.0f;
117 		material.Ambient.a = 0.0f;
118 		material.Emissive.r = 0.0f;
119 		material.Emissive.g = 0.0f;
120 		material.Emissive.b = 0.0f;
121 		material.Emissive.a = 0.0f;
122 		material.Specular.r = 0.0f;
123 		material.Specular.g = 0.0f;
124 		material.Specular.b = 0.0f;
125 		material.Specular.a = 0.0f;
126 		material.Power = 0.0f;
127 
128 		SetMaterial(&material);
129 
130 		D3DMATRIX identity = {1, 0, 0, 0,
131 		                      0, 1, 0, 0,
132 		                      0, 0, 1, 0,
133 		                      0, 0, 0, 1};
134 
135 		SetTransform(D3DTS_VIEW, &identity);
136 		SetTransform(D3DTS_PROJECTION, &identity);
137 		SetTransform(D3DTS_TEXTURE0, &identity);
138 		SetTransform(D3DTS_TEXTURE1, &identity);
139 		SetTransform(D3DTS_TEXTURE2, &identity);
140 		SetTransform(D3DTS_TEXTURE3, &identity);
141 		SetTransform(D3DTS_TEXTURE4, &identity);
142 		SetTransform(D3DTS_TEXTURE5, &identity);
143 		SetTransform(D3DTS_TEXTURE6, &identity);
144 		SetTransform(D3DTS_TEXTURE7, &identity);
145 
146 		for(int i = 0; i < 12; i++)
147 		{
148 			SetTransform(D3DTS_WORLDMATRIX(i), &identity);
149 		}
150 
151 		for(int i = 0; i < MAX_PIXEL_SHADER_CONST; i++)
152 		{
153 			float zero[4] = {0, 0, 0, 0};
154 
155 			SetPixelShaderConstantF(i, zero, 1);
156 		}
157 
158 		for(int i = 0; i < MAX_VERTEX_SHADER_CONST; i++)
159 		{
160 			float zero[4] = {0, 0, 0, 0};
161 
162 			SetVertexShaderConstantF(i, zero, 1);
163 		}
164 
165 		for(int i = 0; i < 16; i++)
166 		{
167 			int zero[4] = {0, 0, 0, 0};
168 
169 			SetPixelShaderConstantI(i, zero, 1);
170 			SetVertexShaderConstantI(i, zero, 1);
171 			SetPixelShaderConstantB(i, &zero[0], 1);
172 			SetVertexShaderConstantB(i, &zero[0], 1);
173 		}
174 
175 		init = false;
176 
177 		if(!(behaviourFlags & D3DCREATE_FPU_PRESERVE))
178 		{
179 			configureFPU();
180 		}
181 
182 		instancingEnabled = pixelShaderVersionX >= D3DPS_VERSION(3, 0);
183 	}
184 
~Direct3DDevice9()185 	Direct3DDevice9::~Direct3DDevice9()
186 	{
187 		delete renderer;
188 		renderer = 0;
189 		delete context;
190 		context = 0;
191 
192 		d3d9->Release();
193 		d3d9 = 0;
194 
195 		swapChain->unbind();
196 		swapChain = 0;
197 
198 		if(depthStencil)
199 		{
200 			depthStencil->unbind();
201 			depthStencil = 0;
202 		}
203 
204 		if(autoDepthStencil)
205 		{
206 			autoDepthStencil->unbind();
207 			autoDepthStencil = 0;
208 		}
209 
210 		for(int index = 0; index < 4; index++)
211 		{
212 			if(renderTarget[index])
213 			{
214 				renderTarget[index]->unbind();
215 				renderTarget[index] = 0;
216 			}
217 		}
218 
219 		if(vertexDeclaration)
220 		{
221 			vertexDeclaration->unbind();
222 			vertexDeclaration = 0;
223 		}
224 
225 		for(int i = 0; i < 16 + 4; i++)
226 		{
227 			if(texture[i])
228 			{
229 				texture[i]->unbind();
230 				texture[i] = 0;
231 			}
232 		}
233 
234 		for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
235 		{
236 			if(dataStream[i])
237 			{
238 				dataStream[i]->unbind();
239 				dataStream[i] = 0;
240 			}
241 		}
242 
243 		if(indexData)
244 		{
245 			indexData->unbind();
246 			indexData = 0;
247 		}
248 
249 		if(pixelShader)
250 		{
251 			pixelShader->unbind();
252 			pixelShader = 0;
253 		}
254 
255 		if(vertexShader)
256 		{
257 			vertexShader->unbind();
258 			vertexShader = 0;
259 		}
260 
261 		if(stateRecorder)
262 		{
263 			stateRecorder->unbind();
264 			stateRecorder = 0;
265 		}
266 
267 		palette.clear();
268 
269 		delete cursor;
270 
271 		DeleteCriticalSection(&criticalSection);
272 	}
273 
QueryInterface(const IID & iid,void ** object)274 	long Direct3DDevice9::QueryInterface(const IID &iid, void **object)
275 	{
276 		CriticalSection cs(this);
277 
278 		TRACE("const IID &iid = 0x%0.8p, void **object = 0x%0.8p", iid, object);
279 
280 		if(iid == IID_IDirect3DDevice9 ||
281 		   iid == IID_IUnknown)
282 		{
283 			AddRef();
284 			*object = this;
285 
286 			return S_OK;
287 		}
288 
289 		*object = 0;
290 
291 		return NOINTERFACE(iid);
292 	}
293 
AddRef()294 	unsigned long Direct3DDevice9::AddRef()
295 	{
296 		TRACE("void");
297 
298 		return Unknown::AddRef();
299 	}
300 
Release()301 	unsigned long Direct3DDevice9::Release()
302 	{
303 		TRACE("void");
304 
305 		return Unknown::Release();
306 	}
307 
BeginScene()308 	long Direct3DDevice9::BeginScene()
309 	{
310 		CriticalSection cs(this);
311 
312 		TRACE("void");
313 
314 		return D3D_OK;
315 	}
316 
BeginStateBlock()317 	long Direct3DDevice9::BeginStateBlock()
318 	{
319 		CriticalSection cs(this);
320 
321 		TRACE("void");
322 
323 		if(stateRecorder)
324 		{
325 			return INVALIDCALL();
326 		}
327 
328 		stateRecorder = new Direct3DStateBlock9(this, (D3DSTATEBLOCKTYPE)0);
329 
330 		if(!stateRecorder)
331 		{
332 			return OUTOFMEMORY();
333 		}
334 
335 		stateRecorder->bind();
336 
337 		return D3D_OK;
338 	}
339 
Clear(unsigned long count,const D3DRECT * rects,unsigned long flags,unsigned long color,float z,unsigned long stencil)340 	long Direct3DDevice9::Clear(unsigned long count, const D3DRECT *rects, unsigned long flags, unsigned long color, float z, unsigned long stencil)
341 	{
342 		CriticalSection cs(this);
343 
344 		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);
345 
346 		if(rects == 0 && count != 0)
347 		{
348 			return INVALIDCALL();
349 		}
350 
351 		if(flags & (D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL) && !depthStencil)
352 		{
353 			return INVALIDCALL();
354 		}
355 
356 		if(flags & D3DCLEAR_STENCIL)   // Check for stencil component
357 		{
358 			D3DSURFACE_DESC description;
359 			depthStencil->GetDesc(&description);
360 
361 			switch(description.Format)
362 			{
363 			case D3DFMT_D15S1:
364 			case D3DFMT_D24S8:
365 			case D3DFMT_D24X8:
366 			case D3DFMT_D24X4S4:
367 			case D3DFMT_D24FS8:
368 			case D3DFMT_S8_LOCKABLE:   // FIXME: INVALIDCALL when trying to clear depth?
369 			case D3DFMT_DF24:
370 			case D3DFMT_DF16:
371 			case D3DFMT_INTZ:
372 				break;
373 			case D3DFMT_D16_LOCKABLE:
374 			case D3DFMT_D32:
375 			case D3DFMT_D16:
376 			case D3DFMT_D32F_LOCKABLE:
377 			case D3DFMT_D32_LOCKABLE:
378 				return INVALIDCALL();
379 			default:
380 				ASSERT(false);
381 			}
382 		}
383 
384 		if(!rects)
385 		{
386 			count = 1;
387 
388 			D3DRECT rect;
389 			rect.x1 = viewport.X;
390 			rect.x2 = viewport.X + viewport.Width;
391 			rect.y1 = viewport.Y;
392 			rect.y2 = viewport.Y + viewport.Height;
393 
394 			rects = &rect;
395 		}
396 
397 		for(unsigned int i = 0; i < count; i++)
398 		{
399 			sw::SliceRect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2, 0);
400 
401 			clearRect.clip(viewport.X, viewport.Y, viewport.X + viewport.Width, viewport.Y + viewport.Height);
402 
403 			if(scissorEnable)
404 			{
405 				clearRect.clip(scissorRect.left, scissorRect.top, scissorRect.right, scissorRect.bottom);
406 			}
407 
408 			if(flags & D3DCLEAR_TARGET)
409 			{
410 				for(int index = 0; index < 4; index++)
411 				{
412 					if(renderTarget[index])
413 					{
414 						D3DSURFACE_DESC description;
415 						renderTarget[index]->GetDesc(&description);
416 
417 						float rgba[4];
418 						rgba[0] = (float)(color & 0x00FF0000) / 0x00FF0000;
419 						rgba[1] = (float)(color & 0x0000FF00) / 0x0000FF00;
420 						rgba[2] = (float)(color & 0x000000FF) / 0x000000FF;
421 						rgba[3] = (float)(color & 0xFF000000) / 0xFF000000;
422 
423 						if(renderState[D3DRS_SRGBWRITEENABLE] != FALSE && index == 0 && Capabilities::isSRGBwritable(description.Format))
424 						{
425 							rgba[0] = sw::linearToSRGB(rgba[0]);
426 							rgba[1] = sw::linearToSRGB(rgba[1]);
427 							rgba[2] = sw::linearToSRGB(rgba[2]);
428 						}
429 
430 						renderer->clear(rgba, sw::FORMAT_A32B32G32R32F, renderTarget[index], clearRect, 0xF);
431 					}
432 				}
433 			}
434 
435 			if(flags & D3DCLEAR_ZBUFFER)
436 			{
437 				z = sw::clamp01(z);
438 				depthStencil->clearDepth(z, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
439 			}
440 
441 			if(flags & D3DCLEAR_STENCIL)
442 			{
443 				depthStencil->clearStencil(stencil, 0xFF, clearRect.x0, clearRect.y0, clearRect.width(), clearRect.height());
444 			}
445 		}
446 
447 		return D3D_OK;
448 	}
449 
ColorFill(IDirect3DSurface9 * surface,const RECT * rect,D3DCOLOR color)450 	long Direct3DDevice9::ColorFill(IDirect3DSurface9 *surface, const RECT *rect, D3DCOLOR color)
451 	{
452 		CriticalSection cs(this);
453 
454 		TRACE("IDirect3DSurface9 *surface = 0x%0.8p, const RECT *rect = 0x%0.8p, D3DCOLOR color = 0x%0.8X", surface, rect, color);
455 
456 		if(!surface)
457 		{
458 			return INVALIDCALL();
459 		}
460 
461 		D3DSURFACE_DESC description;
462 
463 		surface->GetDesc(&description);
464 
465 		if(description.Pool != D3DPOOL_DEFAULT)
466 		{
467 			return INVALIDCALL();
468 		}
469 
470 		if(!rect)
471 		{
472 			RECT lock;
473 
474 			lock.left = 0;
475 			lock.top = 0;
476 			lock.right = description.Width;
477 			lock.bottom = description.Height;
478 
479 			rect = &lock;
480 		}
481 
482 		static_cast<Direct3DSurface9*>(surface)->fill(color, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top);
483 
484 		return D3D_OK;
485 	}
486 
CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS * presentParameters,IDirect3DSwapChain9 ** swapChain)487 	long Direct3DDevice9::CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *presentParameters, IDirect3DSwapChain9 **swapChain)
488 	{
489 		CriticalSection cs(this);
490 
491 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p, IDirect3DSwapChain9 **swapChain = 0x%0.8p", presentParameters, swapChain);
492 
493 		if(!swapChain)
494 		{
495 			return INVALIDCALL();
496 		}
497 
498 		*swapChain = 0;
499 
500 		if(!presentParameters)
501 		{
502 			return INVALIDCALL();
503 		}
504 
505 		if(presentParameters->BackBufferCount > 3)
506 		{
507 			return INVALIDCALL();   // Maximum of three back buffers
508 		}
509 
510 		*swapChain = new Direct3DSwapChain9(this, presentParameters);
511 
512 		if(!*swapChain)
513 		{
514 			return OUTOFMEMORY();
515 		}
516 
517 		if(GetAvailableTextureMem() == 0)
518 		{
519 			delete *swapChain;
520 			*swapChain = 0;
521 
522 			return OUTOFVIDEOMEMORY();
523 		}
524 
525 		(*swapChain)->AddRef();
526 
527 		return D3D_OK;
528 	}
529 
CreateCubeTexture(unsigned int edgeLength,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DCubeTexture9 ** cubeTexture,void ** sharedHandle)530 	long Direct3DDevice9::CreateCubeTexture(unsigned int edgeLength, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DCubeTexture9 **cubeTexture, void **sharedHandle)
531 	{
532 		CriticalSection cs(this);
533 
534 		TRACE("unsigned int edgeLength = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DCubeTexture9 **cubeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", edgeLength, levels, usage, format, pool, cubeTexture, sharedHandle);
535 
536 		*cubeTexture = 0;
537 
538 		if(edgeLength == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_CUBETEXTURE, format) != D3D_OK)
539 		{
540 			return INVALIDCALL();
541 		}
542 
543 		*cubeTexture = new Direct3DCubeTexture9(this, edgeLength, levels, usage, format, pool);
544 
545 		if(!*cubeTexture)
546 		{
547 			return OUTOFMEMORY();
548 		}
549 
550 		if(GetAvailableTextureMem() == 0)
551 		{
552 			delete *cubeTexture;
553 			*cubeTexture = 0;
554 
555 			return OUTOFVIDEOMEMORY();
556 		}
557 
558 		(*cubeTexture)->AddRef();
559 
560 		return D3D_OK;
561 	}
562 
CreateDepthStencilSurface(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,unsigned long multiSampleQuality,int discard,IDirect3DSurface9 ** surface,void ** sharedHandle)563 	long Direct3DDevice9::CreateDepthStencilSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int discard, IDirect3DSurface9 **surface, void **sharedHandle)
564 	{
565 		CriticalSection cs(this);
566 
567 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int discard = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, discard, surface, sharedHandle);
568 
569 		*surface = 0;
570 
571 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
572 		{
573 			return INVALIDCALL();
574 		}
575 
576 		bool lockable = false;
577 
578 		switch(format)
579 		{
580 		case D3DFMT_D15S1:
581 		case D3DFMT_D24S8:
582 		case D3DFMT_D24X8:
583 		case D3DFMT_D24X4S4:
584 		case D3DFMT_D24FS8:
585 		case D3DFMT_D32:
586 		case D3DFMT_D16:
587 		case D3DFMT_DF24:
588 		case D3DFMT_DF16:
589 		case D3DFMT_INTZ:
590 			lockable = false;
591 			break;
592 		case D3DFMT_S8_LOCKABLE:
593 		case D3DFMT_D16_LOCKABLE:
594 		case D3DFMT_D32F_LOCKABLE:
595 		case D3DFMT_D32_LOCKABLE:
596 			lockable = true;
597 			break;
598 		default:
599 			ASSERT(false);
600 		}
601 
602 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL);
603 
604 		if(!*surface)
605 		{
606 			return OUTOFMEMORY();
607 		}
608 
609 		if(GetAvailableTextureMem() == 0)
610 		{
611 			delete *surface;
612 			*surface = 0;
613 
614 			return OUTOFVIDEOMEMORY();
615 		}
616 
617 		(*surface)->AddRef();
618 
619 		return D3D_OK;
620 	}
621 
CreateIndexBuffer(unsigned int length,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DIndexBuffer9 ** indexBuffer,void ** sharedHandle)622 	long Direct3DDevice9::CreateIndexBuffer(unsigned int length, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DIndexBuffer9 **indexBuffer, void **sharedHandle)
623 	{
624 		CriticalSection cs(this);
625 
626 		TRACE("unsigned int length = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DIndexBuffer9 **indexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, format, pool, indexBuffer, sharedHandle);
627 
628 		*indexBuffer = new Direct3DIndexBuffer9(this, length, usage, format, pool);
629 
630 		if(!*indexBuffer)
631 		{
632 			return OUTOFMEMORY();
633 		}
634 
635 		if(GetAvailableTextureMem() == 0)
636 		{
637 			delete *indexBuffer;
638 			*indexBuffer = 0;
639 
640 			return OUTOFVIDEOMEMORY();
641 		}
642 
643 		(*indexBuffer)->AddRef();
644 
645 		return D3D_OK;
646 	}
647 
CreateOffscreenPlainSurface(unsigned int width,unsigned int height,D3DFORMAT format,D3DPOOL pool,IDirect3DSurface9 ** surface,void ** sharedHandle)648 	long Direct3DDevice9::CreateOffscreenPlainSurface(unsigned int width, unsigned int height, D3DFORMAT format, D3DPOOL pool, IDirect3DSurface9 **surface, void **sharedHandle)
649 	{
650 		CriticalSection cs(this);
651 
652 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, pool, surface, sharedHandle);
653 
654 		*surface = 0;
655 
656 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, format) != D3D_OK)   // FIXME: Allow all formats supported by runtime/REF
657 		{
658 			return INVALIDCALL();
659 		}
660 
661 		if(pool == D3DPOOL_MANAGED)
662 		{
663 			return INVALIDCALL();
664 		}
665 
666 		*surface = new Direct3DSurface9(this, this, width, height, format, pool, D3DMULTISAMPLE_NONE, 0, true, 0);
667 
668 		if(!*surface)
669 		{
670 			return OUTOFMEMORY();
671 		}
672 
673 		if(GetAvailableTextureMem() == 0)
674 		{
675 			delete *surface;
676 			*surface = 0;
677 
678 			return OUTOFVIDEOMEMORY();
679 		}
680 
681 		(*surface)->AddRef();
682 
683 		return D3D_OK;
684 	}
685 
CreatePixelShader(const unsigned long * function,IDirect3DPixelShader9 ** shader)686 	long Direct3DDevice9::CreatePixelShader(const unsigned long *function, IDirect3DPixelShader9 **shader)
687 	{
688 		CriticalSection cs(this);
689 
690 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DPixelShader9 **shader = 0x%0.8p", function, shader);
691 
692 		if(!shader)
693 		{
694 			return INVALIDCALL();
695 		}
696 
697 		*shader = 0;
698 
699 		if(!sw::PixelShader::validate(function) || function[0] > pixelShaderVersionX)
700 		{
701 			return INVALIDCALL();   // Shader contains unsupported operations
702 		}
703 
704 		*shader = new Direct3DPixelShader9(this, function);
705 
706 		if(!*shader)
707 		{
708 			return OUTOFMEMORY();
709 		}
710 
711 		(*shader)->AddRef();
712 
713 		return D3D_OK;
714 	}
715 
CreateQuery(D3DQUERYTYPE type,IDirect3DQuery9 ** query)716 	long Direct3DDevice9::CreateQuery(D3DQUERYTYPE type, IDirect3DQuery9 **query)
717 	{
718 		CriticalSection cs(this);
719 
720 		TRACE("D3DQUERYTYPE type = %d, IDirect3DQuery9 **query = 0x%0.8p", type, query);
721 
722 		if(query == 0)   // Support checked
723 		{
724 			switch(type)
725 			{
726 			case D3DQUERYTYPE_VCACHE:				return D3D_OK;
727 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE();
728 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE();
729 			case D3DQUERYTYPE_EVENT:				return D3D_OK;
730 			case D3DQUERYTYPE_OCCLUSION:			return D3D_OK;
731 			case D3DQUERYTYPE_TIMESTAMP:			return D3D_OK;
732 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	return D3D_OK;
733 			case D3DQUERYTYPE_TIMESTAMPFREQ:		return D3D_OK;
734 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE();
735 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE();
736 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE();
737 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE();
738 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE();
739 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE();
740 			default:								ASSERT(false);   return NOTAVAILABLE();
741 			}
742 		}
743 		else
744 		{
745 			switch(type)
746 			{
747 			case D3DQUERYTYPE_VCACHE:				break;
748 			case D3DQUERYTYPE_RESOURCEMANAGER:		return NOTAVAILABLE();
749 			case D3DQUERYTYPE_VERTEXSTATS:			return NOTAVAILABLE();
750 			case D3DQUERYTYPE_EVENT:				break;
751 			case D3DQUERYTYPE_OCCLUSION:			break;
752 			case D3DQUERYTYPE_TIMESTAMP:			break;
753 			case D3DQUERYTYPE_TIMESTAMPDISJOINT:	break;
754 			case D3DQUERYTYPE_TIMESTAMPFREQ:		break;
755 			case D3DQUERYTYPE_PIPELINETIMINGS:		return NOTAVAILABLE();
756 			case D3DQUERYTYPE_INTERFACETIMINGS:		return NOTAVAILABLE();
757 			case D3DQUERYTYPE_VERTEXTIMINGS:		return NOTAVAILABLE();
758 			case D3DQUERYTYPE_PIXELTIMINGS:			return NOTAVAILABLE();
759 			case D3DQUERYTYPE_BANDWIDTHTIMINGS:		return NOTAVAILABLE();
760 			case D3DQUERYTYPE_CACHEUTILIZATION:		return NOTAVAILABLE();
761 			default:								ASSERT(false);   return NOTAVAILABLE();
762 			}
763 
764 			*query = new Direct3DQuery9(this, type);
765 
766 			if(!*query)
767 			{
768 				return OUTOFMEMORY();
769 			}
770 
771 			(*query)->AddRef();
772 
773 			return D3D_OK;
774 		}
775 	}
776 
CreateRenderTarget(unsigned int width,unsigned int height,D3DFORMAT format,D3DMULTISAMPLE_TYPE multiSample,unsigned long multiSampleQuality,int lockable,IDirect3DSurface9 ** surface,void ** sharedHandle)777 	long Direct3DDevice9::CreateRenderTarget(unsigned int width, unsigned int height, D3DFORMAT format, D3DMULTISAMPLE_TYPE multiSample, unsigned long multiSampleQuality, int lockable, IDirect3DSurface9 **surface, void **sharedHandle)
778 	{
779 		CriticalSection cs(this);
780 
781 		TRACE("unsigned int width = %d, unsigned int height = %d, D3DFORMAT format = %d, D3DMULTISAMPLE_TYPE multiSample = %d, unsigned long multiSampleQuality = %d, int lockable = %d, IDirect3DSurface9 **surface = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, format, multiSample, multiSampleQuality, lockable, surface, sharedHandle);
782 
783 		*surface = 0;
784 
785 		if(width == 0 || height == 0 || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, format) != D3D_OK || height > sw::OUTLINE_RESOLUTION)
786 		{
787 			return INVALIDCALL();
788 		}
789 
790 		*surface = new Direct3DSurface9(this, this, width, height, format, D3DPOOL_DEFAULT, multiSample, multiSampleQuality, lockable != FALSE, D3DUSAGE_RENDERTARGET);
791 
792 		if(!*surface)
793 		{
794 			return OUTOFMEMORY();
795 		}
796 
797 		if(GetAvailableTextureMem() == 0)
798 		{
799 			delete *surface;
800 			*surface = 0;
801 
802 			return OUTOFVIDEOMEMORY();
803 		}
804 
805 		(*surface)->AddRef();
806 
807 		return D3D_OK;
808 	}
809 
CreateStateBlock(D3DSTATEBLOCKTYPE type,IDirect3DStateBlock9 ** stateBlock)810 	long Direct3DDevice9::CreateStateBlock(D3DSTATEBLOCKTYPE type, IDirect3DStateBlock9 **stateBlock)
811 	{
812 		CriticalSection cs(this);
813 
814 		TRACE("D3DSTATEBLOCKTYPE type = %d, IDirect3DStateBlock9 **stateBlock = 0x%0.8p", type, stateBlock);
815 
816 		*stateBlock = new Direct3DStateBlock9(this, type);
817 
818 		if(!*stateBlock)
819 		{
820 			return OUTOFMEMORY();
821 		}
822 
823 		(*stateBlock)->AddRef();
824 
825 		return D3D_OK;
826 	}
827 
CreateTexture(unsigned int width,unsigned int height,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DTexture9 ** texture,void ** sharedHandle)828 	long Direct3DDevice9::CreateTexture(unsigned int width, unsigned int height, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DTexture9 **texture, void **sharedHandle)
829 	{
830 		CriticalSection cs(this);
831 
832 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DTexture9 **texture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, levels, usage, format, pool, texture, sharedHandle);
833 
834 		*texture = 0;
835 
836 		if(width == 0 || height == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_TEXTURE, format) != D3D_OK)
837 		{
838 			return INVALIDCALL();
839 		}
840 
841 		*texture = new Direct3DTexture9(this, width, height, levels, usage, format, pool);
842 
843 		if(!*texture)
844 		{
845 			return OUTOFMEMORY();
846 		}
847 
848 		if(GetAvailableTextureMem() == 0)
849 		{
850 			delete *texture;
851 			*texture = 0;
852 
853 			return OUTOFVIDEOMEMORY();
854 		}
855 
856 		(*texture)->AddRef();
857 
858 		return D3D_OK;
859 	}
860 
CreateVertexBuffer(unsigned int length,unsigned long usage,unsigned long FVF,D3DPOOL pool,IDirect3DVertexBuffer9 ** vertexBuffer,void ** sharedHandle)861 	long Direct3DDevice9::CreateVertexBuffer(unsigned int length, unsigned long usage, unsigned long FVF, D3DPOOL pool, IDirect3DVertexBuffer9 **vertexBuffer, void **sharedHandle)
862 	{
863 		CriticalSection cs(this);
864 
865 		TRACE("unsigned int length = %d, unsigned long usage = %d, unsigned long FVF = 0x%0.8X, D3DPOOL pool = %d, IDirect3DVertexBuffer9 **vertexBuffer = 0x%0.8p, void **sharedHandle = 0x%0.8p", length, usage, FVF, pool, vertexBuffer, sharedHandle);
866 
867 		*vertexBuffer = new Direct3DVertexBuffer9(this, length, usage, FVF, pool);
868 
869 		if(!*vertexBuffer)
870 		{
871 			return OUTOFMEMORY();
872 		}
873 
874 		if(GetAvailableTextureMem() == 0)
875 		{
876 			delete *vertexBuffer;
877 			*vertexBuffer = 0;
878 
879 			return OUTOFVIDEOMEMORY();
880 		}
881 
882 		(*vertexBuffer)->AddRef();
883 
884 		return D3D_OK;
885 	}
886 
CreateVertexDeclaration(const D3DVERTEXELEMENT9 * vertexElements,IDirect3DVertexDeclaration9 ** declaration)887 	long Direct3DDevice9::CreateVertexDeclaration(const D3DVERTEXELEMENT9 *vertexElements, IDirect3DVertexDeclaration9 **declaration)
888 	{
889 		CriticalSection cs(this);
890 
891 		TRACE("const D3DVERTEXELEMENT9 *vertexElements = 0x%0.8p, IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", vertexElements, declaration);
892 
893 		if(!declaration)
894 		{
895 			return INVALIDCALL();
896 		}
897 
898 		const D3DVERTEXELEMENT9 *element = vertexElements;
899 
900 		while(element->Stream != 0xFF)
901 		{
902 			if(element->Type > D3DDECLTYPE_UNUSED)   // FIXME: Check other fields too
903 			{
904 				return FAIL();
905 			}
906 
907 			element++;
908 		}
909 
910 		*declaration = new Direct3DVertexDeclaration9(this, vertexElements);
911 
912 		if(!*declaration)
913 		{
914 			return OUTOFMEMORY();
915 		}
916 
917 		(*declaration)->AddRef();
918 
919 		return D3D_OK;
920 	}
921 
CreateVertexShader(const unsigned long * function,IDirect3DVertexShader9 ** shader)922 	long Direct3DDevice9::CreateVertexShader(const unsigned long *function, IDirect3DVertexShader9 **shader)
923 	{
924 		CriticalSection cs(this);
925 
926 		TRACE("const unsigned long *function = 0x%0.8p, IDirect3DVertexShader9 **shader = 0x%0.8p", function, shader);
927 
928 		if(!shader)
929 		{
930 			return INVALIDCALL();
931 		}
932 
933 		*shader = 0;
934 
935 		if(!sw::VertexShader::validate(function) || function[0] > vertexShaderVersionX)
936 		{
937 			return INVALIDCALL();   // Shader contains unsupported operations
938 		}
939 
940 		*shader = new Direct3DVertexShader9(this, function);
941 
942 		if(!*shader)
943 		{
944 			return OUTOFMEMORY();
945 		}
946 
947 		(*shader)->AddRef();
948 
949 		return D3D_OK;
950 	}
951 
CreateVolumeTexture(unsigned int width,unsigned int height,unsigned int depth,unsigned int levels,unsigned long usage,D3DFORMAT format,D3DPOOL pool,IDirect3DVolumeTexture9 ** volumeTexture,void ** sharedHandle)952 	long Direct3DDevice9::CreateVolumeTexture(unsigned int width, unsigned int height, unsigned int depth, unsigned int levels, unsigned long usage, D3DFORMAT format, D3DPOOL pool, IDirect3DVolumeTexture9 **volumeTexture, void **sharedHandle)
953 	{
954 		CriticalSection cs(this);
955 
956 		TRACE("unsigned int width = %d, unsigned int height = %d, unsigned int depth = %d, unsigned int levels = %d, unsigned long usage = %d, D3DFORMAT format = %d, D3DPOOL pool = %d, IDirect3DVolumeTexture9 **volumeTexture = 0x%0.8p, void **sharedHandle = 0x%0.8p", width, height, depth, levels, usage, format, pool, volumeTexture, sharedHandle);
957 
958 		*volumeTexture = 0;
959 
960 		if(width == 0 || height == 0 || depth == 0 || (usage & D3DUSAGE_AUTOGENMIPMAP && levels > 1) || d3d9->CheckDeviceFormat(adapter, deviceType, D3DFMT_X8R8G8B8, usage, D3DRTYPE_VOLUMETEXTURE, format) != D3D_OK)
961 		{
962 			return INVALIDCALL();
963 		}
964 
965 		*volumeTexture = new Direct3DVolumeTexture9(this, width, height, depth, levels, usage, format, pool);
966 
967 		if(!*volumeTexture)
968 		{
969 			return OUTOFMEMORY();
970 		}
971 
972 		if(GetAvailableTextureMem() == 0)
973 		{
974 			delete *volumeTexture;
975 			*volumeTexture = 0;
976 
977 			return OUTOFVIDEOMEMORY();
978 		}
979 
980 		(*volumeTexture)->AddRef();
981 
982 		return D3D_OK;
983 	}
984 
DeletePatch(unsigned int handle)985 	long Direct3DDevice9::DeletePatch(unsigned int handle)
986 	{
987 		CriticalSection cs(this);
988 
989 		TRACE("unsigned int handle = %d", handle);
990 
991 		UNIMPLEMENTED();
992 
993 		return D3D_OK;
994 	}
995 
DrawIndexedPrimitive(D3DPRIMITIVETYPE type,int baseVertexIndex,unsigned int minIndex,unsigned int numVertices,unsigned int startIndex,unsigned int primitiveCount)996 	long Direct3DDevice9::DrawIndexedPrimitive(D3DPRIMITIVETYPE type, int baseVertexIndex, unsigned int minIndex, unsigned int numVertices, unsigned int startIndex, unsigned int primitiveCount)
997 	{
998 		CriticalSection cs(this);
999 
1000 		TRACE("D3DPRIMITIVETYPE type = %d, int baseVertexIndex = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int startIndex = %d, unsigned int primitiveCount = %d", type, baseVertexIndex, minIndex, numVertices, startIndex, primitiveCount);
1001 
1002 		if(!indexData)
1003 		{
1004 			return INVALIDCALL();
1005 		}
1006 
1007 		if(!bindResources(indexData) || !primitiveCount)
1008 		{
1009 			return D3D_OK;
1010 		}
1011 
1012 		unsigned int indexOffset = startIndex * (indexData->is32Bit() ? 4 : 2);   // FIXME: Doesn't take stream frequencies into account
1013 
1014 		sw::DrawType drawType;
1015 
1016 		if(indexData->is32Bit())
1017 		{
1018 			switch(type)
1019 			{
1020 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
1021 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
1022 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
1023 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
1024 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
1025 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break;
1026 			default:
1027 				ASSERT(false);
1028 			}
1029 		}
1030 		else
1031 		{
1032 			switch(type)
1033 			{
1034 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
1035 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
1036 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
1037 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
1038 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
1039 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
1040 			default:
1041 				ASSERT(false);
1042 			}
1043 		}
1044 
1045 		if((streamSourceFreq[0] & D3DSTREAMSOURCE_INDEXEDDATA) && instanceData())
1046 		{
1047 			int instanceCount = (streamSourceFreq[0] & ~D3DSTREAMSOURCE_INDEXEDDATA);
1048 
1049 			for(int instance = 0; instance < instanceCount; instance++)
1050 			{
1051 				bindVertexStreams(baseVertexIndex, true, instance);
1052 				renderer->draw(drawType, indexOffset, primitiveCount, instance == 0);
1053 			}
1054 		}
1055 		else
1056 		{
1057 			bindVertexStreams(baseVertexIndex, false, 0);
1058 			renderer->draw(drawType, indexOffset, primitiveCount);
1059 		}
1060 
1061 		return D3D_OK;
1062 	}
1063 
DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type,unsigned int minIndex,unsigned int numVertices,unsigned int primitiveCount,const void * indexData,D3DFORMAT indexDataFormat,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)1064 	long Direct3DDevice9::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, unsigned int minIndex, unsigned int numVertices, unsigned int primitiveCount, const void *indexData, D3DFORMAT indexDataFormat, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
1065 	{
1066 		CriticalSection cs(this);
1067 
1068 		TRACE("D3DPRIMITIVETYPE type = %d, unsigned int minIndex = %d, unsigned int numVertices = %d, unsigned int primitiveCount = %d, const void *indexData = 0x%0.8p, D3DFORMAT indexDataFormat = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", type, minIndex, numVertices, primitiveCount, indexData, indexDataFormat, vertexStreamZeroData, vertexStreamZeroStride);
1069 
1070 		if(!vertexStreamZeroData || !indexData)
1071 		{
1072 			return INVALIDCALL();
1073 		}
1074 
1075 		int length = (minIndex + numVertices) * vertexStreamZeroStride;
1076 
1077 		Direct3DVertexBuffer9 *vertexBuffer = new Direct3DVertexBuffer9(this, length, 0, 0, D3DPOOL_DEFAULT);
1078 
1079 		void *data;
1080 		vertexBuffer->Lock(0, 0, &data, 0);
1081 		memcpy(data, vertexStreamZeroData, length);
1082 		vertexBuffer->Unlock();
1083 
1084 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride);
1085 
1086 		switch(type)
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 *= indexDataFormat == D3DFMT_INDEX32 ? 4 : 2;
1099 
1100 		Direct3DIndexBuffer9 *indexBuffer = new Direct3DIndexBuffer9(this, length, 0, indexDataFormat, D3DPOOL_DEFAULT);
1101 
1102 		indexBuffer->Lock(0, 0, &data, 0);
1103 		memcpy(data, indexData, length);
1104 		indexBuffer->Unlock();
1105 
1106 		SetIndices(indexBuffer);
1107 
1108 		if(!bindResources(indexBuffer) || !primitiveCount)
1109 		{
1110 			vertexBuffer->Release();
1111 
1112 			return D3D_OK;
1113 		}
1114 
1115 		sw::DrawType drawType;
1116 
1117 		if(indexDataFormat == D3DFMT_INDEX32)
1118 		{
1119 			switch(type)
1120 			{
1121 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST32;     break;
1122 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST32;      break;
1123 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP32;     break;
1124 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST32;  break;
1125 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP32; break;
1126 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN32;   break;
1127 			default:
1128 				ASSERT(false);
1129 			}
1130 		}
1131 		else
1132 		{
1133 			switch(type)
1134 			{
1135 			case D3DPT_POINTLIST:     drawType = sw::DRAW_INDEXEDPOINTLIST16;     break;
1136 			case D3DPT_LINELIST:      drawType = sw::DRAW_INDEXEDLINELIST16;      break;
1137 			case D3DPT_LINESTRIP:     drawType = sw::DRAW_INDEXEDLINESTRIP16;     break;
1138 			case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_INDEXEDTRIANGLELIST16;  break;
1139 			case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_INDEXEDTRIANGLESTRIP16; break;
1140 			case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_INDEXEDTRIANGLEFAN16;   break;
1141 			default:
1142 				ASSERT(false);
1143 			}
1144 		}
1145 
1146 		bindVertexStreams(0, false, 0);
1147 		renderer->draw(drawType, 0, primitiveCount);
1148 
1149 		SetStreamSource(0, 0, 0, 0);
1150 		SetIndices(0);
1151 
1152 		return D3D_OK;
1153 	}
1154 
DrawPrimitive(D3DPRIMITIVETYPE primitiveType,unsigned int startVertex,unsigned int primitiveCount)1155 	long Direct3DDevice9::DrawPrimitive(D3DPRIMITIVETYPE primitiveType, unsigned int startVertex, unsigned int primitiveCount)
1156 	{
1157 		CriticalSection cs(this);
1158 
1159 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int startVertex = %d, unsigned int primitiveCount = %d", primitiveType, startVertex, primitiveCount);
1160 
1161 		if(!bindResources(0) || !primitiveCount)
1162 		{
1163 			return D3D_OK;
1164 		}
1165 
1166 		sw::DrawType drawType;
1167 
1168 		switch(primitiveType)
1169 		{
1170 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
1171 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
1172 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
1173 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
1174 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
1175 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
1176 		default:
1177 			ASSERT(false);
1178 		}
1179 
1180 		bindVertexStreams(startVertex, false, 0);
1181 		renderer->draw(drawType, 0, primitiveCount);
1182 
1183 		return D3D_OK;
1184 	}
1185 
DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType,unsigned int primitiveCount,const void * vertexStreamZeroData,unsigned int vertexStreamZeroStride)1186 	long Direct3DDevice9::DrawPrimitiveUP(D3DPRIMITIVETYPE primitiveType, unsigned int primitiveCount, const void *vertexStreamZeroData, unsigned int vertexStreamZeroStride)
1187 	{
1188 		CriticalSection cs(this);
1189 
1190 		TRACE("D3DPRIMITIVETYPE primitiveType = %d, unsigned int primitiveCount = %d, const void *vertexStreamZeroData = 0x%0.8p, unsigned int vertexStreamZeroStride = %d", primitiveType, primitiveCount, vertexStreamZeroData, vertexStreamZeroStride);
1191 
1192 		if(!vertexStreamZeroData)
1193 		{
1194 			return INVALIDCALL();
1195 		}
1196 
1197 		IDirect3DVertexBuffer9 *vertexBuffer = 0;
1198 		int length = 0;
1199 
1200 		switch(primitiveType)
1201 		{
1202 		case D3DPT_POINTLIST:		length = primitiveCount;		break;
1203 		case D3DPT_LINELIST:		length = primitiveCount * 2;	break;
1204 		case D3DPT_LINESTRIP:		length = primitiveCount + 1;	break;
1205 		case D3DPT_TRIANGLELIST:	length = primitiveCount * 3;	break;
1206 		case D3DPT_TRIANGLESTRIP:	length = primitiveCount + 2;	break;
1207 		case D3DPT_TRIANGLEFAN:		length = primitiveCount + 2;	break;
1208 		default:
1209 			ASSERT(false);
1210 		}
1211 
1212 		length *= vertexStreamZeroStride;
1213 
1214 		CreateVertexBuffer(length, 0, 0, D3DPOOL_DEFAULT, &vertexBuffer, 0);
1215 
1216 		void *data;
1217 		vertexBuffer->Lock(0, 0, &data, 0);
1218 		memcpy(data, vertexStreamZeroData, length);
1219 		vertexBuffer->Unlock();
1220 
1221 		SetStreamSource(0, vertexBuffer, 0, vertexStreamZeroStride);
1222 
1223 		if(!bindResources(0) || !primitiveCount)
1224 		{
1225 			vertexBuffer->Release();
1226 
1227 			return D3D_OK;
1228 		}
1229 
1230 		sw::DrawType drawType;
1231 
1232 		switch(primitiveType)
1233 		{
1234 		case D3DPT_POINTLIST:     drawType = sw::DRAW_POINTLIST;     break;
1235 		case D3DPT_LINELIST:      drawType = sw::DRAW_LINELIST;      break;
1236 		case D3DPT_LINESTRIP:     drawType = sw::DRAW_LINESTRIP;     break;
1237 		case D3DPT_TRIANGLELIST:  drawType = sw::DRAW_TRIANGLELIST;  break;
1238 		case D3DPT_TRIANGLESTRIP: drawType = sw::DRAW_TRIANGLESTRIP; break;
1239 		case D3DPT_TRIANGLEFAN:   drawType = sw::DRAW_TRIANGLEFAN;   break;
1240 		default:
1241 			ASSERT(false);
1242 		}
1243 
1244 		bindVertexStreams(0, false, 0);
1245 		renderer->draw(drawType, 0, primitiveCount);
1246 
1247 		SetStreamSource(0, 0, 0, 0);
1248 		vertexBuffer->Release();
1249 
1250 		return D3D_OK;
1251 	}
1252 
DrawRectPatch(unsigned int handle,const float * numSegs,const D3DRECTPATCH_INFO * rectPatchInfo)1253 	long Direct3DDevice9::DrawRectPatch(unsigned int handle, const float *numSegs, const D3DRECTPATCH_INFO *rectPatchInfo)
1254 	{
1255 		CriticalSection cs(this);
1256 
1257 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DRECTPATCH_INFO *rectPatchInfo = 0x%0.8p", handle, numSegs, rectPatchInfo);
1258 
1259 		if(!numSegs || !rectPatchInfo)
1260 		{
1261 			return INVALIDCALL();
1262 		}
1263 
1264 		UNIMPLEMENTED();
1265 
1266 		return D3D_OK;
1267 	}
1268 
DrawTriPatch(unsigned int handle,const float * numSegs,const D3DTRIPATCH_INFO * triPatchInfo)1269 	long Direct3DDevice9::DrawTriPatch(unsigned int handle, const float *numSegs, const D3DTRIPATCH_INFO *triPatchInfo)
1270 	{
1271 		CriticalSection cs(this);
1272 
1273 		TRACE("unsigned int handle = %d, const float *numSegs = 0x%0.8p, const D3DTRIPATCH_INFO *triPatchInfo = 0x%0.8p", handle, numSegs, triPatchInfo);
1274 
1275 		if(!numSegs || !triPatchInfo)
1276 		{
1277 			return INVALIDCALL();
1278 		}
1279 
1280 		UNIMPLEMENTED();
1281 
1282 		return D3D_OK;
1283 	}
1284 
EndScene()1285 	long Direct3DDevice9::EndScene()
1286 	{
1287 		CriticalSection cs(this);
1288 
1289 		TRACE("void");
1290 
1291 		return D3D_OK;
1292 	}
1293 
EndStateBlock(IDirect3DStateBlock9 ** stateBlock)1294 	long Direct3DDevice9::EndStateBlock(IDirect3DStateBlock9 **stateBlock)
1295 	{
1296 		CriticalSection cs(this);
1297 
1298 		TRACE("IDirect3DStateBlock9 **stateBlock = 0x%0.8p", stateBlock);
1299 
1300 		if(!stateBlock)
1301 		{
1302 			return INVALIDCALL();
1303 		}
1304 
1305 		*stateBlock = 0;
1306 
1307 		if(!stateRecorder)
1308 		{
1309 			return INVALIDCALL();
1310 		}
1311 
1312 		*stateBlock = stateRecorder;
1313 		stateRecorder->AddRef();
1314 		stateRecorder->unbind();
1315 		stateRecorder = 0;   // Stop recording
1316 
1317 		return D3D_OK;
1318 	}
1319 
EvictManagedResources()1320 	long Direct3DDevice9::EvictManagedResources()
1321 	{
1322 		CriticalSection cs(this);
1323 
1324 		TRACE("void");
1325 
1326 		//	UNIMPLEMENTED();   // FIXME
1327 
1328 		return D3D_OK;
1329 	}
1330 
GetAvailableTextureMem()1331 	unsigned int Direct3DDevice9::GetAvailableTextureMem()
1332 	{
1333 		CriticalSection cs(this);
1334 
1335 		TRACE("void");
1336 
1337 		int availableMemory = textureMemory - Direct3DResource9::getMemoryUsage();
1338 		if(availableMemory < 0) availableMemory = 0;
1339 
1340 		// Round to nearest MB
1341 		return (availableMemory + 0x80000) & 0xFFF00000;
1342 	}
1343 
GetBackBuffer(unsigned int swapChainIndex,unsigned int backBufferIndex,D3DBACKBUFFER_TYPE type,IDirect3DSurface9 ** backBuffer)1344 	long Direct3DDevice9::GetBackBuffer(unsigned int swapChainIndex, unsigned int backBufferIndex, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer)
1345 	{
1346 		CriticalSection cs(this);
1347 
1348 		TRACE("unsigned int swapChainIndex = %d, unsigned int backBufferIndex = %d, D3DBACKBUFFER_TYPE type = %d, IDirect3DSurface9 **backBuffer = 0x%0.8p", swapChainIndex, backBufferIndex, type, backBuffer);
1349 
1350 		if(swapChainIndex >= GetNumberOfSwapChains())
1351 		{
1352 			return INVALIDCALL();
1353 		}
1354 
1355 		return swapChain->GetBackBuffer(backBufferIndex, type, backBuffer);
1356 	}
1357 
GetClipPlane(unsigned long index,float * plane)1358 	long Direct3DDevice9::GetClipPlane(unsigned long index, float *plane)
1359 	{
1360 		CriticalSection cs(this);
1361 
1362 		TRACE("unsigned long index = %d, float *plane = 0x%0.8p", index, plane);
1363 
1364 		if(!plane || index >= 6)
1365 		{
1366 			return INVALIDCALL();
1367 		}
1368 
1369 		plane[0] = this->plane[index][0];
1370 		plane[1] = this->plane[index][1];
1371 		plane[2] = this->plane[index][2];
1372 		plane[3] = this->plane[index][3];
1373 
1374 		return D3D_OK;
1375 	}
1376 
GetClipStatus(D3DCLIPSTATUS9 * clipStatus)1377 	long Direct3DDevice9::GetClipStatus(D3DCLIPSTATUS9 *clipStatus)
1378 	{
1379 		CriticalSection cs(this);
1380 
1381 		TRACE("D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus);
1382 
1383 		if(!clipStatus)
1384 		{
1385 			return INVALIDCALL();
1386 		}
1387 
1388 		*clipStatus = this->clipStatus;
1389 
1390 		return D3D_OK;
1391 	}
1392 
GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS * parameters)1393 	long Direct3DDevice9::GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *parameters)
1394 	{
1395 		CriticalSection cs(this);
1396 
1397 		TRACE("D3DDEVICE_CREATION_PARAMETERS *parameters = 0x%0.8p", parameters);
1398 
1399 		if(!parameters)
1400 		{
1401 			return INVALIDCALL();
1402 		}
1403 
1404 		parameters->AdapterOrdinal = adapter;
1405 		parameters->BehaviorFlags = behaviourFlags;
1406 		parameters->DeviceType = deviceType;
1407 		parameters->hFocusWindow = focusWindow;
1408 
1409 		return D3D_OK;
1410 	}
1411 
GetCurrentTexturePalette(unsigned int * paletteNumber)1412 	long Direct3DDevice9::GetCurrentTexturePalette(unsigned int *paletteNumber)
1413 	{
1414 		CriticalSection cs(this);
1415 
1416 		TRACE("unsigned int *paletteNumber = 0x%0.8p", paletteNumber);
1417 
1418 		if(!paletteNumber)
1419 		{
1420 			return INVALIDCALL();
1421 		}
1422 
1423 		*paletteNumber = currentPalette;
1424 
1425 		return D3D_OK;
1426 	}
1427 
GetDepthStencilSurface(IDirect3DSurface9 ** depthStencilSurface)1428 	long Direct3DDevice9::GetDepthStencilSurface(IDirect3DSurface9 **depthStencilSurface)
1429 	{
1430 		CriticalSection cs(this);
1431 
1432 		TRACE("IDirect3DSurface9 **depthStencilSurface = 0x%0.8p", depthStencilSurface);
1433 
1434 		if(!depthStencilSurface)
1435 		{
1436 			return INVALIDCALL();
1437 		}
1438 
1439 		*depthStencilSurface = depthStencil;
1440 
1441 		if(depthStencil)
1442 		{
1443 			depthStencil->AddRef();
1444 		}
1445 		else
1446 		{
1447 			return NOTFOUND();
1448 		}
1449 
1450 		return D3D_OK;
1451 	}
1452 
GetDeviceCaps(D3DCAPS9 * caps)1453 	long Direct3DDevice9::GetDeviceCaps(D3DCAPS9 *caps)
1454 	{
1455 		CriticalSection cs(this);
1456 
1457 		TRACE("D3DCAPS9 *caps = 0x%0.8p", caps);
1458 
1459 		return d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, caps);
1460 	}
1461 
GetDirect3D(IDirect3D9 ** d3d9)1462 	long Direct3DDevice9::GetDirect3D(IDirect3D9 **d3d9)
1463 	{
1464 		CriticalSection cs(this);
1465 
1466 		TRACE("IDirect3D9 **d3d9 = 0x%0.8p", d3d9);
1467 
1468 		if(!d3d9)
1469 		{
1470 			return INVALIDCALL();
1471 		}
1472 
1473 		*d3d9 = this->d3d9;
1474 		this->d3d9->AddRef();
1475 
1476 		return D3D_OK;
1477 	}
1478 
GetDisplayMode(unsigned int index,D3DDISPLAYMODE * mode)1479 	long Direct3DDevice9::GetDisplayMode(unsigned int index, D3DDISPLAYMODE *mode)
1480 	{
1481 		CriticalSection cs(this);
1482 
1483 		TRACE("unsigned int index = %d, D3DDISPLAYMODE *mode = 0x%0.8p", index, mode);
1484 
1485 		if(index >= GetNumberOfSwapChains())
1486 		{
1487 			return INVALIDCALL();
1488 		}
1489 
1490 		return swapChain->GetDisplayMode(mode);
1491 	}
1492 
GetFrontBufferData(unsigned int index,IDirect3DSurface9 * destSurface)1493 	long Direct3DDevice9::GetFrontBufferData(unsigned int index, IDirect3DSurface9 *destSurface)
1494 	{
1495 		CriticalSection cs(this);
1496 
1497 		TRACE("unsigned int index = %d, IDirect3DSurface9 *destSurface = %p", index, destSurface);
1498 
1499 		if(index >= GetNumberOfSwapChains())
1500 		{
1501 			return INVALIDCALL();
1502 		}
1503 
1504 		return swapChain->GetFrontBufferData(destSurface);
1505 	}
1506 
GetFVF(unsigned long * FVF)1507 	long Direct3DDevice9::GetFVF(unsigned long *FVF)
1508 	{
1509 		CriticalSection cs(this);
1510 
1511 		TRACE("unsigned long *FVF = 0x%0.8p", FVF);
1512 
1513 		if(!FVF)
1514 		{
1515 			return INVALIDCALL();
1516 		}
1517 
1518 		if(vertexDeclaration)
1519 		{
1520 			*FVF = vertexDeclaration->getFVF();
1521 		}
1522 		else
1523 		{
1524 			*FVF = 0;
1525 		}
1526 
1527 		return D3D_OK;
1528 	}
1529 
GetGammaRamp(unsigned int index,D3DGAMMARAMP * ramp)1530 	void Direct3DDevice9::GetGammaRamp(unsigned int index, D3DGAMMARAMP *ramp)
1531 	{
1532 		CriticalSection cs(this);
1533 
1534 		TRACE("unsigned int index = %d, D3DGAMMARAMP *ramp = 0x%0.8p", index, ramp);
1535 
1536 		if(!ramp || index >= GetNumberOfSwapChains())
1537 		{
1538 			return;
1539 		}
1540 
1541 		swapChain->getGammaRamp((sw::GammaRamp*)ramp);
1542 	}
1543 
GetIndices(IDirect3DIndexBuffer9 ** indexData)1544 	long Direct3DDevice9::GetIndices(IDirect3DIndexBuffer9 **indexData)
1545 	{
1546 		CriticalSection cs(this);
1547 
1548 		TRACE("IDirect3DIndexBuffer9 **indexData = 0x%0.8p", indexData);
1549 
1550 		if(!indexData)
1551 		{
1552 			return INVALIDCALL();
1553 		}
1554 
1555 		*indexData = this->indexData;
1556 
1557 		if(this->indexData)
1558 		{
1559 			this->indexData->AddRef();
1560 		}
1561 
1562 		return D3D_OK;
1563 	}
1564 
GetLight(unsigned long index,D3DLIGHT9 * light)1565 	long Direct3DDevice9::GetLight(unsigned long index, D3DLIGHT9 *light)
1566 	{
1567 		CriticalSection cs(this);
1568 
1569 		TRACE("unsigned long index = %d, D3DLIGHT9 *light = 0x%0.8p", index, light);
1570 
1571 		if(!light)
1572 		{
1573 			return INVALIDCALL();
1574 		}
1575 
1576 		if(!this->light.exists(index))
1577 		{
1578 			return INVALIDCALL();
1579 		}
1580 
1581 		*light = this->light[index];
1582 
1583 		return D3D_OK;
1584 	}
1585 
GetLightEnable(unsigned long index,int * enable)1586 	long Direct3DDevice9::GetLightEnable(unsigned long index, int *enable)
1587 	{
1588 		CriticalSection cs(this);
1589 
1590 		TRACE("unsigned long index = %d, int *enable = 0x%0.8p", index, enable);
1591 
1592 		if(!enable)
1593 		{
1594 			return INVALIDCALL();
1595 		}
1596 
1597 		if(!light.exists(index))
1598 		{
1599 			return INVALIDCALL();
1600 		}
1601 
1602 		*enable = light[index].enable ? 128 : 0;
1603 
1604 		return D3D_OK;
1605 	}
1606 
GetMaterial(D3DMATERIAL9 * material)1607 	long Direct3DDevice9::GetMaterial(D3DMATERIAL9 *material)
1608 	{
1609 		CriticalSection cs(this);
1610 
1611 		TRACE("D3DMATERIAL9 *material = 0x%0.8p", material);
1612 
1613 		if(!material)
1614 		{
1615 			return INVALIDCALL();
1616 		}
1617 
1618 		*material = this->material;
1619 
1620 		return D3D_OK;
1621 	}
1622 
GetNPatchMode()1623 	float Direct3DDevice9::GetNPatchMode()
1624 	{
1625 		CriticalSection cs(this);
1626 
1627 		TRACE("void");
1628 
1629 		return 0.0f;   // FIXME: Unimplemented
1630 	}
1631 
GetNumberOfSwapChains()1632 	unsigned int Direct3DDevice9::GetNumberOfSwapChains()
1633 	{
1634 		CriticalSection cs(this);
1635 
1636 		TRACE("void");
1637 
1638 		return 1;
1639 	}
1640 
GetPaletteEntries(unsigned int paletteNumber,PALETTEENTRY * entries)1641 	long Direct3DDevice9::GetPaletteEntries(unsigned int paletteNumber, PALETTEENTRY *entries)
1642 	{
1643 		CriticalSection cs(this);
1644 
1645 		TRACE("unsigned int paletteNumber = %d, PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries);
1646 
1647 		if(paletteNumber > 0xFFFF || !entries)
1648 		{
1649 			return INVALIDCALL();
1650 		}
1651 
1652 		for(int i = 0; i < 256; i++)
1653 		{
1654 			entries[i] = palette[paletteNumber].entry[i];
1655 		}
1656 
1657 		return D3D_OK;
1658 	}
1659 
GetPixelShader(IDirect3DPixelShader9 ** shader)1660 	long Direct3DDevice9::GetPixelShader(IDirect3DPixelShader9 **shader)
1661 	{
1662 		CriticalSection cs(this);
1663 
1664 		TRACE("IDirect3DPixelShader9 **shader = 0x%0.8p", shader);
1665 
1666 		if(!shader)
1667 		{
1668 			return INVALIDCALL();
1669 		}
1670 
1671 		if(pixelShader)
1672 		{
1673 			pixelShader->AddRef();
1674 		}
1675 
1676 		*shader = pixelShader;
1677 
1678 		return D3D_OK;
1679 	}
1680 
GetPixelShaderConstantB(unsigned int startRegister,int * constantData,unsigned int count)1681 	long Direct3DDevice9::GetPixelShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count)
1682 	{
1683 		CriticalSection cs(this);
1684 
1685 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1686 
1687 		if(!constantData)
1688 		{
1689 			return INVALIDCALL();
1690 		}
1691 
1692 		for(unsigned int i = 0; i < count; i++)
1693 		{
1694 			constantData[i] = pixelShaderConstantB[startRegister + i];
1695 		}
1696 
1697 		return D3D_OK;
1698 	}
1699 
GetPixelShaderConstantF(unsigned int startRegister,float * constantData,unsigned int count)1700 	long Direct3DDevice9::GetPixelShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count)
1701 	{
1702 		CriticalSection cs(this);
1703 
1704 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1705 
1706 		if(!constantData)
1707 		{
1708 			return INVALIDCALL();
1709 		}
1710 
1711 		for(unsigned int i = 0; i < count; i++)
1712 		{
1713 			constantData[i * 4 + 0] = pixelShaderConstantF[startRegister + i][0];
1714 			constantData[i * 4 + 1] = pixelShaderConstantF[startRegister + i][1];
1715 			constantData[i * 4 + 2] = pixelShaderConstantF[startRegister + i][2];
1716 			constantData[i * 4 + 3] = pixelShaderConstantF[startRegister + i][3];
1717 		}
1718 
1719 		return D3D_OK;
1720 	}
1721 
GetPixelShaderConstantI(unsigned int startRegister,int * constantData,unsigned int count)1722 	long Direct3DDevice9::GetPixelShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count)
1723 	{
1724 		CriticalSection cs(this);
1725 
1726 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
1727 
1728 		if(!constantData)
1729 		{
1730 			return INVALIDCALL();
1731 		}
1732 
1733 		for(unsigned int i = 0; i < count; i++)
1734 		{
1735 			constantData[i * 4 + 0] = pixelShaderConstantI[startRegister + i][0];
1736 			constantData[i * 4 + 1] = pixelShaderConstantI[startRegister + i][1];
1737 			constantData[i * 4 + 2] = pixelShaderConstantI[startRegister + i][2];
1738 			constantData[i * 4 + 3] = pixelShaderConstantI[startRegister + i][3];
1739 		}
1740 
1741 		return D3D_OK;
1742 	}
1743 
GetRasterStatus(unsigned int index,D3DRASTER_STATUS * rasterStatus)1744 	long Direct3DDevice9::GetRasterStatus(unsigned int index, D3DRASTER_STATUS *rasterStatus)
1745 	{
1746 		CriticalSection cs(this);
1747 
1748 		TRACE("unsigned int swapChain = %d, D3DRASTER_STATUS *rasterStatus = 0x%0.8p", index, rasterStatus);
1749 
1750 		if(index >= GetNumberOfSwapChains())
1751 		{
1752 			return INVALIDCALL();
1753 		}
1754 
1755 		return swapChain->GetRasterStatus(rasterStatus);
1756 	}
1757 
GetRenderState(D3DRENDERSTATETYPE state,unsigned long * value)1758 	long Direct3DDevice9::GetRenderState(D3DRENDERSTATETYPE state, unsigned long *value)
1759 	{
1760 		CriticalSection cs(this);
1761 
1762 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long *value = 0x%0.8p", state, value);
1763 
1764 		if(!value)
1765 		{
1766 			return INVALIDCALL();
1767 		}
1768 
1769 		*value = renderState[state];
1770 
1771 		return D3D_OK;
1772 	}
1773 
GetRenderTarget(unsigned long index,IDirect3DSurface9 ** renderTarget)1774 	long Direct3DDevice9::GetRenderTarget(unsigned long index, IDirect3DSurface9 **renderTarget)
1775 	{
1776 		CriticalSection cs(this);
1777 
1778 		TRACE("unsigned long index = %d, IDirect3DSurface9 **renderTarget = 0x%0.8p", index, renderTarget);
1779 
1780 		if(index >= 4 || !renderTarget)
1781 		{
1782 			return INVALIDCALL();
1783 		}
1784 
1785 		*renderTarget = 0;
1786 
1787 		if(!this->renderTarget[index])
1788 		{
1789 			return NOTFOUND();
1790 		}
1791 
1792 		*renderTarget = this->renderTarget[index];
1793 		this->renderTarget[index]->AddRef();
1794 
1795 		return D3D_OK;
1796 	}
1797 
GetRenderTargetData(IDirect3DSurface9 * renderTarget,IDirect3DSurface9 * destSurface)1798 	long Direct3DDevice9::GetRenderTargetData(IDirect3DSurface9 *renderTarget, IDirect3DSurface9 *destSurface)
1799 	{
1800 		CriticalSection cs(this);
1801 
1802 		TRACE("IDirect3DSurface9 *renderTarget = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p", renderTarget, destSurface);
1803 
1804 		if(!renderTarget || !destSurface)
1805 		{
1806 			return INVALIDCALL();
1807 		}
1808 
1809 		D3DSURFACE_DESC sourceDescription;
1810 		D3DSURFACE_DESC destinationDescription;
1811 
1812 		renderTarget->GetDesc(&sourceDescription);
1813 		destSurface->GetDesc(&destinationDescription);
1814 
1815 		if(sourceDescription.Width  != destinationDescription.Width ||
1816 		   sourceDescription.Height != destinationDescription.Height ||
1817 		   sourceDescription.Format != destinationDescription.Format ||
1818 		   sourceDescription.MultiSampleType != D3DMULTISAMPLE_NONE)
1819 		{
1820 			return INVALIDCALL();
1821 		}
1822 
1823 		if(sourceDescription.Format == D3DFMT_A8R8G8B8 ||
1824 		   sourceDescription.Format == D3DFMT_X8R8G8B8)
1825 		{
1826 			sw::Surface *source = static_cast<Direct3DSurface9*>(renderTarget);
1827 			sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface);
1828 
1829 			void *sourceBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
1830 			void *destBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
1831 
1832 			static void (__cdecl *blitFunction)(void *dst, void *src);
1833 			static sw::Routine *blitRoutine;
1834 			static sw::BlitState blitState = {0};
1835 
1836 			sw::BlitState update;
1837 			update.width = sourceDescription.Width;
1838 			update.height = sourceDescription.Height;
1839 			update.sourceFormat = sw::FORMAT_A8R8G8B8;
1840 			update.destFormat = sw::FORMAT_A8R8G8B8;
1841 			update.stride = dest->getExternalPitchB();
1842 			update.cursorHeight = 0;
1843 			update.cursorWidth = 0;
1844 
1845 			if(memcmp(&blitState, &update, sizeof(sw::BlitState)) != 0)
1846 			{
1847 				blitState = update;
1848 				delete blitRoutine;
1849 
1850 				blitRoutine = sw::FrameBuffer::copyRoutine(blitState);
1851 				blitFunction = (void(__cdecl*)(void*, void*))blitRoutine->getEntry();
1852 			}
1853 
1854 			blitFunction(destBuffer, sourceBuffer);
1855 
1856 			dest->unlockExternal();
1857 			source->unlockExternal();
1858 		}
1859 		else
1860 		{
1861 			return UpdateSurface(renderTarget, 0, destSurface, 0);
1862 		}
1863 
1864 		return D3D_OK;
1865 	}
1866 
GetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long * value)1867 	long Direct3DDevice9::GetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long *value)
1868 	{
1869 		CriticalSection cs(this);
1870 
1871 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE type = %d, unsigned long *value = 0x%0.8p", sampler, state, value);
1872 
1873 		if(!value || state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)   // FIXME: Set *value to 0?
1874 		{
1875 			return INVALIDCALL();
1876 		}
1877 
1878 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1879 		{
1880 			return INVALIDCALL();
1881 		}
1882 
1883 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
1884 		{
1885 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
1886 		}
1887 
1888 		*value = samplerState[sampler][state];
1889 
1890 		return D3D_OK;
1891 	}
1892 
GetScissorRect(RECT * rect)1893 	long Direct3DDevice9::GetScissorRect(RECT *rect)
1894 	{
1895 		CriticalSection cs(this);
1896 
1897 		TRACE("RECT *rect = 0x%0.8p", rect);
1898 
1899 		if(!rect)
1900 		{
1901 			return INVALIDCALL();
1902 		}
1903 
1904 		*rect = scissorRect;
1905 
1906 		return D3D_OK;
1907 	}
1908 
GetSoftwareVertexProcessing()1909 	int Direct3DDevice9::GetSoftwareVertexProcessing()
1910 	{
1911 		CriticalSection cs(this);
1912 
1913 		TRACE("void");
1914 
1915 		return softwareVertexProcessing ? TRUE : FALSE;
1916 	}
1917 
GetStreamSource(unsigned int streamNumber,IDirect3DVertexBuffer9 ** streamData,unsigned int * offset,unsigned int * stride)1918 	long Direct3DDevice9::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer9 **streamData, unsigned int *offset, unsigned int *stride)
1919 	{
1920 		CriticalSection cs(this);
1921 
1922 		TRACE("unsigned int streamNumber = %d, IDirect3DVertexBuffer9 **streamData = 0x%0.8p, unsigned int *offset = 0x%0.8p, unsigned int *stride = 0x%0.8p", streamNumber, streamData, offset, stride);
1923 
1924 		if(streamNumber >= 16 || !streamData || !offset || !stride)
1925 		{
1926 			return INVALIDCALL();
1927 		}
1928 
1929 		*streamData = dataStream[streamNumber];
1930 
1931 		if(dataStream[streamNumber])
1932 		{
1933 			dataStream[streamNumber]->AddRef();
1934 		}
1935 
1936 		*offset = streamOffset[streamNumber];
1937 		*stride = streamStride[streamNumber];
1938 
1939 		return D3D_OK;
1940 	}
1941 
GetStreamSourceFreq(unsigned int streamNumber,unsigned int * divider)1942 	long Direct3DDevice9::GetStreamSourceFreq(unsigned int streamNumber, unsigned int *divider)
1943 	{
1944 		CriticalSection cs(this);
1945 
1946 		TRACE("unsigned int streamNumber = %d, unsigned int *divider = 0x%0.8p", streamNumber, divider);
1947 
1948 		if(streamNumber >= 16 || !divider)
1949 		{
1950 			return INVALIDCALL();
1951 		}
1952 
1953 		*divider = streamSourceFreq[streamNumber];
1954 
1955 		return D3D_OK;
1956 	}
1957 
GetSwapChain(unsigned int index,IDirect3DSwapChain9 ** swapChain)1958 	long Direct3DDevice9::GetSwapChain(unsigned int index, IDirect3DSwapChain9 **swapChain)
1959 	{
1960 		CriticalSection cs(this);
1961 
1962 		TRACE("unsigned int index = %d, IDirect3DSwapChain9 **swapChain = 0x%0.8p", index, swapChain);
1963 
1964 		if(!swapChain || index >= GetNumberOfSwapChains())
1965 		{
1966 			return INVALIDCALL();
1967 		}
1968 
1969 		*swapChain = this->swapChain;
1970 
1971 		if(*swapChain)
1972 		{
1973 			(*swapChain)->AddRef();
1974 		}
1975 
1976 		return D3D_OK;
1977 	}
1978 
GetTexture(unsigned long sampler,IDirect3DBaseTexture9 ** texture)1979 	long Direct3DDevice9::GetTexture(unsigned long sampler, IDirect3DBaseTexture9 **texture)
1980 	{
1981 		CriticalSection cs(this);
1982 
1983 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 **texture = 0x%0.8p", sampler, texture);
1984 
1985 		if(!texture)
1986 		{
1987 			return INVALIDCALL();
1988 		}
1989 
1990 		*texture = 0;
1991 
1992 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1993 		{
1994 			return INVALIDCALL();
1995 		}
1996 
1997 		*texture = this->texture[sampler];
1998 
1999 		if(this->texture[sampler])
2000 		{
2001 			this->texture[sampler]->AddRef();
2002 		}
2003 
2004 		return D3D_OK;
2005 	}
2006 
GetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long * value)2007 	long Direct3DDevice9::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long *value)
2008 	{
2009 		CriticalSection cs(this);
2010 
2011 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long *value = 0x%0.8p", stage, type, value);
2012 
2013 		if(!value)
2014 		{
2015 			return INVALIDCALL();
2016 		}
2017 
2018 		*value = textureStageState[stage][type];
2019 
2020 		return D3D_OK;
2021 	}
2022 
GetTransform(D3DTRANSFORMSTATETYPE state,D3DMATRIX * matrix)2023 	long Direct3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
2024 	{
2025 		CriticalSection cs(this);
2026 
2027 		TRACE("D3DTRANSFORMSTATETYPE state = %d, D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2028 
2029 		if(!matrix || state < 0 || state > 511)
2030 		{
2031 			return INVALIDCALL();
2032 		}
2033 
2034 		*matrix = this->matrix[state];
2035 
2036 		return D3D_OK;
2037 	}
2038 
GetVertexDeclaration(IDirect3DVertexDeclaration9 ** declaration)2039 	long Direct3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9 **declaration)
2040 	{
2041 		CriticalSection cs(this);
2042 
2043 		TRACE("IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", declaration);
2044 
2045 		if(!declaration)
2046 		{
2047 			return INVALIDCALL();
2048 		}
2049 
2050 		*declaration = vertexDeclaration;
2051 
2052 		if(vertexDeclaration)
2053 		{
2054 			vertexDeclaration->AddRef();
2055 		}
2056 
2057 		return D3D_OK;
2058 	}
2059 
GetVertexShader(IDirect3DVertexShader9 ** shader)2060 	long Direct3DDevice9::GetVertexShader(IDirect3DVertexShader9 **shader)
2061 	{
2062 		CriticalSection cs(this);
2063 
2064 		TRACE("IDirect3DVertexShader9 **shader = 0x%0.8p", shader);
2065 
2066 		if(!shader)
2067 		{
2068 			return INVALIDCALL();
2069 		}
2070 
2071 		*shader = vertexShader;
2072 
2073 		if(vertexShader)
2074 		{
2075 			vertexShader->AddRef();
2076 		}
2077 
2078 		return D3D_OK;
2079 	}
2080 
GetVertexShaderConstantB(unsigned int startRegister,int * constantData,unsigned int count)2081 	long Direct3DDevice9::GetVertexShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count)
2082 	{
2083 		CriticalSection cs(this);
2084 
2085 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2086 
2087 		if(!constantData)
2088 		{
2089 			return INVALIDCALL();
2090 		}
2091 
2092 		for(unsigned int i = 0; i < count; i++)
2093 		{
2094 			constantData[i] = vertexShaderConstantB[startRegister + i];
2095 		}
2096 
2097 		return D3D_OK;
2098 	}
2099 
GetVertexShaderConstantF(unsigned int startRegister,float * constantData,unsigned int count)2100 	long Direct3DDevice9::GetVertexShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count)
2101 	{
2102 		CriticalSection cs(this);
2103 
2104 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2105 
2106 		if(!constantData)
2107 		{
2108 			return INVALIDCALL();
2109 		}
2110 
2111 		for(unsigned int i = 0; i < count; i++)
2112 		{
2113 			constantData[i * 4 + 0] = vertexShaderConstantF[startRegister + i][0];
2114 			constantData[i * 4 + 1] = vertexShaderConstantF[startRegister + i][1];
2115 			constantData[i * 4 + 2] = vertexShaderConstantF[startRegister + i][2];
2116 			constantData[i * 4 + 3] = vertexShaderConstantF[startRegister + i][3];
2117 		}
2118 
2119 		return D3D_OK;
2120 	}
2121 
GetVertexShaderConstantI(unsigned int startRegister,int * constantData,unsigned int count)2122 	long Direct3DDevice9::GetVertexShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count)
2123 	{
2124 		CriticalSection cs(this);
2125 
2126 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2127 
2128 		if(!constantData)
2129 		{
2130 			return INVALIDCALL();
2131 		}
2132 
2133 		for(unsigned int i = 0; i < count; i++)
2134 		{
2135 			constantData[i * 4 + 0] = vertexShaderConstantI[startRegister + i][0];
2136 			constantData[i * 4 + 1] = vertexShaderConstantI[startRegister + i][1];
2137 			constantData[i * 4 + 2] = vertexShaderConstantI[startRegister + i][2];
2138 			constantData[i * 4 + 3] = vertexShaderConstantI[startRegister + i][3];
2139 		}
2140 
2141 		return D3D_OK;
2142 	}
2143 
GetViewport(D3DVIEWPORT9 * viewport)2144 	long Direct3DDevice9::GetViewport(D3DVIEWPORT9 *viewport)
2145 	{
2146 		CriticalSection cs(this);
2147 
2148 		TRACE("D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
2149 
2150 		if(!viewport)
2151 		{
2152 			return INVALIDCALL();
2153 		}
2154 
2155 		*viewport = this->viewport;
2156 
2157 		return D3D_OK;
2158 	}
2159 
LightEnable(unsigned long index,int enable)2160 	long Direct3DDevice9::LightEnable(unsigned long index, int enable)
2161 	{
2162 		CriticalSection cs(this);
2163 
2164 		TRACE("unsigned long index = %d, int enable = %d", index, enable);
2165 
2166 		if(!light.exists(index))   // Insert default light
2167 		{
2168 			D3DLIGHT9 light;
2169 
2170 			light.Type = D3DLIGHT_DIRECTIONAL;
2171 			light.Diffuse.r = 1;
2172 			light.Diffuse.g = 1;
2173 			light.Diffuse.b = 1;
2174 			light.Diffuse.a = 0;
2175 			light.Specular.r = 0;
2176 			light.Specular.g = 0;
2177 			light.Specular.b = 0;
2178 			light.Specular.a = 0;
2179 			light.Ambient.r = 0;
2180 			light.Ambient.g = 0;
2181 			light.Ambient.b = 0;
2182 			light.Ambient.a = 0;
2183 			light.Position.x = 0;
2184 			light.Position.y = 0;
2185 			light.Position.z = 0;
2186 			light.Direction.x = 0;
2187 			light.Direction.y = 0;
2188 			light.Direction.z = 1;
2189 			light.Range = 0;
2190 			light.Falloff = 0;
2191 			light.Attenuation0 = 0;
2192 			light.Attenuation1 = 0;
2193 			light.Attenuation2 = 0;
2194 			light.Theta = 0;
2195 			light.Phi = 0;
2196 
2197 			this->light[index] = light;
2198 			this->light[index].enable = false;
2199 		}
2200 
2201 		if(!stateRecorder)
2202 		{
2203 			light[index].enable = (enable != FALSE);
2204 
2205 			lightsDirty = true;
2206 		}
2207 		else
2208 		{
2209 			stateRecorder->lightEnable(index, enable);
2210 		}
2211 
2212 		return D3D_OK;
2213 	}
2214 
MultiplyTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)2215 	long Direct3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
2216 	{
2217 		CriticalSection cs(this);
2218 
2219 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2220 
2221 		if(!matrix)
2222 		{
2223 			return INVALIDCALL();
2224 		}
2225 
2226 		D3DMATRIX *current = &this->matrix[state];
2227 
2228 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41,
2229 		             current->_12, current->_22, current->_32, current->_42,
2230 		             current->_13, current->_23, current->_33, current->_43,
2231 		             current->_14, current->_24, current->_34, current->_44);
2232 
2233 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
2234 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
2235 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
2236 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
2237 
2238 		switch(state)
2239 		{
2240 		case D3DTS_WORLD:
2241 			renderer->setModelMatrix(C * M);
2242 			break;
2243 		case D3DTS_VIEW:
2244 			renderer->setViewMatrix(C * M);
2245 			break;
2246 		case D3DTS_PROJECTION:
2247 			renderer->setProjectionMatrix(C * M);
2248 			break;
2249 		case D3DTS_TEXTURE0:
2250 			renderer->setTextureMatrix(0, C * M);
2251 			break;
2252 		case D3DTS_TEXTURE1:
2253 			renderer->setTextureMatrix(1, C * M);
2254 			break;
2255 		case D3DTS_TEXTURE2:
2256 			renderer->setTextureMatrix(2, C * M);
2257 			break;
2258 		case D3DTS_TEXTURE3:
2259 			renderer->setTextureMatrix(3, C * M);
2260 			break;
2261 		case D3DTS_TEXTURE4:
2262 			renderer->setTextureMatrix(4, C * M);
2263 			break;
2264 		case D3DTS_TEXTURE5:
2265 			renderer->setTextureMatrix(5, C * M);
2266 			break;
2267 		case D3DTS_TEXTURE6:
2268 			renderer->setTextureMatrix(6, C * M);
2269 			break;
2270 		case D3DTS_TEXTURE7:
2271 			renderer->setTextureMatrix(7, C * M);
2272 			break;
2273 		default:
2274 			if(state > 256 && state < 512)
2275 			{
2276 				renderer->setModelMatrix(C * M, state - 256);
2277 			}
2278 			else ASSERT(false);
2279 		}
2280 
2281 		return D3D_OK;
2282 	}
2283 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion)2284 	long Direct3DDevice9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
2285 	{
2286 		CriticalSection cs(this);
2287 
2288 		TRACE("const RECT *sourceRect = 0x%0.8p, const RECT *destRect = 0x%0.8p, HWND destWindowOverride = %d, const RGNDATA *dirtyRegion = 0x%0.8p", sourceRect, destRect, destWindowOverride, dirtyRegion);
2289 
2290 		return swapChain->Present(sourceRect, destRect, destWindowOverride, dirtyRegion, 0);
2291 	}
2292 
ProcessVertices(unsigned int srcStartIndex,unsigned int destIndex,unsigned int vertexCount,IDirect3DVertexBuffer9 * destBuffer,IDirect3DVertexDeclaration9 * vertexDeclaration,unsigned long flags)2293 	long Direct3DDevice9::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer9 *destBuffer, IDirect3DVertexDeclaration9 *vertexDeclaration, unsigned long flags)
2294 	{
2295 		CriticalSection cs(this);
2296 
2297 		TRACE("unsigned int srcStartIndex = %d, unsigned int destIndex = %d, unsigned int vertexCount = %d, IDirect3DVertexBuffer9 *destBuffer = 0x%0.8p, IDirect3DVertexDeclaration9 *vertexDeclaration = 0x%0.8p, unsigned long flags = %d", srcStartIndex, destIndex, vertexCount, destBuffer, vertexDeclaration, flags);
2298 
2299 		if(!destBuffer)
2300 		{
2301 			return INVALIDCALL();
2302 		}
2303 
2304 		UNIMPLEMENTED();
2305 
2306 		return D3D_OK;
2307 	}
2308 
Reset(D3DPRESENT_PARAMETERS * presentParameters)2309 	long Direct3DDevice9::Reset(D3DPRESENT_PARAMETERS *presentParameters)
2310 	{
2311 		CriticalSection cs(this);
2312 
2313 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p", presentParameters);
2314 
2315 		if(!presentParameters)
2316 		{
2317 			return INVALIDCALL();
2318 		}
2319 
2320 		deviceWindow = presentParameters->hDeviceWindow;
2321 
2322 		if(depthStencil)
2323 		{
2324 			depthStencil->unbind();
2325 			depthStencil = 0;
2326 		}
2327 
2328 		if(autoDepthStencil)
2329 		{
2330 			autoDepthStencil->unbind();
2331 			autoDepthStencil = 0;
2332 		}
2333 
2334 		for(int index = 0; index < 4; index++)
2335 		{
2336 			if(renderTarget[index])
2337 			{
2338 				renderTarget[index]->unbind();
2339 				renderTarget[index] = 0;
2340 			}
2341 		}
2342 
2343 		if(!swapChain)
2344 		{
2345 			swapChain = new Direct3DSwapChain9(this, presentParameters);
2346 			swapChain->bind();
2347 		}
2348 		else
2349 		{
2350 			swapChain->reset(presentParameters);
2351 		}
2352 
2353 		if(presentParameters->EnableAutoDepthStencil != FALSE)
2354 		{
2355 			bool lockable = false;
2356 
2357 			switch(presentParameters->AutoDepthStencilFormat)
2358 			{
2359 			case D3DFMT_D15S1:
2360 			case D3DFMT_D24S8:
2361 			case D3DFMT_D24X8:
2362 			case D3DFMT_D24X4S4:
2363 			case D3DFMT_D24FS8:
2364 			case D3DFMT_D32:
2365 			case D3DFMT_D16:
2366 			case D3DFMT_DF24:
2367 			case D3DFMT_DF16:
2368 			case D3DFMT_INTZ:
2369 				lockable = false;
2370 				break;
2371 			case D3DFMT_S8_LOCKABLE:
2372 			case D3DFMT_D16_LOCKABLE:
2373 			case D3DFMT_D32F_LOCKABLE:
2374 			case D3DFMT_D32_LOCKABLE:
2375 				lockable = true;
2376 				break;
2377 			default:
2378 				ASSERT(false);
2379 			}
2380 
2381 			autoDepthStencil = new Direct3DSurface9(this, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL);
2382 			autoDepthStencil->bind();
2383 
2384 			SetDepthStencilSurface(autoDepthStencil);
2385 		}
2386 
2387 		IDirect3DSurface9 *renderTarget;
2388 		swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget);
2389 		SetRenderTarget(0, renderTarget);
2390 		renderTarget->Release();
2391 
2392 		SetRenderTarget(1, 0);
2393 		SetRenderTarget(2, 0);
2394 		SetRenderTarget(3, 0);
2395 
2396 		softwareVertexProcessing = (behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == D3DCREATE_SOFTWARE_VERTEXPROCESSING;
2397 
2398 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE);
2399 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2400 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
2401 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2402 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2403 		SetRenderState(D3DRS_LASTPIXEL, TRUE);
2404 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
2405 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
2406 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
2407 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2408 		SetRenderState(D3DRS_ALPHAREF, 0);
2409 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
2410 		SetRenderState(D3DRS_DITHERENABLE, FALSE);
2411 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2412 		SetRenderState(D3DRS_FOGENABLE, FALSE);
2413 		SetRenderState(D3DRS_SPECULARENABLE, FALSE);
2414 	//	SetRenderState(D3DRS_ZVISIBLE, 0);
2415 		SetRenderState(D3DRS_FOGCOLOR, 0);
2416 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
2417 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f));
2418 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f));
2419 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f));
2420 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
2421 		SetRenderState(D3DRS_STENCILENABLE, FALSE);
2422 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
2423 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
2424 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
2425 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2426 		SetRenderState(D3DRS_STENCILREF, 0);
2427 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
2428 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
2429 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
2430 		SetRenderState(D3DRS_WRAP0, 0);
2431 		SetRenderState(D3DRS_WRAP1, 0);
2432 		SetRenderState(D3DRS_WRAP2, 0);
2433 		SetRenderState(D3DRS_WRAP3, 0);
2434 		SetRenderState(D3DRS_WRAP4, 0);
2435 		SetRenderState(D3DRS_WRAP5, 0);
2436 		SetRenderState(D3DRS_WRAP6, 0);
2437 		SetRenderState(D3DRS_WRAP7, 0);
2438 		SetRenderState(D3DRS_CLIPPING, TRUE);
2439 		SetRenderState(D3DRS_LIGHTING, TRUE);
2440 		SetRenderState(D3DRS_AMBIENT, 0);
2441 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
2442 		SetRenderState(D3DRS_COLORVERTEX, TRUE);
2443 		SetRenderState(D3DRS_LOCALVIEWER, TRUE);
2444 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
2445 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
2446 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
2447 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
2448 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
2449 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
2450 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2451 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f));
2452 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
2453 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
2454 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
2455 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f));
2456 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
2457 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
2458 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
2459 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
2460 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
2461 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
2462 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f));
2463 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
2464 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F);
2465 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f));
2466 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
2467 		SetRenderState(D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC);
2468 		SetRenderState(D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR);
2469 		SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
2470 		SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FtoDW(0.0f));
2471 		SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
2472 		SetRenderState(D3DRS_MINTESSELLATIONLEVEL, FtoDW(1.0f));
2473 		SetRenderState(D3DRS_MAXTESSELLATIONLEVEL, FtoDW(1.0f));
2474 		SetRenderState(D3DRS_ADAPTIVETESS_X, FtoDW(0.0f));
2475 		SetRenderState(D3DRS_ADAPTIVETESS_Y, FtoDW(0.0f));
2476 		SetRenderState(D3DRS_ADAPTIVETESS_Z, FtoDW(1.0f));
2477 		SetRenderState(D3DRS_ADAPTIVETESS_W, FtoDW(0.0f));
2478 		SetRenderState(D3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
2479 		SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2480 		SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
2481 		SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
2482 		SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
2483 		SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
2484 		SetRenderState(D3DRS_COLORWRITEENABLE1, 0x0000000F);
2485 		SetRenderState(D3DRS_COLORWRITEENABLE2, 0x0000000F);
2486 		SetRenderState(D3DRS_COLORWRITEENABLE3, 0x0000000F);
2487 		SetRenderState(D3DRS_BLENDFACTOR, 0xFFFFFFFF);
2488 		SetRenderState(D3DRS_SRGBWRITEENABLE, 0);
2489 		SetRenderState(D3DRS_DEPTHBIAS, FtoDW(0.0f));
2490 		SetRenderState(D3DRS_WRAP8, 0);
2491 		SetRenderState(D3DRS_WRAP9, 0);
2492 		SetRenderState(D3DRS_WRAP10, 0);
2493 		SetRenderState(D3DRS_WRAP11, 0);
2494 		SetRenderState(D3DRS_WRAP12, 0);
2495 		SetRenderState(D3DRS_WRAP13, 0);
2496 		SetRenderState(D3DRS_WRAP14, 0);
2497 		SetRenderState(D3DRS_WRAP15, 0);
2498 		SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
2499 		SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
2500 		SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
2501 		SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
2502 
2503 		for(int i = 0; i < 8; i++)
2504 		{
2505 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE);
2506 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2507 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
2508 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE);
2509 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
2510 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
2511 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f));
2512 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f));
2513 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f));
2514 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f));
2515 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
2516 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f));
2517 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f));
2518 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2519 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
2520 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
2521 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
2522 			SetTextureStageState(i, D3DTSS_CONSTANT, 0x00000000);
2523 		}
2524 
2525 		for(int i = 0; i <= D3DVERTEXTEXTURESAMPLER3; i = (i != 15) ? (i + 1) : D3DVERTEXTEXTURESAMPLER0)
2526 		{
2527 			SetTexture(i, 0);
2528 
2529 			SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
2530 			SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
2531 			SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
2532 			SetSamplerState(i, D3DSAMP_BORDERCOLOR, 0x00000000);
2533 			SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2534 			SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2535 			SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2536 			SetSamplerState(i, D3DSAMP_MIPMAPLODBIAS, 0);
2537 			SetSamplerState(i, D3DSAMP_MAXMIPLEVEL, 0);
2538 			SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 1);
2539 			SetSamplerState(i, D3DSAMP_SRGBTEXTURE, 0);
2540 			SetSamplerState(i, D3DSAMP_ELEMENTINDEX, 0);
2541 			SetSamplerState(i, D3DSAMP_DMAPOFFSET, 0);
2542 		}
2543 
2544 		for(int i = 0; i < 6; i++)
2545 		{
2546 			float plane[4] = {0, 0, 0, 0};
2547 
2548 			SetClipPlane(i, plane);
2549 		}
2550 
2551 		currentPalette = 0xFFFF;
2552 
2553 		ShowCursor(FALSE);
2554 		delete cursor;
2555 		cursor = 0;
2556 
2557 		return D3D_OK;
2558 	}
2559 
SetClipPlane(unsigned long index,const float * plane)2560 	long Direct3DDevice9::SetClipPlane(unsigned long index, const float *plane)
2561 	{
2562 		CriticalSection cs(this);
2563 
2564 		TRACE("unsigned long index = %d, const float *plane = 0x%0.8p", index, plane);
2565 
2566 		if(!plane || index >= 6)
2567 		{
2568 			return INVALIDCALL();
2569 		}
2570 
2571 		if(!stateRecorder)
2572 		{
2573 			this->plane[index][0] = plane[0];
2574 			this->plane[index][1] = plane[1];
2575 			this->plane[index][2] = plane[2];
2576 			this->plane[index][3] = plane[3];
2577 
2578 			renderer->setClipPlane(index, plane);
2579 		}
2580 		else
2581 		{
2582 			stateRecorder->setClipPlane(index, plane);
2583 		}
2584 
2585 		return D3D_OK;
2586 	}
2587 
SetClipStatus(const D3DCLIPSTATUS9 * clipStatus)2588 	long Direct3DDevice9::SetClipStatus(const D3DCLIPSTATUS9 *clipStatus)
2589 	{
2590 		CriticalSection cs(this);
2591 
2592 		TRACE("const D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus);
2593 
2594 		if(!clipStatus)
2595 		{
2596 			return INVALIDCALL();
2597 		}
2598 
2599 		this->clipStatus = *clipStatus;
2600 
2601 		UNIMPLEMENTED();
2602 
2603 		return D3D_OK;
2604 	}
2605 
SetCurrentTexturePalette(unsigned int paletteNumber)2606 	long Direct3DDevice9::SetCurrentTexturePalette(unsigned int paletteNumber)
2607 	{
2608 		CriticalSection cs(this);
2609 
2610 		TRACE("unsigned int paletteNumber = %d", paletteNumber);
2611 
2612 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end())
2613 		{
2614 			return INVALIDCALL();
2615 		}
2616 
2617 		if(!stateRecorder)
2618 		{
2619 			currentPalette = paletteNumber;
2620 
2621 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2622 		}
2623 		else
2624 		{
2625 			stateRecorder->setCurrentTexturePalette(paletteNumber);
2626 		}
2627 
2628 		return D3D_OK;
2629 	}
2630 
SetCursorPosition(int x,int y,unsigned long flags)2631 	void Direct3DDevice9::SetCursorPosition(int x, int y, unsigned long flags)
2632 	{
2633 		CriticalSection cs(this);
2634 
2635 		TRACE("int x = %d, int y = %d, unsigned long flags = 0x%0.8X", x, y, flags);
2636 
2637 		POINT point = {x, y};
2638 		HWND window = deviceWindow ? deviceWindow : focusWindow;
2639 		ScreenToClient(window, &point);
2640 
2641 		sw::FrameBuffer::setCursorPosition(point.x, point.y);
2642 	}
2643 
SetCursorProperties(unsigned int x0,unsigned int y0,IDirect3DSurface9 * cursorBitmap)2644 	long Direct3DDevice9::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface9 *cursorBitmap)
2645 	{
2646 		CriticalSection cs(this);
2647 
2648 		TRACE("unsigned int x0 = %d, unsigned int y0 = %d, IDirect3DSurface9 *cursorBitmap = 0x%0.8p", x0, y0, cursorBitmap);
2649 
2650 		if(!cursorBitmap)
2651 		{
2652 			return INVALIDCALL();
2653 		}
2654 
2655 		sw::Surface *cursorSurface = static_cast<Direct3DSurface9*>(cursorBitmap);
2656 
2657 		int width = cursorSurface->getWidth();
2658 		int height = cursorSurface->getHeight();
2659 		void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
2660 
2661 		delete cursor;
2662 		cursor = new sw::Surface(0, width, height, 1, sw::FORMAT_A8R8G8B8, false, false);
2663 
2664 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
2665 		memcpy(buffer, bitmap, width * height * sizeof(unsigned int));
2666 		cursor->unlockExternal();
2667 
2668 		cursorSurface->unlockExternal();
2669 
2670 		if(showCursor)
2671 		{
2672 			sw::FrameBuffer::setCursorImage(cursor);
2673 		}
2674 		else
2675 		{
2676 			sw::FrameBuffer::setCursorImage(0);
2677 		}
2678 
2679 		sw::FrameBuffer::setCursorOrigin(x0, y0);
2680 
2681 		return D3D_OK;
2682 	}
2683 
SetDepthStencilSurface(IDirect3DSurface9 * iDepthStencil)2684 	long Direct3DDevice9::SetDepthStencilSurface(IDirect3DSurface9 *iDepthStencil)
2685 	{
2686 		CriticalSection cs(this);
2687 
2688 		TRACE("IDirect3DSurface9 *newDepthStencil = 0x%0.8p", iDepthStencil);
2689 
2690 		Direct3DSurface9 *depthStencil = static_cast<Direct3DSurface9*>(iDepthStencil);
2691 
2692 		if(this->depthStencil == depthStencil)
2693 		{
2694 			return D3D_OK;
2695 		}
2696 
2697 		if(depthStencil)
2698 		{
2699 			depthStencil->bind();
2700 		}
2701 
2702 		if(this->depthStencil)
2703 		{
2704 			this->depthStencil->unbind();
2705 		}
2706 
2707 		this->depthStencil = depthStencil;
2708 
2709 		renderer->setDepthBuffer(depthStencil);
2710 		renderer->setStencilBuffer(depthStencil);
2711 
2712 		return D3D_OK;
2713 	}
2714 
SetDialogBoxMode(int enableDialogs)2715 	long Direct3DDevice9::SetDialogBoxMode(int enableDialogs)
2716 	{
2717 		CriticalSection cs(this);
2718 
2719 		TRACE("int enableDialogs = %d", enableDialogs);
2720 
2721 		UNIMPLEMENTED();
2722 
2723 		return D3D_OK;
2724 	}
2725 
SetFVF(unsigned long FVF)2726 	long Direct3DDevice9::SetFVF(unsigned long FVF)
2727 	{
2728 		CriticalSection cs(this);
2729 
2730 		TRACE("unsigned long FVF = 0x%0.8X", FVF);
2731 
2732 		if(!stateRecorder)
2733 		{
2734 			if(FVF != 0 || !this->vertexDeclaration)
2735 			{
2736 				Direct3DVertexDeclaration9 *vertexDeclaration = new Direct3DVertexDeclaration9(this, FVF);
2737 				vertexDeclaration->bind();
2738 
2739 				if(this->vertexDeclaration)
2740 				{
2741 					this->vertexDeclaration->unbind();
2742 				}
2743 
2744 				this->vertexDeclaration = vertexDeclaration;
2745 			}
2746 		}
2747 		else
2748 		{
2749 			stateRecorder->setFVF(FVF);
2750 		}
2751 
2752 		return D3D_OK;
2753 	}
2754 
SetGammaRamp(unsigned int index,unsigned long flags,const D3DGAMMARAMP * ramp)2755 	void Direct3DDevice9::SetGammaRamp(unsigned int index, unsigned long flags, const D3DGAMMARAMP *ramp)
2756 	{
2757 		CriticalSection cs(this);
2758 
2759 		TRACE("unsigned int index = %d, unsigned long flags = 0x%0.8X, const D3DGAMMARAMP *ramp = 0x%0.8p", index, flags, ramp);
2760 
2761 		if(!ramp || index >= GetNumberOfSwapChains())
2762 		{
2763 			return;
2764 		}
2765 
2766 		swapChain->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE);
2767 	}
2768 
SetIndices(IDirect3DIndexBuffer9 * iIndexBuffer)2769 	long Direct3DDevice9::SetIndices(IDirect3DIndexBuffer9* iIndexBuffer)
2770 	{
2771 		CriticalSection cs(this);
2772 
2773 		TRACE("IDirect3DIndexBuffer9* indexData = 0x%0.8p", iIndexBuffer);
2774 
2775 		Direct3DIndexBuffer9 *indexBuffer = static_cast<Direct3DIndexBuffer9*>(iIndexBuffer);
2776 
2777 		if(!stateRecorder)
2778 		{
2779 			if(this->indexData == indexBuffer)
2780 			{
2781 				return D3D_OK;
2782 			}
2783 
2784 			if(indexBuffer)
2785 			{
2786 				indexBuffer->bind();
2787 			}
2788 
2789 			if(this->indexData)
2790 			{
2791 				this->indexData->unbind();
2792 			}
2793 
2794 			this->indexData = indexBuffer;
2795 		}
2796 		else
2797 		{
2798 			stateRecorder->setIndices(indexBuffer);
2799 		}
2800 
2801 		return D3D_OK;
2802 	}
2803 
SetLight(unsigned long index,const D3DLIGHT9 * light)2804 	long Direct3DDevice9::SetLight(unsigned long index, const D3DLIGHT9 *light)
2805 	{
2806 		CriticalSection cs(this);
2807 
2808 		TRACE("unsigned long index = %d, const D3DLIGHT9 *light = 0x%0.8p", index, light);
2809 
2810 		if(!light)
2811 		{
2812 			return INVALIDCALL();
2813 		}
2814 
2815 		if(!stateRecorder)
2816 		{
2817 			this->light[index] = *light;
2818 
2819 			lightsDirty = true;
2820 		}
2821 		else
2822 		{
2823 			stateRecorder->setLight(index, light);
2824 		}
2825 
2826 		return D3D_OK;
2827 	}
2828 
SetMaterial(const D3DMATERIAL9 * material)2829 	long Direct3DDevice9::SetMaterial(const D3DMATERIAL9 *material)
2830 	{
2831 		CriticalSection cs(this);
2832 
2833 		TRACE("const D3DMATERIAL9 *material = 0x%0.8p", material);
2834 
2835 		if(!material)
2836 		{
2837 			return INVALIDCALL();   // FIXME: Correct behaviour?
2838 		}
2839 
2840 		if(!stateRecorder)
2841 		{
2842 			this->material = *material;
2843 
2844 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a));
2845 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a));
2846 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a));
2847 			renderer->setMaterialShininess(material->Power);
2848 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a));
2849 		}
2850 		else
2851 		{
2852 			stateRecorder->setMaterial(material);
2853 		}
2854 
2855 		return D3D_OK;
2856 	}
2857 
SetNPatchMode(float segments)2858 	long Direct3DDevice9::SetNPatchMode(float segments)
2859 	{
2860 		CriticalSection cs(this);
2861 
2862 		TRACE("float segments = %f", segments);
2863 
2864 		if(!stateRecorder)
2865 		{
2866 			if(segments < 1)
2867 			{
2868 				// NOTE: Disable
2869 			}
2870 			else
2871 			{
2872 				UNIMPLEMENTED();
2873 			}
2874 		}
2875 		else
2876 		{
2877 			stateRecorder->setNPatchMode(segments);
2878 		}
2879 
2880 		return D3D_OK;
2881 	}
2882 
SetPaletteEntries(unsigned int paletteNumber,const PALETTEENTRY * entries)2883 	long Direct3DDevice9::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries)
2884 	{
2885 		CriticalSection cs(this);
2886 
2887 		TRACE("unsigned int paletteNumber = %d, const PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries);
2888 
2889 		if(paletteNumber > 0xFFFF || !entries)
2890 		{
2891 			return INVALIDCALL();
2892 		}
2893 
2894 		for(int i = 0; i < 256; i++)
2895 		{
2896 			palette[paletteNumber].entry[i] = entries[i];
2897 		}
2898 
2899 		if(paletteNumber == currentPalette)
2900 		{
2901 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2902 		}
2903 
2904 		return D3D_OK;
2905 	}
2906 
SetPixelShader(IDirect3DPixelShader9 * iPixelShader)2907 	long Direct3DDevice9::SetPixelShader(IDirect3DPixelShader9 *iPixelShader)
2908 	{
2909 		CriticalSection cs(this);
2910 
2911 		TRACE("IDirect3DPixelShader9 *shader = 0x%0.8p", iPixelShader);
2912 
2913 		Direct3DPixelShader9 *pixelShader = static_cast<Direct3DPixelShader9*>(iPixelShader);
2914 
2915 		if(!stateRecorder)
2916 		{
2917 			if(this->pixelShader == pixelShader)
2918 			{
2919 				return D3D_OK;
2920 			}
2921 
2922 			if(pixelShader)
2923 			{
2924 				pixelShader->bind();
2925 			}
2926 
2927 			if(this->pixelShader)
2928 			{
2929 				this->pixelShader->unbind();
2930 			}
2931 
2932 			this->pixelShader = pixelShader;
2933 			pixelShaderDirty = true;
2934 		}
2935 		else
2936 		{
2937 			stateRecorder->setPixelShader(pixelShader);
2938 		}
2939 
2940 		return D3D_OK;
2941 	}
2942 
SetPixelShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)2943 	long Direct3DDevice9::SetPixelShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
2944 	{
2945 		CriticalSection cs(this);
2946 
2947 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2948 
2949 		if(!stateRecorder)
2950 		{
2951 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
2952 			{
2953 				pixelShaderConstantB[startRegister + i] = constantData[i];
2954 			}
2955 
2956 			pixelShaderConstantsBDirty = sw::max(startRegister + count, pixelShaderConstantsBDirty);
2957 			pixelShaderDirty = true;   // Reload DEF constants
2958 		}
2959 		else
2960 		{
2961 			stateRecorder->setPixelShaderConstantB(startRegister, constantData, count);
2962 		}
2963 
2964 		return D3D_OK;
2965 	}
2966 
SetPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)2967 	long Direct3DDevice9::SetPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
2968 	{
2969 		CriticalSection cs(this);
2970 
2971 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2972 
2973 		if(!stateRecorder)
2974 		{
2975 			for(unsigned int i = 0; i < count && startRegister + i < MAX_PIXEL_SHADER_CONST; i++)
2976 			{
2977 				pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
2978 				pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
2979 				pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
2980 				pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
2981 			}
2982 
2983 			pixelShaderConstantsFDirty = sw::max(startRegister + count, pixelShaderConstantsFDirty);
2984 			pixelShaderDirty = true;   // Reload DEF constants
2985 		}
2986 		else
2987 		{
2988 			stateRecorder->setPixelShaderConstantF(startRegister, constantData, count);
2989 		}
2990 
2991 		return D3D_OK;
2992 	}
2993 
SetPixelShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)2994 	long Direct3DDevice9::SetPixelShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
2995 	{
2996 		CriticalSection cs(this);
2997 
2998 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2999 
3000 		if(!stateRecorder)
3001 		{
3002 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
3003 			{
3004 				pixelShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
3005 				pixelShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
3006 				pixelShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
3007 				pixelShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
3008 			}
3009 
3010 			pixelShaderConstantsIDirty = sw::max(startRegister + count, pixelShaderConstantsIDirty);
3011 			pixelShaderDirty = true;   // Reload DEF constants
3012 		}
3013 		else
3014 		{
3015 			stateRecorder->setPixelShaderConstantI(startRegister, constantData, count);
3016 		}
3017 
3018 		return D3D_OK;
3019 	}
3020 
SetRenderState(D3DRENDERSTATETYPE state,unsigned long value)3021 	long Direct3DDevice9::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value)
3022 	{
3023 		CriticalSection cs(this);
3024 
3025 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value);
3026 
3027 		if(state < D3DRS_ZENABLE || state > D3DRS_BLENDOPALPHA)
3028 		{
3029 			return D3D_OK;   // FIXME: Warning
3030 		}
3031 
3032 		if(!stateRecorder)
3033 		{
3034 			if(!init && renderState[state] == value)
3035 			{
3036 				return D3D_OK;
3037 			}
3038 
3039 			renderState[state] = value;
3040 
3041 			switch(state)
3042 			{
3043 			case D3DRS_ZENABLE:
3044 				switch(value)
3045 				{
3046 				case D3DZB_TRUE:
3047 				case D3DZB_USEW:
3048 					renderer->setDepthBufferEnable(true);
3049 					break;
3050 				case D3DZB_FALSE:
3051 					renderer->setDepthBufferEnable(false);
3052 					break;
3053 				default:
3054 					ASSERT(false);
3055 				}
3056 				break;
3057 			case D3DRS_FILLMODE:
3058 				switch(value)
3059 				{
3060 				case D3DFILL_POINT:
3061 					renderer->setFillMode(sw::FILL_VERTEX);
3062 					break;
3063 				case D3DFILL_WIREFRAME:
3064 					renderer->setFillMode(sw::FILL_WIREFRAME);
3065 					break;
3066 				case D3DFILL_SOLID:
3067 					renderer->setFillMode(sw::FILL_SOLID);
3068 					break;
3069 				default:
3070 					ASSERT(false);
3071 				}
3072 				break;
3073 			case D3DRS_SHADEMODE:
3074 				switch(value)
3075 				{
3076 				case D3DSHADE_FLAT:
3077 					renderer->setShadingMode(sw::SHADING_FLAT);
3078 					break;
3079 				case D3DSHADE_GOURAUD:
3080 					renderer->setShadingMode(sw::SHADING_GOURAUD);
3081 					break;
3082 				case D3DSHADE_PHONG:
3083 					break;
3084 				default:
3085 					ASSERT(false);
3086 				}
3087 				break;
3088 			case D3DRS_ZWRITEENABLE:
3089 				renderer->setDepthWriteEnable(value != FALSE);
3090 				break;
3091 			case D3DRS_ALPHATESTENABLE:
3092 				renderer->setAlphaTestEnable(value != FALSE);
3093 				break;
3094 			case D3DRS_LASTPIXEL:
3095 			//	if(!init) UNIMPLEMENTED();   // FIXME
3096 				break;
3097 			case D3DRS_SRCBLEND:
3098 				switch(value)
3099 				{
3100 				case D3DBLEND_ZERO:
3101 					renderer->setSourceBlendFactor(sw::BLEND_ZERO);
3102 					break;
3103 				case D3DBLEND_ONE:
3104 					renderer->setSourceBlendFactor(sw::BLEND_ONE);
3105 					break;
3106 				case D3DBLEND_SRCCOLOR:
3107 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE);
3108 					break;
3109 				case D3DBLEND_INVSRCCOLOR:
3110 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE);
3111 					break;
3112 				case D3DBLEND_SRCALPHA:
3113 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3114 					break;
3115 				case D3DBLEND_INVSRCALPHA:
3116 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3117 					break;
3118 				case D3DBLEND_DESTALPHA:
3119 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA);
3120 					break;
3121 				case D3DBLEND_INVDESTALPHA:
3122 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA);
3123 					break;
3124 				case D3DBLEND_DESTCOLOR:
3125 					renderer->setSourceBlendFactor(sw::BLEND_DEST);
3126 					break;
3127 				case D3DBLEND_INVDESTCOLOR:
3128 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST);
3129 					break;
3130 				case D3DBLEND_SRCALPHASAT:
3131 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT);
3132 					break;
3133 				case D3DBLEND_BOTHSRCALPHA:
3134 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3135 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3136 					break;
3137 				case D3DBLEND_BOTHINVSRCALPHA:
3138 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3139 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3140 					break;
3141 				case D3DBLEND_BLENDFACTOR:
3142 					renderer->setSourceBlendFactor(sw::BLEND_CONSTANT);
3143 					break;
3144 				case D3DBLEND_INVBLENDFACTOR:
3145 					renderer->setSourceBlendFactor(sw::BLEND_INVCONSTANT);
3146 					break;
3147 				default:
3148 					ASSERT(false);
3149 				}
3150 				break;
3151 			case D3DRS_DESTBLEND:
3152 				switch(value)
3153 				{
3154 				case D3DBLEND_ZERO:
3155 					renderer->setDestBlendFactor(sw::BLEND_ZERO);
3156 					break;
3157 				case D3DBLEND_ONE:
3158 					renderer->setDestBlendFactor(sw::BLEND_ONE);
3159 					break;
3160 				case D3DBLEND_SRCCOLOR:
3161 					renderer->setDestBlendFactor(sw::BLEND_SOURCE);
3162 					break;
3163 				case D3DBLEND_INVSRCCOLOR:
3164 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE);
3165 					break;
3166 				case D3DBLEND_SRCALPHA:
3167 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3168 					break;
3169 				case D3DBLEND_INVSRCALPHA:
3170 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3171 					break;
3172 				case D3DBLEND_DESTALPHA:
3173 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA);
3174 					break;
3175 				case D3DBLEND_INVDESTALPHA:
3176 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA);
3177 					break;
3178 				case D3DBLEND_DESTCOLOR:
3179 					renderer->setDestBlendFactor(sw::BLEND_DEST);
3180 					break;
3181 				case D3DBLEND_INVDESTCOLOR:
3182 					renderer->setDestBlendFactor(sw::BLEND_INVDEST);
3183 					break;
3184 				case D3DBLEND_SRCALPHASAT:
3185 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT);
3186 					break;
3187 				case D3DBLEND_BOTHSRCALPHA:
3188 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3189 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3190 					break;
3191 				case D3DBLEND_BOTHINVSRCALPHA:
3192 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3193 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3194 					break;
3195 				case D3DBLEND_BLENDFACTOR:
3196 					renderer->setDestBlendFactor(sw::BLEND_CONSTANT);
3197 					break;
3198 				case D3DBLEND_INVBLENDFACTOR:
3199 					renderer->setDestBlendFactor(sw::BLEND_INVCONSTANT);
3200 					break;
3201 				default:
3202 					ASSERT(false);
3203 				}
3204 				break;
3205 			case D3DRS_CULLMODE:
3206 				switch(value)
3207 				{
3208 				case D3DCULL_NONE:
3209 					renderer->setCullMode(sw::CULL_NONE);
3210 					break;
3211 				case D3DCULL_CCW:
3212 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE);
3213 					break;
3214 				case D3DCULL_CW:
3215 					renderer->setCullMode(sw::CULL_CLOCKWISE);
3216 					break;
3217 				default:
3218 					ASSERT(false);
3219 				}
3220 				break;
3221 			case D3DRS_ZFUNC:
3222 				switch(value)
3223 				{
3224 				case D3DCMP_NEVER:
3225 					renderer->setDepthCompare(sw::DEPTH_NEVER);
3226 					break;
3227 				case D3DCMP_LESS:
3228 					renderer->setDepthCompare(sw::DEPTH_LESS);
3229 					break;
3230 				case D3DCMP_EQUAL:
3231 					renderer->setDepthCompare(sw::DEPTH_EQUAL);
3232 					break;
3233 				case D3DCMP_LESSEQUAL:
3234 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL);
3235 					break;
3236 				case D3DCMP_GREATER:
3237 					renderer->setDepthCompare(sw::DEPTH_GREATER);
3238 					break;
3239 				case D3DCMP_NOTEQUAL:
3240 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL);
3241 					break;
3242 				case D3DCMP_GREATEREQUAL:
3243 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL);
3244 					break;
3245 				case D3DCMP_ALWAYS:
3246 					renderer->setDepthCompare(sw::DEPTH_ALWAYS);
3247 					break;
3248 				default:
3249 					ASSERT(false);
3250 				}
3251 				break;
3252 			case D3DRS_ALPHAREF:
3253 				renderer->setAlphaReference(value & 0x000000FF);
3254 				break;
3255 			case D3DRS_ALPHAFUNC:
3256 				switch(value)
3257 				{
3258 				case D3DCMP_NEVER:
3259 					renderer->setAlphaCompare(sw::ALPHA_NEVER);
3260 					break;
3261 				case D3DCMP_LESS:
3262 					renderer->setAlphaCompare(sw::ALPHA_LESS);
3263 					break;
3264 				case D3DCMP_EQUAL:
3265 					renderer->setAlphaCompare(sw::ALPHA_EQUAL);
3266 					break;
3267 				case D3DCMP_LESSEQUAL:
3268 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL);
3269 					break;
3270 				case D3DCMP_GREATER:
3271 					renderer->setAlphaCompare(sw::ALPHA_GREATER);
3272 					break;
3273 				case D3DCMP_NOTEQUAL:
3274 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL);
3275 					break;
3276 				case D3DCMP_GREATEREQUAL:
3277 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL);
3278 					break;
3279 				case D3DCMP_ALWAYS:
3280 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS);
3281 					break;
3282 				default:
3283 					ASSERT(false);
3284 				}
3285 				break;
3286 			case D3DRS_DITHERENABLE:
3287 			//	if(!init) UNIMPLEMENTED();
3288 				break;
3289 			case D3DRS_ALPHABLENDENABLE:
3290 				renderer->setAlphaBlendEnable(value != FALSE);
3291 				break;
3292 			case D3DRS_FOGENABLE:
3293 				renderer->setFogEnable(value != FALSE);
3294 				break;
3295 			case D3DRS_FOGCOLOR:
3296 				renderer->setFogColor(value);
3297 				break;
3298 			case D3DRS_FOGTABLEMODE:
3299 				switch(value)
3300 				{
3301 				case D3DFOG_NONE:
3302 					renderer->setPixelFogMode(sw::FOG_NONE);
3303 					break;
3304 				case D3DFOG_LINEAR:
3305 					renderer->setPixelFogMode(sw::FOG_LINEAR);
3306 					break;
3307 				case D3DFOG_EXP:
3308 					renderer->setPixelFogMode(sw::FOG_EXP);
3309 					break;
3310 				case D3DFOG_EXP2:
3311 					renderer->setPixelFogMode(sw::FOG_EXP2);
3312 					break;
3313 				default:
3314 					ASSERT(false);
3315 				}
3316 				break;
3317 			case D3DRS_FOGSTART:
3318 				renderer->setFogStart((float&)value);
3319 				break;
3320 			case D3DRS_FOGEND:
3321 				renderer->setFogEnd((float&)value);
3322 				break;
3323 			case D3DRS_FOGDENSITY:
3324 				renderer->setFogDensity((float&)value);
3325 				break;
3326 			case D3DRS_RANGEFOGENABLE:
3327 				renderer->setRangeFogEnable(value != FALSE);
3328 				break;
3329 			case D3DRS_SPECULARENABLE:
3330 				renderer->setSpecularEnable(value != FALSE);
3331 				break;
3332 			case D3DRS_STENCILENABLE:
3333 				renderer->setStencilEnable(value != FALSE);
3334 				break;
3335 			case D3DRS_STENCILFAIL:
3336 				switch(value)
3337 				{
3338 				case D3DSTENCILOP_KEEP:
3339 					renderer->setStencilFailOperation(sw::OPERATION_KEEP);
3340 					break;
3341 				case D3DSTENCILOP_ZERO:
3342 					renderer->setStencilFailOperation(sw::OPERATION_ZERO);
3343 					break;
3344 				case D3DSTENCILOP_REPLACE:
3345 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE);
3346 					break;
3347 				case D3DSTENCILOP_INCRSAT:
3348 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT);
3349 					break;
3350 				case D3DSTENCILOP_DECRSAT:
3351 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT);
3352 					break;
3353 				case D3DSTENCILOP_INVERT:
3354 					renderer->setStencilFailOperation(sw::OPERATION_INVERT);
3355 					break;
3356 				case D3DSTENCILOP_INCR:
3357 					renderer->setStencilFailOperation(sw::OPERATION_INCR);
3358 					break;
3359 				case D3DSTENCILOP_DECR:
3360 					renderer->setStencilFailOperation(sw::OPERATION_DECR);
3361 					break;
3362 				default:
3363 					ASSERT(false);
3364 				}
3365 				break;
3366 			case D3DRS_STENCILZFAIL:
3367 				switch(value)
3368 				{
3369 				case D3DSTENCILOP_KEEP:
3370 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP);
3371 					break;
3372 				case D3DSTENCILOP_ZERO:
3373 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO);
3374 					break;
3375 				case D3DSTENCILOP_REPLACE:
3376 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE);
3377 					break;
3378 				case D3DSTENCILOP_INCRSAT:
3379 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT);
3380 					break;
3381 				case D3DSTENCILOP_DECRSAT:
3382 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT);
3383 					break;
3384 				case D3DSTENCILOP_INVERT:
3385 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT);
3386 					break;
3387 				case D3DSTENCILOP_INCR:
3388 					renderer->setStencilZFailOperation(sw::OPERATION_INCR);
3389 					break;
3390 				case D3DSTENCILOP_DECR:
3391 					renderer->setStencilZFailOperation(sw::OPERATION_DECR);
3392 					break;
3393 				default:
3394 					ASSERT(false);
3395 				}
3396 				break;
3397 			case D3DRS_STENCILPASS:
3398 				switch(value)
3399 				{
3400 				case D3DSTENCILOP_KEEP:
3401 					renderer->setStencilPassOperation(sw::OPERATION_KEEP);
3402 					break;
3403 				case D3DSTENCILOP_ZERO:
3404 					renderer->setStencilPassOperation(sw::OPERATION_ZERO);
3405 					break;
3406 				case D3DSTENCILOP_REPLACE:
3407 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE);
3408 					break;
3409 				case D3DSTENCILOP_INCRSAT:
3410 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT);
3411 					break;
3412 				case D3DSTENCILOP_DECRSAT:
3413 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT);
3414 					break;
3415 				case D3DSTENCILOP_INVERT:
3416 					renderer->setStencilPassOperation(sw::OPERATION_INVERT);
3417 					break;
3418 				case D3DSTENCILOP_INCR:
3419 					renderer->setStencilPassOperation(sw::OPERATION_INCR);
3420 					break;
3421 				case D3DSTENCILOP_DECR:
3422 					renderer->setStencilPassOperation(sw::OPERATION_DECR);
3423 					break;
3424 				default:
3425 					ASSERT(false);
3426 				}
3427 				break;
3428 			case D3DRS_STENCILFUNC:
3429 				switch(value)
3430 				{
3431 				case D3DCMP_NEVER:
3432 					renderer->setStencilCompare(sw::STENCIL_NEVER);
3433 					break;
3434 				case D3DCMP_LESS:
3435 					renderer->setStencilCompare(sw::STENCIL_LESS);
3436 					break;
3437 				case D3DCMP_EQUAL:
3438 					renderer->setStencilCompare(sw::STENCIL_EQUAL);
3439 					break;
3440 				case D3DCMP_LESSEQUAL:
3441 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL);
3442 					break;
3443 				case D3DCMP_GREATER:
3444 					renderer->setStencilCompare(sw::STENCIL_GREATER);
3445 					break;
3446 				case D3DCMP_NOTEQUAL:
3447 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL);
3448 					break;
3449 				case D3DCMP_GREATEREQUAL:
3450 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL);
3451 					break;
3452 				case D3DCMP_ALWAYS:
3453 					renderer->setStencilCompare(sw::STENCIL_ALWAYS);
3454 					break;
3455 				default:
3456 					ASSERT(false);
3457 				}
3458 				break;
3459 			case D3DRS_STENCILREF:
3460 				renderer->setStencilReference(value);
3461 				renderer->setStencilReferenceCCW(value);
3462 				break;
3463 			case D3DRS_STENCILMASK:
3464 				renderer->setStencilMask(value);
3465 				renderer->setStencilMaskCCW(value);
3466 				break;
3467 			case D3DRS_STENCILWRITEMASK:
3468 				renderer->setStencilWriteMask(value);
3469 				renderer->setStencilWriteMaskCCW(value);
3470 				break;
3471 			case D3DRS_TEXTUREFACTOR:
3472 				renderer->setTextureFactor(value);
3473 				break;
3474 			case D3DRS_WRAP0:
3475 				renderer->setTextureWrap(0, value);
3476 				break;
3477 			case D3DRS_WRAP1:
3478 				renderer->setTextureWrap(1, value);
3479 				break;
3480 			case D3DRS_WRAP2:
3481 				renderer->setTextureWrap(2, value);
3482 				break;
3483 			case D3DRS_WRAP3:
3484 				renderer->setTextureWrap(3, value);
3485 				break;
3486 			case D3DRS_WRAP4:
3487 				renderer->setTextureWrap(4, value);
3488 				break;
3489 			case D3DRS_WRAP5:
3490 				renderer->setTextureWrap(5, value);
3491 				break;
3492 			case D3DRS_WRAP6:
3493 				renderer->setTextureWrap(6, value);
3494 				break;
3495 			case D3DRS_WRAP7:
3496 				renderer->setTextureWrap(7, value);
3497 				break;
3498 			case D3DRS_CLIPPING:
3499 				// Ignored, clipping is always performed
3500 				break;
3501 			case D3DRS_LIGHTING:
3502 				renderer->setLightingEnable(value != FALSE);
3503 				break;
3504 			case D3DRS_AMBIENT:
3505 				renderer->setGlobalAmbient(value);
3506 				break;
3507 			case D3DRS_FOGVERTEXMODE:
3508 				switch(value)
3509 				{
3510 				case D3DFOG_NONE:
3511 					renderer->setVertexFogMode(sw::FOG_NONE);
3512 					break;
3513 				case D3DFOG_LINEAR:
3514 					renderer->setVertexFogMode(sw::FOG_LINEAR);
3515 					break;
3516 				case D3DFOG_EXP:
3517 					renderer->setVertexFogMode(sw::FOG_EXP);
3518 					break;
3519 				case D3DFOG_EXP2:
3520 					renderer->setVertexFogMode(sw::FOG_EXP2);
3521 					break;
3522 				default:
3523 					ASSERT(false);
3524 				}
3525 				break;
3526 			case D3DRS_COLORVERTEX:
3527 				renderer->setColorVertexEnable(value != FALSE);
3528 				break;
3529 			case D3DRS_LOCALVIEWER:
3530 				renderer->setLocalViewer(value != FALSE);
3531 				break;
3532 			case D3DRS_NORMALIZENORMALS:
3533 				renderer->setNormalizeNormals(value != FALSE);
3534 				break;
3535 			case D3DRS_DIFFUSEMATERIALSOURCE:
3536 				switch(value)
3537 				{
3538 				case D3DMCS_MATERIAL:
3539 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);
3540 					break;
3541 				case D3DMCS_COLOR1:
3542 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
3543 					break;
3544 				case D3DMCS_COLOR2:
3545 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2);
3546 					break;
3547 				default:
3548 					ASSERT(false);
3549 				}
3550 				break;
3551 			case D3DRS_SPECULARMATERIALSOURCE:
3552 				switch(value)
3553 				{
3554 				case D3DMCS_MATERIAL:
3555 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
3556 					break;
3557 				case D3DMCS_COLOR1:
3558 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1);
3559 					break;
3560 				case D3DMCS_COLOR2:
3561 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2);
3562 					break;
3563 				default:
3564 					ASSERT(false);
3565 				}
3566 				break;
3567 			case D3DRS_AMBIENTMATERIALSOURCE:
3568 				switch(value)
3569 				{
3570 				case D3DMCS_MATERIAL:
3571 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
3572 					break;
3573 				case D3DMCS_COLOR1:
3574 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1);
3575 					break;
3576 				case D3DMCS_COLOR2:
3577 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2);
3578 					break;
3579 				default:
3580 					ASSERT(false);
3581 				}
3582 				break;
3583 			case D3DRS_EMISSIVEMATERIALSOURCE:
3584 				switch(value)
3585 				{
3586 				case D3DMCS_MATERIAL:
3587 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
3588 					break;
3589 				case D3DMCS_COLOR1:
3590 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1);
3591 					break;
3592 				case D3DMCS_COLOR2:
3593 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2);
3594 					break;
3595 				default:
3596 					ASSERT(false);
3597 				}
3598 				break;
3599 			case D3DRS_VERTEXBLEND:
3600 				switch(value)
3601 				{
3602 				case D3DVBF_DISABLE:
3603 					renderer->setVertexBlendMatrixCount(0);
3604 					break;
3605 				case D3DVBF_1WEIGHTS:
3606 					renderer->setVertexBlendMatrixCount(2);
3607 					break;
3608 				case D3DVBF_2WEIGHTS:
3609 					renderer->setVertexBlendMatrixCount(3);
3610 					break;
3611 				case D3DVBF_3WEIGHTS:
3612 					renderer->setVertexBlendMatrixCount(4);
3613 					break;
3614 				case D3DVBF_TWEENING:
3615 					UNIMPLEMENTED();
3616 					break;
3617 				case D3DVBF_0WEIGHTS:
3618 					renderer->setVertexBlendMatrixCount(1);
3619 					break;
3620 				default:
3621 					ASSERT(false);
3622 				}
3623 				break;
3624 			case D3DRS_CLIPPLANEENABLE:
3625 				renderer->setClipFlags(value);
3626 				break;
3627 			case D3DRS_POINTSIZE:
3628 				if(value == D3DFMT_INST && pixelShaderVersionX >= D3DPS_VERSION(2, 0))   // ATI hack to enable instancing on SM 2.0 hardware
3629 				{
3630 					instancingEnabled = true;
3631 				}
3632 				else if(value == D3DFMT_A2M1)   // ATI hack to enable transparency anti-aliasing
3633 				{
3634 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3635 					renderer->setAlphaTestEnable(true);
3636 				}
3637 				else if(value == D3DFMT_A2M0)   // ATI hack to disable transparency anti-aliasing
3638 				{
3639 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3640 					renderer->setAlphaTestEnable(false);
3641 				}
3642 				else
3643 				{
3644 					renderer->setPointSize((float&)value);
3645 				}
3646 				break;
3647 			case D3DRS_POINTSIZE_MIN:
3648 				renderer->setPointSizeMin((float&)value);
3649 				break;
3650 			case D3DRS_POINTSPRITEENABLE:
3651 				renderer->setPointSpriteEnable(value != FALSE);
3652 				break;
3653 			case D3DRS_POINTSCALEENABLE:
3654 				renderer->setPointScaleEnable(value != FALSE);
3655 				break;
3656 			case D3DRS_POINTSCALE_A:
3657 				renderer->setPointScaleA((float&)value);
3658 				break;
3659 			case D3DRS_POINTSCALE_B:
3660 				renderer->setPointScaleB((float&)value);
3661 				break;
3662 			case D3DRS_POINTSCALE_C:
3663 				renderer->setPointScaleC((float&)value);
3664 				break;
3665 			case D3DRS_MULTISAMPLEANTIALIAS:
3666 			//	if(!init) UNIMPLEMENTED();
3667 				break;
3668 			case D3DRS_MULTISAMPLEMASK:
3669 				SetRenderTarget(0, renderTarget[0]);   // Sets the multi-sample mask, if maskable
3670 				break;
3671 			case D3DRS_PATCHEDGESTYLE:
3672 				if(!init) if(value != D3DPATCHEDGE_DISCRETE) UNIMPLEMENTED();
3673 				break;
3674 			case D3DRS_DEBUGMONITORTOKEN:
3675 				if(!init) UNIMPLEMENTED();
3676 				break;
3677 			case D3DRS_POINTSIZE_MAX:
3678 				renderer->setPointSizeMax((float&)value);
3679 				break;
3680 			case D3DRS_INDEXEDVERTEXBLENDENABLE:
3681 				renderer->setIndexedVertexBlendEnable(value != FALSE);
3682 				break;
3683 			case D3DRS_COLORWRITEENABLE:
3684 				renderer->setColorWriteMask(0, value & 0x0000000F);
3685 				break;
3686 			case D3DRS_TWEENFACTOR:
3687 				if(!init) UNIMPLEMENTED();
3688 				break;
3689 			case D3DRS_BLENDOP:
3690 				switch(value)
3691 				{
3692 				case D3DBLENDOP_ADD:
3693 					renderer->setBlendOperation(sw::BLENDOP_ADD);
3694 					break;
3695 				case D3DBLENDOP_SUBTRACT:
3696 					renderer->setBlendOperation(sw::BLENDOP_SUB);
3697 					break;
3698 				case D3DBLENDOP_REVSUBTRACT:
3699 					renderer->setBlendOperation(sw::BLENDOP_INVSUB);
3700 					break;
3701 				case D3DBLENDOP_MIN:
3702 					renderer->setBlendOperation(sw::BLENDOP_MIN);
3703 					break;
3704 				case D3DBLENDOP_MAX:
3705 					renderer->setBlendOperation(sw::BLENDOP_MAX);
3706 					break;
3707 				default:
3708 					ASSERT(false);
3709 				}
3710 				break;
3711 			case D3DRS_POSITIONDEGREE:
3712 				if(!init) UNIMPLEMENTED();
3713 				break;
3714 			case D3DRS_NORMALDEGREE:
3715 				if(!init) UNIMPLEMENTED();
3716 				break;
3717 			case D3DRS_SCISSORTESTENABLE:
3718 				scissorEnable = (value != FALSE);
3719 				break;
3720 			case D3DRS_SLOPESCALEDEPTHBIAS:
3721 				renderer->setSlopeDepthBias((float&)value);
3722 				break;
3723 			case D3DRS_ANTIALIASEDLINEENABLE:
3724 				if(!init) if(value != FALSE) UNIMPLEMENTED();
3725 				break;
3726 			case D3DRS_MINTESSELLATIONLEVEL:
3727 				if(!init) UNIMPLEMENTED();
3728 				break;
3729 			case D3DRS_MAXTESSELLATIONLEVEL:
3730 				if(!init) UNIMPLEMENTED();
3731 				break;
3732 			case D3DRS_ADAPTIVETESS_X:
3733 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3734 				break;
3735 			case D3DRS_ADAPTIVETESS_Y:
3736 				if(value == D3DFMT_ATOC)   // NVIDIA hack to enable transparency anti-aliasing
3737 				{
3738 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3739 				}
3740 				else if(value == D3DFMT_UNKNOWN)   // NVIDIA hack to disable transparency anti-aliasing
3741 				{
3742 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3743 				}
3744 				else
3745 				{
3746 					if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3747 				}
3748 				break;
3749 			case D3DRS_ADAPTIVETESS_Z:
3750 				if(!init) if((float&)value != 1.0f) UNIMPLEMENTED();
3751 				break;
3752 			case D3DRS_ADAPTIVETESS_W:
3753 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3754 				break;
3755 			case D3DRS_ENABLEADAPTIVETESSELLATION:
3756 				if(!init) UNIMPLEMENTED();
3757 				break;
3758 			case D3DRS_TWOSIDEDSTENCILMODE:
3759 				renderer->setTwoSidedStencil(value != FALSE);
3760 				break;
3761 			case D3DRS_CCW_STENCILFAIL:
3762 				switch(value)
3763 				{
3764 				case D3DSTENCILOP_KEEP:
3765 					renderer->setStencilFailOperationCCW(sw::OPERATION_KEEP);
3766 					break;
3767 				case D3DSTENCILOP_ZERO:
3768 					renderer->setStencilFailOperationCCW(sw::OPERATION_ZERO);
3769 					break;
3770 				case D3DSTENCILOP_REPLACE:
3771 					renderer->setStencilFailOperationCCW(sw::OPERATION_REPLACE);
3772 					break;
3773 				case D3DSTENCILOP_INCRSAT:
3774 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCRSAT);
3775 					break;
3776 				case D3DSTENCILOP_DECRSAT:
3777 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECRSAT);
3778 					break;
3779 				case D3DSTENCILOP_INVERT:
3780 					renderer->setStencilFailOperationCCW(sw::OPERATION_INVERT);
3781 					break;
3782 				case D3DSTENCILOP_INCR:
3783 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCR);
3784 					break;
3785 				case D3DSTENCILOP_DECR:
3786 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECR);
3787 					break;
3788 				default:
3789 					ASSERT(false);
3790 				}
3791 				break;
3792 			case D3DRS_CCW_STENCILZFAIL:
3793 				switch(value)
3794 				{
3795 				case D3DSTENCILOP_KEEP:
3796 					renderer->setStencilZFailOperationCCW(sw::OPERATION_KEEP);
3797 					break;
3798 				case D3DSTENCILOP_ZERO:
3799 					renderer->setStencilZFailOperationCCW(sw::OPERATION_ZERO);
3800 					break;
3801 				case D3DSTENCILOP_REPLACE:
3802 					renderer->setStencilZFailOperationCCW(sw::OPERATION_REPLACE);
3803 					break;
3804 				case D3DSTENCILOP_INCRSAT:
3805 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCRSAT);
3806 					break;
3807 				case D3DSTENCILOP_DECRSAT:
3808 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECRSAT);
3809 					break;
3810 				case D3DSTENCILOP_INVERT:
3811 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INVERT);
3812 					break;
3813 				case D3DSTENCILOP_INCR:
3814 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCR);
3815 					break;
3816 				case D3DSTENCILOP_DECR:
3817 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECR);
3818 					break;
3819 				default:
3820 					ASSERT(false);
3821 				}
3822 				break;
3823 			case D3DRS_CCW_STENCILPASS:
3824 				switch(value)
3825 				{
3826 				case D3DSTENCILOP_KEEP:
3827 					renderer->setStencilPassOperationCCW(sw::OPERATION_KEEP);
3828 					break;
3829 				case D3DSTENCILOP_ZERO:
3830 					renderer->setStencilPassOperationCCW(sw::OPERATION_ZERO);
3831 					break;
3832 				case D3DSTENCILOP_REPLACE:
3833 					renderer->setStencilPassOperationCCW(sw::OPERATION_REPLACE);
3834 					break;
3835 				case D3DSTENCILOP_INCRSAT:
3836 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCRSAT);
3837 					break;
3838 				case D3DSTENCILOP_DECRSAT:
3839 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECRSAT);
3840 					break;
3841 				case D3DSTENCILOP_INVERT:
3842 					renderer->setStencilPassOperationCCW(sw::OPERATION_INVERT);
3843 					break;
3844 				case D3DSTENCILOP_INCR:
3845 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCR);
3846 					break;
3847 				case D3DSTENCILOP_DECR:
3848 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECR);
3849 					break;
3850 				default:
3851 					ASSERT(false);
3852 				}
3853 				break;
3854 			case D3DRS_CCW_STENCILFUNC:
3855 				switch(value)
3856 				{
3857 				case D3DCMP_NEVER:
3858 					renderer->setStencilCompareCCW(sw::STENCIL_NEVER);
3859 					break;
3860 				case D3DCMP_LESS:
3861 					renderer->setStencilCompareCCW(sw::STENCIL_LESS);
3862 					break;
3863 				case D3DCMP_EQUAL:
3864 					renderer->setStencilCompareCCW(sw::STENCIL_EQUAL);
3865 					break;
3866 				case D3DCMP_LESSEQUAL:
3867 					renderer->setStencilCompareCCW(sw::STENCIL_LESSEQUAL);
3868 					break;
3869 				case D3DCMP_GREATER:
3870 					renderer->setStencilCompareCCW(sw::STENCIL_GREATER);
3871 					break;
3872 				case D3DCMP_NOTEQUAL:
3873 					renderer->setStencilCompareCCW(sw::STENCIL_NOTEQUAL);
3874 					break;
3875 				case D3DCMP_GREATEREQUAL:
3876 					renderer->setStencilCompareCCW(sw::STENCIL_GREATEREQUAL);
3877 					break;
3878 				case D3DCMP_ALWAYS:
3879 					renderer->setStencilCompareCCW(sw::STENCIL_ALWAYS);
3880 					break;
3881 				default:
3882 					ASSERT(false);
3883 				}
3884 				break;
3885 			case D3DRS_COLORWRITEENABLE1:
3886 				renderer->setColorWriteMask(1, value);
3887 				break;
3888 			case D3DRS_COLORWRITEENABLE2:
3889 				renderer->setColorWriteMask(2, value);
3890 				break;
3891 			case D3DRS_COLORWRITEENABLE3:
3892 				renderer->setColorWriteMask(3, value);
3893 				break;
3894 			case D3DRS_BLENDFACTOR:
3895 				renderer->setBlendConstant(sw::Color<float>(value));
3896 				break;
3897 			case D3DRS_SRGBWRITEENABLE:
3898 				renderer->setWriteSRGB(value != FALSE);
3899 				break;
3900 			case D3DRS_DEPTHBIAS:
3901 				renderer->setDepthBias((float&)value);
3902 				break;
3903 			case D3DRS_WRAP8:
3904 				renderer->setTextureWrap(8, value);
3905 				break;
3906 			case D3DRS_WRAP9:
3907 				renderer->setTextureWrap(9, value);
3908 				break;
3909 			case D3DRS_WRAP10:
3910 				renderer->setTextureWrap(10, value);
3911 				break;
3912 			case D3DRS_WRAP11:
3913 				renderer->setTextureWrap(11, value);
3914 				break;
3915 			case D3DRS_WRAP12:
3916 				renderer->setTextureWrap(12, value);
3917 				break;
3918 			case D3DRS_WRAP13:
3919 				renderer->setTextureWrap(13, value);
3920 				break;
3921 			case D3DRS_WRAP14:
3922 				renderer->setTextureWrap(14, value);
3923 				break;
3924 			case D3DRS_WRAP15:
3925 				renderer->setTextureWrap(15, value);
3926 				break;
3927 			case D3DRS_SEPARATEALPHABLENDENABLE:
3928 				renderer->setSeparateAlphaBlendEnable(value != FALSE);
3929 				break;
3930 			case D3DRS_SRCBLENDALPHA:
3931 				switch(value)
3932 				{
3933 				case D3DBLEND_ZERO:
3934 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ZERO);
3935 					break;
3936 				case D3DBLEND_ONE:
3937 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ONE);
3938 					break;
3939 				case D3DBLEND_SRCCOLOR:
3940 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCE);
3941 					break;
3942 				case D3DBLEND_INVSRCCOLOR:
3943 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCE);
3944 					break;
3945 				case D3DBLEND_SRCALPHA:
3946 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3947 					break;
3948 				case D3DBLEND_INVSRCALPHA:
3949 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3950 					break;
3951 				case D3DBLEND_DESTALPHA:
3952 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DESTALPHA);
3953 					break;
3954 				case D3DBLEND_INVDESTALPHA:
3955 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
3956 					break;
3957 				case D3DBLEND_DESTCOLOR:
3958 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DEST);
3959 					break;
3960 				case D3DBLEND_INVDESTCOLOR:
3961 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDEST);
3962 					break;
3963 				case D3DBLEND_SRCALPHASAT:
3964 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
3965 					break;
3966 				case D3DBLEND_BOTHSRCALPHA:
3967 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3968 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3969 					break;
3970 				case D3DBLEND_BOTHINVSRCALPHA:
3971 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3972 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3973 					break;
3974 				case D3DBLEND_BLENDFACTOR:
3975 					renderer->setSourceBlendFactorAlpha(sw::BLEND_CONSTANT);
3976 					break;
3977 				case D3DBLEND_INVBLENDFACTOR:
3978 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVCONSTANT);
3979 					break;
3980 				default:
3981 					ASSERT(false);
3982 				}
3983 				break;
3984 			case D3DRS_DESTBLENDALPHA:
3985 				switch(value)
3986 				{
3987 				case D3DBLEND_ZERO:
3988 					renderer->setDestBlendFactorAlpha(sw::BLEND_ZERO);
3989 					break;
3990 				case D3DBLEND_ONE:
3991 					renderer->setDestBlendFactorAlpha(sw::BLEND_ONE);
3992 					break;
3993 				case D3DBLEND_SRCCOLOR:
3994 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCE);
3995 					break;
3996 				case D3DBLEND_INVSRCCOLOR:
3997 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCE);
3998 					break;
3999 				case D3DBLEND_SRCALPHA:
4000 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4001 					break;
4002 				case D3DBLEND_INVSRCALPHA:
4003 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4004 					break;
4005 				case D3DBLEND_DESTALPHA:
4006 					renderer->setDestBlendFactorAlpha(sw::BLEND_DESTALPHA);
4007 					break;
4008 				case D3DBLEND_INVDESTALPHA:
4009 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
4010 					break;
4011 				case D3DBLEND_DESTCOLOR:
4012 					renderer->setDestBlendFactorAlpha(sw::BLEND_DEST);
4013 					break;
4014 				case D3DBLEND_INVDESTCOLOR:
4015 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDEST);
4016 					break;
4017 				case D3DBLEND_SRCALPHASAT:
4018 					renderer->setDestBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
4019 					break;
4020 				case D3DBLEND_BOTHSRCALPHA:
4021 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4022 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4023 					break;
4024 				case D3DBLEND_BOTHINVSRCALPHA:
4025 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4026 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4027 					break;
4028 				case D3DBLEND_BLENDFACTOR:
4029 					renderer->setDestBlendFactorAlpha(sw::BLEND_CONSTANT);
4030 					break;
4031 				case D3DBLEND_INVBLENDFACTOR:
4032 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVCONSTANT);
4033 					break;
4034 				default:
4035 					ASSERT(false);
4036 				}
4037 				break;
4038 			case D3DRS_BLENDOPALPHA:
4039 				switch(value)
4040 				{
4041 				case D3DBLENDOP_ADD:
4042 					renderer->setBlendOperationAlpha(sw::BLENDOP_ADD);
4043 					break;
4044 				case D3DBLENDOP_SUBTRACT:
4045 					renderer->setBlendOperationAlpha(sw::BLENDOP_SUB);
4046 					break;
4047 				case D3DBLENDOP_REVSUBTRACT:
4048 					renderer->setBlendOperationAlpha(sw::BLENDOP_INVSUB);
4049 					break;
4050 				case D3DBLENDOP_MIN:
4051 					renderer->setBlendOperationAlpha(sw::BLENDOP_MIN);
4052 					break;
4053 				case D3DBLENDOP_MAX:
4054 					renderer->setBlendOperationAlpha(sw::BLENDOP_MAX);
4055 					break;
4056 				default:
4057 					ASSERT(false);
4058 				}
4059 				break;
4060 			default:
4061 				ASSERT(false);
4062 			}
4063 		}
4064 		else   // stateRecorder
4065 		{
4066 			stateRecorder->setRenderState(state, value);
4067 		}
4068 
4069 		return D3D_OK;
4070 	}
4071 
SetRenderTarget(unsigned long index,IDirect3DSurface9 * iRenderTarget)4072 	long Direct3DDevice9::SetRenderTarget(unsigned long index, IDirect3DSurface9 *iRenderTarget)
4073 	{
4074 		CriticalSection cs(this);
4075 
4076 		TRACE("unsigned long index = %d, IDirect3DSurface9 *newRenderTarget = 0x%0.8p", index, iRenderTarget);
4077 
4078 		// FIXME: Check for D3DUSAGE_RENDERTARGET
4079 
4080 		if(index >= 4 || (index == 0 && !iRenderTarget))
4081 		{
4082 			return INVALIDCALL();
4083 		}
4084 
4085 		Direct3DSurface9 *renderTarget = static_cast<Direct3DSurface9*>(iRenderTarget);
4086 
4087 		if(renderTarget)
4088 		{
4089 			renderTarget->bind();
4090 		}
4091 
4092 		if(this->renderTarget[index])
4093 		{
4094 			this->renderTarget[index]->unbind();
4095 		}
4096 
4097 		this->renderTarget[index] = renderTarget;
4098 
4099 		if(renderTarget && index == 0)
4100 		{
4101 			D3DSURFACE_DESC renderTargetDesc;
4102 			renderTarget->GetDesc(&renderTargetDesc);
4103 
4104 			// Reset viewport to size of current render target
4105 			viewport.X = 0;
4106 			viewport.Y = 0;
4107 			viewport.Width = renderTargetDesc.Width;
4108 			viewport.Height = renderTargetDesc.Height;
4109 			viewport.MinZ = 0;
4110 			viewport.MaxZ = 1;
4111 
4112 			// Reset scissor rectangle to size of current render target
4113 			scissorRect.left = 0;
4114 			scissorRect.top = 0;
4115 			scissorRect.right = renderTargetDesc.Width;
4116 			scissorRect.bottom = renderTargetDesc.Height;
4117 
4118 			// Set the multi-sample mask, if maskable
4119 			if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE &&
4120 			   renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONMASKABLE)
4121 			{
4122 				renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]);
4123 			}
4124 			else
4125 			{
4126 				renderer->setMultiSampleMask(0xFFFFFFFF);
4127 			}
4128 		}
4129 
4130 		renderer->setRenderTarget(index, renderTarget);
4131 
4132 		return D3D_OK;
4133 	}
4134 
SetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long value)4135 	long Direct3DDevice9::SetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long value)
4136 	{
4137 		CriticalSection cs(this);
4138 
4139 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE state = %d, unsigned long value = %d", sampler, state, value);
4140 
4141 		if(state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)
4142 		{
4143 			return INVALIDCALL();
4144 		}
4145 
4146 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4147 		{
4148 			return INVALIDCALL();
4149 		}
4150 
4151 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4152 		{
4153 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4154 		}
4155 
4156 		if(!stateRecorder)
4157 		{
4158 			if(!init && samplerState[sampler][state] == value)
4159 			{
4160 				return D3D_OK;
4161 			}
4162 
4163 			samplerState[sampler][state] = value;
4164 
4165 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX;
4166 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group
4167 
4168 			switch(state)
4169 			{
4170 			case D3DSAMP_ADDRESSU:
4171 				switch(value)
4172 				{
4173 				case D3DTADDRESS_WRAP:
4174 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_WRAP);
4175 					break;
4176 				case D3DTADDRESS_MIRROR:
4177 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRROR);
4178 					break;
4179 				case D3DTADDRESS_CLAMP:
4180 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_CLAMP);
4181 					break;
4182 				case D3DTADDRESS_BORDER:
4183 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_BORDER);
4184 					break;
4185 				case D3DTADDRESS_MIRRORONCE:
4186 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRRORONCE);
4187 					break;
4188 				default:
4189 					ASSERT(false);
4190 				}
4191 				break;
4192 			case D3DSAMP_ADDRESSV:
4193 				switch(value)
4194 				{
4195 				case D3DTADDRESS_WRAP:
4196 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_WRAP);
4197 					break;
4198 				case D3DTADDRESS_MIRROR:
4199 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRROR);
4200 					break;
4201 				case D3DTADDRESS_CLAMP:
4202 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_CLAMP);
4203 					break;
4204 				case D3DTADDRESS_BORDER:
4205 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_BORDER);
4206 					break;
4207 				case D3DTADDRESS_MIRRORONCE:
4208 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRRORONCE);
4209 					break;
4210 				default:
4211 					ASSERT(false);
4212 				}
4213 				break;
4214 			case D3DSAMP_ADDRESSW:
4215 				switch(value)
4216 				{
4217 				case D3DTADDRESS_WRAP:
4218 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_WRAP);
4219 					break;
4220 				case D3DTADDRESS_MIRROR:
4221 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRROR);
4222 					break;
4223 				case D3DTADDRESS_CLAMP:
4224 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_CLAMP);
4225 					break;
4226 				case D3DTADDRESS_BORDER:
4227 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_BORDER);
4228 					break;
4229 				case D3DTADDRESS_MIRRORONCE:
4230 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRRORONCE);
4231 					break;
4232 				default:
4233 					ASSERT(false);
4234 				}
4235 				break;
4236 			case D3DSAMP_BORDERCOLOR:
4237 				renderer->setBorderColor(type, index, value);
4238 				break;
4239 			case D3DSAMP_MAGFILTER:
4240 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4241 				switch(value)
4242 				{
4243 				case D3DTEXF_NONE:
4244 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4245 					break;
4246 				case D3DTEXF_POINT:
4247 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4248 					break;
4249 				case D3DTEXF_LINEAR:
4250 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4251 					break;
4252 				case D3DTEXF_ANISOTROPIC:
4253 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4254 					break;
4255 				case D3DTEXF_PYRAMIDALQUAD:
4256 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4257 					break;
4258 				case D3DTEXF_GAUSSIANQUAD:
4259 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4260 					break;
4261 				default:
4262 					return INVALIDCALL();
4263 				};
4264 				break;
4265 			case D3DSAMP_MINFILTER:
4266 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4267 				switch(value)
4268 				{
4269 				case D3DTEXF_NONE:
4270 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4271 					break;
4272 				case D3DTEXF_POINT:
4273 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4274 					break;
4275 				case D3DTEXF_LINEAR:
4276 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4277 					break;
4278 				case D3DTEXF_ANISOTROPIC:
4279 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4280 					break;
4281 				case D3DTEXF_PYRAMIDALQUAD:
4282 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4283 					break;
4284 				case D3DTEXF_GAUSSIANQUAD:
4285 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4286 					break;
4287 				default:
4288 					return INVALIDCALL();
4289 				};
4290 				break;
4291 			case D3DSAMP_MIPFILTER:
4292 				switch(value)
4293 				{
4294 				case D3DTEXF_NONE:
4295 					renderer->setMipmapFilter(type, index, sw::MIPMAP_NONE);
4296 					break;
4297 				case D3DTEXF_POINT:
4298 					renderer->setMipmapFilter(type, index, sw::MIPMAP_POINT);
4299 					break;
4300 				case D3DTEXF_LINEAR:
4301 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);
4302 					break;
4303 				case D3DTEXF_ANISOTROPIC:
4304 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4305 					break;
4306 				case D3DTEXF_PYRAMIDALQUAD:
4307 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4308 					break;
4309 				case D3DTEXF_GAUSSIANQUAD:
4310 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4311 					break;
4312 				default:
4313 					return INVALIDCALL();
4314 				};
4315 				break;
4316 			case D3DSAMP_MIPMAPLODBIAS:
4317 				if(value == D3DFMT_GET4)   // ATI hack to enable Fetch4
4318 				{
4319 					renderer->setGatherEnable(type, index, true);
4320 				}
4321 				else if(value == D3DFMT_GET1)   // ATI hack to disable Fetch4
4322 				{
4323 					renderer->setGatherEnable(type, index, false);
4324 				}
4325 				else
4326 				{
4327 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes
4328 					renderer->setMipmapLOD(type, index, LOD);
4329 				}
4330 				break;
4331 			case D3DSAMP_MAXMIPLEVEL:
4332 				break;
4333 			case D3DSAMP_MAXANISOTROPY:
4334 				renderer->setMaxAnisotropy(type, index, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy));
4335 				break;
4336 			case D3DSAMP_SRGBTEXTURE:
4337 				renderer->setReadSRGB(type, index, value != FALSE);
4338 				break;
4339 			case D3DSAMP_ELEMENTINDEX:
4340 				if(!init) UNIMPLEMENTED();   // Multi-element textures deprecated in favor of multiple render targets
4341 				break;
4342 			case D3DSAMP_DMAPOFFSET:
4343 			//	if(!init) UNIMPLEMENTED();
4344 				break;
4345 			default:
4346 				ASSERT(false);
4347 			}
4348 		}
4349 		else   // stateRecorder
4350 		{
4351 			stateRecorder->setSamplerState(sampler, state, value);
4352 		}
4353 
4354 		return D3D_OK;
4355 	}
4356 
SetScissorRect(const RECT * rect)4357 	long Direct3DDevice9::SetScissorRect(const RECT *rect)
4358 	{
4359 		CriticalSection cs(this);
4360 
4361 		TRACE("const RECT *rect = 0x%0.8p", rect);
4362 
4363 		if(!rect)
4364 		{
4365 			return INVALIDCALL();
4366 		}
4367 
4368 		if(!stateRecorder)
4369 		{
4370 			scissorRect = *rect;
4371 		}
4372 		else
4373 		{
4374 			stateRecorder->setScissorRect(rect);
4375 		}
4376 
4377 		return D3D_OK;
4378 	}
4379 
SetSoftwareVertexProcessing(int software)4380 	long Direct3DDevice9::SetSoftwareVertexProcessing(int software)
4381 	{
4382 		CriticalSection cs(this);
4383 
4384 		TRACE("int software = %d", software);
4385 
4386 		if(behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING && software == FALSE)
4387 		{
4388 			return INVALIDCALL();
4389 		}
4390 
4391 		if(behaviourFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING && software == TRUE)
4392 		{
4393 			return INVALIDCALL();
4394 		}
4395 
4396 		softwareVertexProcessing = (software != FALSE);
4397 
4398 		return D3D_OK;
4399 	}
4400 
SetStreamSource(unsigned int stream,IDirect3DVertexBuffer9 * iVertexBuffer,unsigned int offset,unsigned int stride)4401 	long Direct3DDevice9::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer9 *iVertexBuffer, unsigned int offset, unsigned int stride)
4402 	{
4403 		CriticalSection cs(this);
4404 
4405 		TRACE("unsigned int stream = %d, IDirect3DVertexBuffer9 *data = 0x%0.8p, unsigned int offset = %d, unsigned int stride = %d", stream, iVertexBuffer, offset, stride);
4406 
4407 		Direct3DVertexBuffer9 *vertexBuffer = static_cast<Direct3DVertexBuffer9*>(iVertexBuffer);
4408 
4409 		if(!stateRecorder)
4410 		{
4411 			if(dataStream[stream] == vertexBuffer && streamOffset[stream] == offset && streamStride[stream] == stride)
4412 			{
4413 				return D3D_OK;
4414 			}
4415 
4416 			if(vertexBuffer)
4417 			{
4418 				vertexBuffer->bind();
4419 			}
4420 
4421 			if(dataStream[stream])
4422 			{
4423 				dataStream[stream]->unbind();
4424 			}
4425 
4426 			dataStream[stream] = vertexBuffer;
4427 			streamOffset[stream] = offset;
4428 			streamStride[stream] = stride;
4429 		}
4430 		else
4431 		{
4432 			stateRecorder->setStreamSource(stream, vertexBuffer, offset, stride);
4433 		}
4434 
4435 		return D3D_OK;
4436 	}
4437 
SetStreamSourceFreq(unsigned int streamNumber,unsigned int divider)4438 	long Direct3DDevice9::SetStreamSourceFreq(unsigned int streamNumber, unsigned int divider)
4439 	{
4440 		CriticalSection cs(this);
4441 
4442 		TRACE("unsigned int streamNumber = %d, unsigned int divider = %d", streamNumber, divider);
4443 
4444 		if(!instancingEnabled)
4445 		{
4446 			return INVALIDCALL();
4447 		}
4448 
4449 		if(!stateRecorder)
4450 		{
4451 			streamSourceFreq[streamNumber] = divider;
4452 		}
4453 		else
4454 		{
4455 			stateRecorder->setStreamSourceFreq(streamNumber, divider);
4456 		}
4457 
4458 		return D3D_OK;
4459 	}
4460 
SetTexture(unsigned long sampler,IDirect3DBaseTexture9 * iBaseTexture)4461 	long Direct3DDevice9::SetTexture(unsigned long sampler, IDirect3DBaseTexture9 *iBaseTexture)
4462 	{
4463 		CriticalSection cs(this);
4464 
4465 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 *texture = 0x%0.8p", sampler, iBaseTexture);
4466 
4467 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4468 		{
4469 			return INVALIDCALL();
4470 		}
4471 
4472 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4473 		{
4474 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4475 		}
4476 
4477 		Direct3DBaseTexture9 *baseTexture = dynamic_cast<Direct3DBaseTexture9*>(iBaseTexture);
4478 
4479 		if(!stateRecorder)
4480 		{
4481 			if(texture[sampler] == baseTexture)
4482 			{
4483 				return D3D_OK;
4484 			}
4485 
4486 			if(baseTexture)
4487 			{
4488 				baseTexture->bind();   // FIXME: Bind individual sub-surfaces?
4489 			}
4490 
4491 			if(texture[sampler])
4492 			{
4493 				texture[sampler]->unbind();
4494 			}
4495 
4496 			texture[sampler] = baseTexture;
4497 		}
4498 		else
4499 		{
4500 			stateRecorder->setTexture(sampler, baseTexture);
4501 		}
4502 
4503 		return D3D_OK;
4504 	}
4505 
SetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long value)4506 	long Direct3DDevice9::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value)
4507 	{
4508 		CriticalSection cs(this);
4509 
4510 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value);
4511 
4512 		if(stage < 0 || stage >= 8 || type < D3DTSS_COLOROP || type > D3DTSS_CONSTANT)
4513 		{
4514 			return INVALIDCALL();
4515 		}
4516 
4517 		if(!stateRecorder)
4518 		{
4519 			if(!init && textureStageState[stage][type] == value)
4520 			{
4521 				return D3D_OK;
4522 			}
4523 
4524 			textureStageState[stage][type] = value;
4525 
4526 			switch(type)
4527 			{
4528 			case D3DTSS_COLOROP:
4529 				switch(value)
4530 				{
4531 				case D3DTOP_DISABLE:
4532 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE);
4533 					break;
4534 				case D3DTOP_SELECTARG1:
4535 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1);
4536 					break;
4537 				case D3DTOP_SELECTARG2:
4538 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2);
4539 					break;
4540 				case D3DTOP_MODULATE:
4541 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE);
4542 					break;
4543 				case D3DTOP_MODULATE2X:
4544 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X);
4545 					break;
4546 				case D3DTOP_MODULATE4X:
4547 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X);
4548 					break;
4549 				case D3DTOP_ADD:
4550 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD);
4551 					break;
4552 				case D3DTOP_ADDSIGNED:
4553 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED);
4554 					break;
4555 				case D3DTOP_ADDSIGNED2X:
4556 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4557 					break;
4558 				case D3DTOP_SUBTRACT:
4559 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT);
4560 					break;
4561 				case D3DTOP_ADDSMOOTH:
4562 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4563 					break;
4564 				case D3DTOP_BLENDDIFFUSEALPHA:
4565 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4566 					break;
4567 				case D3DTOP_BLENDTEXTUREALPHA:
4568 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4569 					break;
4570 				case D3DTOP_BLENDFACTORALPHA:
4571 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4572 					break;
4573 				case D3DTOP_BLENDTEXTUREALPHAPM:
4574 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4575 					break;
4576 				case D3DTOP_BLENDCURRENTALPHA:
4577 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4578 					break;
4579 				case D3DTOP_PREMODULATE:
4580 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE);
4581 					break;
4582 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4583 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4584 					break;
4585 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4586 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4587 					break;
4588 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4589 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4590 					break;
4591 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4592 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4593 					break;
4594 				case D3DTOP_BUMPENVMAP:
4595 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4596 					break;
4597 				case D3DTOP_BUMPENVMAPLUMINANCE:
4598 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4599 					break;
4600 				case D3DTOP_DOTPRODUCT3:
4601 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3);
4602 					break;
4603 				case D3DTOP_MULTIPLYADD:
4604 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4605 					break;
4606 				case D3DTOP_LERP:
4607 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP);
4608 					break;
4609 				default:
4610 					ASSERT(false);
4611 				}
4612 				break;
4613 			case D3DTSS_COLORARG1:
4614 				switch(value & D3DTA_SELECTMASK)
4615 				{
4616 				case D3DTA_DIFFUSE:
4617 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4618 					break;
4619 				case D3DTA_CURRENT:
4620 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4621 					break;
4622 				case D3DTA_TEXTURE:
4623 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4624 					break;
4625 				case D3DTA_TFACTOR:
4626 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4627 					break;
4628 				case D3DTA_SPECULAR:
4629 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4630 					break;
4631 				case D3DTA_TEMP:
4632 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP);
4633 					break;
4634 				case D3DTA_CONSTANT:
4635 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4636 					break;
4637 				default:
4638 					ASSERT(false);
4639 				}
4640 
4641 				switch(value & ~D3DTA_SELECTMASK)
4642 				{
4643 				case 0:
4644 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4645 					break;
4646 				case D3DTA_COMPLEMENT:
4647 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4648 					break;
4649 				case D3DTA_ALPHAREPLICATE:
4650 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4651 					break;
4652 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4653 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4654 					break;
4655 				default:
4656 					ASSERT(false);
4657 				}
4658 				break;
4659 			case D3DTSS_COLORARG2:
4660 				switch(value & D3DTA_SELECTMASK)
4661 				{
4662 				case D3DTA_DIFFUSE:
4663 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4664 					break;
4665 				case D3DTA_CURRENT:
4666 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4667 					break;
4668 				case D3DTA_TEXTURE:
4669 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4670 					break;
4671 				case D3DTA_TFACTOR:
4672 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4673 					break;
4674 				case D3DTA_SPECULAR:
4675 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4676 					break;
4677 				case D3DTA_TEMP:
4678 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP);
4679 					break;
4680 				case D3DTA_CONSTANT:
4681 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4682 					break;
4683 				default:
4684 					ASSERT(false);
4685 				}
4686 
4687 				switch(value & ~D3DTA_SELECTMASK)
4688 				{
4689 				case 0:
4690 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4691 					break;
4692 				case D3DTA_COMPLEMENT:
4693 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4694 					break;
4695 				case D3DTA_ALPHAREPLICATE:
4696 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4697 					break;
4698 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4699 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4700 					break;
4701 				default:
4702 					ASSERT(false);
4703 				}
4704 				break;
4705 			case D3DTSS_ALPHAOP:
4706 				switch(value)
4707 				{
4708 				case D3DTOP_DISABLE:
4709 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE);
4710 					break;
4711 				case D3DTOP_SELECTARG1:
4712 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1);
4713 					break;
4714 				case D3DTOP_SELECTARG2:
4715 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2);
4716 					break;
4717 				case D3DTOP_MODULATE:
4718 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE);
4719 					break;
4720 				case D3DTOP_MODULATE2X:
4721 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X);
4722 					break;
4723 				case D3DTOP_MODULATE4X:
4724 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X);
4725 					break;
4726 				case D3DTOP_ADD:
4727 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD);
4728 					break;
4729 				case D3DTOP_ADDSIGNED:
4730 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED);
4731 					break;
4732 				case D3DTOP_ADDSIGNED2X:
4733 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4734 					break;
4735 				case D3DTOP_SUBTRACT:
4736 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT);
4737 					break;
4738 				case D3DTOP_ADDSMOOTH:
4739 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4740 					break;
4741 				case D3DTOP_BLENDDIFFUSEALPHA:
4742 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4743 					break;
4744 				case D3DTOP_BLENDTEXTUREALPHA:
4745 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4746 					break;
4747 				case D3DTOP_BLENDFACTORALPHA:
4748 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4749 					break;
4750 				case D3DTOP_BLENDTEXTUREALPHAPM:
4751 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4752 					break;
4753 				case D3DTOP_BLENDCURRENTALPHA:
4754 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4755 					break;
4756 				case D3DTOP_PREMODULATE:
4757 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE);
4758 					break;
4759 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4760 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4761 					break;
4762 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4763 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4764 					break;
4765 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4766 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4767 					break;
4768 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4769 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4770 					break;
4771 				case D3DTOP_BUMPENVMAP:
4772 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4773 					break;
4774 				case D3DTOP_BUMPENVMAPLUMINANCE:
4775 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4776 					break;
4777 				case D3DTOP_DOTPRODUCT3:
4778 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3);
4779 					break;
4780 				case D3DTOP_MULTIPLYADD:
4781 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4782 					break;
4783 				case D3DTOP_LERP:
4784 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP);
4785 					break;
4786 				default:
4787 					ASSERT(false);
4788 				}
4789 				break;
4790 			case D3DTSS_ALPHAARG1:
4791 				switch(value & D3DTA_SELECTMASK)
4792 				{
4793 				case D3DTA_DIFFUSE:
4794 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4795 					break;
4796 				case D3DTA_CURRENT:
4797 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4798 					break;
4799 				case D3DTA_TEXTURE:
4800 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4801 					break;
4802 				case D3DTA_TFACTOR:
4803 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4804 					break;
4805 				case D3DTA_SPECULAR:
4806 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4807 					break;
4808 				case D3DTA_TEMP:
4809 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4810 					break;
4811 				case D3DTA_CONSTANT:
4812 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4813 					break;
4814 				default:
4815 					ASSERT(false);
4816 				}
4817 
4818 				switch(value & ~D3DTA_SELECTMASK)
4819 				{
4820 				case 0:
4821 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4822 					break;
4823 				case D3DTA_COMPLEMENT:
4824 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4825 					break;
4826 				case D3DTA_ALPHAREPLICATE:
4827 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4828 					break;
4829 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4830 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4831 					break;
4832 				default:
4833 					ASSERT(false);
4834 				}
4835 				break;
4836 			case D3DTSS_ALPHAARG2:
4837 				switch(value & D3DTA_SELECTMASK)
4838 				{
4839 				case D3DTA_DIFFUSE:
4840 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4841 					break;
4842 				case D3DTA_CURRENT:
4843 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4844 					break;
4845 				case D3DTA_TEXTURE:
4846 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4847 					break;
4848 				case D3DTA_TFACTOR:
4849 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4850 					break;
4851 				case D3DTA_SPECULAR:
4852 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4853 					break;
4854 				case D3DTA_TEMP:
4855 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4856 					break;
4857 				case D3DTA_CONSTANT:
4858 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4859 					break;
4860 				default:
4861 					ASSERT(false);
4862 				}
4863 
4864 				switch(value & ~D3DTA_SELECTMASK)
4865 				{
4866 				case 0:
4867 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4868 					break;
4869 				case D3DTA_COMPLEMENT:
4870 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4871 					break;
4872 				case D3DTA_ALPHAREPLICATE:
4873 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4874 					break;
4875 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4876 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
4877 					break;
4878 				default:
4879 					ASSERT(false);
4880 				}
4881 				break;
4882 			case D3DTSS_BUMPENVMAT00:
4883 				renderer->setBumpmapMatrix(stage, 0, (float&)value);
4884 				break;
4885 			case D3DTSS_BUMPENVMAT01:
4886 				renderer->setBumpmapMatrix(stage, 1, (float&)value);
4887 				break;
4888 			case D3DTSS_BUMPENVMAT10:
4889 				renderer->setBumpmapMatrix(stage, 2, (float&)value);
4890 				break;
4891 			case D3DTSS_BUMPENVMAT11:
4892 				renderer->setBumpmapMatrix(stage, 3, (float&)value);
4893 				break;
4894 			case D3DTSS_TEXCOORDINDEX:
4895 				renderer->setTexCoordIndex(stage, value & 0x0000FFFF);
4896 
4897 				switch(value & 0xFFFF0000)
4898 				{
4899 				case D3DTSS_TCI_PASSTHRU:
4900 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU);
4901 					break;
4902 				case D3DTSS_TCI_CAMERASPACENORMAL:
4903 					renderer->setTexCoordIndex(stage, stage);
4904 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL);
4905 					break;
4906 				case D3DTSS_TCI_CAMERASPACEPOSITION:
4907 					renderer->setTexCoordIndex(stage, stage);
4908 					renderer->setTexGen(stage, sw::TEXGEN_POSITION);
4909 					break;
4910 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4911 					renderer->setTexCoordIndex(stage, stage);
4912 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION);
4913 					break;
4914 				case D3DTSS_TCI_SPHEREMAP:
4915 					renderer->setTexCoordIndex(stage, stage);
4916 					renderer->setTexGen(stage, sw::TEXGEN_SPHEREMAP);
4917 					break;
4918 				default:
4919 					ASSERT(false);
4920 				}
4921 				break;
4922 			case D3DTSS_BUMPENVLSCALE:
4923 				renderer->setLuminanceScale(stage, (float&)value);
4924 				break;
4925 			case D3DTSS_BUMPENVLOFFSET:
4926 				renderer->setLuminanceOffset(stage, (float&)value);
4927 				break;
4928 			case D3DTSS_TEXTURETRANSFORMFLAGS:
4929 				switch(value & ~D3DTTFF_PROJECTED)
4930 				{
4931 				case D3DTTFF_DISABLE:
4932 					renderer->setTextureTransform(stage, 0, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4933 					break;
4934 				case D3DTTFF_COUNT1:
4935 					renderer->setTextureTransform(stage, 1, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4936 					break;
4937 				case D3DTTFF_COUNT2:
4938 					renderer->setTextureTransform(stage, 2, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4939 					break;
4940 				case D3DTTFF_COUNT3:
4941 					renderer->setTextureTransform(stage, 3, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4942 					break;
4943 				case D3DTTFF_COUNT4:
4944 					renderer->setTextureTransform(stage, 4, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4945 					break;
4946 				default:
4947 					ASSERT(false);
4948 				}
4949 				break;
4950 			case D3DTSS_COLORARG0:
4951 				switch(value & D3DTA_SELECTMASK)
4952 				{
4953 				case D3DTA_CURRENT:
4954 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4955 					break;
4956 				case D3DTA_DIFFUSE:
4957 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4958 					break;
4959 				case D3DTA_SPECULAR:
4960 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4961 					break;
4962 				case D3DTA_TEMP:
4963 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP);
4964 					break;
4965 				case D3DTA_TEXTURE:
4966 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4967 					break;
4968 				case D3DTA_TFACTOR:
4969 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4970 					break;
4971 				default:
4972 					ASSERT(false);
4973 				}
4974 
4975 				switch(value & ~D3DTA_SELECTMASK)
4976 				{
4977 				case 0:
4978 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4979 					break;
4980 				case D3DTA_COMPLEMENT:
4981 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4982 					break;
4983 				case D3DTA_ALPHAREPLICATE:
4984 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4985 					break;
4986 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4987 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4988 					break;
4989 				default:
4990 					ASSERT(false);
4991 				}
4992 				break;
4993 			case D3DTSS_ALPHAARG0:
4994 				switch(value & D3DTA_SELECTMASK)
4995 				{
4996 				case D3DTA_DIFFUSE:
4997 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4998 					break;
4999 				case D3DTA_CURRENT:
5000 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
5001 					break;
5002 				case D3DTA_TEXTURE:
5003 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
5004 					break;
5005 				case D3DTA_TFACTOR:
5006 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
5007 					break;
5008 				case D3DTA_SPECULAR:
5009 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
5010 					break;
5011 				case D3DTA_TEMP:
5012 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
5013 					break;
5014 				case D3DTA_CONSTANT:
5015 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
5016 					break;
5017 				default:
5018 					ASSERT(false);
5019 				}
5020 
5021 				switch(value & ~D3DTA_SELECTMASK)
5022 				{
5023 				case 0:
5024 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
5025 					break;
5026 				case D3DTA_COMPLEMENT:
5027 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
5028 					break;
5029 				case D3DTA_ALPHAREPLICATE:
5030 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
5031 					break;
5032 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
5033 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
5034 					break;
5035 				default:
5036 					ASSERT(false);
5037 				}
5038 				break;
5039 			case D3DTSS_RESULTARG:
5040 				switch(value & D3DTA_SELECTMASK)
5041 				{
5042 				case D3DTA_CURRENT:
5043 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT);
5044 					break;
5045 				case D3DTA_TEMP:
5046 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP);
5047 					break;
5048 				default:
5049 					ASSERT(false);
5050 				}
5051 				break;
5052 			case D3DTSS_CONSTANT:
5053 				renderer->setConstantColor(stage, value);
5054 				break;
5055 			default:
5056 				ASSERT(false);
5057 			}
5058 		}
5059 		else   // stateRecorder
5060 		{
5061 			stateRecorder->setTextureStageState(stage, type, value);
5062 		}
5063 
5064 		return D3D_OK;
5065 	}
5066 
SetTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)5067 	long Direct3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
5068 	{
5069 		CriticalSection cs(this);
5070 
5071 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
5072 
5073 		if(!matrix)
5074 		{
5075 			return INVALIDCALL();
5076 		}
5077 
5078 		if(!stateRecorder)
5079 		{
5080 			this->matrix[state] = *matrix;
5081 
5082 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
5083 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
5084 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
5085 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
5086 
5087 			switch(state)
5088 			{
5089 			case D3DTS_WORLD:
5090 				renderer->setModelMatrix(M);
5091 				break;
5092 			case D3DTS_VIEW:
5093 				renderer->setViewMatrix(M);
5094 				break;
5095 			case D3DTS_PROJECTION:
5096 				renderer->setProjectionMatrix(M);
5097 				break;
5098 			case D3DTS_TEXTURE0:
5099 				renderer->setTextureMatrix(0, M);
5100 				break;
5101 			case D3DTS_TEXTURE1:
5102 				renderer->setTextureMatrix(1, M);
5103 				break;
5104 			case D3DTS_TEXTURE2:
5105 				renderer->setTextureMatrix(2, M);
5106 				break;
5107 			case D3DTS_TEXTURE3:
5108 				renderer->setTextureMatrix(3, M);
5109 				break;
5110 			case D3DTS_TEXTURE4:
5111 				renderer->setTextureMatrix(4, M);
5112 				break;
5113 			case D3DTS_TEXTURE5:
5114 				renderer->setTextureMatrix(5, M);
5115 				break;
5116 			case D3DTS_TEXTURE6:
5117 				renderer->setTextureMatrix(6, M);
5118 				break;
5119 			case D3DTS_TEXTURE7:
5120 				renderer->setTextureMatrix(7, M);
5121 				break;
5122 			default:
5123 				if(state > 256 && state < 512)
5124 				{
5125 					renderer->setModelMatrix(M, state - 256);
5126 				}
5127 				else ASSERT(false);
5128 			}
5129 		}
5130 		else   // stateRecorder
5131 		{
5132 			stateRecorder->setTransform(state, matrix);
5133 		}
5134 
5135 		return D3D_OK;
5136 	}
5137 
SetVertexDeclaration(IDirect3DVertexDeclaration9 * iVertexDeclaration)5138 	long Direct3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9 *iVertexDeclaration)
5139 	{
5140 		CriticalSection cs(this);
5141 
5142 		TRACE("IDirect3DVertexDeclaration9 *declaration = 0x%0.8p", iVertexDeclaration);
5143 
5144 		Direct3DVertexDeclaration9 *vertexDeclaration = static_cast<Direct3DVertexDeclaration9*>(iVertexDeclaration);
5145 
5146 		if(!stateRecorder)
5147 		{
5148 			if(this->vertexDeclaration == vertexDeclaration)
5149 			{
5150 				return D3D_OK;
5151 			}
5152 
5153 			if(vertexDeclaration)
5154 			{
5155 				vertexDeclaration->bind();
5156 			}
5157 
5158 			if(this->vertexDeclaration)
5159 			{
5160 				this->vertexDeclaration->unbind();
5161 			}
5162 
5163 			this->vertexDeclaration = vertexDeclaration;
5164 		}
5165 		else
5166 		{
5167 			stateRecorder->setVertexDeclaration(vertexDeclaration);
5168 		}
5169 
5170 		return D3D_OK;
5171 	}
5172 
SetVertexShader(IDirect3DVertexShader9 * iVertexShader)5173 	long Direct3DDevice9::SetVertexShader(IDirect3DVertexShader9 *iVertexShader)
5174 	{
5175 		CriticalSection cs(this);
5176 
5177 		TRACE("IDirect3DVertexShader9 *shader = 0x%0.8p", iVertexShader);
5178 
5179 		Direct3DVertexShader9 *vertexShader = static_cast<Direct3DVertexShader9*>(iVertexShader);
5180 
5181 		if(!stateRecorder)
5182 		{
5183 			if(this->vertexShader == vertexShader)
5184 			{
5185 				return D3D_OK;
5186 			}
5187 
5188 			if(vertexShader)
5189 			{
5190 				vertexShader->bind();
5191 			}
5192 
5193 			if(this->vertexShader)
5194 			{
5195 				this->vertexShader->unbind();
5196 			}
5197 
5198 			this->vertexShader = vertexShader;
5199 			vertexShaderDirty = true;
5200 		}
5201 		else
5202 		{
5203 			stateRecorder->setVertexShader(vertexShader);
5204 		}
5205 
5206 		return D3D_OK;
5207 	}
5208 
SetVertexShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)5209 	long Direct3DDevice9::SetVertexShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
5210 	{
5211 		CriticalSection cs(this);
5212 
5213 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5214 
5215 		if(!constantData)
5216 		{
5217 			return INVALIDCALL();
5218 		}
5219 
5220 		if(!stateRecorder)
5221 		{
5222 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5223 			{
5224 				vertexShaderConstantB[startRegister + i] = constantData[i];
5225 			}
5226 
5227 			vertexShaderConstantsBDirty = sw::max(startRegister + count, vertexShaderConstantsBDirty);
5228 			vertexShaderDirty = true;   // Reload DEF constants
5229 		}
5230 		else
5231 		{
5232 			stateRecorder->setVertexShaderConstantB(startRegister, constantData, count);
5233 		}
5234 
5235 		return D3D_OK;
5236 	}
5237 
SetVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)5238 	long Direct3DDevice9::SetVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
5239 	{
5240 		CriticalSection cs(this);
5241 
5242 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5243 
5244 		if(!constantData)
5245 		{
5246 			return INVALIDCALL();
5247 		}
5248 
5249 		if(!stateRecorder)
5250 		{
5251 			for(unsigned int i = 0; i < count && startRegister + i < MAX_VERTEX_SHADER_CONST; i++)
5252 			{
5253 				vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
5254 				vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
5255 				vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
5256 				vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
5257 			}
5258 
5259 			vertexShaderConstantsFDirty = sw::max(startRegister + count, vertexShaderConstantsFDirty);
5260 			vertexShaderDirty = true;   // Reload DEF constants
5261 		}
5262 		else
5263 		{
5264 			stateRecorder->setVertexShaderConstantF(startRegister, constantData, count);
5265 		}
5266 
5267 		return D3D_OK;
5268 	}
5269 
SetVertexShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)5270 	long Direct3DDevice9::SetVertexShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
5271 	{
5272 		CriticalSection cs(this);
5273 
5274 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5275 
5276 		if(!constantData)
5277 		{
5278 			return INVALIDCALL();
5279 		}
5280 
5281 		if(!stateRecorder)
5282 		{
5283 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5284 			{
5285 				vertexShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
5286 				vertexShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
5287 				vertexShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
5288 				vertexShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
5289 			}
5290 
5291 			vertexShaderConstantsIDirty = sw::max(startRegister + count, vertexShaderConstantsIDirty);
5292 			vertexShaderDirty = true;   // Reload DEF constants
5293 		}
5294 		else
5295 		{
5296 			stateRecorder->setVertexShaderConstantI(startRegister, constantData, count);
5297 		}
5298 
5299 		return D3D_OK;
5300 	}
5301 
SetViewport(const D3DVIEWPORT9 * viewport)5302 	long Direct3DDevice9::SetViewport(const D3DVIEWPORT9 *viewport)
5303 	{
5304 		CriticalSection cs(this);
5305 
5306 		TRACE("const D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
5307 
5308 		if(!viewport)   // FIXME: Check if valid
5309 		{
5310 			return INVALIDCALL();
5311 		}
5312 
5313 		if(!stateRecorder)
5314 		{
5315 			this->viewport = *viewport;
5316 		}
5317 		else
5318 		{
5319 			stateRecorder->setViewport(viewport);
5320 		}
5321 
5322 		return D3D_OK;
5323 	}
5324 
ShowCursor(int show)5325 	int Direct3DDevice9::ShowCursor(int show)
5326 	{
5327 		CriticalSection cs(this);
5328 
5329 		TRACE("int show = %d", show);
5330 
5331 		int oldValue = showCursor ? TRUE : FALSE;
5332 		showCursor = show != FALSE;
5333 
5334 		if(showCursor)
5335 		{
5336 			sw::FrameBuffer::setCursorImage(cursor);
5337 		}
5338 		else
5339 		{
5340 			sw::FrameBuffer::setCursorImage(0);
5341 		}
5342 
5343 		return oldValue;
5344 	}
5345 
StretchRect(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destSurface,const RECT * destRect,D3DTEXTUREFILTERTYPE filter)5346 	long Direct3DDevice9::StretchRect(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destSurface, const RECT *destRect, D3DTEXTUREFILTERTYPE filter)
5347 	{
5348 		CriticalSection cs(this);
5349 
5350 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destSurface = 0x%0.8p, const RECT *destRect = 0x%0.8p, D3DTEXTUREFILTERTYPE filter = %d", sourceSurface, sourceRect, destSurface, destRect, filter);
5351 
5352 		if(!sourceSurface || !destSurface || !validRectangle(sourceRect, sourceSurface) || !validRectangle(destRect, destSurface))
5353 		{
5354 			return INVALIDCALL();
5355 		}
5356 
5357 		D3DSURFACE_DESC sourceDescription;
5358 		D3DSURFACE_DESC destDescription;
5359 
5360 		sourceSurface->GetDesc(&sourceDescription);
5361 		destSurface->GetDesc(&destDescription);
5362 
5363 		if(sourceDescription.Pool != D3DPOOL_DEFAULT || destDescription.Pool != D3DPOOL_DEFAULT)
5364 		{
5365 			return INVALIDCALL();
5366 		}
5367 
5368 		Direct3DSurface9 *source = static_cast<Direct3DSurface9*>(sourceSurface);
5369 		Direct3DSurface9 *dest = static_cast<Direct3DSurface9*>(destSurface);
5370 
5371 		stretchRect(source, sourceRect, dest, destRect, filter);
5372 
5373 		return D3D_OK;
5374 	}
5375 
TestCooperativeLevel()5376 	long Direct3DDevice9::TestCooperativeLevel()
5377 	{
5378 		CriticalSection cs(this);
5379 
5380 		TRACE("void");
5381 
5382 		return D3D_OK;
5383 	}
5384 
UpdateSurface(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destinationSurface,const POINT * destPoint)5385 	long Direct3DDevice9::UpdateSurface(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destinationSurface, const POINT *destPoint)
5386 	{
5387 		CriticalSection cs(this);
5388 
5389 		TRACE("IDirect3DSurface9 *sourceSurface = 0x%0.8p, const RECT *sourceRect = 0x%0.8p, IDirect3DSurface9 *destinationSurface = 0x%0.8p, const POINT *destPoint = 0x%0.8p", sourceSurface, sourceRect, destinationSurface, destPoint);
5390 
5391 		if(!sourceSurface || !destinationSurface)
5392 		{
5393 			return INVALIDCALL();
5394 		}
5395 
5396 		D3DSURFACE_DESC sourceDescription;
5397 		D3DSURFACE_DESC destinationDescription;
5398 
5399 		sourceSurface->GetDesc(&sourceDescription);
5400 		destinationSurface->GetDesc(&destinationDescription);
5401 
5402 		RECT sRect;
5403 		RECT dRect;
5404 
5405 		if(sourceRect)
5406 		{
5407 			sRect.left = sourceRect->left;
5408 			sRect.top = sourceRect->top;
5409 			sRect.right = sourceRect->right;
5410 			sRect.bottom = sourceRect->bottom;
5411 		}
5412 		else
5413 		{
5414 			sRect.left = 0;
5415 			sRect.top = 0;
5416 			sRect.right = sourceDescription.Width;
5417 			sRect.bottom = sourceDescription.Height;
5418 		}
5419 
5420 		if(destPoint)
5421 		{
5422 			dRect.left = destPoint->x;
5423 			dRect.top = destPoint->y;
5424 			dRect.right = destPoint->x + sRect.right - sRect.left;
5425 			dRect.bottom = destPoint->y + sRect.bottom - sRect.top;
5426 		}
5427 		else
5428 		{
5429 			dRect.left = 0;
5430 			dRect.top = 0;
5431 			dRect.right = sRect.right - sRect.left;
5432 			dRect.bottom = sRect.bottom - sRect.top;
5433 		}
5434 
5435 		if(!validRectangle(&sRect, sourceSurface) || !validRectangle(&dRect, destinationSurface))
5436 		{
5437 			return INVALIDCALL();
5438 		}
5439 
5440 		int sWidth = sRect.right - sRect.left;
5441 		int sHeight = sRect.bottom - sRect.top;
5442 
5443 		int dWidth = dRect.right - dRect.left;
5444 		int dHeight = dRect.bottom - dRect.top;
5445 
5446 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE ||
5447 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE ||
5448 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags
5449 		// destinationDescription.Pool != D3DPOOL_DEFAULT ||
5450 		   sourceDescription.Format != destinationDescription.Format)
5451 		{
5452 			return INVALIDCALL();
5453 		}
5454 
5455 		sw::Surface *source = static_cast<Direct3DSurface9*>(sourceSurface);
5456 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destinationSurface);
5457 
5458 		unsigned char *sBuffer = (unsigned char*)source->lockExternal(sRect.left, sRect.top, 0, sw::LOCK_READONLY, sw::PUBLIC);
5459 		unsigned char *dBuffer = (unsigned char*)dest->lockExternal(dRect.left, dRect.top, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
5460 		int sPitch = source->getExternalPitchB();
5461 		int dPitch = dest->getExternalPitchB();
5462 
5463 		unsigned int width;
5464 		unsigned int height;
5465 		unsigned int bytes;
5466 
5467 		switch(sourceDescription.Format)
5468 		{
5469 		case D3DFMT_DXT1:
5470 		case D3DFMT_ATI1:
5471 			width = (dWidth + 3) / 4;
5472 			height = (dHeight + 3) / 4;
5473 			bytes = width * 8;   // 64 bit per 4x4 block
5474 			break;
5475 		case D3DFMT_DXT2:
5476 		case D3DFMT_DXT3:
5477 		case D3DFMT_DXT4:
5478 		case D3DFMT_DXT5:
5479 		case D3DFMT_ATI2:
5480 			width = (dWidth + 3) / 4;
5481 			height = (dHeight + 3) / 4;
5482 			bytes = width * 16;   // 128 bit per 4x4 block
5483 			break;
5484 		default:
5485 			width = dWidth;
5486 			height = dHeight;
5487 			bytes = width * Direct3DSurface9::bytes(sourceDescription.Format);
5488 		}
5489 
5490 		if(sourceDescription.Format == D3DFMT_ATI1 || sourceDescription.Format == D3DFMT_ATI2)
5491 		{
5492 			// Make the pitch correspond to 4 rows
5493 			sPitch *= 4;
5494 			dPitch *= 4;
5495 		}
5496 
5497 		for(unsigned int y = 0; y < height; y++)
5498 		{
5499 			memcpy(dBuffer, sBuffer, bytes);
5500 
5501 			sBuffer += sPitch;
5502 			dBuffer += dPitch;
5503 		}
5504 
5505 		source->unlockExternal();
5506 		dest->unlockExternal();
5507 
5508 		return D3D_OK;
5509 	}
5510 
UpdateTexture(IDirect3DBaseTexture9 * sourceTexture,IDirect3DBaseTexture9 * destinationTexture)5511 	long Direct3DDevice9::UpdateTexture(IDirect3DBaseTexture9 *sourceTexture, IDirect3DBaseTexture9 *destinationTexture)
5512 	{
5513 		CriticalSection cs(this);
5514 
5515 		TRACE("IDirect3DBaseTexture9 *sourceTexture = 0x%0.8p, IDirect3DBaseTexture9 *destinationTexture = 0x%0.8p", sourceTexture, destinationTexture);
5516 
5517 		if(!sourceTexture || !destinationTexture)
5518 		{
5519 			return INVALIDCALL();
5520 		}
5521 
5522 		// FIXME: Check memory pools
5523 
5524 		D3DRESOURCETYPE type = sourceTexture->GetType();
5525 
5526 		if(type != destinationTexture->GetType())
5527 		{
5528 			return INVALIDCALL();
5529 		}
5530 
5531 		switch(type)
5532 		{
5533 		case D3DRTYPE_TEXTURE:
5534 			{
5535 				IDirect3DTexture9 *source;
5536 				IDirect3DTexture9 *dest;
5537 
5538 				sourceTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&source);
5539 				destinationTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&dest);
5540 
5541 				ASSERT(source && dest);
5542 
5543 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5544 				{
5545 					IDirect3DSurface9 *sourceSurface;
5546 					IDirect3DSurface9 *destinationSurface;
5547 
5548 					source->GetSurfaceLevel(level, &sourceSurface);
5549 					dest->GetSurfaceLevel(level, &destinationSurface);
5550 
5551 					UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5552 
5553 					sourceSurface->Release();
5554 					destinationSurface->Release();
5555 				}
5556 
5557 				source->Release();
5558 				dest->Release();
5559 			}
5560 			break;
5561 		case D3DRTYPE_VOLUMETEXTURE:
5562 			{
5563 				IDirect3DVolumeTexture9 *source;
5564 				IDirect3DVolumeTexture9 *dest;
5565 
5566 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&source);
5567 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&dest);
5568 
5569 				ASSERT(source && dest);
5570 
5571 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5572 				{
5573 					IDirect3DVolume9 *sourceVolume;
5574 					IDirect3DVolume9 *destinationVolume;
5575 
5576 					source->GetVolumeLevel(level, &sourceVolume);
5577 					dest->GetVolumeLevel(level, &destinationVolume);
5578 
5579 					updateVolume(sourceVolume, destinationVolume);
5580 
5581 					sourceVolume->Release();
5582 					destinationVolume->Release();
5583 				}
5584 
5585 				source->Release();
5586 				dest->Release();
5587 			}
5588 			break;
5589 		case D3DRTYPE_CUBETEXTURE:
5590 			{
5591 				IDirect3DCubeTexture9 *source;
5592 				IDirect3DCubeTexture9 *dest;
5593 
5594 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&source);
5595 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&dest);
5596 
5597 				ASSERT(source && dest);
5598 
5599 				for(int face = 0; face < 6; face++)
5600 				{
5601 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5602 					{
5603 						IDirect3DSurface9 *sourceSurface;
5604 						IDirect3DSurface9 *destinationSurface;
5605 
5606 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface);
5607 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface);
5608 
5609 						UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5610 
5611 						sourceSurface->Release();
5612 						destinationSurface->Release();
5613 					}
5614 				}
5615 
5616 				source->Release();
5617 				dest->Release();
5618 			}
5619 			break;
5620 		default:
5621 			UNIMPLEMENTED();
5622 		}
5623 
5624 		return D3D_OK;
5625 	}
5626 
ValidateDevice(unsigned long * numPasses)5627 	long Direct3DDevice9::ValidateDevice(unsigned long *numPasses)
5628 	{
5629 		CriticalSection cs(this);
5630 
5631 		TRACE("unsigned long *numPasses = 0x%0.8p", numPasses);
5632 
5633 		if(!numPasses)
5634 		{
5635 			return INVALIDCALL();
5636 		}
5637 
5638 		*numPasses = 1;
5639 
5640 		return D3D_OK;
5641 	}
5642 
getAdapterDisplayMode(unsigned int adapter,D3DDISPLAYMODE * mode)5643 	long Direct3DDevice9::getAdapterDisplayMode(unsigned int adapter, D3DDISPLAYMODE *mode)
5644 	{
5645 		return d3d9->GetAdapterDisplayMode(adapter, mode);
5646 	}
5647 
typeStride(unsigned char streamType)5648 	int Direct3DDevice9::typeStride(unsigned char streamType)
5649 	{
5650 		static int LUT[] =
5651 		{
5652 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.)
5653 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.)
5654 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.)
5655 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float
5656 			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)
5657 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte
5658 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.)
5659 			8,	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short
5660 			4,	// D3DDECLTYPE_UBYTE4N   =  8,  // Each of 4 bytes is normalized by dividing to 255.0
5661 			4,	// D3DDECLTYPE_SHORT2N   =  9,  // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
5662 			8,	// D3DDECLTYPE_SHORT4N   = 10,  // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
5663 			4,	// D3DDECLTYPE_USHORT2N  = 11,  // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
5664 			8,	// D3DDECLTYPE_USHORT4N  = 12,  // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
5665 			4,	// D3DDECLTYPE_UDEC3     = 13,  // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
5666 			4,	// D3DDECLTYPE_DEC3N     = 14,  // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
5667 			4,	// D3DDECLTYPE_FLOAT16_2 = 15,  // Two 16-bit floating point values, expanded to (value, value, 0, 1)
5668 			8,	// D3DDECLTYPE_FLOAT16_4 = 16,  // Four 16-bit floating point values
5669 			0,	// D3DDECLTYPE_UNUSED    = 17,  // When the type field in a decl is unused.
5670 		};
5671 
5672 		return LUT[streamType];
5673 	}
5674 
instanceData()5675 	bool Direct3DDevice9::instanceData()
5676 	{
5677 		ASSERT(vertexDeclaration);
5678 
5679 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5680 		unsigned int numElements;
5681 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5682 
5683 		bool instanceData = false;
5684 
5685 		for(unsigned int i = 0; i < numElements - 1; i++)
5686 		{
5687 			unsigned short stream = vertexElement[i].Stream;
5688 
5689 			if(stream != 0)
5690 			{
5691 				instanceData = instanceData || (streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA) != 0;
5692 			}
5693 		}
5694 
5695 		return instanceData;
5696 	}
5697 
bindResources(Direct3DIndexBuffer9 * indexBuffer)5698 	bool Direct3DDevice9::bindResources(Direct3DIndexBuffer9 *indexBuffer)
5699 	{
5700 		if(!bindViewport())
5701 		{
5702 			return false;   // Zero-area target region
5703 		}
5704 
5705 		bindTextures();
5706 		bindIndexBuffer(indexBuffer);
5707 		bindShaderConstants();
5708 		bindLights();
5709 
5710 		return true;
5711 	}
5712 
bindVertexStreams(int base,bool instancing,int instance)5713 	void Direct3DDevice9::bindVertexStreams(int base, bool instancing, int instance)
5714 	{
5715 		ASSERT(vertexDeclaration);
5716 
5717 		renderer->resetInputStreams(vertexDeclaration->isPreTransformed());
5718 
5719 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5720 		unsigned int numElements;
5721 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5722 
5723 		// Bind vertex data streams
5724 		for(unsigned int i = 0; i < numElements - 1; i++)
5725 		{
5726 			unsigned short stream = vertexElement[i].Stream;
5727 			unsigned short offset = vertexElement[i].Offset;
5728 			unsigned char type = vertexElement[i].Type;
5729 			unsigned char method = vertexElement[i].Method;
5730 			unsigned char usage = vertexElement[i].Usage;
5731 			unsigned char index = vertexElement[i].UsageIndex;
5732 
5733 			ASSERT(method == D3DDECLMETHOD_DEFAULT);	// FIXME: Unimplemented
5734 
5735 			if(!dataStream[stream])
5736 			{
5737 				continue;
5738 			}
5739 
5740 			Direct3DVertexBuffer9 *streamBuffer = dataStream[stream];
5741 			sw::Resource *resource = streamBuffer->getResource();
5742 			const void *buffer = ((char*)resource->data() + streamOffset[stream]) + offset;
5743 
5744 			int stride = streamStride[stream];
5745 
5746 			if(instancing && streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA)
5747 			{
5748 				int instanceFrequency = streamSourceFreq[stream] & ~D3DSTREAMSOURCE_INSTANCEDATA;
5749 				buffer = (char*)buffer + stride * (instance / instanceFrequency);
5750 
5751 				stride = 0;
5752 			}
5753 			else
5754 			{
5755 				buffer = (char*)buffer + stride * base;
5756 			}
5757 
5758 			sw::Stream attribute(resource, buffer, stride);
5759 
5760 			switch(type)
5761 			{
5762 			case D3DDECLTYPE_FLOAT1:    attribute.define(sw::STREAMTYPE_FLOAT, 1, false);  break;
5763 			case D3DDECLTYPE_FLOAT2:    attribute.define(sw::STREAMTYPE_FLOAT, 2, false);  break;
5764 			case D3DDECLTYPE_FLOAT3:    attribute.define(sw::STREAMTYPE_FLOAT, 3, false);  break;
5765 			case D3DDECLTYPE_FLOAT4:    attribute.define(sw::STREAMTYPE_FLOAT, 4, false);  break;
5766 			case D3DDECLTYPE_D3DCOLOR:  attribute.define(sw::STREAMTYPE_COLOR, 4, false);  break;
5767 			case D3DDECLTYPE_UBYTE4:    attribute.define(sw::STREAMTYPE_BYTE, 4, false);   break;
5768 			case D3DDECLTYPE_SHORT2:    attribute.define(sw::STREAMTYPE_SHORT, 2, false);  break;
5769 			case D3DDECLTYPE_SHORT4:    attribute.define(sw::STREAMTYPE_SHORT, 4, false);  break;
5770 			case D3DDECLTYPE_UBYTE4N:   attribute.define(sw::STREAMTYPE_BYTE, 4, true);    break;
5771 			case D3DDECLTYPE_SHORT2N:   attribute.define(sw::STREAMTYPE_SHORT, 2, true);   break;
5772 			case D3DDECLTYPE_SHORT4N:   attribute.define(sw::STREAMTYPE_SHORT, 4, true);   break;
5773 			case D3DDECLTYPE_USHORT2N:  attribute.define(sw::STREAMTYPE_USHORT, 2, true);  break;
5774 			case D3DDECLTYPE_USHORT4N:  attribute.define(sw::STREAMTYPE_USHORT, 4, true);  break;
5775 			case D3DDECLTYPE_UDEC3:     attribute.define(sw::STREAMTYPE_UDEC3, 3, false);  break;
5776 			case D3DDECLTYPE_DEC3N:     attribute.define(sw::STREAMTYPE_DEC3N, 3, true);   break;
5777 			case D3DDECLTYPE_FLOAT16_2: attribute.define(sw::STREAMTYPE_HALF, 2, false);   break;
5778 			case D3DDECLTYPE_FLOAT16_4: attribute.define(sw::STREAMTYPE_HALF, 4, false);   break;
5779 			case D3DDECLTYPE_UNUSED:    attribute.defaults();                              break;
5780 			default:
5781 				ASSERT(false);
5782 			}
5783 
5784 			if(vertexShader)
5785 			{
5786 				const sw::VertexShader *shader = vertexShader->getVertexShader();
5787 
5788 				if(!vertexDeclaration->isPreTransformed())
5789 				{
5790 					for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
5791 					{
5792 						if(usage == shader->input[i].usage &&
5793 						   index == shader->input[i].index)
5794 						{
5795 							renderer->setInputStream(i, attribute);
5796 
5797 							break;
5798 						}
5799 					}
5800 				}
5801 				else   // Bind directly to the output
5802 				{
5803 					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
5804 					{
5805 						if((usage == shader->output[i][0].usage || (usage == D3DDECLUSAGE_POSITIONT && shader->output[i][0].usage == D3DDECLUSAGE_POSITION)) &&
5806 						    index == shader->output[i][0].index)
5807 						{
5808 							renderer->setInputStream(i, attribute);
5809 
5810 							break;
5811 						}
5812 					}
5813 				}
5814 			}
5815 			else
5816 			{
5817 				switch(usage)
5818 				{
5819 				case D3DDECLUSAGE_POSITION:     renderer->setInputStream(sw::Position, attribute);                                       break;
5820 				case D3DDECLUSAGE_BLENDWEIGHT:  renderer->setInputStream(sw::BlendWeight, attribute);                                    break;
5821 				case D3DDECLUSAGE_BLENDINDICES: renderer->setInputStream(sw::BlendIndices, attribute.define(sw::STREAMTYPE_INDICES, 1)); break;
5822 				case D3DDECLUSAGE_NORMAL:       renderer->setInputStream(sw::Normal, attribute.define(sw::STREAMTYPE_FLOAT, 3));         break;
5823 				case D3DDECLUSAGE_PSIZE:        renderer->setInputStream(sw::PointSize, attribute.define(sw::STREAMTYPE_FLOAT, 1));      break;
5824 				case D3DDECLUSAGE_TEXCOORD:     renderer->setInputStream(sw::TexCoord0 + index, attribute);                              break;
5825 				case D3DDECLUSAGE_TANGENT:      /* Ignored */                                                                            break;
5826 				case D3DDECLUSAGE_BINORMAL:     /* Ignored */                                                                            break;
5827 				case D3DDECLUSAGE_TESSFACTOR:   UNIMPLEMENTED();                                                                         break;
5828 				case D3DDECLUSAGE_POSITIONT:    renderer->setInputStream(sw::PositionT, attribute.define(sw::STREAMTYPE_FLOAT, 4));      break;
5829 				case D3DDECLUSAGE_COLOR:        renderer->setInputStream(sw::Color0 + index, attribute.define(sw::STREAMTYPE_COLOR, 4)); break;
5830 				case D3DDECLUSAGE_FOG:          /* Ignored */                                                                            break;
5831 				case D3DDECLUSAGE_DEPTH:        /* Ignored */                                                                            break;
5832 				case D3DDECLUSAGE_SAMPLE:       UNIMPLEMENTED();                                                                         break;
5833 				default:
5834 					ASSERT(false);
5835 				}
5836 			}
5837 		}
5838 	}
5839 
bindIndexBuffer(Direct3DIndexBuffer9 * indexBuffer)5840 	void Direct3DDevice9::bindIndexBuffer(Direct3DIndexBuffer9 *indexBuffer)
5841 	{
5842 		sw::Resource *resource = 0;
5843 
5844 		if(indexBuffer)
5845 		{
5846 			resource = indexBuffer->getResource();
5847 		}
5848 
5849 		renderer->setIndexBuffer(resource);
5850 	}
5851 
bindShaderConstants()5852 	void Direct3DDevice9::bindShaderConstants()
5853 	{
5854 		if(pixelShaderDirty)
5855 		{
5856 			if(pixelShader)
5857 			{
5858 				if(pixelShaderConstantsBDirty)
5859 				{
5860 					renderer->setPixelShaderConstantB(0, pixelShaderConstantB, pixelShaderConstantsBDirty);
5861 				}
5862 
5863 				if(pixelShaderConstantsFDirty)
5864 				{
5865 					renderer->setPixelShaderConstantF(0, pixelShaderConstantF[0], pixelShaderConstantsFDirty);
5866 				}
5867 
5868 				if(pixelShaderConstantsIDirty)
5869 				{
5870 					renderer->setPixelShaderConstantI(0, pixelShaderConstantI[0], pixelShaderConstantsIDirty);
5871 				}
5872 
5873 				renderer->setPixelShader(pixelShader->getPixelShader());   // Loads shader constants set with DEF
5874 				pixelShaderConstantsBDirty = pixelShader->getPixelShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty
5875 				pixelShaderConstantsFDirty = pixelShader->getPixelShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty
5876 				pixelShaderConstantsIDirty = pixelShader->getPixelShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty
5877 			}
5878 			else
5879 			{
5880 				renderer->setPixelShader(0);
5881 			}
5882 
5883 			pixelShaderDirty = false;
5884 		}
5885 
5886 		if(vertexShaderDirty)
5887 		{
5888 			if(vertexShader)
5889 			{
5890 				if(vertexShaderConstantsBDirty)
5891 				{
5892 					renderer->setVertexShaderConstantB(0, vertexShaderConstantB, vertexShaderConstantsBDirty);
5893 				}
5894 
5895 				if(vertexShaderConstantsFDirty)
5896 				{
5897 					renderer->setVertexShaderConstantF(0, vertexShaderConstantF[0], vertexShaderConstantsFDirty);
5898 				}
5899 
5900 				if(vertexShaderConstantsIDirty)
5901 				{
5902 					renderer->setVertexShaderConstantI(0, vertexShaderConstantI[0], vertexShaderConstantsIDirty);
5903 				}
5904 
5905 				renderer->setVertexShader(vertexShader->getVertexShader());   // Loads shader constants set with DEF
5906 				vertexShaderConstantsBDirty = vertexShader->getVertexShader()->dirtyConstantsB;   // Shader DEF'ed constants are dirty
5907 				vertexShaderConstantsFDirty = vertexShader->getVertexShader()->dirtyConstantsF;   // Shader DEF'ed constants are dirty
5908 				vertexShaderConstantsIDirty = vertexShader->getVertexShader()->dirtyConstantsI;   // Shader DEF'ed constants are dirty
5909 			}
5910 			else
5911 			{
5912 				renderer->setVertexShader(0);
5913 			}
5914 
5915 			vertexShaderDirty = false;
5916 		}
5917 	}
5918 
bindLights()5919 	void Direct3DDevice9::bindLights()
5920 	{
5921 		if(!lightsDirty) return;
5922 
5923 		Lights::iterator i = light.begin();
5924 		int active = 0;
5925 
5926 		// Set and enable renderer lights
5927 		while(active < 8)
5928 		{
5929 			while(i != light.end() && !i->second.enable)
5930 			{
5931 				i++;
5932 			}
5933 
5934 			if(i == light.end())
5935 			{
5936 				break;
5937 			}
5938 
5939 			const Light &l = i->second;
5940 
5941 			sw::Point position(l.Position.x, l.Position.y, l.Position.z);
5942 			sw::Color<float> diffuse(l.Diffuse.r, l.Diffuse.g, l.Diffuse.b, l.Diffuse.a);
5943 			sw::Color<float> specular(l.Specular.r, l.Specular.g, l.Specular.b, l.Specular.a);
5944 			sw::Color<float> ambient(l.Ambient.r, l.Ambient.g, l.Ambient.b, l.Ambient.a);
5945 			sw::Vector direction(l.Direction.x, l.Direction.y, l.Direction.z);
5946 
5947 			renderer->setLightDiffuse(active, diffuse);
5948 			renderer->setLightSpecular(active, specular);
5949 			renderer->setLightAmbient(active, ambient);
5950 
5951 			if(l.Type == D3DLIGHT_DIRECTIONAL)
5952 			{
5953 				// FIXME: Unsupported, make it a positional light far away without falloff
5954 				renderer->setLightPosition(active, -1e10f * direction);
5955 				renderer->setLightRange(active, l.Range);
5956 				renderer->setLightAttenuation(active, 1, 0, 0);
5957 			}
5958 			else if(l.Type == D3DLIGHT_SPOT)
5959 			{
5960 				// FIXME: Unsupported, make it a positional light
5961 				renderer->setLightPosition(active, position);
5962 				renderer->setLightRange(active, l.Range);
5963 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
5964 			}
5965 			else
5966 			{
5967 				renderer->setLightPosition(active, position);
5968 				renderer->setLightRange(active, l.Range);
5969 				renderer->setLightAttenuation(active, l.Attenuation0, l.Attenuation1, l.Attenuation2);
5970 			}
5971 
5972 			renderer->setLightEnable(active, true);
5973 
5974 			active++;
5975 			i++;
5976 		}
5977 
5978 		// Remaining lights are disabled
5979 		while(active < 8)
5980 		{
5981 			renderer->setLightEnable(active, false);
5982 
5983 			active++;
5984 		}
5985 
5986 		lightsDirty = false;
5987 	}
5988 
bindViewport()5989 	bool Direct3DDevice9::bindViewport()
5990 	{
5991 		if(viewport.Width <= 0 || viewport.Height <= 0)
5992 		{
5993 			return false;
5994 		}
5995 
5996 		if(scissorEnable)
5997 		{
5998 			if(scissorRect.left >= scissorRect.right || scissorRect.top >= scissorRect.bottom)
5999 			{
6000 				return false;
6001 			}
6002 
6003 			sw::Rect scissor;
6004 			scissor.x0 = scissorRect.left;
6005 			scissor.x1 = scissorRect.right;
6006 			scissor.y0 = scissorRect.top;
6007 			scissor.y1 = scissorRect.bottom;
6008 
6009 			renderer->setScissor(scissor);
6010 		}
6011 		else
6012 		{
6013 			sw::Rect scissor;
6014 			scissor.x0 = viewport.X;
6015 			scissor.x1 = viewport.X + viewport.Width;
6016 			scissor.y0 = viewport.Y;
6017 			scissor.y1 = viewport.Y + viewport.Height;
6018 
6019 			renderer->setScissor(scissor);
6020 		}
6021 
6022 		sw::Viewport view;
6023 		view.x0 = (float)viewport.X;
6024 		view.y0 = (float)viewport.Y + viewport.Height;
6025 		view.width = (float)viewport.Width;
6026 		view.height = -(float)viewport.Height;
6027 		view.minZ = viewport.MinZ;
6028 		view.maxZ = viewport.MaxZ;
6029 
6030 		renderer->setViewport(view);
6031 
6032 		return true;
6033 	}
6034 
bindTextures()6035 	void Direct3DDevice9::bindTextures()
6036 	{
6037 		for(int sampler = 0; sampler < 16 + 4; sampler++)
6038 		{
6039 			Direct3DBaseTexture9 *baseTexture = texture[sampler];
6040 
6041 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX;
6042 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group
6043 
6044 			bool textureUsed = false;
6045 
6046 			if(type == sw::SAMPLER_PIXEL && pixelShader)
6047 			{
6048 				textureUsed = pixelShader->getPixelShader()->usesSampler(index);
6049 			}
6050 			else if(type == sw::SAMPLER_VERTEX && vertexShader)
6051 			{
6052 				textureUsed = vertexShader->getVertexShader()->usesSampler(index);
6053 			}
6054 			else
6055 			{
6056 				textureUsed = true;   // FIXME: Check fixed-function use?
6057 			}
6058 
6059 			sw::Resource *resource = 0;
6060 
6061 			if(baseTexture && textureUsed)
6062 			{
6063 				resource = baseTexture->getResource();
6064 			}
6065 
6066 			renderer->setTextureResource(sampler, resource);
6067 
6068 			if(baseTexture && textureUsed)
6069 			{
6070 				baseTexture->GenerateMipSubLevels();
6071 			}
6072 
6073 			if(baseTexture && textureUsed)
6074 			{
6075 				int levelCount = baseTexture->getInternalLevelCount();
6076 
6077 				int textureLOD = baseTexture->GetLOD();
6078 				int samplerLOD = samplerState[sampler][D3DSAMP_MAXMIPLEVEL];
6079 				int LOD = textureLOD > samplerLOD ? textureLOD : samplerLOD;
6080 
6081 				if(samplerState[sampler][D3DSAMP_MIPFILTER] == D3DTEXF_NONE)
6082 				{
6083 					LOD = 0;
6084 				}
6085 
6086 				switch(baseTexture->GetType())
6087 				{
6088 				case D3DRTYPE_TEXTURE:
6089 					{
6090 						Direct3DTexture9 *texture = dynamic_cast<Direct3DTexture9*>(baseTexture);
6091 						Direct3DSurface9 *surface;
6092 
6093 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6094 						{
6095 							int surfaceLevel = mipmapLevel;
6096 
6097 							if(surfaceLevel < LOD)
6098 							{
6099 								surfaceLevel = LOD;
6100 							}
6101 
6102 							if(surfaceLevel < 0)
6103 							{
6104 								surfaceLevel = 0;
6105 							}
6106 							else if(surfaceLevel >= levelCount)
6107 							{
6108 								surfaceLevel = levelCount - 1;
6109 							}
6110 
6111 							surface = texture->getInternalSurfaceLevel(surfaceLevel);
6112 							renderer->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);
6113 						}
6114 					}
6115 					break;
6116 				case D3DRTYPE_CUBETEXTURE:
6117 					for(int face = 0; face < 6; face++)
6118 					{
6119 						Direct3DCubeTexture9 *cubeTexture = dynamic_cast<Direct3DCubeTexture9*>(baseTexture);
6120 						Direct3DSurface9 *surface;
6121 
6122 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6123 						{
6124 							int surfaceLevel = mipmapLevel;
6125 
6126 							if(surfaceLevel < LOD)
6127 							{
6128 								surfaceLevel = LOD;
6129 							}
6130 
6131 							if(surfaceLevel < 0)
6132 							{
6133 								surfaceLevel = 0;
6134 							}
6135 							else if(surfaceLevel >= levelCount)
6136 							{
6137 								surfaceLevel = levelCount - 1;
6138 							}
6139 
6140 							surface = cubeTexture->getInternalCubeMapSurface((D3DCUBEMAP_FACES)face, surfaceLevel);
6141 							renderer->setTextureLevel(sampler, face, mipmapLevel, surface, sw::TEXTURE_CUBE);
6142 						}
6143 					}
6144 					break;
6145 				case D3DRTYPE_VOLUMETEXTURE:
6146 					{
6147 						Direct3DVolumeTexture9 *volumeTexture = dynamic_cast<Direct3DVolumeTexture9*>(baseTexture);
6148 						Direct3DVolume9 *volume;
6149 
6150 						for(int mipmapLevel = 0; mipmapLevel < sw::MIPMAP_LEVELS; mipmapLevel++)
6151 						{
6152 							int surfaceLevel = mipmapLevel;
6153 
6154 							if(surfaceLevel < LOD)
6155 							{
6156 								surfaceLevel = LOD;
6157 							}
6158 
6159 							if(surfaceLevel < 0)
6160 							{
6161 								surfaceLevel = 0;
6162 							}
6163 							else if(surfaceLevel >= levelCount)
6164 							{
6165 								surfaceLevel = levelCount - 1;
6166 							}
6167 
6168 							volume = volumeTexture->getInternalVolumeLevel(surfaceLevel);
6169 							renderer->setTextureLevel(sampler, 0, mipmapLevel, volume, sw::TEXTURE_3D);
6170 						}
6171 					}
6172 					break;
6173 				default:
6174 					UNIMPLEMENTED();
6175 				}
6176 			}
6177 			else
6178 			{
6179 				renderer->setTextureLevel(sampler, 0, 0, 0, sw::TEXTURE_NULL);
6180 			}
6181 		}
6182 	}
6183 
isRecording() const6184 	bool Direct3DDevice9::isRecording() const
6185 	{
6186 		return stateRecorder != 0;
6187 	}
6188 
setOcclusionEnabled(bool enable)6189 	void Direct3DDevice9::setOcclusionEnabled(bool enable)
6190 	{
6191 		renderer->setOcclusionEnabled(enable);
6192 	}
6193 
removeQuery(sw::Query * query)6194 	void Direct3DDevice9::removeQuery(sw::Query *query)
6195 	{
6196 		renderer->removeQuery(query);
6197 	}
6198 
addQuery(sw::Query * query)6199 	void Direct3DDevice9::addQuery(sw::Query *query)
6200 	{
6201 		renderer->addQuery(query);
6202 	}
6203 
stretchRect(Direct3DSurface9 * source,const RECT * sourceRect,Direct3DSurface9 * dest,const RECT * destRect,D3DTEXTUREFILTERTYPE filter)6204 	void Direct3DDevice9::stretchRect(Direct3DSurface9 *source, const RECT *sourceRect, Direct3DSurface9 *dest, const RECT *destRect, D3DTEXTUREFILTERTYPE filter)
6205 	{
6206 		D3DSURFACE_DESC sourceDescription;
6207 		D3DSURFACE_DESC destDescription;
6208 
6209 		source->GetDesc(&sourceDescription);
6210 		dest->GetDesc(&destDescription);
6211 
6212 		int sWidth = source->getWidth();
6213 		int sHeight = source->getHeight();
6214 		int dWidth = dest->getWidth();
6215 		int dHeight = dest->getHeight();
6216 
6217 		sw::Rect sRect(0, 0, sWidth, sHeight);
6218 		sw::Rect dRect(0, 0, dWidth, dHeight);
6219 
6220 		if(sourceRect)
6221 		{
6222 			sRect.x0 = sourceRect->left;
6223 			sRect.y0 = sourceRect->top;
6224 			sRect.x1 = sourceRect->right;
6225 			sRect.y1 = sourceRect->bottom;
6226 		}
6227 
6228 		if(destRect)
6229 		{
6230 			dRect.x0 = destRect->left;
6231 			dRect.y0 = destRect->top;
6232 			dRect.x1 = destRect->right;
6233 			dRect.y1 = destRect->bottom;
6234 		}
6235 
6236 		bool scaling = (sRect.x1 - sRect.x0 != dRect.x1 - dRect.x0) || (sRect.y1 - sRect.y0 != dRect.y1 - dRect.y0);
6237 		bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();
6238 		bool depthStencil = (sourceDescription.Usage & D3DUSAGE_DEPTHSTENCIL) == D3DUSAGE_DEPTHSTENCIL;
6239 		bool alpha0xFF = false;
6240 
6241 		if((sourceDescription.Format == D3DFMT_A8R8G8B8 && destDescription.Format == D3DFMT_X8R8G8B8) ||
6242 		   (sourceDescription.Format == D3DFMT_X8R8G8B8 && destDescription.Format == D3DFMT_A8R8G8B8))
6243 		{
6244 			equalFormats = true;
6245 			alpha0xFF = true;
6246 		}
6247 
6248 		if(depthStencil)   // Copy entirely, internally   // FIXME: Check
6249 		{
6250 			if(source->hasDepth())
6251 			{
6252 				byte *sourceBuffer = (byte*)source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6253 				byte *destBuffer = (byte*)dest->lockInternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
6254 
6255 				unsigned int width = source->getWidth();
6256 				unsigned int height = source->getHeight();
6257 				unsigned int pitch = source->getInternalPitchB();
6258 
6259 				for(unsigned int y = 0; y < height; y++)
6260 				{
6261 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
6262 
6263 					sourceBuffer += pitch;
6264 					destBuffer += pitch;
6265 				}
6266 
6267 				source->unlockInternal();
6268 				dest->unlockInternal();
6269 			}
6270 
6271 			if(source->hasStencil())
6272 			{
6273 				byte *sourceBuffer = (byte*)source->lockStencil(0, sw::PUBLIC);
6274 				byte *destBuffer = (byte*)dest->lockStencil(0, sw::PUBLIC);
6275 
6276 				unsigned int width = source->getWidth();
6277 				unsigned int height = source->getHeight();
6278 				unsigned int pitch = source->getStencilPitchB();
6279 
6280 				for(unsigned int y = 0; y < height; y++)
6281 				{
6282 					memcpy(destBuffer, sourceBuffer, pitch);   // FIXME: Only copy width * bytes
6283 
6284 					sourceBuffer += pitch;
6285 					destBuffer += pitch;
6286 				}
6287 
6288 				source->unlockStencil();
6289 				dest->unlockStencil();
6290 			}
6291 		}
6292 		else if(!scaling && equalFormats)
6293 		{
6294 			unsigned char *sourceBytes = (unsigned char*)source->lockInternal(sRect.x0, sRect.y0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6295 			unsigned char *destBytes = (unsigned char*)dest->lockInternal(dRect.x0, dRect.y0, 0, sw::LOCK_READWRITE, sw::PUBLIC);
6296 			unsigned int sourcePitch = source->getInternalPitchB();
6297 			unsigned int destPitch = dest->getInternalPitchB();
6298 
6299 			unsigned int width = dRect.x1 - dRect.x0;
6300 			unsigned int height = dRect.y1 - dRect.y0;
6301 			unsigned int bytes = width * sw::Surface::bytes(source->getInternalFormat());
6302 
6303 			for(unsigned int y = 0; y < height; y++)
6304 			{
6305 				memcpy(destBytes, sourceBytes, bytes);
6306 
6307 				if(alpha0xFF)
6308 				{
6309 					for(unsigned int x = 0; x < width; x++)
6310 					{
6311 						destBytes[4 * x + 3] = 0xFF;
6312 					}
6313 				}
6314 
6315 				sourceBytes += sourcePitch;
6316 				destBytes += destPitch;
6317 			}
6318 
6319 			source->unlockInternal();
6320 			dest->unlockInternal();
6321 		}
6322 		else
6323 		{
6324 			renderer->blit(source, sRect, dest, dRect, filter >= D3DTEXF_LINEAR);
6325 		}
6326 	}
6327 
updateVolume(IDirect3DVolume9 * sourceVolume,IDirect3DVolume9 * destinationVolume)6328 	long Direct3DDevice9::updateVolume(IDirect3DVolume9 *sourceVolume, IDirect3DVolume9 *destinationVolume)
6329 	{
6330 		TRACE("IDirect3DVolume9 *sourceVolume = 0x%0.8p, IDirect3DVolume9 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume);
6331 
6332 		if(!sourceVolume || !destinationVolume)
6333 		{
6334 			return INVALIDCALL();
6335 		}
6336 
6337 		D3DVOLUME_DESC sourceDescription;
6338 		D3DVOLUME_DESC destinationDescription;
6339 
6340 		sourceVolume->GetDesc(&sourceDescription);
6341 		destinationVolume->GetDesc(&destinationDescription);
6342 
6343 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||
6344 		   destinationDescription.Pool != D3DPOOL_DEFAULT ||
6345 		   sourceDescription.Format != destinationDescription.Format ||
6346 		   sourceDescription.Width  != destinationDescription.Width ||
6347 		   sourceDescription.Height != destinationDescription.Height ||
6348 		   sourceDescription.Depth  != destinationDescription.Depth)
6349 		{
6350 			return INVALIDCALL();
6351 		}
6352 
6353 		sw::Surface *source = static_cast<Direct3DVolume9*>(sourceVolume);
6354 		sw::Surface *dest = static_cast<Direct3DVolume9*>(destinationVolume);
6355 
6356 		if(source->getExternalPitchB() != dest->getExternalPitchB() ||
6357 		   source->getExternalSliceB() != dest->getExternalSliceB())
6358 		{
6359 			UNIMPLEMENTED();
6360 		}
6361 
6362 		void *sBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6363 		void *dBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
6364 
6365 		memcpy(dBuffer, sBuffer, source->getExternalSliceB() * sourceDescription.Depth);
6366 
6367 		source->unlockExternal();
6368 		dest->unlockExternal();
6369 
6370 		return D3D_OK;
6371 	}
6372 
validRectangle(const RECT * rect,IDirect3DSurface9 * surface)6373 	bool Direct3DDevice9::validRectangle(const RECT *rect, IDirect3DSurface9 *surface)
6374 	{
6375 		if(!rect)
6376 		{
6377 			return true;
6378 		}
6379 
6380 		if(rect->right <= rect->left || rect->bottom <= rect->top)
6381 		{
6382 			return false;
6383 		}
6384 
6385 		if(rect->left < 0 || rect->top < 0)
6386 		{
6387 			return false;
6388 		}
6389 
6390 		D3DSURFACE_DESC description;
6391 		surface->GetDesc(&description);
6392 
6393 		if(rect->right > (int)description.Width || rect->bottom > (int)description.Height)
6394 		{
6395 			return false;
6396 		}
6397 
6398 		return true;
6399 	}
6400 
configureFPU()6401 	void Direct3DDevice9::configureFPU()
6402 	{
6403 	//	_controlfp(_PC_24, _MCW_PC);     // Single-precision
6404 		_controlfp(_MCW_EM, _MCW_EM);    // Mask all exceptions
6405 		_controlfp(_RC_NEAR, _MCW_RC);   // Round to nearest
6406 	}
6407 }
6408