• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 && 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::Rect clearRect(rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
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 std::shared_ptr<sw::Routine> blitRoutine;
1834 			static sw::BlitState blitState = {};
1835 
1836 			sw::BlitState update;
1837 			update.width = sourceDescription.Width;
1838 			update.height = sourceDescription.Height;
1839 			update.sourceFormat = sw::FORMAT_A8R8G8B8;
1840 			update.sourceStride = source->getExternalPitchB();
1841 			update.destFormat = sw::FORMAT_A8R8G8B8;
1842 			update.destStride = dest->getExternalPitchB();
1843 			update.cursorHeight = 0;
1844 			update.cursorWidth = 0;
1845 
1846 			if(memcmp(&blitState, &update, sizeof(sw::BlitState)) != 0)
1847 			{
1848 				blitState = update;
1849 				blitRoutine = sw::FrameBuffer::copyRoutine(blitState);
1850 				blitFunction = (void(__cdecl*)(void*, void*))blitRoutine->getEntry();
1851 			}
1852 
1853 			blitFunction(destBuffer, sourceBuffer);
1854 
1855 			dest->unlockExternal();
1856 			source->unlockExternal();
1857 		}
1858 		else
1859 		{
1860 			return UpdateSurface(renderTarget, 0, destSurface, 0);
1861 		}
1862 
1863 		return D3D_OK;
1864 	}
1865 
GetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long * value)1866 	long Direct3DDevice9::GetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long *value)
1867 	{
1868 		CriticalSection cs(this);
1869 
1870 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE type = %d, unsigned long *value = 0x%0.8p", sampler, state, value);
1871 
1872 		if(!value || state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)   // FIXME: Set *value to 0?
1873 		{
1874 			return INVALIDCALL();
1875 		}
1876 
1877 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1878 		{
1879 			return INVALIDCALL();
1880 		}
1881 
1882 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
1883 		{
1884 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
1885 		}
1886 
1887 		*value = samplerState[sampler][state];
1888 
1889 		return D3D_OK;
1890 	}
1891 
GetScissorRect(RECT * rect)1892 	long Direct3DDevice9::GetScissorRect(RECT *rect)
1893 	{
1894 		CriticalSection cs(this);
1895 
1896 		TRACE("RECT *rect = 0x%0.8p", rect);
1897 
1898 		if(!rect)
1899 		{
1900 			return INVALIDCALL();
1901 		}
1902 
1903 		*rect = scissorRect;
1904 
1905 		return D3D_OK;
1906 	}
1907 
GetSoftwareVertexProcessing()1908 	int Direct3DDevice9::GetSoftwareVertexProcessing()
1909 	{
1910 		CriticalSection cs(this);
1911 
1912 		TRACE("void");
1913 
1914 		return softwareVertexProcessing ? TRUE : FALSE;
1915 	}
1916 
GetStreamSource(unsigned int streamNumber,IDirect3DVertexBuffer9 ** streamData,unsigned int * offset,unsigned int * stride)1917 	long Direct3DDevice9::GetStreamSource(unsigned int streamNumber, IDirect3DVertexBuffer9 **streamData, unsigned int *offset, unsigned int *stride)
1918 	{
1919 		CriticalSection cs(this);
1920 
1921 		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);
1922 
1923 		if(streamNumber >= 16 || !streamData || !offset || !stride)
1924 		{
1925 			return INVALIDCALL();
1926 		}
1927 
1928 		*streamData = dataStream[streamNumber];
1929 
1930 		if(dataStream[streamNumber])
1931 		{
1932 			dataStream[streamNumber]->AddRef();
1933 		}
1934 
1935 		*offset = streamOffset[streamNumber];
1936 		*stride = streamStride[streamNumber];
1937 
1938 		return D3D_OK;
1939 	}
1940 
GetStreamSourceFreq(unsigned int streamNumber,unsigned int * divider)1941 	long Direct3DDevice9::GetStreamSourceFreq(unsigned int streamNumber, unsigned int *divider)
1942 	{
1943 		CriticalSection cs(this);
1944 
1945 		TRACE("unsigned int streamNumber = %d, unsigned int *divider = 0x%0.8p", streamNumber, divider);
1946 
1947 		if(streamNumber >= 16 || !divider)
1948 		{
1949 			return INVALIDCALL();
1950 		}
1951 
1952 		*divider = streamSourceFreq[streamNumber];
1953 
1954 		return D3D_OK;
1955 	}
1956 
GetSwapChain(unsigned int index,IDirect3DSwapChain9 ** swapChain)1957 	long Direct3DDevice9::GetSwapChain(unsigned int index, IDirect3DSwapChain9 **swapChain)
1958 	{
1959 		CriticalSection cs(this);
1960 
1961 		TRACE("unsigned int index = %d, IDirect3DSwapChain9 **swapChain = 0x%0.8p", index, swapChain);
1962 
1963 		if(!swapChain || index >= GetNumberOfSwapChains())
1964 		{
1965 			return INVALIDCALL();
1966 		}
1967 
1968 		*swapChain = this->swapChain;
1969 
1970 		if(*swapChain)
1971 		{
1972 			(*swapChain)->AddRef();
1973 		}
1974 
1975 		return D3D_OK;
1976 	}
1977 
GetTexture(unsigned long sampler,IDirect3DBaseTexture9 ** texture)1978 	long Direct3DDevice9::GetTexture(unsigned long sampler, IDirect3DBaseTexture9 **texture)
1979 	{
1980 		CriticalSection cs(this);
1981 
1982 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 **texture = 0x%0.8p", sampler, texture);
1983 
1984 		if(!texture)
1985 		{
1986 			return INVALIDCALL();
1987 		}
1988 
1989 		*texture = 0;
1990 
1991 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
1992 		{
1993 			return INVALIDCALL();
1994 		}
1995 
1996 		*texture = this->texture[sampler];
1997 
1998 		if(this->texture[sampler])
1999 		{
2000 			this->texture[sampler]->AddRef();
2001 		}
2002 
2003 		return D3D_OK;
2004 	}
2005 
GetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long * value)2006 	long Direct3DDevice9::GetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long *value)
2007 	{
2008 		CriticalSection cs(this);
2009 
2010 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long *value = 0x%0.8p", stage, type, value);
2011 
2012 		if(!value)
2013 		{
2014 			return INVALIDCALL();
2015 		}
2016 
2017 		*value = textureStageState[stage][type];
2018 
2019 		return D3D_OK;
2020 	}
2021 
GetTransform(D3DTRANSFORMSTATETYPE state,D3DMATRIX * matrix)2022 	long Direct3DDevice9::GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX *matrix)
2023 	{
2024 		CriticalSection cs(this);
2025 
2026 		TRACE("D3DTRANSFORMSTATETYPE state = %d, D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2027 
2028 		if(!matrix || state < 0 || state > 511)
2029 		{
2030 			return INVALIDCALL();
2031 		}
2032 
2033 		*matrix = this->matrix[state];
2034 
2035 		return D3D_OK;
2036 	}
2037 
GetVertexDeclaration(IDirect3DVertexDeclaration9 ** declaration)2038 	long Direct3DDevice9::GetVertexDeclaration(IDirect3DVertexDeclaration9 **declaration)
2039 	{
2040 		CriticalSection cs(this);
2041 
2042 		TRACE("IDirect3DVertexDeclaration9 **declaration = 0x%0.8p", declaration);
2043 
2044 		if(!declaration)
2045 		{
2046 			return INVALIDCALL();
2047 		}
2048 
2049 		*declaration = vertexDeclaration;
2050 
2051 		if(vertexDeclaration)
2052 		{
2053 			vertexDeclaration->AddRef();
2054 		}
2055 
2056 		return D3D_OK;
2057 	}
2058 
GetVertexShader(IDirect3DVertexShader9 ** shader)2059 	long Direct3DDevice9::GetVertexShader(IDirect3DVertexShader9 **shader)
2060 	{
2061 		CriticalSection cs(this);
2062 
2063 		TRACE("IDirect3DVertexShader9 **shader = 0x%0.8p", shader);
2064 
2065 		if(!shader)
2066 		{
2067 			return INVALIDCALL();
2068 		}
2069 
2070 		*shader = vertexShader;
2071 
2072 		if(vertexShader)
2073 		{
2074 			vertexShader->AddRef();
2075 		}
2076 
2077 		return D3D_OK;
2078 	}
2079 
GetVertexShaderConstantB(unsigned int startRegister,int * constantData,unsigned int count)2080 	long Direct3DDevice9::GetVertexShaderConstantB(unsigned int startRegister, int *constantData, unsigned int count)
2081 	{
2082 		CriticalSection cs(this);
2083 
2084 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2085 
2086 		if(!constantData)
2087 		{
2088 			return INVALIDCALL();
2089 		}
2090 
2091 		for(unsigned int i = 0; i < count; i++)
2092 		{
2093 			constantData[i] = vertexShaderConstantB[startRegister + i];
2094 		}
2095 
2096 		return D3D_OK;
2097 	}
2098 
GetVertexShaderConstantF(unsigned int startRegister,float * constantData,unsigned int count)2099 	long Direct3DDevice9::GetVertexShaderConstantF(unsigned int startRegister, float *constantData, unsigned int count)
2100 	{
2101 		CriticalSection cs(this);
2102 
2103 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2104 
2105 		if(!constantData)
2106 		{
2107 			return INVALIDCALL();
2108 		}
2109 
2110 		for(unsigned int i = 0; i < count; i++)
2111 		{
2112 			constantData[i * 4 + 0] = vertexShaderConstantF[startRegister + i][0];
2113 			constantData[i * 4 + 1] = vertexShaderConstantF[startRegister + i][1];
2114 			constantData[i * 4 + 2] = vertexShaderConstantF[startRegister + i][2];
2115 			constantData[i * 4 + 3] = vertexShaderConstantF[startRegister + i][3];
2116 		}
2117 
2118 		return D3D_OK;
2119 	}
2120 
GetVertexShaderConstantI(unsigned int startRegister,int * constantData,unsigned int count)2121 	long Direct3DDevice9::GetVertexShaderConstantI(unsigned int startRegister, int *constantData, unsigned int count)
2122 	{
2123 		CriticalSection cs(this);
2124 
2125 		TRACE("unsigned int startRegister = %d, int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2126 
2127 		if(!constantData)
2128 		{
2129 			return INVALIDCALL();
2130 		}
2131 
2132 		for(unsigned int i = 0; i < count; i++)
2133 		{
2134 			constantData[i * 4 + 0] = vertexShaderConstantI[startRegister + i][0];
2135 			constantData[i * 4 + 1] = vertexShaderConstantI[startRegister + i][1];
2136 			constantData[i * 4 + 2] = vertexShaderConstantI[startRegister + i][2];
2137 			constantData[i * 4 + 3] = vertexShaderConstantI[startRegister + i][3];
2138 		}
2139 
2140 		return D3D_OK;
2141 	}
2142 
GetViewport(D3DVIEWPORT9 * viewport)2143 	long Direct3DDevice9::GetViewport(D3DVIEWPORT9 *viewport)
2144 	{
2145 		CriticalSection cs(this);
2146 
2147 		TRACE("D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
2148 
2149 		if(!viewport)
2150 		{
2151 			return INVALIDCALL();
2152 		}
2153 
2154 		*viewport = this->viewport;
2155 
2156 		return D3D_OK;
2157 	}
2158 
LightEnable(unsigned long index,int enable)2159 	long Direct3DDevice9::LightEnable(unsigned long index, int enable)
2160 	{
2161 		CriticalSection cs(this);
2162 
2163 		TRACE("unsigned long index = %d, int enable = %d", index, enable);
2164 
2165 		if(!light.exists(index))   // Insert default light
2166 		{
2167 			D3DLIGHT9 light;
2168 
2169 			light.Type = D3DLIGHT_DIRECTIONAL;
2170 			light.Diffuse.r = 1;
2171 			light.Diffuse.g = 1;
2172 			light.Diffuse.b = 1;
2173 			light.Diffuse.a = 0;
2174 			light.Specular.r = 0;
2175 			light.Specular.g = 0;
2176 			light.Specular.b = 0;
2177 			light.Specular.a = 0;
2178 			light.Ambient.r = 0;
2179 			light.Ambient.g = 0;
2180 			light.Ambient.b = 0;
2181 			light.Ambient.a = 0;
2182 			light.Position.x = 0;
2183 			light.Position.y = 0;
2184 			light.Position.z = 0;
2185 			light.Direction.x = 0;
2186 			light.Direction.y = 0;
2187 			light.Direction.z = 1;
2188 			light.Range = 0;
2189 			light.Falloff = 0;
2190 			light.Attenuation0 = 0;
2191 			light.Attenuation1 = 0;
2192 			light.Attenuation2 = 0;
2193 			light.Theta = 0;
2194 			light.Phi = 0;
2195 
2196 			this->light[index] = light;
2197 			this->light[index].enable = false;
2198 		}
2199 
2200 		if(!stateRecorder)
2201 		{
2202 			light[index].enable = (enable != FALSE);
2203 
2204 			lightsDirty = true;
2205 		}
2206 		else
2207 		{
2208 			stateRecorder->lightEnable(index, enable);
2209 		}
2210 
2211 		return D3D_OK;
2212 	}
2213 
MultiplyTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)2214 	long Direct3DDevice9::MultiplyTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
2215 	{
2216 		CriticalSection cs(this);
2217 
2218 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
2219 
2220 		if(!matrix)
2221 		{
2222 			return INVALIDCALL();
2223 		}
2224 
2225 		D3DMATRIX *current = &this->matrix[state];
2226 
2227 		sw::Matrix C(current->_11, current->_21, current->_31, current->_41,
2228 		             current->_12, current->_22, current->_32, current->_42,
2229 		             current->_13, current->_23, current->_33, current->_43,
2230 		             current->_14, current->_24, current->_34, current->_44);
2231 
2232 		sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
2233 		             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
2234 		             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
2235 		             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
2236 
2237 		switch(state)
2238 		{
2239 		case D3DTS_WORLD:
2240 			renderer->setModelMatrix(C * M);
2241 			break;
2242 		case D3DTS_VIEW:
2243 			renderer->setViewMatrix(C * M);
2244 			break;
2245 		case D3DTS_PROJECTION:
2246 			renderer->setProjectionMatrix(C * M);
2247 			break;
2248 		case D3DTS_TEXTURE0:
2249 			renderer->setTextureMatrix(0, C * M);
2250 			break;
2251 		case D3DTS_TEXTURE1:
2252 			renderer->setTextureMatrix(1, C * M);
2253 			break;
2254 		case D3DTS_TEXTURE2:
2255 			renderer->setTextureMatrix(2, C * M);
2256 			break;
2257 		case D3DTS_TEXTURE3:
2258 			renderer->setTextureMatrix(3, C * M);
2259 			break;
2260 		case D3DTS_TEXTURE4:
2261 			renderer->setTextureMatrix(4, C * M);
2262 			break;
2263 		case D3DTS_TEXTURE5:
2264 			renderer->setTextureMatrix(5, C * M);
2265 			break;
2266 		case D3DTS_TEXTURE6:
2267 			renderer->setTextureMatrix(6, C * M);
2268 			break;
2269 		case D3DTS_TEXTURE7:
2270 			renderer->setTextureMatrix(7, C * M);
2271 			break;
2272 		default:
2273 			if(state > 256 && state < 512)
2274 			{
2275 				renderer->setModelMatrix(C * M, state - 256);
2276 			}
2277 			else ASSERT(false);
2278 		}
2279 
2280 		return D3D_OK;
2281 	}
2282 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion)2283 	long Direct3DDevice9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
2284 	{
2285 		CriticalSection cs(this);
2286 
2287 		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);
2288 
2289 		return swapChain->Present(sourceRect, destRect, destWindowOverride, dirtyRegion, 0);
2290 	}
2291 
ProcessVertices(unsigned int srcStartIndex,unsigned int destIndex,unsigned int vertexCount,IDirect3DVertexBuffer9 * destBuffer,IDirect3DVertexDeclaration9 * vertexDeclaration,unsigned long flags)2292 	long Direct3DDevice9::ProcessVertices(unsigned int srcStartIndex, unsigned int destIndex, unsigned int vertexCount, IDirect3DVertexBuffer9 *destBuffer, IDirect3DVertexDeclaration9 *vertexDeclaration, unsigned long flags)
2293 	{
2294 		CriticalSection cs(this);
2295 
2296 		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);
2297 
2298 		if(!destBuffer)
2299 		{
2300 			return INVALIDCALL();
2301 		}
2302 
2303 		UNIMPLEMENTED();
2304 
2305 		return D3D_OK;
2306 	}
2307 
Reset(D3DPRESENT_PARAMETERS * presentParameters)2308 	long Direct3DDevice9::Reset(D3DPRESENT_PARAMETERS *presentParameters)
2309 	{
2310 		CriticalSection cs(this);
2311 
2312 		TRACE("D3DPRESENT_PARAMETERS *presentParameters = 0x%0.8p", presentParameters);
2313 
2314 		if(!presentParameters)
2315 		{
2316 			return INVALIDCALL();
2317 		}
2318 
2319 		deviceWindow = presentParameters->hDeviceWindow;
2320 
2321 		if(depthStencil)
2322 		{
2323 			depthStencil->unbind();
2324 			depthStencil = 0;
2325 		}
2326 
2327 		if(autoDepthStencil)
2328 		{
2329 			autoDepthStencil->unbind();
2330 			autoDepthStencil = 0;
2331 		}
2332 
2333 		for(int index = 0; index < 4; index++)
2334 		{
2335 			if(renderTarget[index])
2336 			{
2337 				renderTarget[index]->unbind();
2338 				renderTarget[index] = 0;
2339 			}
2340 		}
2341 
2342 		if(!swapChain)
2343 		{
2344 			swapChain = new Direct3DSwapChain9(this, presentParameters);
2345 			swapChain->bind();
2346 		}
2347 		else
2348 		{
2349 			swapChain->reset(presentParameters);
2350 		}
2351 
2352 		if(presentParameters->EnableAutoDepthStencil != FALSE)
2353 		{
2354 			bool lockable = false;
2355 
2356 			switch(presentParameters->AutoDepthStencilFormat)
2357 			{
2358 			case D3DFMT_D15S1:
2359 			case D3DFMT_D24S8:
2360 			case D3DFMT_D24X8:
2361 			case D3DFMT_D24X4S4:
2362 			case D3DFMT_D24FS8:
2363 			case D3DFMT_D32:
2364 			case D3DFMT_D16:
2365 			case D3DFMT_DF24:
2366 			case D3DFMT_DF16:
2367 			case D3DFMT_INTZ:
2368 				lockable = false;
2369 				break;
2370 			case D3DFMT_S8_LOCKABLE:
2371 			case D3DFMT_D16_LOCKABLE:
2372 			case D3DFMT_D32F_LOCKABLE:
2373 			case D3DFMT_D32_LOCKABLE:
2374 				lockable = true;
2375 				break;
2376 			default:
2377 				ASSERT(false);
2378 			}
2379 
2380 			autoDepthStencil = new Direct3DSurface9(this, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->AutoDepthStencilFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_DEPTHSTENCIL);
2381 			autoDepthStencil->bind();
2382 
2383 			SetDepthStencilSurface(autoDepthStencil);
2384 		}
2385 
2386 		IDirect3DSurface9 *renderTarget;
2387 		swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &renderTarget);
2388 		SetRenderTarget(0, renderTarget);
2389 		renderTarget->Release();
2390 
2391 		SetRenderTarget(1, 0);
2392 		SetRenderTarget(2, 0);
2393 		SetRenderTarget(3, 0);
2394 
2395 		softwareVertexProcessing = (behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) == D3DCREATE_SOFTWARE_VERTEXPROCESSING;
2396 
2397 		SetRenderState(D3DRS_ZENABLE, presentParameters->EnableAutoDepthStencil != FALSE ? D3DZB_TRUE : D3DZB_FALSE);
2398 		SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2399 		SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
2400 		SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2401 		SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2402 		SetRenderState(D3DRS_LASTPIXEL, TRUE);
2403 		SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
2404 		SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
2405 		SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
2406 		SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2407 		SetRenderState(D3DRS_ALPHAREF, 0);
2408 		SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS);
2409 		SetRenderState(D3DRS_DITHERENABLE, FALSE);
2410 		SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2411 		SetRenderState(D3DRS_FOGENABLE, FALSE);
2412 		SetRenderState(D3DRS_SPECULARENABLE, FALSE);
2413 	//	SetRenderState(D3DRS_ZVISIBLE, 0);
2414 		SetRenderState(D3DRS_FOGCOLOR, 0);
2415 		SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE);
2416 		SetRenderState(D3DRS_FOGSTART, FtoDW(0.0f));
2417 		SetRenderState(D3DRS_FOGEND, FtoDW(1.0f));
2418 		SetRenderState(D3DRS_FOGDENSITY, FtoDW(1.0f));
2419 		SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
2420 		SetRenderState(D3DRS_STENCILENABLE, FALSE);
2421 		SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
2422 		SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
2423 		SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
2424 		SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2425 		SetRenderState(D3DRS_STENCILREF, 0);
2426 		SetRenderState(D3DRS_STENCILMASK, 0xFFFFFFFF);
2427 		SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF);
2428 		SetRenderState(D3DRS_TEXTUREFACTOR, 0xFFFFFFFF);
2429 		SetRenderState(D3DRS_WRAP0, 0);
2430 		SetRenderState(D3DRS_WRAP1, 0);
2431 		SetRenderState(D3DRS_WRAP2, 0);
2432 		SetRenderState(D3DRS_WRAP3, 0);
2433 		SetRenderState(D3DRS_WRAP4, 0);
2434 		SetRenderState(D3DRS_WRAP5, 0);
2435 		SetRenderState(D3DRS_WRAP6, 0);
2436 		SetRenderState(D3DRS_WRAP7, 0);
2437 		SetRenderState(D3DRS_CLIPPING, TRUE);
2438 		SetRenderState(D3DRS_LIGHTING, TRUE);
2439 		SetRenderState(D3DRS_AMBIENT, 0);
2440 		SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
2441 		SetRenderState(D3DRS_COLORVERTEX, TRUE);
2442 		SetRenderState(D3DRS_LOCALVIEWER, TRUE);
2443 		SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
2444 		SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
2445 		SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
2446 		SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
2447 		SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL);
2448 		SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE);
2449 		SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2450 		SetRenderState(D3DRS_POINTSIZE, FtoDW(1.0f));
2451 		SetRenderState(D3DRS_POINTSIZE_MIN, FtoDW(1.0f));
2452 		SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
2453 		SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
2454 		SetRenderState(D3DRS_POINTSCALE_A, FtoDW(1.0f));
2455 		SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
2456 		SetRenderState(D3DRS_POINTSCALE_C, FtoDW(0.0f));
2457 		SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
2458 		SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
2459 		SetRenderState(D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE);
2460 		SetRenderState(D3DRS_DEBUGMONITORTOKEN, D3DDMT_ENABLE);
2461 		SetRenderState(D3DRS_POINTSIZE_MAX, FtoDW(64.0f));
2462 		SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE);
2463 		SetRenderState(D3DRS_COLORWRITEENABLE, 0x0000000F);
2464 		SetRenderState(D3DRS_TWEENFACTOR, FtoDW(0.0f));
2465 		SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
2466 		SetRenderState(D3DRS_POSITIONDEGREE, D3DDEGREE_CUBIC);
2467 		SetRenderState(D3DRS_NORMALDEGREE, D3DDEGREE_LINEAR);
2468 		SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
2469 		SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, FtoDW(0.0f));
2470 		SetRenderState(D3DRS_ANTIALIASEDLINEENABLE, FALSE);
2471 		SetRenderState(D3DRS_MINTESSELLATIONLEVEL, FtoDW(1.0f));
2472 		SetRenderState(D3DRS_MAXTESSELLATIONLEVEL, FtoDW(1.0f));
2473 		SetRenderState(D3DRS_ADAPTIVETESS_X, FtoDW(0.0f));
2474 		SetRenderState(D3DRS_ADAPTIVETESS_Y, FtoDW(0.0f));
2475 		SetRenderState(D3DRS_ADAPTIVETESS_Z, FtoDW(1.0f));
2476 		SetRenderState(D3DRS_ADAPTIVETESS_W, FtoDW(0.0f));
2477 		SetRenderState(D3DRS_ENABLEADAPTIVETESSELLATION, FALSE);
2478 		SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2479 		SetRenderState(D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_KEEP);
2480 		SetRenderState(D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP);
2481 		SetRenderState(D3DRS_CCW_STENCILPASS, D3DSTENCILOP_KEEP);
2482 		SetRenderState(D3DRS_CCW_STENCILFUNC, D3DCMP_ALWAYS);
2483 		SetRenderState(D3DRS_COLORWRITEENABLE1, 0x0000000F);
2484 		SetRenderState(D3DRS_COLORWRITEENABLE2, 0x0000000F);
2485 		SetRenderState(D3DRS_COLORWRITEENABLE3, 0x0000000F);
2486 		SetRenderState(D3DRS_BLENDFACTOR, 0xFFFFFFFF);
2487 		SetRenderState(D3DRS_SRGBWRITEENABLE, 0);
2488 		SetRenderState(D3DRS_DEPTHBIAS, FtoDW(0.0f));
2489 		SetRenderState(D3DRS_WRAP8, 0);
2490 		SetRenderState(D3DRS_WRAP9, 0);
2491 		SetRenderState(D3DRS_WRAP10, 0);
2492 		SetRenderState(D3DRS_WRAP11, 0);
2493 		SetRenderState(D3DRS_WRAP12, 0);
2494 		SetRenderState(D3DRS_WRAP13, 0);
2495 		SetRenderState(D3DRS_WRAP14, 0);
2496 		SetRenderState(D3DRS_WRAP15, 0);
2497 		SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
2498 		SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
2499 		SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ZERO);
2500 		SetRenderState(D3DRS_BLENDOPALPHA, D3DBLENDOP_ADD);
2501 
2502 		for(int i = 0; i < 8; i++)
2503 		{
2504 			SetTextureStageState(i, D3DTSS_COLOROP, i == 0 ? D3DTOP_MODULATE : D3DTOP_DISABLE);
2505 			SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2506 			SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT);
2507 			SetTextureStageState(i, D3DTSS_ALPHAOP, i == 0 ? D3DTOP_SELECTARG1 : D3DTOP_DISABLE);
2508 			SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
2509 			SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
2510 			SetTextureStageState(i, D3DTSS_BUMPENVMAT00, FtoDW(0.0f));
2511 			SetTextureStageState(i, D3DTSS_BUMPENVMAT01, FtoDW(0.0f));
2512 			SetTextureStageState(i, D3DTSS_BUMPENVMAT10, FtoDW(0.0f));
2513 			SetTextureStageState(i, D3DTSS_BUMPENVMAT11, FtoDW(0.0f));
2514 			SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, i);
2515 			SetTextureStageState(i, D3DTSS_BUMPENVLSCALE, FtoDW(0.0f));
2516 			SetTextureStageState(i, D3DTSS_BUMPENVLOFFSET, FtoDW(0.0f));
2517 			SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2518 			SetTextureStageState(i, D3DTSS_COLORARG0, D3DTA_CURRENT);
2519 			SetTextureStageState(i, D3DTSS_ALPHAARG0, D3DTA_CURRENT);
2520 			SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT);
2521 			SetTextureStageState(i, D3DTSS_CONSTANT, 0x00000000);
2522 		}
2523 
2524 		for(int i = 0; i <= D3DVERTEXTEXTURESAMPLER3; i = (i != 15) ? (i + 1) : D3DVERTEXTEXTURESAMPLER0)
2525 		{
2526 			SetTexture(i, 0);
2527 
2528 			SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
2529 			SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
2530 			SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_WRAP);
2531 			SetSamplerState(i, D3DSAMP_BORDERCOLOR, 0x00000000);
2532 			SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2533 			SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2534 			SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2535 			SetSamplerState(i, D3DSAMP_MIPMAPLODBIAS, 0);
2536 			SetSamplerState(i, D3DSAMP_MAXMIPLEVEL, 0);
2537 			SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 1);
2538 			SetSamplerState(i, D3DSAMP_SRGBTEXTURE, 0);
2539 			SetSamplerState(i, D3DSAMP_ELEMENTINDEX, 0);
2540 			SetSamplerState(i, D3DSAMP_DMAPOFFSET, 0);
2541 		}
2542 
2543 		for(int i = 0; i < 6; i++)
2544 		{
2545 			float plane[4] = {0, 0, 0, 0};
2546 
2547 			SetClipPlane(i, plane);
2548 		}
2549 
2550 		currentPalette = 0xFFFF;
2551 
2552 		ShowCursor(FALSE);
2553 		delete cursor;
2554 		cursor = 0;
2555 
2556 		return D3D_OK;
2557 	}
2558 
SetClipPlane(unsigned long index,const float * plane)2559 	long Direct3DDevice9::SetClipPlane(unsigned long index, const float *plane)
2560 	{
2561 		CriticalSection cs(this);
2562 
2563 		TRACE("unsigned long index = %d, const float *plane = 0x%0.8p", index, plane);
2564 
2565 		if(!plane || index >= 6)
2566 		{
2567 			return INVALIDCALL();
2568 		}
2569 
2570 		if(!stateRecorder)
2571 		{
2572 			this->plane[index][0] = plane[0];
2573 			this->plane[index][1] = plane[1];
2574 			this->plane[index][2] = plane[2];
2575 			this->plane[index][3] = plane[3];
2576 
2577 			renderer->setClipPlane(index, plane);
2578 		}
2579 		else
2580 		{
2581 			stateRecorder->setClipPlane(index, plane);
2582 		}
2583 
2584 		return D3D_OK;
2585 	}
2586 
SetClipStatus(const D3DCLIPSTATUS9 * clipStatus)2587 	long Direct3DDevice9::SetClipStatus(const D3DCLIPSTATUS9 *clipStatus)
2588 	{
2589 		CriticalSection cs(this);
2590 
2591 		TRACE("const D3DCLIPSTATUS9 *clipStatus = 0x%0.8p", clipStatus);
2592 
2593 		if(!clipStatus)
2594 		{
2595 			return INVALIDCALL();
2596 		}
2597 
2598 		this->clipStatus = *clipStatus;
2599 
2600 		UNIMPLEMENTED();
2601 
2602 		return D3D_OK;
2603 	}
2604 
SetCurrentTexturePalette(unsigned int paletteNumber)2605 	long Direct3DDevice9::SetCurrentTexturePalette(unsigned int paletteNumber)
2606 	{
2607 		CriticalSection cs(this);
2608 
2609 		TRACE("unsigned int paletteNumber = %d", paletteNumber);
2610 
2611 		if(paletteNumber > 0xFFFF || palette.find(paletteNumber) == palette.end())
2612 		{
2613 			return INVALIDCALL();
2614 		}
2615 
2616 		if(!stateRecorder)
2617 		{
2618 			currentPalette = paletteNumber;
2619 
2620 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2621 		}
2622 		else
2623 		{
2624 			stateRecorder->setCurrentTexturePalette(paletteNumber);
2625 		}
2626 
2627 		return D3D_OK;
2628 	}
2629 
SetCursorPosition(int x,int y,unsigned long flags)2630 	void Direct3DDevice9::SetCursorPosition(int x, int y, unsigned long flags)
2631 	{
2632 		CriticalSection cs(this);
2633 
2634 		TRACE("int x = %d, int y = %d, unsigned long flags = 0x%0.8X", x, y, flags);
2635 
2636 		POINT point = {x, y};
2637 		HWND window = deviceWindow ? deviceWindow : focusWindow;
2638 		ScreenToClient(window, &point);
2639 
2640 		sw::FrameBuffer::setCursorPosition(point.x, point.y);
2641 	}
2642 
SetCursorProperties(unsigned int x0,unsigned int y0,IDirect3DSurface9 * cursorBitmap)2643 	long Direct3DDevice9::SetCursorProperties(unsigned int x0, unsigned int y0, IDirect3DSurface9 *cursorBitmap)
2644 	{
2645 		CriticalSection cs(this);
2646 
2647 		TRACE("unsigned int x0 = %d, unsigned int y0 = %d, IDirect3DSurface9 *cursorBitmap = 0x%0.8p", x0, y0, cursorBitmap);
2648 
2649 		if(!cursorBitmap)
2650 		{
2651 			return INVALIDCALL();
2652 		}
2653 
2654 		sw::Surface *cursorSurface = static_cast<Direct3DSurface9*>(cursorBitmap);
2655 
2656 		int width = cursorSurface->getWidth();
2657 		int height = cursorSurface->getHeight();
2658 		void *bitmap = cursorSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
2659 
2660 		delete cursor;
2661 		cursor = sw::Surface::create(nullptr, width, height, 1, 0, 1, sw::FORMAT_A8R8G8B8, false, false);
2662 
2663 		void *buffer = cursor->lockExternal(0, 0, 0, sw::LOCK_DISCARD, sw::PUBLIC);
2664 		memcpy(buffer, bitmap, width * height * sizeof(unsigned int));
2665 		cursor->unlockExternal();
2666 
2667 		cursorSurface->unlockExternal();
2668 
2669 		if(showCursor)
2670 		{
2671 			sw::FrameBuffer::setCursorImage(cursor);
2672 		}
2673 		else
2674 		{
2675 			sw::FrameBuffer::setCursorImage(nullptr);
2676 		}
2677 
2678 		sw::FrameBuffer::setCursorOrigin(x0, y0);
2679 
2680 		return D3D_OK;
2681 	}
2682 
SetDepthStencilSurface(IDirect3DSurface9 * iDepthStencil)2683 	long Direct3DDevice9::SetDepthStencilSurface(IDirect3DSurface9 *iDepthStencil)
2684 	{
2685 		CriticalSection cs(this);
2686 
2687 		TRACE("IDirect3DSurface9 *newDepthStencil = 0x%0.8p", iDepthStencil);
2688 
2689 		Direct3DSurface9 *depthStencil = static_cast<Direct3DSurface9*>(iDepthStencil);
2690 
2691 		if(this->depthStencil == depthStencil)
2692 		{
2693 			return D3D_OK;
2694 		}
2695 
2696 		if(depthStencil)
2697 		{
2698 			depthStencil->bind();
2699 		}
2700 
2701 		if(this->depthStencil)
2702 		{
2703 			this->depthStencil->unbind();
2704 		}
2705 
2706 		this->depthStencil = depthStencil;
2707 
2708 		renderer->setDepthBuffer(depthStencil);
2709 		renderer->setStencilBuffer(depthStencil);
2710 
2711 		return D3D_OK;
2712 	}
2713 
SetDialogBoxMode(int enableDialogs)2714 	long Direct3DDevice9::SetDialogBoxMode(int enableDialogs)
2715 	{
2716 		CriticalSection cs(this);
2717 
2718 		TRACE("int enableDialogs = %d", enableDialogs);
2719 
2720 		UNIMPLEMENTED();
2721 
2722 		return D3D_OK;
2723 	}
2724 
SetFVF(unsigned long FVF)2725 	long Direct3DDevice9::SetFVF(unsigned long FVF)
2726 	{
2727 		CriticalSection cs(this);
2728 
2729 		TRACE("unsigned long FVF = 0x%0.8X", FVF);
2730 
2731 		if(!stateRecorder)
2732 		{
2733 			if(FVF != 0 || !this->vertexDeclaration)
2734 			{
2735 				Direct3DVertexDeclaration9 *vertexDeclaration = new Direct3DVertexDeclaration9(this, FVF);
2736 				vertexDeclaration->bind();
2737 
2738 				if(this->vertexDeclaration)
2739 				{
2740 					this->vertexDeclaration->unbind();
2741 				}
2742 
2743 				this->vertexDeclaration = vertexDeclaration;
2744 			}
2745 		}
2746 		else
2747 		{
2748 			stateRecorder->setFVF(FVF);
2749 		}
2750 
2751 		return D3D_OK;
2752 	}
2753 
SetGammaRamp(unsigned int index,unsigned long flags,const D3DGAMMARAMP * ramp)2754 	void Direct3DDevice9::SetGammaRamp(unsigned int index, unsigned long flags, const D3DGAMMARAMP *ramp)
2755 	{
2756 		CriticalSection cs(this);
2757 
2758 		TRACE("unsigned int index = %d, unsigned long flags = 0x%0.8X, const D3DGAMMARAMP *ramp = 0x%0.8p", index, flags, ramp);
2759 
2760 		if(!ramp || index >= GetNumberOfSwapChains())
2761 		{
2762 			return;
2763 		}
2764 
2765 		swapChain->setGammaRamp((sw::GammaRamp*)ramp, flags & D3DSGR_CALIBRATE);
2766 	}
2767 
SetIndices(IDirect3DIndexBuffer9 * iIndexBuffer)2768 	long Direct3DDevice9::SetIndices(IDirect3DIndexBuffer9* iIndexBuffer)
2769 	{
2770 		CriticalSection cs(this);
2771 
2772 		TRACE("IDirect3DIndexBuffer9* indexData = 0x%0.8p", iIndexBuffer);
2773 
2774 		Direct3DIndexBuffer9 *indexBuffer = static_cast<Direct3DIndexBuffer9*>(iIndexBuffer);
2775 
2776 		if(!stateRecorder)
2777 		{
2778 			if(this->indexData == indexBuffer)
2779 			{
2780 				return D3D_OK;
2781 			}
2782 
2783 			if(indexBuffer)
2784 			{
2785 				indexBuffer->bind();
2786 			}
2787 
2788 			if(this->indexData)
2789 			{
2790 				this->indexData->unbind();
2791 			}
2792 
2793 			this->indexData = indexBuffer;
2794 		}
2795 		else
2796 		{
2797 			stateRecorder->setIndices(indexBuffer);
2798 		}
2799 
2800 		return D3D_OK;
2801 	}
2802 
SetLight(unsigned long index,const D3DLIGHT9 * light)2803 	long Direct3DDevice9::SetLight(unsigned long index, const D3DLIGHT9 *light)
2804 	{
2805 		CriticalSection cs(this);
2806 
2807 		TRACE("unsigned long index = %d, const D3DLIGHT9 *light = 0x%0.8p", index, light);
2808 
2809 		if(!light)
2810 		{
2811 			return INVALIDCALL();
2812 		}
2813 
2814 		if(!stateRecorder)
2815 		{
2816 			this->light[index] = *light;
2817 
2818 			lightsDirty = true;
2819 		}
2820 		else
2821 		{
2822 			stateRecorder->setLight(index, light);
2823 		}
2824 
2825 		return D3D_OK;
2826 	}
2827 
SetMaterial(const D3DMATERIAL9 * material)2828 	long Direct3DDevice9::SetMaterial(const D3DMATERIAL9 *material)
2829 	{
2830 		CriticalSection cs(this);
2831 
2832 		TRACE("const D3DMATERIAL9 *material = 0x%0.8p", material);
2833 
2834 		if(!material)
2835 		{
2836 			return INVALIDCALL();   // FIXME: Correct behaviour?
2837 		}
2838 
2839 		if(!stateRecorder)
2840 		{
2841 			this->material = *material;
2842 
2843 			renderer->setMaterialAmbient(sw::Color<float>(material->Ambient.r, material->Ambient.g, material->Ambient.b, material->Ambient.a));
2844 			renderer->setMaterialDiffuse(sw::Color<float>(material->Diffuse.r, material->Diffuse.g, material->Diffuse.b, material->Diffuse.a));
2845 			renderer->setMaterialEmission(sw::Color<float>(material->Emissive.r, material->Emissive.g, material->Emissive.b, material->Emissive.a));
2846 			renderer->setMaterialShininess(material->Power);
2847 			renderer->setMaterialSpecular(sw::Color<float>(material->Specular.r, material->Specular.g, material->Specular.b, material->Specular.a));
2848 		}
2849 		else
2850 		{
2851 			stateRecorder->setMaterial(material);
2852 		}
2853 
2854 		return D3D_OK;
2855 	}
2856 
SetNPatchMode(float segments)2857 	long Direct3DDevice9::SetNPatchMode(float segments)
2858 	{
2859 		CriticalSection cs(this);
2860 
2861 		TRACE("float segments = %f", segments);
2862 
2863 		if(!stateRecorder)
2864 		{
2865 			if(segments < 1)
2866 			{
2867 				// NOTE: Disable
2868 			}
2869 			else
2870 			{
2871 				UNIMPLEMENTED();
2872 			}
2873 		}
2874 		else
2875 		{
2876 			stateRecorder->setNPatchMode(segments);
2877 		}
2878 
2879 		return D3D_OK;
2880 	}
2881 
SetPaletteEntries(unsigned int paletteNumber,const PALETTEENTRY * entries)2882 	long Direct3DDevice9::SetPaletteEntries(unsigned int paletteNumber, const PALETTEENTRY *entries)
2883 	{
2884 		CriticalSection cs(this);
2885 
2886 		TRACE("unsigned int paletteNumber = %d, const PALETTEENTRY *entries = 0x%0.8p", paletteNumber, entries);
2887 
2888 		if(paletteNumber > 0xFFFF || !entries)
2889 		{
2890 			return INVALIDCALL();
2891 		}
2892 
2893 		for(int i = 0; i < 256; i++)
2894 		{
2895 			palette[paletteNumber].entry[i] = entries[i];
2896 		}
2897 
2898 		if(paletteNumber == currentPalette)
2899 		{
2900 			sw::Surface::setTexturePalette((unsigned int*)&palette[currentPalette]);
2901 		}
2902 
2903 		return D3D_OK;
2904 	}
2905 
SetPixelShader(IDirect3DPixelShader9 * iPixelShader)2906 	long Direct3DDevice9::SetPixelShader(IDirect3DPixelShader9 *iPixelShader)
2907 	{
2908 		CriticalSection cs(this);
2909 
2910 		TRACE("IDirect3DPixelShader9 *shader = 0x%0.8p", iPixelShader);
2911 
2912 		Direct3DPixelShader9 *pixelShader = static_cast<Direct3DPixelShader9*>(iPixelShader);
2913 
2914 		if(!stateRecorder)
2915 		{
2916 			if(this->pixelShader == pixelShader)
2917 			{
2918 				return D3D_OK;
2919 			}
2920 
2921 			if(pixelShader)
2922 			{
2923 				pixelShader->bind();
2924 			}
2925 
2926 			if(this->pixelShader)
2927 			{
2928 				this->pixelShader->unbind();
2929 			}
2930 
2931 			this->pixelShader = pixelShader;
2932 			pixelShaderDirty = true;
2933 		}
2934 		else
2935 		{
2936 			stateRecorder->setPixelShader(pixelShader);
2937 		}
2938 
2939 		return D3D_OK;
2940 	}
2941 
SetPixelShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)2942 	long Direct3DDevice9::SetPixelShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
2943 	{
2944 		CriticalSection cs(this);
2945 
2946 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2947 
2948 		if(!stateRecorder)
2949 		{
2950 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
2951 			{
2952 				pixelShaderConstantB[startRegister + i] = constantData[i];
2953 			}
2954 
2955 			pixelShaderConstantsBDirty = sw::max(startRegister + count, pixelShaderConstantsBDirty);
2956 			pixelShaderDirty = true;   // Reload DEF constants
2957 		}
2958 		else
2959 		{
2960 			stateRecorder->setPixelShaderConstantB(startRegister, constantData, count);
2961 		}
2962 
2963 		return D3D_OK;
2964 	}
2965 
SetPixelShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)2966 	long Direct3DDevice9::SetPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
2967 	{
2968 		CriticalSection cs(this);
2969 
2970 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2971 
2972 		if(!stateRecorder)
2973 		{
2974 			for(unsigned int i = 0; i < count && startRegister + i < MAX_PIXEL_SHADER_CONST; i++)
2975 			{
2976 				pixelShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
2977 				pixelShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
2978 				pixelShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
2979 				pixelShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
2980 			}
2981 
2982 			pixelShaderConstantsFDirty = sw::max(startRegister + count, pixelShaderConstantsFDirty);
2983 			pixelShaderDirty = true;   // Reload DEF constants
2984 		}
2985 		else
2986 		{
2987 			stateRecorder->setPixelShaderConstantF(startRegister, constantData, count);
2988 		}
2989 
2990 		return D3D_OK;
2991 	}
2992 
SetPixelShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)2993 	long Direct3DDevice9::SetPixelShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
2994 	{
2995 		CriticalSection cs(this);
2996 
2997 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
2998 
2999 		if(!stateRecorder)
3000 		{
3001 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
3002 			{
3003 				pixelShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
3004 				pixelShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
3005 				pixelShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
3006 				pixelShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
3007 			}
3008 
3009 			pixelShaderConstantsIDirty = sw::max(startRegister + count, pixelShaderConstantsIDirty);
3010 			pixelShaderDirty = true;   // Reload DEF constants
3011 		}
3012 		else
3013 		{
3014 			stateRecorder->setPixelShaderConstantI(startRegister, constantData, count);
3015 		}
3016 
3017 		return D3D_OK;
3018 	}
3019 
SetRenderState(D3DRENDERSTATETYPE state,unsigned long value)3020 	long Direct3DDevice9::SetRenderState(D3DRENDERSTATETYPE state, unsigned long value)
3021 	{
3022 		CriticalSection cs(this);
3023 
3024 		TRACE("D3DRENDERSTATETYPE state = %d, unsigned long value = %d", state, value);
3025 
3026 		if(state < D3DRS_ZENABLE || state > D3DRS_BLENDOPALPHA)
3027 		{
3028 			return D3D_OK;   // FIXME: Warning
3029 		}
3030 
3031 		if(!stateRecorder)
3032 		{
3033 			if(!init && renderState[state] == value)
3034 			{
3035 				return D3D_OK;
3036 			}
3037 
3038 			renderState[state] = value;
3039 
3040 			switch(state)
3041 			{
3042 			case D3DRS_ZENABLE:
3043 				switch(value)
3044 				{
3045 				case D3DZB_TRUE:
3046 				case D3DZB_USEW:
3047 					renderer->setDepthBufferEnable(true);
3048 					break;
3049 				case D3DZB_FALSE:
3050 					renderer->setDepthBufferEnable(false);
3051 					break;
3052 				default:
3053 					ASSERT(false);
3054 				}
3055 				break;
3056 			case D3DRS_FILLMODE:
3057 				switch(value)
3058 				{
3059 				case D3DFILL_POINT:
3060 					renderer->setFillMode(sw::FILL_VERTEX);
3061 					break;
3062 				case D3DFILL_WIREFRAME:
3063 					renderer->setFillMode(sw::FILL_WIREFRAME);
3064 					break;
3065 				case D3DFILL_SOLID:
3066 					renderer->setFillMode(sw::FILL_SOLID);
3067 					break;
3068 				default:
3069 					ASSERT(false);
3070 				}
3071 				break;
3072 			case D3DRS_SHADEMODE:
3073 				switch(value)
3074 				{
3075 				case D3DSHADE_FLAT:
3076 					renderer->setShadingMode(sw::SHADING_FLAT);
3077 					break;
3078 				case D3DSHADE_GOURAUD:
3079 					renderer->setShadingMode(sw::SHADING_GOURAUD);
3080 					break;
3081 				case D3DSHADE_PHONG:
3082 					break;
3083 				default:
3084 					ASSERT(false);
3085 				}
3086 				break;
3087 			case D3DRS_ZWRITEENABLE:
3088 				renderer->setDepthWriteEnable(value != FALSE);
3089 				break;
3090 			case D3DRS_ALPHATESTENABLE:
3091 				renderer->setAlphaTestEnable(value != FALSE);
3092 				break;
3093 			case D3DRS_LASTPIXEL:
3094 			//	if(!init) UNIMPLEMENTED();   // FIXME
3095 				break;
3096 			case D3DRS_SRCBLEND:
3097 				switch(value)
3098 				{
3099 				case D3DBLEND_ZERO:
3100 					renderer->setSourceBlendFactor(sw::BLEND_ZERO);
3101 					break;
3102 				case D3DBLEND_ONE:
3103 					renderer->setSourceBlendFactor(sw::BLEND_ONE);
3104 					break;
3105 				case D3DBLEND_SRCCOLOR:
3106 					renderer->setSourceBlendFactor(sw::BLEND_SOURCE);
3107 					break;
3108 				case D3DBLEND_INVSRCCOLOR:
3109 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCE);
3110 					break;
3111 				case D3DBLEND_SRCALPHA:
3112 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3113 					break;
3114 				case D3DBLEND_INVSRCALPHA:
3115 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3116 					break;
3117 				case D3DBLEND_DESTALPHA:
3118 					renderer->setSourceBlendFactor(sw::BLEND_DESTALPHA);
3119 					break;
3120 				case D3DBLEND_INVDESTALPHA:
3121 					renderer->setSourceBlendFactor(sw::BLEND_INVDESTALPHA);
3122 					break;
3123 				case D3DBLEND_DESTCOLOR:
3124 					renderer->setSourceBlendFactor(sw::BLEND_DEST);
3125 					break;
3126 				case D3DBLEND_INVDESTCOLOR:
3127 					renderer->setSourceBlendFactor(sw::BLEND_INVDEST);
3128 					break;
3129 				case D3DBLEND_SRCALPHASAT:
3130 					renderer->setSourceBlendFactor(sw::BLEND_SRCALPHASAT);
3131 					break;
3132 				case D3DBLEND_BOTHSRCALPHA:
3133 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3134 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3135 					break;
3136 				case D3DBLEND_BOTHINVSRCALPHA:
3137 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3138 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3139 					break;
3140 				case D3DBLEND_BLENDFACTOR:
3141 					renderer->setSourceBlendFactor(sw::BLEND_CONSTANT);
3142 					break;
3143 				case D3DBLEND_INVBLENDFACTOR:
3144 					renderer->setSourceBlendFactor(sw::BLEND_INVCONSTANT);
3145 					break;
3146 				default:
3147 					ASSERT(false);
3148 				}
3149 				break;
3150 			case D3DRS_DESTBLEND:
3151 				switch(value)
3152 				{
3153 				case D3DBLEND_ZERO:
3154 					renderer->setDestBlendFactor(sw::BLEND_ZERO);
3155 					break;
3156 				case D3DBLEND_ONE:
3157 					renderer->setDestBlendFactor(sw::BLEND_ONE);
3158 					break;
3159 				case D3DBLEND_SRCCOLOR:
3160 					renderer->setDestBlendFactor(sw::BLEND_SOURCE);
3161 					break;
3162 				case D3DBLEND_INVSRCCOLOR:
3163 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCE);
3164 					break;
3165 				case D3DBLEND_SRCALPHA:
3166 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3167 					break;
3168 				case D3DBLEND_INVSRCALPHA:
3169 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3170 					break;
3171 				case D3DBLEND_DESTALPHA:
3172 					renderer->setDestBlendFactor(sw::BLEND_DESTALPHA);
3173 					break;
3174 				case D3DBLEND_INVDESTALPHA:
3175 					renderer->setDestBlendFactor(sw::BLEND_INVDESTALPHA);
3176 					break;
3177 				case D3DBLEND_DESTCOLOR:
3178 					renderer->setDestBlendFactor(sw::BLEND_DEST);
3179 					break;
3180 				case D3DBLEND_INVDESTCOLOR:
3181 					renderer->setDestBlendFactor(sw::BLEND_INVDEST);
3182 					break;
3183 				case D3DBLEND_SRCALPHASAT:
3184 					renderer->setDestBlendFactor(sw::BLEND_SRCALPHASAT);
3185 					break;
3186 				case D3DBLEND_BOTHSRCALPHA:
3187 					renderer->setSourceBlendFactor(sw::BLEND_SOURCEALPHA);
3188 					renderer->setDestBlendFactor(sw::BLEND_INVSOURCEALPHA);
3189 					break;
3190 				case D3DBLEND_BOTHINVSRCALPHA:
3191 					renderer->setSourceBlendFactor(sw::BLEND_INVSOURCEALPHA);
3192 					renderer->setDestBlendFactor(sw::BLEND_SOURCEALPHA);
3193 					break;
3194 				case D3DBLEND_BLENDFACTOR:
3195 					renderer->setDestBlendFactor(sw::BLEND_CONSTANT);
3196 					break;
3197 				case D3DBLEND_INVBLENDFACTOR:
3198 					renderer->setDestBlendFactor(sw::BLEND_INVCONSTANT);
3199 					break;
3200 				default:
3201 					ASSERT(false);
3202 				}
3203 				break;
3204 			case D3DRS_CULLMODE:
3205 				switch(value)
3206 				{
3207 				case D3DCULL_NONE:
3208 					renderer->setCullMode(sw::CULL_NONE, true);
3209 					break;
3210 				case D3DCULL_CCW:
3211 					renderer->setCullMode(sw::CULL_COUNTERCLOCKWISE, true);
3212 					break;
3213 				case D3DCULL_CW:
3214 					renderer->setCullMode(sw::CULL_CLOCKWISE, true);
3215 					break;
3216 				default:
3217 					ASSERT(false);
3218 				}
3219 				break;
3220 			case D3DRS_ZFUNC:
3221 				switch(value)
3222 				{
3223 				case D3DCMP_NEVER:
3224 					renderer->setDepthCompare(sw::DEPTH_NEVER);
3225 					break;
3226 				case D3DCMP_LESS:
3227 					renderer->setDepthCompare(sw::DEPTH_LESS);
3228 					break;
3229 				case D3DCMP_EQUAL:
3230 					renderer->setDepthCompare(sw::DEPTH_EQUAL);
3231 					break;
3232 				case D3DCMP_LESSEQUAL:
3233 					renderer->setDepthCompare(sw::DEPTH_LESSEQUAL);
3234 					break;
3235 				case D3DCMP_GREATER:
3236 					renderer->setDepthCompare(sw::DEPTH_GREATER);
3237 					break;
3238 				case D3DCMP_NOTEQUAL:
3239 					renderer->setDepthCompare(sw::DEPTH_NOTEQUAL);
3240 					break;
3241 				case D3DCMP_GREATEREQUAL:
3242 					renderer->setDepthCompare(sw::DEPTH_GREATEREQUAL);
3243 					break;
3244 				case D3DCMP_ALWAYS:
3245 					renderer->setDepthCompare(sw::DEPTH_ALWAYS);
3246 					break;
3247 				default:
3248 					ASSERT(false);
3249 				}
3250 				break;
3251 			case D3DRS_ALPHAREF:
3252 				renderer->setAlphaReference(value & 0x000000FF);
3253 				break;
3254 			case D3DRS_ALPHAFUNC:
3255 				switch(value)
3256 				{
3257 				case D3DCMP_NEVER:
3258 					renderer->setAlphaCompare(sw::ALPHA_NEVER);
3259 					break;
3260 				case D3DCMP_LESS:
3261 					renderer->setAlphaCompare(sw::ALPHA_LESS);
3262 					break;
3263 				case D3DCMP_EQUAL:
3264 					renderer->setAlphaCompare(sw::ALPHA_EQUAL);
3265 					break;
3266 				case D3DCMP_LESSEQUAL:
3267 					renderer->setAlphaCompare(sw::ALPHA_LESSEQUAL);
3268 					break;
3269 				case D3DCMP_GREATER:
3270 					renderer->setAlphaCompare(sw::ALPHA_GREATER);
3271 					break;
3272 				case D3DCMP_NOTEQUAL:
3273 					renderer->setAlphaCompare(sw::ALPHA_NOTEQUAL);
3274 					break;
3275 				case D3DCMP_GREATEREQUAL:
3276 					renderer->setAlphaCompare(sw::ALPHA_GREATEREQUAL);
3277 					break;
3278 				case D3DCMP_ALWAYS:
3279 					renderer->setAlphaCompare(sw::ALPHA_ALWAYS);
3280 					break;
3281 				default:
3282 					ASSERT(false);
3283 				}
3284 				break;
3285 			case D3DRS_DITHERENABLE:
3286 			//	if(!init) UNIMPLEMENTED();
3287 				break;
3288 			case D3DRS_ALPHABLENDENABLE:
3289 				renderer->setAlphaBlendEnable(value != FALSE);
3290 				break;
3291 			case D3DRS_FOGENABLE:
3292 				renderer->setFogEnable(value != FALSE);
3293 				break;
3294 			case D3DRS_FOGCOLOR:
3295 				renderer->setFogColor(value);
3296 				break;
3297 			case D3DRS_FOGTABLEMODE:
3298 				switch(value)
3299 				{
3300 				case D3DFOG_NONE:
3301 					renderer->setPixelFogMode(sw::FOG_NONE);
3302 					break;
3303 				case D3DFOG_LINEAR:
3304 					renderer->setPixelFogMode(sw::FOG_LINEAR);
3305 					break;
3306 				case D3DFOG_EXP:
3307 					renderer->setPixelFogMode(sw::FOG_EXP);
3308 					break;
3309 				case D3DFOG_EXP2:
3310 					renderer->setPixelFogMode(sw::FOG_EXP2);
3311 					break;
3312 				default:
3313 					ASSERT(false);
3314 				}
3315 				break;
3316 			case D3DRS_FOGSTART:
3317 				renderer->setFogStart((float&)value);
3318 				break;
3319 			case D3DRS_FOGEND:
3320 				renderer->setFogEnd((float&)value);
3321 				break;
3322 			case D3DRS_FOGDENSITY:
3323 				renderer->setFogDensity((float&)value);
3324 				break;
3325 			case D3DRS_RANGEFOGENABLE:
3326 				renderer->setRangeFogEnable(value != FALSE);
3327 				break;
3328 			case D3DRS_SPECULARENABLE:
3329 				renderer->setSpecularEnable(value != FALSE);
3330 				break;
3331 			case D3DRS_STENCILENABLE:
3332 				renderer->setStencilEnable(value != FALSE);
3333 				break;
3334 			case D3DRS_STENCILFAIL:
3335 				switch(value)
3336 				{
3337 				case D3DSTENCILOP_KEEP:
3338 					renderer->setStencilFailOperation(sw::OPERATION_KEEP);
3339 					break;
3340 				case D3DSTENCILOP_ZERO:
3341 					renderer->setStencilFailOperation(sw::OPERATION_ZERO);
3342 					break;
3343 				case D3DSTENCILOP_REPLACE:
3344 					renderer->setStencilFailOperation(sw::OPERATION_REPLACE);
3345 					break;
3346 				case D3DSTENCILOP_INCRSAT:
3347 					renderer->setStencilFailOperation(sw::OPERATION_INCRSAT);
3348 					break;
3349 				case D3DSTENCILOP_DECRSAT:
3350 					renderer->setStencilFailOperation(sw::OPERATION_DECRSAT);
3351 					break;
3352 				case D3DSTENCILOP_INVERT:
3353 					renderer->setStencilFailOperation(sw::OPERATION_INVERT);
3354 					break;
3355 				case D3DSTENCILOP_INCR:
3356 					renderer->setStencilFailOperation(sw::OPERATION_INCR);
3357 					break;
3358 				case D3DSTENCILOP_DECR:
3359 					renderer->setStencilFailOperation(sw::OPERATION_DECR);
3360 					break;
3361 				default:
3362 					ASSERT(false);
3363 				}
3364 				break;
3365 			case D3DRS_STENCILZFAIL:
3366 				switch(value)
3367 				{
3368 				case D3DSTENCILOP_KEEP:
3369 					renderer->setStencilZFailOperation(sw::OPERATION_KEEP);
3370 					break;
3371 				case D3DSTENCILOP_ZERO:
3372 					renderer->setStencilZFailOperation(sw::OPERATION_ZERO);
3373 					break;
3374 				case D3DSTENCILOP_REPLACE:
3375 					renderer->setStencilZFailOperation(sw::OPERATION_REPLACE);
3376 					break;
3377 				case D3DSTENCILOP_INCRSAT:
3378 					renderer->setStencilZFailOperation(sw::OPERATION_INCRSAT);
3379 					break;
3380 				case D3DSTENCILOP_DECRSAT:
3381 					renderer->setStencilZFailOperation(sw::OPERATION_DECRSAT);
3382 					break;
3383 				case D3DSTENCILOP_INVERT:
3384 					renderer->setStencilZFailOperation(sw::OPERATION_INVERT);
3385 					break;
3386 				case D3DSTENCILOP_INCR:
3387 					renderer->setStencilZFailOperation(sw::OPERATION_INCR);
3388 					break;
3389 				case D3DSTENCILOP_DECR:
3390 					renderer->setStencilZFailOperation(sw::OPERATION_DECR);
3391 					break;
3392 				default:
3393 					ASSERT(false);
3394 				}
3395 				break;
3396 			case D3DRS_STENCILPASS:
3397 				switch(value)
3398 				{
3399 				case D3DSTENCILOP_KEEP:
3400 					renderer->setStencilPassOperation(sw::OPERATION_KEEP);
3401 					break;
3402 				case D3DSTENCILOP_ZERO:
3403 					renderer->setStencilPassOperation(sw::OPERATION_ZERO);
3404 					break;
3405 				case D3DSTENCILOP_REPLACE:
3406 					renderer->setStencilPassOperation(sw::OPERATION_REPLACE);
3407 					break;
3408 				case D3DSTENCILOP_INCRSAT:
3409 					renderer->setStencilPassOperation(sw::OPERATION_INCRSAT);
3410 					break;
3411 				case D3DSTENCILOP_DECRSAT:
3412 					renderer->setStencilPassOperation(sw::OPERATION_DECRSAT);
3413 					break;
3414 				case D3DSTENCILOP_INVERT:
3415 					renderer->setStencilPassOperation(sw::OPERATION_INVERT);
3416 					break;
3417 				case D3DSTENCILOP_INCR:
3418 					renderer->setStencilPassOperation(sw::OPERATION_INCR);
3419 					break;
3420 				case D3DSTENCILOP_DECR:
3421 					renderer->setStencilPassOperation(sw::OPERATION_DECR);
3422 					break;
3423 				default:
3424 					ASSERT(false);
3425 				}
3426 				break;
3427 			case D3DRS_STENCILFUNC:
3428 				switch(value)
3429 				{
3430 				case D3DCMP_NEVER:
3431 					renderer->setStencilCompare(sw::STENCIL_NEVER);
3432 					break;
3433 				case D3DCMP_LESS:
3434 					renderer->setStencilCompare(sw::STENCIL_LESS);
3435 					break;
3436 				case D3DCMP_EQUAL:
3437 					renderer->setStencilCompare(sw::STENCIL_EQUAL);
3438 					break;
3439 				case D3DCMP_LESSEQUAL:
3440 					renderer->setStencilCompare(sw::STENCIL_LESSEQUAL);
3441 					break;
3442 				case D3DCMP_GREATER:
3443 					renderer->setStencilCompare(sw::STENCIL_GREATER);
3444 					break;
3445 				case D3DCMP_NOTEQUAL:
3446 					renderer->setStencilCompare(sw::STENCIL_NOTEQUAL);
3447 					break;
3448 				case D3DCMP_GREATEREQUAL:
3449 					renderer->setStencilCompare(sw::STENCIL_GREATEREQUAL);
3450 					break;
3451 				case D3DCMP_ALWAYS:
3452 					renderer->setStencilCompare(sw::STENCIL_ALWAYS);
3453 					break;
3454 				default:
3455 					ASSERT(false);
3456 				}
3457 				break;
3458 			case D3DRS_STENCILREF:
3459 				renderer->setStencilReference(value);
3460 				renderer->setStencilReferenceCCW(value);
3461 				break;
3462 			case D3DRS_STENCILMASK:
3463 				renderer->setStencilMask(value);
3464 				renderer->setStencilMaskCCW(value);
3465 				break;
3466 			case D3DRS_STENCILWRITEMASK:
3467 				renderer->setStencilWriteMask(value);
3468 				renderer->setStencilWriteMaskCCW(value);
3469 				break;
3470 			case D3DRS_TEXTUREFACTOR:
3471 				renderer->setTextureFactor(value);
3472 				break;
3473 			case D3DRS_WRAP0:
3474 				renderer->setTextureWrap(0, value);
3475 				break;
3476 			case D3DRS_WRAP1:
3477 				renderer->setTextureWrap(1, value);
3478 				break;
3479 			case D3DRS_WRAP2:
3480 				renderer->setTextureWrap(2, value);
3481 				break;
3482 			case D3DRS_WRAP3:
3483 				renderer->setTextureWrap(3, value);
3484 				break;
3485 			case D3DRS_WRAP4:
3486 				renderer->setTextureWrap(4, value);
3487 				break;
3488 			case D3DRS_WRAP5:
3489 				renderer->setTextureWrap(5, value);
3490 				break;
3491 			case D3DRS_WRAP6:
3492 				renderer->setTextureWrap(6, value);
3493 				break;
3494 			case D3DRS_WRAP7:
3495 				renderer->setTextureWrap(7, value);
3496 				break;
3497 			case D3DRS_CLIPPING:
3498 				// Ignored, clipping is always performed
3499 				break;
3500 			case D3DRS_LIGHTING:
3501 				renderer->setLightingEnable(value != FALSE);
3502 				break;
3503 			case D3DRS_AMBIENT:
3504 				renderer->setGlobalAmbient(value);
3505 				break;
3506 			case D3DRS_FOGVERTEXMODE:
3507 				switch(value)
3508 				{
3509 				case D3DFOG_NONE:
3510 					renderer->setVertexFogMode(sw::FOG_NONE);
3511 					break;
3512 				case D3DFOG_LINEAR:
3513 					renderer->setVertexFogMode(sw::FOG_LINEAR);
3514 					break;
3515 				case D3DFOG_EXP:
3516 					renderer->setVertexFogMode(sw::FOG_EXP);
3517 					break;
3518 				case D3DFOG_EXP2:
3519 					renderer->setVertexFogMode(sw::FOG_EXP2);
3520 					break;
3521 				default:
3522 					ASSERT(false);
3523 				}
3524 				break;
3525 			case D3DRS_COLORVERTEX:
3526 				renderer->setColorVertexEnable(value != FALSE);
3527 				break;
3528 			case D3DRS_LOCALVIEWER:
3529 				renderer->setLocalViewer(value != FALSE);
3530 				break;
3531 			case D3DRS_NORMALIZENORMALS:
3532 				renderer->setNormalizeNormals(value != FALSE);
3533 				break;
3534 			case D3DRS_DIFFUSEMATERIALSOURCE:
3535 				switch(value)
3536 				{
3537 				case D3DMCS_MATERIAL:
3538 					renderer->setDiffuseMaterialSource(sw::MATERIAL_MATERIAL);
3539 					break;
3540 				case D3DMCS_COLOR1:
3541 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR1);
3542 					break;
3543 				case D3DMCS_COLOR2:
3544 					renderer->setDiffuseMaterialSource(sw::MATERIAL_COLOR2);
3545 					break;
3546 				default:
3547 					ASSERT(false);
3548 				}
3549 				break;
3550 			case D3DRS_SPECULARMATERIALSOURCE:
3551 				switch(value)
3552 				{
3553 				case D3DMCS_MATERIAL:
3554 					renderer->setSpecularMaterialSource(sw::MATERIAL_MATERIAL);
3555 					break;
3556 				case D3DMCS_COLOR1:
3557 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR1);
3558 					break;
3559 				case D3DMCS_COLOR2:
3560 					renderer->setSpecularMaterialSource(sw::MATERIAL_COLOR2);
3561 					break;
3562 				default:
3563 					ASSERT(false);
3564 				}
3565 				break;
3566 			case D3DRS_AMBIENTMATERIALSOURCE:
3567 				switch(value)
3568 				{
3569 				case D3DMCS_MATERIAL:
3570 					renderer->setAmbientMaterialSource(sw::MATERIAL_MATERIAL);
3571 					break;
3572 				case D3DMCS_COLOR1:
3573 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR1);
3574 					break;
3575 				case D3DMCS_COLOR2:
3576 					renderer->setAmbientMaterialSource(sw::MATERIAL_COLOR2);
3577 					break;
3578 				default:
3579 					ASSERT(false);
3580 				}
3581 				break;
3582 			case D3DRS_EMISSIVEMATERIALSOURCE:
3583 				switch(value)
3584 				{
3585 				case D3DMCS_MATERIAL:
3586 					renderer->setEmissiveMaterialSource(sw::MATERIAL_MATERIAL);
3587 					break;
3588 				case D3DMCS_COLOR1:
3589 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR1);
3590 					break;
3591 				case D3DMCS_COLOR2:
3592 					renderer->setEmissiveMaterialSource(sw::MATERIAL_COLOR2);
3593 					break;
3594 				default:
3595 					ASSERT(false);
3596 				}
3597 				break;
3598 			case D3DRS_VERTEXBLEND:
3599 				switch(value)
3600 				{
3601 				case D3DVBF_DISABLE:
3602 					renderer->setVertexBlendMatrixCount(0);
3603 					break;
3604 				case D3DVBF_1WEIGHTS:
3605 					renderer->setVertexBlendMatrixCount(2);
3606 					break;
3607 				case D3DVBF_2WEIGHTS:
3608 					renderer->setVertexBlendMatrixCount(3);
3609 					break;
3610 				case D3DVBF_3WEIGHTS:
3611 					renderer->setVertexBlendMatrixCount(4);
3612 					break;
3613 				case D3DVBF_TWEENING:
3614 					UNIMPLEMENTED();
3615 					break;
3616 				case D3DVBF_0WEIGHTS:
3617 					renderer->setVertexBlendMatrixCount(1);
3618 					break;
3619 				default:
3620 					ASSERT(false);
3621 				}
3622 				break;
3623 			case D3DRS_CLIPPLANEENABLE:
3624 				renderer->setClipFlags(value);
3625 				break;
3626 			case D3DRS_POINTSIZE:
3627 				if(value == D3DFMT_INST && pixelShaderVersionX >= D3DPS_VERSION(2, 0))   // ATI hack to enable instancing on SM 2.0 hardware
3628 				{
3629 					instancingEnabled = true;
3630 				}
3631 				else if(value == D3DFMT_A2M1)   // ATI hack to enable transparency anti-aliasing
3632 				{
3633 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3634 					renderer->setAlphaTestEnable(true);
3635 				}
3636 				else if(value == D3DFMT_A2M0)   // ATI hack to disable transparency anti-aliasing
3637 				{
3638 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3639 					renderer->setAlphaTestEnable(false);
3640 				}
3641 				else
3642 				{
3643 					renderer->setPointSize((float&)value);
3644 				}
3645 				break;
3646 			case D3DRS_POINTSIZE_MIN:
3647 				renderer->setPointSizeMin((float&)value);
3648 				break;
3649 			case D3DRS_POINTSPRITEENABLE:
3650 				renderer->setPointSpriteEnable(value != FALSE);
3651 				break;
3652 			case D3DRS_POINTSCALEENABLE:
3653 				renderer->setPointScaleEnable(value != FALSE);
3654 				break;
3655 			case D3DRS_POINTSCALE_A:
3656 				renderer->setPointScaleA((float&)value);
3657 				break;
3658 			case D3DRS_POINTSCALE_B:
3659 				renderer->setPointScaleB((float&)value);
3660 				break;
3661 			case D3DRS_POINTSCALE_C:
3662 				renderer->setPointScaleC((float&)value);
3663 				break;
3664 			case D3DRS_MULTISAMPLEANTIALIAS:
3665 			//	if(!init) UNIMPLEMENTED();
3666 				break;
3667 			case D3DRS_MULTISAMPLEMASK:
3668 				SetRenderTarget(0, renderTarget[0]);   // Sets the multi-sample mask, if maskable
3669 				break;
3670 			case D3DRS_PATCHEDGESTYLE:
3671 				if(!init) if(value != D3DPATCHEDGE_DISCRETE) UNIMPLEMENTED();
3672 				break;
3673 			case D3DRS_DEBUGMONITORTOKEN:
3674 				if(!init) UNIMPLEMENTED();
3675 				break;
3676 			case D3DRS_POINTSIZE_MAX:
3677 				renderer->setPointSizeMax((float&)value);
3678 				break;
3679 			case D3DRS_INDEXEDVERTEXBLENDENABLE:
3680 				renderer->setIndexedVertexBlendEnable(value != FALSE);
3681 				break;
3682 			case D3DRS_COLORWRITEENABLE:
3683 				renderer->setColorWriteMask(0, value & 0x0000000F);
3684 				break;
3685 			case D3DRS_TWEENFACTOR:
3686 				if(!init) UNIMPLEMENTED();
3687 				break;
3688 			case D3DRS_BLENDOP:
3689 				switch(value)
3690 				{
3691 				case D3DBLENDOP_ADD:
3692 					renderer->setBlendOperation(sw::BLENDOP_ADD);
3693 					break;
3694 				case D3DBLENDOP_SUBTRACT:
3695 					renderer->setBlendOperation(sw::BLENDOP_SUB);
3696 					break;
3697 				case D3DBLENDOP_REVSUBTRACT:
3698 					renderer->setBlendOperation(sw::BLENDOP_INVSUB);
3699 					break;
3700 				case D3DBLENDOP_MIN:
3701 					renderer->setBlendOperation(sw::BLENDOP_MIN);
3702 					break;
3703 				case D3DBLENDOP_MAX:
3704 					renderer->setBlendOperation(sw::BLENDOP_MAX);
3705 					break;
3706 				default:
3707 					ASSERT(false);
3708 				}
3709 				break;
3710 			case D3DRS_POSITIONDEGREE:
3711 				if(!init) UNIMPLEMENTED();
3712 				break;
3713 			case D3DRS_NORMALDEGREE:
3714 				if(!init) UNIMPLEMENTED();
3715 				break;
3716 			case D3DRS_SCISSORTESTENABLE:
3717 				scissorEnable = (value != FALSE);
3718 				break;
3719 			case D3DRS_SLOPESCALEDEPTHBIAS:
3720 				renderer->setSlopeDepthBias((float&)value);
3721 				break;
3722 			case D3DRS_ANTIALIASEDLINEENABLE:
3723 				if(!init) if(value != FALSE) UNIMPLEMENTED();
3724 				break;
3725 			case D3DRS_MINTESSELLATIONLEVEL:
3726 				if(!init) UNIMPLEMENTED();
3727 				break;
3728 			case D3DRS_MAXTESSELLATIONLEVEL:
3729 				if(!init) UNIMPLEMENTED();
3730 				break;
3731 			case D3DRS_ADAPTIVETESS_X:
3732 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3733 				break;
3734 			case D3DRS_ADAPTIVETESS_Y:
3735 				if(value == D3DFMT_ATOC)   // NVIDIA hack to enable transparency anti-aliasing
3736 				{
3737 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_ALPHA_TO_COVERAGE);
3738 				}
3739 				else if(value == D3DFMT_UNKNOWN)   // NVIDIA hack to disable transparency anti-aliasing
3740 				{
3741 					renderer->setTransparencyAntialiasing(sw::TRANSPARENCY_NONE);
3742 				}
3743 				else
3744 				{
3745 					if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3746 				}
3747 				break;
3748 			case D3DRS_ADAPTIVETESS_Z:
3749 				if(!init) if((float&)value != 1.0f) UNIMPLEMENTED();
3750 				break;
3751 			case D3DRS_ADAPTIVETESS_W:
3752 				if(!init) if((float&)value != 0.0f) UNIMPLEMENTED();
3753 				break;
3754 			case D3DRS_ENABLEADAPTIVETESSELLATION:
3755 				if(!init) UNIMPLEMENTED();
3756 				break;
3757 			case D3DRS_TWOSIDEDSTENCILMODE:
3758 				renderer->setTwoSidedStencil(value != FALSE);
3759 				break;
3760 			case D3DRS_CCW_STENCILFAIL:
3761 				switch(value)
3762 				{
3763 				case D3DSTENCILOP_KEEP:
3764 					renderer->setStencilFailOperationCCW(sw::OPERATION_KEEP);
3765 					break;
3766 				case D3DSTENCILOP_ZERO:
3767 					renderer->setStencilFailOperationCCW(sw::OPERATION_ZERO);
3768 					break;
3769 				case D3DSTENCILOP_REPLACE:
3770 					renderer->setStencilFailOperationCCW(sw::OPERATION_REPLACE);
3771 					break;
3772 				case D3DSTENCILOP_INCRSAT:
3773 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCRSAT);
3774 					break;
3775 				case D3DSTENCILOP_DECRSAT:
3776 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECRSAT);
3777 					break;
3778 				case D3DSTENCILOP_INVERT:
3779 					renderer->setStencilFailOperationCCW(sw::OPERATION_INVERT);
3780 					break;
3781 				case D3DSTENCILOP_INCR:
3782 					renderer->setStencilFailOperationCCW(sw::OPERATION_INCR);
3783 					break;
3784 				case D3DSTENCILOP_DECR:
3785 					renderer->setStencilFailOperationCCW(sw::OPERATION_DECR);
3786 					break;
3787 				default:
3788 					ASSERT(false);
3789 				}
3790 				break;
3791 			case D3DRS_CCW_STENCILZFAIL:
3792 				switch(value)
3793 				{
3794 				case D3DSTENCILOP_KEEP:
3795 					renderer->setStencilZFailOperationCCW(sw::OPERATION_KEEP);
3796 					break;
3797 				case D3DSTENCILOP_ZERO:
3798 					renderer->setStencilZFailOperationCCW(sw::OPERATION_ZERO);
3799 					break;
3800 				case D3DSTENCILOP_REPLACE:
3801 					renderer->setStencilZFailOperationCCW(sw::OPERATION_REPLACE);
3802 					break;
3803 				case D3DSTENCILOP_INCRSAT:
3804 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCRSAT);
3805 					break;
3806 				case D3DSTENCILOP_DECRSAT:
3807 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECRSAT);
3808 					break;
3809 				case D3DSTENCILOP_INVERT:
3810 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INVERT);
3811 					break;
3812 				case D3DSTENCILOP_INCR:
3813 					renderer->setStencilZFailOperationCCW(sw::OPERATION_INCR);
3814 					break;
3815 				case D3DSTENCILOP_DECR:
3816 					renderer->setStencilZFailOperationCCW(sw::OPERATION_DECR);
3817 					break;
3818 				default:
3819 					ASSERT(false);
3820 				}
3821 				break;
3822 			case D3DRS_CCW_STENCILPASS:
3823 				switch(value)
3824 				{
3825 				case D3DSTENCILOP_KEEP:
3826 					renderer->setStencilPassOperationCCW(sw::OPERATION_KEEP);
3827 					break;
3828 				case D3DSTENCILOP_ZERO:
3829 					renderer->setStencilPassOperationCCW(sw::OPERATION_ZERO);
3830 					break;
3831 				case D3DSTENCILOP_REPLACE:
3832 					renderer->setStencilPassOperationCCW(sw::OPERATION_REPLACE);
3833 					break;
3834 				case D3DSTENCILOP_INCRSAT:
3835 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCRSAT);
3836 					break;
3837 				case D3DSTENCILOP_DECRSAT:
3838 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECRSAT);
3839 					break;
3840 				case D3DSTENCILOP_INVERT:
3841 					renderer->setStencilPassOperationCCW(sw::OPERATION_INVERT);
3842 					break;
3843 				case D3DSTENCILOP_INCR:
3844 					renderer->setStencilPassOperationCCW(sw::OPERATION_INCR);
3845 					break;
3846 				case D3DSTENCILOP_DECR:
3847 					renderer->setStencilPassOperationCCW(sw::OPERATION_DECR);
3848 					break;
3849 				default:
3850 					ASSERT(false);
3851 				}
3852 				break;
3853 			case D3DRS_CCW_STENCILFUNC:
3854 				switch(value)
3855 				{
3856 				case D3DCMP_NEVER:
3857 					renderer->setStencilCompareCCW(sw::STENCIL_NEVER);
3858 					break;
3859 				case D3DCMP_LESS:
3860 					renderer->setStencilCompareCCW(sw::STENCIL_LESS);
3861 					break;
3862 				case D3DCMP_EQUAL:
3863 					renderer->setStencilCompareCCW(sw::STENCIL_EQUAL);
3864 					break;
3865 				case D3DCMP_LESSEQUAL:
3866 					renderer->setStencilCompareCCW(sw::STENCIL_LESSEQUAL);
3867 					break;
3868 				case D3DCMP_GREATER:
3869 					renderer->setStencilCompareCCW(sw::STENCIL_GREATER);
3870 					break;
3871 				case D3DCMP_NOTEQUAL:
3872 					renderer->setStencilCompareCCW(sw::STENCIL_NOTEQUAL);
3873 					break;
3874 				case D3DCMP_GREATEREQUAL:
3875 					renderer->setStencilCompareCCW(sw::STENCIL_GREATEREQUAL);
3876 					break;
3877 				case D3DCMP_ALWAYS:
3878 					renderer->setStencilCompareCCW(sw::STENCIL_ALWAYS);
3879 					break;
3880 				default:
3881 					ASSERT(false);
3882 				}
3883 				break;
3884 			case D3DRS_COLORWRITEENABLE1:
3885 				renderer->setColorWriteMask(1, value);
3886 				break;
3887 			case D3DRS_COLORWRITEENABLE2:
3888 				renderer->setColorWriteMask(2, value);
3889 				break;
3890 			case D3DRS_COLORWRITEENABLE3:
3891 				renderer->setColorWriteMask(3, value);
3892 				break;
3893 			case D3DRS_BLENDFACTOR:
3894 				renderer->setBlendConstant(sw::Color<float>(value));
3895 				break;
3896 			case D3DRS_SRGBWRITEENABLE:
3897 				renderer->setWriteSRGB(value != FALSE);
3898 				break;
3899 			case D3DRS_DEPTHBIAS:
3900 				renderer->setDepthBias((float&)value);
3901 				break;
3902 			case D3DRS_WRAP8:
3903 				renderer->setTextureWrap(8, value);
3904 				break;
3905 			case D3DRS_WRAP9:
3906 				renderer->setTextureWrap(9, value);
3907 				break;
3908 			case D3DRS_WRAP10:
3909 				renderer->setTextureWrap(10, value);
3910 				break;
3911 			case D3DRS_WRAP11:
3912 				renderer->setTextureWrap(11, value);
3913 				break;
3914 			case D3DRS_WRAP12:
3915 				renderer->setTextureWrap(12, value);
3916 				break;
3917 			case D3DRS_WRAP13:
3918 				renderer->setTextureWrap(13, value);
3919 				break;
3920 			case D3DRS_WRAP14:
3921 				renderer->setTextureWrap(14, value);
3922 				break;
3923 			case D3DRS_WRAP15:
3924 				renderer->setTextureWrap(15, value);
3925 				break;
3926 			case D3DRS_SEPARATEALPHABLENDENABLE:
3927 				renderer->setSeparateAlphaBlendEnable(value != FALSE);
3928 				break;
3929 			case D3DRS_SRCBLENDALPHA:
3930 				switch(value)
3931 				{
3932 				case D3DBLEND_ZERO:
3933 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ZERO);
3934 					break;
3935 				case D3DBLEND_ONE:
3936 					renderer->setSourceBlendFactorAlpha(sw::BLEND_ONE);
3937 					break;
3938 				case D3DBLEND_SRCCOLOR:
3939 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCE);
3940 					break;
3941 				case D3DBLEND_INVSRCCOLOR:
3942 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCE);
3943 					break;
3944 				case D3DBLEND_SRCALPHA:
3945 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3946 					break;
3947 				case D3DBLEND_INVSRCALPHA:
3948 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3949 					break;
3950 				case D3DBLEND_DESTALPHA:
3951 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DESTALPHA);
3952 					break;
3953 				case D3DBLEND_INVDESTALPHA:
3954 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
3955 					break;
3956 				case D3DBLEND_DESTCOLOR:
3957 					renderer->setSourceBlendFactorAlpha(sw::BLEND_DEST);
3958 					break;
3959 				case D3DBLEND_INVDESTCOLOR:
3960 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVDEST);
3961 					break;
3962 				case D3DBLEND_SRCALPHASAT:
3963 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
3964 					break;
3965 				case D3DBLEND_BOTHSRCALPHA:
3966 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3967 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3968 					break;
3969 				case D3DBLEND_BOTHINVSRCALPHA:
3970 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
3971 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
3972 					break;
3973 				case D3DBLEND_BLENDFACTOR:
3974 					renderer->setSourceBlendFactorAlpha(sw::BLEND_CONSTANT);
3975 					break;
3976 				case D3DBLEND_INVBLENDFACTOR:
3977 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVCONSTANT);
3978 					break;
3979 				default:
3980 					ASSERT(false);
3981 				}
3982 				break;
3983 			case D3DRS_DESTBLENDALPHA:
3984 				switch(value)
3985 				{
3986 				case D3DBLEND_ZERO:
3987 					renderer->setDestBlendFactorAlpha(sw::BLEND_ZERO);
3988 					break;
3989 				case D3DBLEND_ONE:
3990 					renderer->setDestBlendFactorAlpha(sw::BLEND_ONE);
3991 					break;
3992 				case D3DBLEND_SRCCOLOR:
3993 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCE);
3994 					break;
3995 				case D3DBLEND_INVSRCCOLOR:
3996 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCE);
3997 					break;
3998 				case D3DBLEND_SRCALPHA:
3999 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4000 					break;
4001 				case D3DBLEND_INVSRCALPHA:
4002 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4003 					break;
4004 				case D3DBLEND_DESTALPHA:
4005 					renderer->setDestBlendFactorAlpha(sw::BLEND_DESTALPHA);
4006 					break;
4007 				case D3DBLEND_INVDESTALPHA:
4008 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDESTALPHA);
4009 					break;
4010 				case D3DBLEND_DESTCOLOR:
4011 					renderer->setDestBlendFactorAlpha(sw::BLEND_DEST);
4012 					break;
4013 				case D3DBLEND_INVDESTCOLOR:
4014 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVDEST);
4015 					break;
4016 				case D3DBLEND_SRCALPHASAT:
4017 					renderer->setDestBlendFactorAlpha(sw::BLEND_SRCALPHASAT);
4018 					break;
4019 				case D3DBLEND_BOTHSRCALPHA:
4020 					renderer->setSourceBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4021 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4022 					break;
4023 				case D3DBLEND_BOTHINVSRCALPHA:
4024 					renderer->setSourceBlendFactorAlpha(sw::BLEND_INVSOURCEALPHA);
4025 					renderer->setDestBlendFactorAlpha(sw::BLEND_SOURCEALPHA);
4026 					break;
4027 				case D3DBLEND_BLENDFACTOR:
4028 					renderer->setDestBlendFactorAlpha(sw::BLEND_CONSTANT);
4029 					break;
4030 				case D3DBLEND_INVBLENDFACTOR:
4031 					renderer->setDestBlendFactorAlpha(sw::BLEND_INVCONSTANT);
4032 					break;
4033 				default:
4034 					ASSERT(false);
4035 				}
4036 				break;
4037 			case D3DRS_BLENDOPALPHA:
4038 				switch(value)
4039 				{
4040 				case D3DBLENDOP_ADD:
4041 					renderer->setBlendOperationAlpha(sw::BLENDOP_ADD);
4042 					break;
4043 				case D3DBLENDOP_SUBTRACT:
4044 					renderer->setBlendOperationAlpha(sw::BLENDOP_SUB);
4045 					break;
4046 				case D3DBLENDOP_REVSUBTRACT:
4047 					renderer->setBlendOperationAlpha(sw::BLENDOP_INVSUB);
4048 					break;
4049 				case D3DBLENDOP_MIN:
4050 					renderer->setBlendOperationAlpha(sw::BLENDOP_MIN);
4051 					break;
4052 				case D3DBLENDOP_MAX:
4053 					renderer->setBlendOperationAlpha(sw::BLENDOP_MAX);
4054 					break;
4055 				default:
4056 					ASSERT(false);
4057 				}
4058 				break;
4059 			default:
4060 				ASSERT(false);
4061 			}
4062 		}
4063 		else   // stateRecorder
4064 		{
4065 			stateRecorder->setRenderState(state, value);
4066 		}
4067 
4068 		return D3D_OK;
4069 	}
4070 
SetRenderTarget(unsigned long index,IDirect3DSurface9 * iRenderTarget)4071 	long Direct3DDevice9::SetRenderTarget(unsigned long index, IDirect3DSurface9 *iRenderTarget)
4072 	{
4073 		CriticalSection cs(this);
4074 
4075 		TRACE("unsigned long index = %d, IDirect3DSurface9 *newRenderTarget = 0x%0.8p", index, iRenderTarget);
4076 
4077 		// FIXME: Check for D3DUSAGE_RENDERTARGET
4078 
4079 		if(index >= 4 || (index == 0 && !iRenderTarget))
4080 		{
4081 			return INVALIDCALL();
4082 		}
4083 
4084 		Direct3DSurface9 *renderTarget = static_cast<Direct3DSurface9*>(iRenderTarget);
4085 
4086 		if(renderTarget)
4087 		{
4088 			renderTarget->bind();
4089 		}
4090 
4091 		if(this->renderTarget[index])
4092 		{
4093 			this->renderTarget[index]->unbind();
4094 		}
4095 
4096 		this->renderTarget[index] = renderTarget;
4097 
4098 		if(renderTarget && index == 0)
4099 		{
4100 			D3DSURFACE_DESC renderTargetDesc;
4101 			renderTarget->GetDesc(&renderTargetDesc);
4102 
4103 			// Reset viewport to size of current render target
4104 			viewport.X = 0;
4105 			viewport.Y = 0;
4106 			viewport.Width = renderTargetDesc.Width;
4107 			viewport.Height = renderTargetDesc.Height;
4108 			viewport.MinZ = 0;
4109 			viewport.MaxZ = 1;
4110 
4111 			// Reset scissor rectangle to size of current render target
4112 			scissorRect.left = 0;
4113 			scissorRect.top = 0;
4114 			scissorRect.right = renderTargetDesc.Width;
4115 			scissorRect.bottom = renderTargetDesc.Height;
4116 
4117 			// Set the multi-sample mask, if maskable
4118 			if(renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONE &&
4119 			   renderTargetDesc.MultiSampleType != D3DMULTISAMPLE_NONMASKABLE)
4120 			{
4121 				renderer->setMultiSampleMask(renderState[D3DRS_MULTISAMPLEMASK]);
4122 			}
4123 			else
4124 			{
4125 				renderer->setMultiSampleMask(0xFFFFFFFF);
4126 			}
4127 		}
4128 
4129 		renderer->setRenderTarget(index, renderTarget);
4130 
4131 		return D3D_OK;
4132 	}
4133 
SetSamplerState(unsigned long sampler,D3DSAMPLERSTATETYPE state,unsigned long value)4134 	long Direct3DDevice9::SetSamplerState(unsigned long sampler, D3DSAMPLERSTATETYPE state, unsigned long value)
4135 	{
4136 		CriticalSection cs(this);
4137 
4138 		TRACE("unsigned long sampler = %d, D3DSAMPLERSTATETYPE state = %d, unsigned long value = %d", sampler, state, value);
4139 
4140 		if(state < D3DSAMP_ADDRESSU || state > D3DSAMP_DMAPOFFSET)
4141 		{
4142 			return INVALIDCALL();
4143 		}
4144 
4145 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4146 		{
4147 			return INVALIDCALL();
4148 		}
4149 
4150 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4151 		{
4152 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4153 		}
4154 
4155 		if(!stateRecorder)
4156 		{
4157 			if(!init && samplerState[sampler][state] == value)
4158 			{
4159 				return D3D_OK;
4160 			}
4161 
4162 			samplerState[sampler][state] = value;
4163 
4164 			sw::SamplerType type = sampler < 16 ? sw::SAMPLER_PIXEL : sw::SAMPLER_VERTEX;
4165 			int index = sampler < 16 ? sampler : sampler - 16;   // Sampler index within type group
4166 
4167 			switch(state)
4168 			{
4169 			case D3DSAMP_ADDRESSU:
4170 				switch(value)
4171 				{
4172 				case D3DTADDRESS_WRAP:
4173 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_WRAP);
4174 					break;
4175 				case D3DTADDRESS_MIRROR:
4176 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRROR);
4177 					break;
4178 				case D3DTADDRESS_CLAMP:
4179 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_CLAMP);
4180 					break;
4181 				case D3DTADDRESS_BORDER:
4182 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_BORDER);
4183 					break;
4184 				case D3DTADDRESS_MIRRORONCE:
4185 					renderer->setAddressingModeU(type, index, sw::ADDRESSING_MIRRORONCE);
4186 					break;
4187 				default:
4188 					ASSERT(false);
4189 				}
4190 				break;
4191 			case D3DSAMP_ADDRESSV:
4192 				switch(value)
4193 				{
4194 				case D3DTADDRESS_WRAP:
4195 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_WRAP);
4196 					break;
4197 				case D3DTADDRESS_MIRROR:
4198 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRROR);
4199 					break;
4200 				case D3DTADDRESS_CLAMP:
4201 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_CLAMP);
4202 					break;
4203 				case D3DTADDRESS_BORDER:
4204 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_BORDER);
4205 					break;
4206 				case D3DTADDRESS_MIRRORONCE:
4207 					renderer->setAddressingModeV(type, index, sw::ADDRESSING_MIRRORONCE);
4208 					break;
4209 				default:
4210 					ASSERT(false);
4211 				}
4212 				break;
4213 			case D3DSAMP_ADDRESSW:
4214 				switch(value)
4215 				{
4216 				case D3DTADDRESS_WRAP:
4217 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_WRAP);
4218 					break;
4219 				case D3DTADDRESS_MIRROR:
4220 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRROR);
4221 					break;
4222 				case D3DTADDRESS_CLAMP:
4223 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_CLAMP);
4224 					break;
4225 				case D3DTADDRESS_BORDER:
4226 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_BORDER);
4227 					break;
4228 				case D3DTADDRESS_MIRRORONCE:
4229 					renderer->setAddressingModeW(type, index, sw::ADDRESSING_MIRRORONCE);
4230 					break;
4231 				default:
4232 					ASSERT(false);
4233 				}
4234 				break;
4235 			case D3DSAMP_BORDERCOLOR:
4236 				renderer->setBorderColor(type, index, value);
4237 				break;
4238 			case D3DSAMP_MAGFILTER:
4239 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4240 				switch(value)
4241 				{
4242 				case D3DTEXF_NONE:
4243 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4244 					break;
4245 				case D3DTEXF_POINT:
4246 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4247 					break;
4248 				case D3DTEXF_LINEAR:
4249 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4250 					break;
4251 				case D3DTEXF_ANISOTROPIC:
4252 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4253 					break;
4254 				case D3DTEXF_PYRAMIDALQUAD:
4255 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4256 					break;
4257 				case D3DTEXF_GAUSSIANQUAD:
4258 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4259 					break;
4260 				default:
4261 					return INVALIDCALL();
4262 				};
4263 				break;
4264 			case D3DSAMP_MINFILTER:
4265 				// NOTE: SwiftShader does not differentiate between minification and magnification filter
4266 				switch(value)
4267 				{
4268 				case D3DTEXF_NONE:
4269 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);   // FIXME: Only for mipmap filter
4270 					break;
4271 				case D3DTEXF_POINT:
4272 					renderer->setTextureFilter(type, index, sw::FILTER_POINT);
4273 					break;
4274 				case D3DTEXF_LINEAR:
4275 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);
4276 					break;
4277 				case D3DTEXF_ANISOTROPIC:
4278 					renderer->setTextureFilter(type, index, sw::FILTER_ANISOTROPIC);
4279 					break;
4280 				case D3DTEXF_PYRAMIDALQUAD:
4281 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4282 					break;
4283 				case D3DTEXF_GAUSSIANQUAD:
4284 					renderer->setTextureFilter(type, index, sw::FILTER_LINEAR);   // FIXME: Unimplemented, fail silently
4285 					break;
4286 				default:
4287 					return INVALIDCALL();
4288 				};
4289 				break;
4290 			case D3DSAMP_MIPFILTER:
4291 				switch(value)
4292 				{
4293 				case D3DTEXF_NONE:
4294 					renderer->setMipmapFilter(type, index, sw::MIPMAP_NONE);
4295 					break;
4296 				case D3DTEXF_POINT:
4297 					renderer->setMipmapFilter(type, index, sw::MIPMAP_POINT);
4298 					break;
4299 				case D3DTEXF_LINEAR:
4300 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);
4301 					break;
4302 				case D3DTEXF_ANISOTROPIC:
4303 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4304 					break;
4305 				case D3DTEXF_PYRAMIDALQUAD:
4306 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4307 					break;
4308 				case D3DTEXF_GAUSSIANQUAD:
4309 					renderer->setMipmapFilter(type, index, sw::MIPMAP_LINEAR);   // FIXME: Only for texture filter
4310 					break;
4311 				default:
4312 					return INVALIDCALL();
4313 				};
4314 				break;
4315 			case D3DSAMP_MIPMAPLODBIAS:
4316 				if(value == D3DFMT_GET4)   // ATI hack to enable Fetch4
4317 				{
4318 					renderer->setGatherEnable(type, index, true);
4319 				}
4320 				else if(value == D3DFMT_GET1)   // ATI hack to disable Fetch4
4321 				{
4322 					renderer->setGatherEnable(type, index, false);
4323 				}
4324 				else
4325 				{
4326 					float LOD = (float&)value - sw::log2((float)context->renderTarget[0]->getSuperSampleCount());   // FIXME: Update when render target changes
4327 					renderer->setMipmapLOD(type, index, LOD);
4328 				}
4329 				break;
4330 			case D3DSAMP_MAXMIPLEVEL:
4331 				break;
4332 			case D3DSAMP_MAXANISOTROPY:
4333 				renderer->setMaxAnisotropy(type, index, sw::clamp((unsigned int)value, (unsigned int)1, maxAnisotropy));
4334 				break;
4335 			case D3DSAMP_SRGBTEXTURE:
4336 				renderer->setReadSRGB(type, index, value != FALSE);
4337 				break;
4338 			case D3DSAMP_ELEMENTINDEX:
4339 				if(!init) UNIMPLEMENTED();   // Multi-element textures deprecated in favor of multiple render targets
4340 				break;
4341 			case D3DSAMP_DMAPOFFSET:
4342 			//	if(!init) UNIMPLEMENTED();
4343 				break;
4344 			default:
4345 				ASSERT(false);
4346 			}
4347 		}
4348 		else   // stateRecorder
4349 		{
4350 			stateRecorder->setSamplerState(sampler, state, value);
4351 		}
4352 
4353 		return D3D_OK;
4354 	}
4355 
SetScissorRect(const RECT * rect)4356 	long Direct3DDevice9::SetScissorRect(const RECT *rect)
4357 	{
4358 		CriticalSection cs(this);
4359 
4360 		TRACE("const RECT *rect = 0x%0.8p", rect);
4361 
4362 		if(!rect)
4363 		{
4364 			return INVALIDCALL();
4365 		}
4366 
4367 		if(!stateRecorder)
4368 		{
4369 			scissorRect = *rect;
4370 		}
4371 		else
4372 		{
4373 			stateRecorder->setScissorRect(rect);
4374 		}
4375 
4376 		return D3D_OK;
4377 	}
4378 
SetSoftwareVertexProcessing(int software)4379 	long Direct3DDevice9::SetSoftwareVertexProcessing(int software)
4380 	{
4381 		CriticalSection cs(this);
4382 
4383 		TRACE("int software = %d", software);
4384 
4385 		if(behaviourFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING && software == FALSE)
4386 		{
4387 			return INVALIDCALL();
4388 		}
4389 
4390 		if(behaviourFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING && software == TRUE)
4391 		{
4392 			return INVALIDCALL();
4393 		}
4394 
4395 		softwareVertexProcessing = (software != FALSE);
4396 
4397 		return D3D_OK;
4398 	}
4399 
SetStreamSource(unsigned int stream,IDirect3DVertexBuffer9 * iVertexBuffer,unsigned int offset,unsigned int stride)4400 	long Direct3DDevice9::SetStreamSource(unsigned int stream, IDirect3DVertexBuffer9 *iVertexBuffer, unsigned int offset, unsigned int stride)
4401 	{
4402 		CriticalSection cs(this);
4403 
4404 		TRACE("unsigned int stream = %d, IDirect3DVertexBuffer9 *data = 0x%0.8p, unsigned int offset = %d, unsigned int stride = %d", stream, iVertexBuffer, offset, stride);
4405 
4406 		Direct3DVertexBuffer9 *vertexBuffer = static_cast<Direct3DVertexBuffer9*>(iVertexBuffer);
4407 
4408 		if(!stateRecorder)
4409 		{
4410 			if(dataStream[stream] == vertexBuffer && streamOffset[stream] == offset && streamStride[stream] == stride)
4411 			{
4412 				return D3D_OK;
4413 			}
4414 
4415 			if(vertexBuffer)
4416 			{
4417 				vertexBuffer->bind();
4418 			}
4419 
4420 			if(dataStream[stream])
4421 			{
4422 				dataStream[stream]->unbind();
4423 			}
4424 
4425 			dataStream[stream] = vertexBuffer;
4426 			streamOffset[stream] = offset;
4427 			streamStride[stream] = stride;
4428 		}
4429 		else
4430 		{
4431 			stateRecorder->setStreamSource(stream, vertexBuffer, offset, stride);
4432 		}
4433 
4434 		return D3D_OK;
4435 	}
4436 
SetStreamSourceFreq(unsigned int streamNumber,unsigned int divider)4437 	long Direct3DDevice9::SetStreamSourceFreq(unsigned int streamNumber, unsigned int divider)
4438 	{
4439 		CriticalSection cs(this);
4440 
4441 		TRACE("unsigned int streamNumber = %d, unsigned int divider = %d", streamNumber, divider);
4442 
4443 		if(!instancingEnabled)
4444 		{
4445 			return INVALIDCALL();
4446 		}
4447 
4448 		if(!stateRecorder)
4449 		{
4450 			streamSourceFreq[streamNumber] = divider;
4451 		}
4452 		else
4453 		{
4454 			stateRecorder->setStreamSourceFreq(streamNumber, divider);
4455 		}
4456 
4457 		return D3D_OK;
4458 	}
4459 
SetTexture(unsigned long sampler,IDirect3DBaseTexture9 * iBaseTexture)4460 	long Direct3DDevice9::SetTexture(unsigned long sampler, IDirect3DBaseTexture9 *iBaseTexture)
4461 	{
4462 		CriticalSection cs(this);
4463 
4464 		TRACE("unsigned long sampler = %d, IDirect3DBaseTexture9 *texture = 0x%0.8p", sampler, iBaseTexture);
4465 
4466 		if((sampler >= 16 && sampler <= D3DDMAPSAMPLER) || sampler > D3DVERTEXTEXTURESAMPLER3)
4467 		{
4468 			return INVALIDCALL();
4469 		}
4470 
4471 		if(sampler >= D3DVERTEXTEXTURESAMPLER0)
4472 		{
4473 			sampler = 16 + (sampler - D3DVERTEXTEXTURESAMPLER0);
4474 		}
4475 
4476 		Direct3DBaseTexture9 *baseTexture = dynamic_cast<Direct3DBaseTexture9*>(iBaseTexture);
4477 
4478 		if(!stateRecorder)
4479 		{
4480 			if(texture[sampler] == baseTexture)
4481 			{
4482 				return D3D_OK;
4483 			}
4484 
4485 			if(baseTexture)
4486 			{
4487 				baseTexture->bind();   // FIXME: Bind individual sub-surfaces?
4488 			}
4489 
4490 			if(texture[sampler])
4491 			{
4492 				texture[sampler]->unbind();
4493 			}
4494 
4495 			texture[sampler] = baseTexture;
4496 		}
4497 		else
4498 		{
4499 			stateRecorder->setTexture(sampler, baseTexture);
4500 		}
4501 
4502 		return D3D_OK;
4503 	}
4504 
SetTextureStageState(unsigned long stage,D3DTEXTURESTAGESTATETYPE type,unsigned long value)4505 	long Direct3DDevice9::SetTextureStageState(unsigned long stage, D3DTEXTURESTAGESTATETYPE type, unsigned long value)
4506 	{
4507 		CriticalSection cs(this);
4508 
4509 		TRACE("unsigned long stage = %d, D3DTEXTURESTAGESTATETYPE type = %d, unsigned long value = %d", stage, type, value);
4510 
4511 		if(stage < 0 || stage >= 8 || type < D3DTSS_COLOROP || type > D3DTSS_CONSTANT)
4512 		{
4513 			return INVALIDCALL();
4514 		}
4515 
4516 		if(!stateRecorder)
4517 		{
4518 			if(!init && textureStageState[stage][type] == value)
4519 			{
4520 				return D3D_OK;
4521 			}
4522 
4523 			textureStageState[stage][type] = value;
4524 
4525 			switch(type)
4526 			{
4527 			case D3DTSS_COLOROP:
4528 				switch(value)
4529 				{
4530 				case D3DTOP_DISABLE:
4531 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DISABLE);
4532 					break;
4533 				case D3DTOP_SELECTARG1:
4534 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG1);
4535 					break;
4536 				case D3DTOP_SELECTARG2:
4537 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SELECTARG2);
4538 					break;
4539 				case D3DTOP_MODULATE:
4540 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE);
4541 					break;
4542 				case D3DTOP_MODULATE2X:
4543 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE2X);
4544 					break;
4545 				case D3DTOP_MODULATE4X:
4546 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATE4X);
4547 					break;
4548 				case D3DTOP_ADD:
4549 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADD);
4550 					break;
4551 				case D3DTOP_ADDSIGNED:
4552 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED);
4553 					break;
4554 				case D3DTOP_ADDSIGNED2X:
4555 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4556 					break;
4557 				case D3DTOP_SUBTRACT:
4558 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_SUBTRACT);
4559 					break;
4560 				case D3DTOP_ADDSMOOTH:
4561 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4562 					break;
4563 				case D3DTOP_BLENDDIFFUSEALPHA:
4564 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4565 					break;
4566 				case D3DTOP_BLENDTEXTUREALPHA:
4567 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4568 					break;
4569 				case D3DTOP_BLENDFACTORALPHA:
4570 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4571 					break;
4572 				case D3DTOP_BLENDTEXTUREALPHAPM:
4573 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4574 					break;
4575 				case D3DTOP_BLENDCURRENTALPHA:
4576 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4577 					break;
4578 				case D3DTOP_PREMODULATE:
4579 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_PREMODULATE);
4580 					break;
4581 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4582 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4583 					break;
4584 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4585 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4586 					break;
4587 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4588 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4589 					break;
4590 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4591 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4592 					break;
4593 				case D3DTOP_BUMPENVMAP:
4594 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4595 					break;
4596 				case D3DTOP_BUMPENVMAPLUMINANCE:
4597 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4598 					break;
4599 				case D3DTOP_DOTPRODUCT3:
4600 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_DOT3);
4601 					break;
4602 				case D3DTOP_MULTIPLYADD:
4603 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4604 					break;
4605 				case D3DTOP_LERP:
4606 					renderer->setStageOperation(stage, sw::TextureStage::STAGE_LERP);
4607 					break;
4608 				default:
4609 					ASSERT(false);
4610 				}
4611 				break;
4612 			case D3DTSS_COLORARG1:
4613 				switch(value & D3DTA_SELECTMASK)
4614 				{
4615 				case D3DTA_DIFFUSE:
4616 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4617 					break;
4618 				case D3DTA_CURRENT:
4619 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4620 					break;
4621 				case D3DTA_TEXTURE:
4622 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4623 					break;
4624 				case D3DTA_TFACTOR:
4625 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4626 					break;
4627 				case D3DTA_SPECULAR:
4628 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4629 					break;
4630 				case D3DTA_TEMP:
4631 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_TEMP);
4632 					break;
4633 				case D3DTA_CONSTANT:
4634 					renderer->setFirstArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4635 					break;
4636 				default:
4637 					ASSERT(false);
4638 				}
4639 
4640 				switch(value & ~D3DTA_SELECTMASK)
4641 				{
4642 				case 0:
4643 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4644 					break;
4645 				case D3DTA_COMPLEMENT:
4646 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4647 					break;
4648 				case D3DTA_ALPHAREPLICATE:
4649 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4650 					break;
4651 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4652 					renderer->setFirstModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4653 					break;
4654 				default:
4655 					ASSERT(false);
4656 				}
4657 				break;
4658 			case D3DTSS_COLORARG2:
4659 				switch(value & D3DTA_SELECTMASK)
4660 				{
4661 				case D3DTA_DIFFUSE:
4662 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4663 					break;
4664 				case D3DTA_CURRENT:
4665 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4666 					break;
4667 				case D3DTA_TEXTURE:
4668 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4669 					break;
4670 				case D3DTA_TFACTOR:
4671 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4672 					break;
4673 				case D3DTA_SPECULAR:
4674 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4675 					break;
4676 				case D3DTA_TEMP:
4677 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_TEMP);
4678 					break;
4679 				case D3DTA_CONSTANT:
4680 					renderer->setSecondArgument(stage, sw::TextureStage::SOURCE_CONSTANT);
4681 					break;
4682 				default:
4683 					ASSERT(false);
4684 				}
4685 
4686 				switch(value & ~D3DTA_SELECTMASK)
4687 				{
4688 				case 0:
4689 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4690 					break;
4691 				case D3DTA_COMPLEMENT:
4692 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4693 					break;
4694 				case D3DTA_ALPHAREPLICATE:
4695 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4696 					break;
4697 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4698 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4699 					break;
4700 				default:
4701 					ASSERT(false);
4702 				}
4703 				break;
4704 			case D3DTSS_ALPHAOP:
4705 				switch(value)
4706 				{
4707 				case D3DTOP_DISABLE:
4708 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DISABLE);
4709 					break;
4710 				case D3DTOP_SELECTARG1:
4711 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG1);
4712 					break;
4713 				case D3DTOP_SELECTARG2:
4714 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SELECTARG2);
4715 					break;
4716 				case D3DTOP_MODULATE:
4717 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE);
4718 					break;
4719 				case D3DTOP_MODULATE2X:
4720 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE2X);
4721 					break;
4722 				case D3DTOP_MODULATE4X:
4723 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATE4X);
4724 					break;
4725 				case D3DTOP_ADD:
4726 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADD);
4727 					break;
4728 				case D3DTOP_ADDSIGNED:
4729 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED);
4730 					break;
4731 				case D3DTOP_ADDSIGNED2X:
4732 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSIGNED2X);
4733 					break;
4734 				case D3DTOP_SUBTRACT:
4735 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_SUBTRACT);
4736 					break;
4737 				case D3DTOP_ADDSMOOTH:
4738 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_ADDSMOOTH);
4739 					break;
4740 				case D3DTOP_BLENDDIFFUSEALPHA:
4741 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDDIFFUSEALPHA);
4742 					break;
4743 				case D3DTOP_BLENDTEXTUREALPHA:
4744 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHA);
4745 					break;
4746 				case D3DTOP_BLENDFACTORALPHA:
4747 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDFACTORALPHA);
4748 					break;
4749 				case D3DTOP_BLENDTEXTUREALPHAPM:
4750 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDTEXTUREALPHAPM);
4751 					break;
4752 				case D3DTOP_BLENDCURRENTALPHA:
4753 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BLENDCURRENTALPHA);
4754 					break;
4755 				case D3DTOP_PREMODULATE:
4756 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_PREMODULATE);
4757 					break;
4758 				case D3DTOP_MODULATEALPHA_ADDCOLOR:
4759 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEALPHA_ADDCOLOR);
4760 					break;
4761 				case D3DTOP_MODULATECOLOR_ADDALPHA:
4762 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATECOLOR_ADDALPHA);
4763 					break;
4764 				case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
4765 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVALPHA_ADDCOLOR);
4766 					break;
4767 				case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
4768 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MODULATEINVCOLOR_ADDALPHA);
4769 					break;
4770 				case D3DTOP_BUMPENVMAP:
4771 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAP);
4772 					break;
4773 				case D3DTOP_BUMPENVMAPLUMINANCE:
4774 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_BUMPENVMAPLUMINANCE);
4775 					break;
4776 				case D3DTOP_DOTPRODUCT3:
4777 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_DOT3);
4778 					break;
4779 				case D3DTOP_MULTIPLYADD:
4780 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_MULTIPLYADD);
4781 					break;
4782 				case D3DTOP_LERP:
4783 					renderer->setStageOperationAlpha(stage, sw::TextureStage::STAGE_LERP);
4784 					break;
4785 				default:
4786 					ASSERT(false);
4787 				}
4788 				break;
4789 			case D3DTSS_ALPHAARG1:
4790 				switch(value & D3DTA_SELECTMASK)
4791 				{
4792 				case D3DTA_DIFFUSE:
4793 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4794 					break;
4795 				case D3DTA_CURRENT:
4796 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4797 					break;
4798 				case D3DTA_TEXTURE:
4799 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4800 					break;
4801 				case D3DTA_TFACTOR:
4802 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4803 					break;
4804 				case D3DTA_SPECULAR:
4805 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4806 					break;
4807 				case D3DTA_TEMP:
4808 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4809 					break;
4810 				case D3DTA_CONSTANT:
4811 					renderer->setFirstArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4812 					break;
4813 				default:
4814 					ASSERT(false);
4815 				}
4816 
4817 				switch(value & ~D3DTA_SELECTMASK)
4818 				{
4819 				case 0:
4820 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4821 					break;
4822 				case D3DTA_COMPLEMENT:
4823 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4824 					break;
4825 				case D3DTA_ALPHAREPLICATE:
4826 					renderer->setFirstModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4827 					break;
4828 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4829 					renderer->setSecondModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4830 					break;
4831 				default:
4832 					ASSERT(false);
4833 				}
4834 				break;
4835 			case D3DTSS_ALPHAARG2:
4836 				switch(value & D3DTA_SELECTMASK)
4837 				{
4838 				case D3DTA_DIFFUSE:
4839 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4840 					break;
4841 				case D3DTA_CURRENT:
4842 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
4843 					break;
4844 				case D3DTA_TEXTURE:
4845 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
4846 					break;
4847 				case D3DTA_TFACTOR:
4848 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
4849 					break;
4850 				case D3DTA_SPECULAR:
4851 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
4852 					break;
4853 				case D3DTA_TEMP:
4854 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
4855 					break;
4856 				case D3DTA_CONSTANT:
4857 					renderer->setSecondArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
4858 					break;
4859 				default:
4860 					ASSERT(false);
4861 				}
4862 
4863 				switch(value & ~D3DTA_SELECTMASK)
4864 				{
4865 				case 0:
4866 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
4867 					break;
4868 				case D3DTA_COMPLEMENT:
4869 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4870 					break;
4871 				case D3DTA_ALPHAREPLICATE:
4872 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
4873 					break;
4874 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4875 					renderer->setSecondModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
4876 					break;
4877 				default:
4878 					ASSERT(false);
4879 				}
4880 				break;
4881 			case D3DTSS_BUMPENVMAT00:
4882 				renderer->setBumpmapMatrix(stage, 0, (float&)value);
4883 				break;
4884 			case D3DTSS_BUMPENVMAT01:
4885 				renderer->setBumpmapMatrix(stage, 1, (float&)value);
4886 				break;
4887 			case D3DTSS_BUMPENVMAT10:
4888 				renderer->setBumpmapMatrix(stage, 2, (float&)value);
4889 				break;
4890 			case D3DTSS_BUMPENVMAT11:
4891 				renderer->setBumpmapMatrix(stage, 3, (float&)value);
4892 				break;
4893 			case D3DTSS_TEXCOORDINDEX:
4894 				renderer->setTexCoordIndex(stage, value & 0x0000FFFF);
4895 
4896 				switch(value & 0xFFFF0000)
4897 				{
4898 				case D3DTSS_TCI_PASSTHRU:
4899 					renderer->setTexGen(stage, sw::TEXGEN_PASSTHRU);
4900 					break;
4901 				case D3DTSS_TCI_CAMERASPACENORMAL:
4902 					renderer->setTexCoordIndex(stage, stage);
4903 					renderer->setTexGen(stage, sw::TEXGEN_NORMAL);
4904 					break;
4905 				case D3DTSS_TCI_CAMERASPACEPOSITION:
4906 					renderer->setTexCoordIndex(stage, stage);
4907 					renderer->setTexGen(stage, sw::TEXGEN_POSITION);
4908 					break;
4909 				case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4910 					renderer->setTexCoordIndex(stage, stage);
4911 					renderer->setTexGen(stage, sw::TEXGEN_REFLECTION);
4912 					break;
4913 				case D3DTSS_TCI_SPHEREMAP:
4914 					renderer->setTexCoordIndex(stage, stage);
4915 					renderer->setTexGen(stage, sw::TEXGEN_SPHEREMAP);
4916 					break;
4917 				default:
4918 					ASSERT(false);
4919 				}
4920 				break;
4921 			case D3DTSS_BUMPENVLSCALE:
4922 				renderer->setLuminanceScale(stage, (float&)value);
4923 				break;
4924 			case D3DTSS_BUMPENVLOFFSET:
4925 				renderer->setLuminanceOffset(stage, (float&)value);
4926 				break;
4927 			case D3DTSS_TEXTURETRANSFORMFLAGS:
4928 				switch(value & ~D3DTTFF_PROJECTED)
4929 				{
4930 				case D3DTTFF_DISABLE:
4931 					renderer->setTextureTransform(stage, 0, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4932 					break;
4933 				case D3DTTFF_COUNT1:
4934 					renderer->setTextureTransform(stage, 1, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4935 					break;
4936 				case D3DTTFF_COUNT2:
4937 					renderer->setTextureTransform(stage, 2, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4938 					break;
4939 				case D3DTTFF_COUNT3:
4940 					renderer->setTextureTransform(stage, 3, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4941 					break;
4942 				case D3DTTFF_COUNT4:
4943 					renderer->setTextureTransform(stage, 4, (value & D3DTTFF_PROJECTED) == D3DTTFF_PROJECTED);
4944 					break;
4945 				default:
4946 					ASSERT(false);
4947 				}
4948 				break;
4949 			case D3DTSS_COLORARG0:
4950 				switch(value & D3DTA_SELECTMASK)
4951 				{
4952 				case D3DTA_CURRENT:
4953 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_CURRENT);
4954 					break;
4955 				case D3DTA_DIFFUSE:
4956 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_DIFFUSE);
4957 					break;
4958 				case D3DTA_SPECULAR:
4959 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_SPECULAR);
4960 					break;
4961 				case D3DTA_TEMP:
4962 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEMP);
4963 					break;
4964 				case D3DTA_TEXTURE:
4965 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TEXTURE);
4966 					break;
4967 				case D3DTA_TFACTOR:
4968 					renderer->setThirdArgument(stage, sw::TextureStage::SOURCE_TFACTOR);
4969 					break;
4970 				default:
4971 					ASSERT(false);
4972 				}
4973 
4974 				switch(value & ~D3DTA_SELECTMASK)
4975 				{
4976 				case 0:
4977 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_COLOR);
4978 					break;
4979 				case D3DTA_COMPLEMENT:
4980 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVCOLOR);
4981 					break;
4982 				case D3DTA_ALPHAREPLICATE:
4983 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_ALPHA);
4984 					break;
4985 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
4986 					renderer->setThirdModifier(stage, sw::TextureStage::MODIFIER_INVALPHA);
4987 					break;
4988 				default:
4989 					ASSERT(false);
4990 				}
4991 				break;
4992 			case D3DTSS_ALPHAARG0:
4993 				switch(value & D3DTA_SELECTMASK)
4994 				{
4995 				case D3DTA_DIFFUSE:
4996 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_DIFFUSE);
4997 					break;
4998 				case D3DTA_CURRENT:
4999 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CURRENT);
5000 					break;
5001 				case D3DTA_TEXTURE:
5002 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEXTURE);
5003 					break;
5004 				case D3DTA_TFACTOR:
5005 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TFACTOR);
5006 					break;
5007 				case D3DTA_SPECULAR:
5008 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_SPECULAR);
5009 					break;
5010 				case D3DTA_TEMP:
5011 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_TEMP);
5012 					break;
5013 				case D3DTA_CONSTANT:
5014 					renderer->setThirdArgumentAlpha(stage, sw::TextureStage::SOURCE_CONSTANT);
5015 					break;
5016 				default:
5017 					ASSERT(false);
5018 				}
5019 
5020 				switch(value & ~D3DTA_SELECTMASK)
5021 				{
5022 				case 0:
5023 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_COLOR);
5024 					break;
5025 				case D3DTA_COMPLEMENT:
5026 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVCOLOR);
5027 					break;
5028 				case D3DTA_ALPHAREPLICATE:
5029 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_ALPHA);
5030 					break;
5031 				case D3DTA_COMPLEMENT | D3DTA_ALPHAREPLICATE:
5032 					renderer->setThirdModifierAlpha(stage, sw::TextureStage::MODIFIER_INVALPHA);
5033 					break;
5034 				default:
5035 					ASSERT(false);
5036 				}
5037 				break;
5038 			case D3DTSS_RESULTARG:
5039 				switch(value & D3DTA_SELECTMASK)
5040 				{
5041 				case D3DTA_CURRENT:
5042 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_CURRENT);
5043 					break;
5044 				case D3DTA_TEMP:
5045 					renderer->setDestinationArgument(stage, sw::TextureStage::DESTINATION_TEMP);
5046 					break;
5047 				default:
5048 					ASSERT(false);
5049 				}
5050 				break;
5051 			case D3DTSS_CONSTANT:
5052 				renderer->setConstantColor(stage, value);
5053 				break;
5054 			default:
5055 				ASSERT(false);
5056 			}
5057 		}
5058 		else   // stateRecorder
5059 		{
5060 			stateRecorder->setTextureStageState(stage, type, value);
5061 		}
5062 
5063 		return D3D_OK;
5064 	}
5065 
SetTransform(D3DTRANSFORMSTATETYPE state,const D3DMATRIX * matrix)5066 	long Direct3DDevice9::SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix)
5067 	{
5068 		CriticalSection cs(this);
5069 
5070 		TRACE("D3DTRANSFORMSTATETYPE state = %d, const D3DMATRIX *matrix = 0x%0.8p", state, matrix);
5071 
5072 		if(!matrix)
5073 		{
5074 			return INVALIDCALL();
5075 		}
5076 
5077 		if(!stateRecorder)
5078 		{
5079 			this->matrix[state] = *matrix;
5080 
5081 			sw::Matrix M(matrix->_11, matrix->_21, matrix->_31, matrix->_41,
5082 			             matrix->_12, matrix->_22, matrix->_32, matrix->_42,
5083 			             matrix->_13, matrix->_23, matrix->_33, matrix->_43,
5084 			             matrix->_14, matrix->_24, matrix->_34, matrix->_44);
5085 
5086 			switch(state)
5087 			{
5088 			case D3DTS_WORLD:
5089 				renderer->setModelMatrix(M);
5090 				break;
5091 			case D3DTS_VIEW:
5092 				renderer->setViewMatrix(M);
5093 				break;
5094 			case D3DTS_PROJECTION:
5095 				renderer->setProjectionMatrix(M);
5096 				break;
5097 			case D3DTS_TEXTURE0:
5098 				renderer->setTextureMatrix(0, M);
5099 				break;
5100 			case D3DTS_TEXTURE1:
5101 				renderer->setTextureMatrix(1, M);
5102 				break;
5103 			case D3DTS_TEXTURE2:
5104 				renderer->setTextureMatrix(2, M);
5105 				break;
5106 			case D3DTS_TEXTURE3:
5107 				renderer->setTextureMatrix(3, M);
5108 				break;
5109 			case D3DTS_TEXTURE4:
5110 				renderer->setTextureMatrix(4, M);
5111 				break;
5112 			case D3DTS_TEXTURE5:
5113 				renderer->setTextureMatrix(5, M);
5114 				break;
5115 			case D3DTS_TEXTURE6:
5116 				renderer->setTextureMatrix(6, M);
5117 				break;
5118 			case D3DTS_TEXTURE7:
5119 				renderer->setTextureMatrix(7, M);
5120 				break;
5121 			default:
5122 				if(state > 256 && state < 512)
5123 				{
5124 					renderer->setModelMatrix(M, state - 256);
5125 				}
5126 				else ASSERT(false);
5127 			}
5128 		}
5129 		else   // stateRecorder
5130 		{
5131 			stateRecorder->setTransform(state, matrix);
5132 		}
5133 
5134 		return D3D_OK;
5135 	}
5136 
SetVertexDeclaration(IDirect3DVertexDeclaration9 * iVertexDeclaration)5137 	long Direct3DDevice9::SetVertexDeclaration(IDirect3DVertexDeclaration9 *iVertexDeclaration)
5138 	{
5139 		CriticalSection cs(this);
5140 
5141 		TRACE("IDirect3DVertexDeclaration9 *declaration = 0x%0.8p", iVertexDeclaration);
5142 
5143 		Direct3DVertexDeclaration9 *vertexDeclaration = static_cast<Direct3DVertexDeclaration9*>(iVertexDeclaration);
5144 
5145 		if(!stateRecorder)
5146 		{
5147 			if(this->vertexDeclaration == vertexDeclaration)
5148 			{
5149 				return D3D_OK;
5150 			}
5151 
5152 			if(vertexDeclaration)
5153 			{
5154 				vertexDeclaration->bind();
5155 			}
5156 
5157 			if(this->vertexDeclaration)
5158 			{
5159 				this->vertexDeclaration->unbind();
5160 			}
5161 
5162 			this->vertexDeclaration = vertexDeclaration;
5163 		}
5164 		else
5165 		{
5166 			stateRecorder->setVertexDeclaration(vertexDeclaration);
5167 		}
5168 
5169 		return D3D_OK;
5170 	}
5171 
SetVertexShader(IDirect3DVertexShader9 * iVertexShader)5172 	long Direct3DDevice9::SetVertexShader(IDirect3DVertexShader9 *iVertexShader)
5173 	{
5174 		CriticalSection cs(this);
5175 
5176 		TRACE("IDirect3DVertexShader9 *shader = 0x%0.8p", iVertexShader);
5177 
5178 		Direct3DVertexShader9 *vertexShader = static_cast<Direct3DVertexShader9*>(iVertexShader);
5179 
5180 		if(!stateRecorder)
5181 		{
5182 			if(this->vertexShader == vertexShader)
5183 			{
5184 				return D3D_OK;
5185 			}
5186 
5187 			if(vertexShader)
5188 			{
5189 				vertexShader->bind();
5190 			}
5191 
5192 			if(this->vertexShader)
5193 			{
5194 				this->vertexShader->unbind();
5195 			}
5196 
5197 			this->vertexShader = vertexShader;
5198 			vertexShaderDirty = true;
5199 		}
5200 		else
5201 		{
5202 			stateRecorder->setVertexShader(vertexShader);
5203 		}
5204 
5205 		return D3D_OK;
5206 	}
5207 
SetVertexShaderConstantB(unsigned int startRegister,const int * constantData,unsigned int count)5208 	long Direct3DDevice9::SetVertexShaderConstantB(unsigned int startRegister, const int *constantData, unsigned int count)
5209 	{
5210 		CriticalSection cs(this);
5211 
5212 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5213 
5214 		if(!constantData)
5215 		{
5216 			return INVALIDCALL();
5217 		}
5218 
5219 		if(!stateRecorder)
5220 		{
5221 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5222 			{
5223 				vertexShaderConstantB[startRegister + i] = constantData[i];
5224 			}
5225 
5226 			vertexShaderConstantsBDirty = sw::max(startRegister + count, vertexShaderConstantsBDirty);
5227 			vertexShaderDirty = true;   // Reload DEF constants
5228 		}
5229 		else
5230 		{
5231 			stateRecorder->setVertexShaderConstantB(startRegister, constantData, count);
5232 		}
5233 
5234 		return D3D_OK;
5235 	}
5236 
SetVertexShaderConstantF(unsigned int startRegister,const float * constantData,unsigned int count)5237 	long Direct3DDevice9::SetVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count)
5238 	{
5239 		CriticalSection cs(this);
5240 
5241 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5242 
5243 		if(!constantData)
5244 		{
5245 			return INVALIDCALL();
5246 		}
5247 
5248 		if(!stateRecorder)
5249 		{
5250 			for(unsigned int i = 0; i < count && startRegister + i < MAX_VERTEX_SHADER_CONST; i++)
5251 			{
5252 				vertexShaderConstantF[startRegister + i][0] = constantData[i * 4 + 0];
5253 				vertexShaderConstantF[startRegister + i][1] = constantData[i * 4 + 1];
5254 				vertexShaderConstantF[startRegister + i][2] = constantData[i * 4 + 2];
5255 				vertexShaderConstantF[startRegister + i][3] = constantData[i * 4 + 3];
5256 			}
5257 
5258 			vertexShaderConstantsFDirty = sw::max(startRegister + count, vertexShaderConstantsFDirty);
5259 			vertexShaderDirty = true;   // Reload DEF constants
5260 		}
5261 		else
5262 		{
5263 			stateRecorder->setVertexShaderConstantF(startRegister, constantData, count);
5264 		}
5265 
5266 		return D3D_OK;
5267 	}
5268 
SetVertexShaderConstantI(unsigned int startRegister,const int * constantData,unsigned int count)5269 	long Direct3DDevice9::SetVertexShaderConstantI(unsigned int startRegister, const int *constantData, unsigned int count)
5270 	{
5271 		CriticalSection cs(this);
5272 
5273 		TRACE("unsigned int startRegister = %d, const int *constantData = 0x%0.8p, unsigned int count = %d", startRegister, constantData, count);
5274 
5275 		if(!constantData)
5276 		{
5277 			return INVALIDCALL();
5278 		}
5279 
5280 		if(!stateRecorder)
5281 		{
5282 			for(unsigned int i = 0; i < count && startRegister + i < 16; i++)
5283 			{
5284 				vertexShaderConstantI[startRegister + i][0] = constantData[i * 4 + 0];
5285 				vertexShaderConstantI[startRegister + i][1] = constantData[i * 4 + 1];
5286 				vertexShaderConstantI[startRegister + i][2] = constantData[i * 4 + 2];
5287 				vertexShaderConstantI[startRegister + i][3] = constantData[i * 4 + 3];
5288 			}
5289 
5290 			vertexShaderConstantsIDirty = sw::max(startRegister + count, vertexShaderConstantsIDirty);
5291 			vertexShaderDirty = true;   // Reload DEF constants
5292 		}
5293 		else
5294 		{
5295 			stateRecorder->setVertexShaderConstantI(startRegister, constantData, count);
5296 		}
5297 
5298 		return D3D_OK;
5299 	}
5300 
SetViewport(const D3DVIEWPORT9 * viewport)5301 	long Direct3DDevice9::SetViewport(const D3DVIEWPORT9 *viewport)
5302 	{
5303 		CriticalSection cs(this);
5304 
5305 		TRACE("const D3DVIEWPORT9 *viewport = 0x%0.8p", viewport);
5306 
5307 		if(!viewport)   // FIXME: Check if valid
5308 		{
5309 			return INVALIDCALL();
5310 		}
5311 
5312 		if(!stateRecorder)
5313 		{
5314 			this->viewport = *viewport;
5315 		}
5316 		else
5317 		{
5318 			stateRecorder->setViewport(viewport);
5319 		}
5320 
5321 		return D3D_OK;
5322 	}
5323 
ShowCursor(int show)5324 	int Direct3DDevice9::ShowCursor(int show)
5325 	{
5326 		CriticalSection cs(this);
5327 
5328 		TRACE("int show = %d", show);
5329 
5330 		int oldValue = showCursor ? TRUE : FALSE;
5331 		showCursor = show != FALSE;
5332 
5333 		if(showCursor)
5334 		{
5335 			sw::FrameBuffer::setCursorImage(cursor);
5336 		}
5337 		else
5338 		{
5339 			sw::FrameBuffer::setCursorImage(0);
5340 		}
5341 
5342 		return oldValue;
5343 	}
5344 
StretchRect(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destSurface,const RECT * destRect,D3DTEXTUREFILTERTYPE filter)5345 	long Direct3DDevice9::StretchRect(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destSurface, const RECT *destRect, D3DTEXTUREFILTERTYPE filter)
5346 	{
5347 		CriticalSection cs(this);
5348 
5349 		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);
5350 
5351 		if(!sourceSurface || !destSurface || !validRectangle(sourceRect, sourceSurface) || !validRectangle(destRect, destSurface))
5352 		{
5353 			return INVALIDCALL();
5354 		}
5355 
5356 		D3DSURFACE_DESC sourceDescription;
5357 		D3DSURFACE_DESC destDescription;
5358 
5359 		sourceSurface->GetDesc(&sourceDescription);
5360 		destSurface->GetDesc(&destDescription);
5361 
5362 		if(sourceDescription.Pool != D3DPOOL_DEFAULT || destDescription.Pool != D3DPOOL_DEFAULT)
5363 		{
5364 			return INVALIDCALL();
5365 		}
5366 
5367 		Direct3DSurface9 *source = static_cast<Direct3DSurface9*>(sourceSurface);
5368 		Direct3DSurface9 *dest = static_cast<Direct3DSurface9*>(destSurface);
5369 
5370 		stretchRect(source, sourceRect, dest, destRect, filter);
5371 
5372 		return D3D_OK;
5373 	}
5374 
TestCooperativeLevel()5375 	long Direct3DDevice9::TestCooperativeLevel()
5376 	{
5377 		CriticalSection cs(this);
5378 
5379 		TRACE("void");
5380 
5381 		return D3D_OK;
5382 	}
5383 
UpdateSurface(IDirect3DSurface9 * sourceSurface,const RECT * sourceRect,IDirect3DSurface9 * destinationSurface,const POINT * destPoint)5384 	long Direct3DDevice9::UpdateSurface(IDirect3DSurface9 *sourceSurface, const RECT *sourceRect, IDirect3DSurface9 *destinationSurface, const POINT *destPoint)
5385 	{
5386 		CriticalSection cs(this);
5387 
5388 		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);
5389 
5390 		if(!sourceSurface || !destinationSurface)
5391 		{
5392 			return INVALIDCALL();
5393 		}
5394 
5395 		D3DSURFACE_DESC sourceDescription;
5396 		D3DSURFACE_DESC destinationDescription;
5397 
5398 		sourceSurface->GetDesc(&sourceDescription);
5399 		destinationSurface->GetDesc(&destinationDescription);
5400 
5401 		RECT sRect;
5402 		RECT dRect;
5403 
5404 		if(sourceRect)
5405 		{
5406 			sRect.left = sourceRect->left;
5407 			sRect.top = sourceRect->top;
5408 			sRect.right = sourceRect->right;
5409 			sRect.bottom = sourceRect->bottom;
5410 		}
5411 		else
5412 		{
5413 			sRect.left = 0;
5414 			sRect.top = 0;
5415 			sRect.right = sourceDescription.Width;
5416 			sRect.bottom = sourceDescription.Height;
5417 		}
5418 
5419 		if(destPoint)
5420 		{
5421 			dRect.left = destPoint->x;
5422 			dRect.top = destPoint->y;
5423 			dRect.right = destPoint->x + sRect.right - sRect.left;
5424 			dRect.bottom = destPoint->y + sRect.bottom - sRect.top;
5425 		}
5426 		else
5427 		{
5428 			dRect.left = 0;
5429 			dRect.top = 0;
5430 			dRect.right = sRect.right - sRect.left;
5431 			dRect.bottom = sRect.bottom - sRect.top;
5432 		}
5433 
5434 		if(!validRectangle(&sRect, sourceSurface) || !validRectangle(&dRect, destinationSurface))
5435 		{
5436 			return INVALIDCALL();
5437 		}
5438 
5439 		int sWidth = sRect.right - sRect.left;
5440 		int sHeight = sRect.bottom - sRect.top;
5441 
5442 		int dWidth = dRect.right - dRect.left;
5443 		int dHeight = dRect.bottom - dRect.top;
5444 
5445 		if(sourceDescription.MultiSampleType      != D3DMULTISAMPLE_NONE ||
5446 		   destinationDescription.MultiSampleType != D3DMULTISAMPLE_NONE ||
5447 		// sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||   // FIXME: Check back buffer and depth buffer memory pool flags
5448 		// destinationDescription.Pool != D3DPOOL_DEFAULT ||
5449 		   sourceDescription.Format != destinationDescription.Format)
5450 		{
5451 			return INVALIDCALL();
5452 		}
5453 
5454 		sw::Surface *source = static_cast<Direct3DSurface9*>(sourceSurface);
5455 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destinationSurface);
5456 
5457 		unsigned char *sBuffer = (unsigned char*)source->lockExternal(sRect.left, sRect.top, 0, sw::LOCK_READONLY, sw::PUBLIC);
5458 		unsigned char *dBuffer = (unsigned char*)dest->lockExternal(dRect.left, dRect.top, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
5459 		int sPitch = source->getExternalPitchB();
5460 		int dPitch = dest->getExternalPitchB();
5461 
5462 		unsigned int width;
5463 		unsigned int height;
5464 		unsigned int bytes;
5465 
5466 		switch(sourceDescription.Format)
5467 		{
5468 		case D3DFMT_DXT1:
5469 		case D3DFMT_ATI1:
5470 			width = (dWidth + 3) / 4;
5471 			height = (dHeight + 3) / 4;
5472 			bytes = width * 8;   // 64 bit per 4x4 block
5473 			break;
5474 		case D3DFMT_DXT2:
5475 		case D3DFMT_DXT3:
5476 		case D3DFMT_DXT4:
5477 		case D3DFMT_DXT5:
5478 		case D3DFMT_ATI2:
5479 			width = (dWidth + 3) / 4;
5480 			height = (dHeight + 3) / 4;
5481 			bytes = width * 16;   // 128 bit per 4x4 block
5482 			break;
5483 		default:
5484 			width = dWidth;
5485 			height = dHeight;
5486 			bytes = width * Direct3DSurface9::bytes(sourceDescription.Format);
5487 		}
5488 
5489 		if(sourceDescription.Format == D3DFMT_ATI1 || sourceDescription.Format == D3DFMT_ATI2)
5490 		{
5491 			// Make the pitch correspond to 4 rows
5492 			sPitch *= 4;
5493 			dPitch *= 4;
5494 		}
5495 
5496 		for(unsigned int y = 0; y < height; y++)
5497 		{
5498 			memcpy(dBuffer, sBuffer, bytes);
5499 
5500 			sBuffer += sPitch;
5501 			dBuffer += dPitch;
5502 		}
5503 
5504 		source->unlockExternal();
5505 		dest->unlockExternal();
5506 
5507 		return D3D_OK;
5508 	}
5509 
UpdateTexture(IDirect3DBaseTexture9 * sourceTexture,IDirect3DBaseTexture9 * destinationTexture)5510 	long Direct3DDevice9::UpdateTexture(IDirect3DBaseTexture9 *sourceTexture, IDirect3DBaseTexture9 *destinationTexture)
5511 	{
5512 		CriticalSection cs(this);
5513 
5514 		TRACE("IDirect3DBaseTexture9 *sourceTexture = 0x%0.8p, IDirect3DBaseTexture9 *destinationTexture = 0x%0.8p", sourceTexture, destinationTexture);
5515 
5516 		if(!sourceTexture || !destinationTexture)
5517 		{
5518 			return INVALIDCALL();
5519 		}
5520 
5521 		// FIXME: Check memory pools
5522 
5523 		D3DRESOURCETYPE type = sourceTexture->GetType();
5524 
5525 		if(type != destinationTexture->GetType())
5526 		{
5527 			return INVALIDCALL();
5528 		}
5529 
5530 		switch(type)
5531 		{
5532 		case D3DRTYPE_TEXTURE:
5533 			{
5534 				IDirect3DTexture9 *source;
5535 				IDirect3DTexture9 *dest;
5536 
5537 				sourceTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&source);
5538 				destinationTexture->QueryInterface(IID_IDirect3DTexture9, (void**)&dest);
5539 
5540 				ASSERT(source && dest);
5541 
5542 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5543 				{
5544 					IDirect3DSurface9 *sourceSurface;
5545 					IDirect3DSurface9 *destinationSurface;
5546 
5547 					source->GetSurfaceLevel(level, &sourceSurface);
5548 					dest->GetSurfaceLevel(level, &destinationSurface);
5549 
5550 					UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5551 
5552 					sourceSurface->Release();
5553 					destinationSurface->Release();
5554 				}
5555 
5556 				source->Release();
5557 				dest->Release();
5558 			}
5559 			break;
5560 		case D3DRTYPE_VOLUMETEXTURE:
5561 			{
5562 				IDirect3DVolumeTexture9 *source;
5563 				IDirect3DVolumeTexture9 *dest;
5564 
5565 				sourceTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&source);
5566 				destinationTexture->QueryInterface(IID_IDirect3DVolumeTexture9, (void**)&dest);
5567 
5568 				ASSERT(source && dest);
5569 
5570 				for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5571 				{
5572 					IDirect3DVolume9 *sourceVolume;
5573 					IDirect3DVolume9 *destinationVolume;
5574 
5575 					source->GetVolumeLevel(level, &sourceVolume);
5576 					dest->GetVolumeLevel(level, &destinationVolume);
5577 
5578 					updateVolume(sourceVolume, destinationVolume);
5579 
5580 					sourceVolume->Release();
5581 					destinationVolume->Release();
5582 				}
5583 
5584 				source->Release();
5585 				dest->Release();
5586 			}
5587 			break;
5588 		case D3DRTYPE_CUBETEXTURE:
5589 			{
5590 				IDirect3DCubeTexture9 *source;
5591 				IDirect3DCubeTexture9 *dest;
5592 
5593 				sourceTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&source);
5594 				destinationTexture->QueryInterface(IID_IDirect3DCubeTexture9, (void**)&dest);
5595 
5596 				ASSERT(source && dest);
5597 
5598 				for(int face = 0; face < 6; face++)
5599 				{
5600 					for(unsigned int level = 0; level < source->GetLevelCount() && level < dest->GetLevelCount(); level++)   // FIXME: Fail when source texture has fewer levels than the destination
5601 					{
5602 						IDirect3DSurface9 *sourceSurface;
5603 						IDirect3DSurface9 *destinationSurface;
5604 
5605 						source->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &sourceSurface);
5606 						dest->GetCubeMapSurface((D3DCUBEMAP_FACES)face, level, &destinationSurface);
5607 
5608 						UpdateSurface(sourceSurface, 0, destinationSurface, 0);
5609 
5610 						sourceSurface->Release();
5611 						destinationSurface->Release();
5612 					}
5613 				}
5614 
5615 				source->Release();
5616 				dest->Release();
5617 			}
5618 			break;
5619 		default:
5620 			UNIMPLEMENTED();
5621 		}
5622 
5623 		return D3D_OK;
5624 	}
5625 
ValidateDevice(unsigned long * numPasses)5626 	long Direct3DDevice9::ValidateDevice(unsigned long *numPasses)
5627 	{
5628 		CriticalSection cs(this);
5629 
5630 		TRACE("unsigned long *numPasses = 0x%0.8p", numPasses);
5631 
5632 		if(!numPasses)
5633 		{
5634 			return INVALIDCALL();
5635 		}
5636 
5637 		*numPasses = 1;
5638 
5639 		return D3D_OK;
5640 	}
5641 
getAdapterDisplayMode(unsigned int adapter,D3DDISPLAYMODE * mode)5642 	long Direct3DDevice9::getAdapterDisplayMode(unsigned int adapter, D3DDISPLAYMODE *mode)
5643 	{
5644 		return d3d9->GetAdapterDisplayMode(adapter, mode);
5645 	}
5646 
typeStride(unsigned char streamType)5647 	int Direct3DDevice9::typeStride(unsigned char streamType)
5648 	{
5649 		static int LUT[] =
5650 		{
5651 			4,	// D3DDECLTYPE_FLOAT1    =  0,  // 1D float expanded to (value, 0., 0., 1.)
5652 			8,	// D3DDECLTYPE_FLOAT2    =  1,  // 2D float expanded to (value, value, 0., 1.)
5653 			12,	// D3DDECLTYPE_FLOAT3    =  2,  // 3D float expanded to (value, value, value, 1.)
5654 			16,	// D3DDECLTYPE_FLOAT4    =  3,  // 4D float
5655 			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)
5656 			4,	// D3DDECLTYPE_UBYTE4    =  5,  // 4D unsigned byte
5657 			4,	// D3DDECLTYPE_SHORT2    =  6,  // 2D signed short expanded to (value, value, 0., 1.)
5658 			8,	// D3DDECLTYPE_SHORT4    =  7,  // 4D signed short
5659 			4,	// D3DDECLTYPE_UBYTE4N   =  8,  // Each of 4 bytes is normalized by dividing to 255.0
5660 			4,	// D3DDECLTYPE_SHORT2N   =  9,  // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
5661 			8,	// D3DDECLTYPE_SHORT4N   = 10,  // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
5662 			4,	// D3DDECLTYPE_USHORT2N  = 11,  // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
5663 			8,	// D3DDECLTYPE_USHORT4N  = 12,  // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
5664 			4,	// D3DDECLTYPE_UDEC3     = 13,  // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
5665 			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)
5666 			4,	// D3DDECLTYPE_FLOAT16_2 = 15,  // Two 16-bit floating point values, expanded to (value, value, 0, 1)
5667 			8,	// D3DDECLTYPE_FLOAT16_4 = 16,  // Four 16-bit floating point values
5668 			0,	// D3DDECLTYPE_UNUSED    = 17,  // When the type field in a decl is unused.
5669 		};
5670 
5671 		return LUT[streamType];
5672 	}
5673 
instanceData()5674 	bool Direct3DDevice9::instanceData()
5675 	{
5676 		ASSERT(vertexDeclaration);
5677 
5678 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5679 		unsigned int numElements;
5680 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5681 
5682 		bool instanceData = false;
5683 
5684 		for(unsigned int i = 0; i < numElements - 1; i++)
5685 		{
5686 			unsigned short stream = vertexElement[i].Stream;
5687 
5688 			if(stream != 0)
5689 			{
5690 				instanceData = instanceData || (streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA) != 0;
5691 			}
5692 		}
5693 
5694 		return instanceData;
5695 	}
5696 
bindResources(Direct3DIndexBuffer9 * indexBuffer)5697 	bool Direct3DDevice9::bindResources(Direct3DIndexBuffer9 *indexBuffer)
5698 	{
5699 		if(!bindViewport())
5700 		{
5701 			return false;   // Zero-area target region
5702 		}
5703 
5704 		bindTextures();
5705 		bindIndexBuffer(indexBuffer);
5706 		bindShaderConstants();
5707 		bindLights();
5708 
5709 		return true;
5710 	}
5711 
bindVertexStreams(int base,bool instancing,int instance)5712 	void Direct3DDevice9::bindVertexStreams(int base, bool instancing, int instance)
5713 	{
5714 		ASSERT(vertexDeclaration);
5715 
5716 		renderer->resetInputStreams(vertexDeclaration->isPreTransformed());
5717 
5718 		D3DVERTEXELEMENT9 vertexElement[MAXD3DDECLLENGTH + 1];
5719 		unsigned int numElements;
5720 		vertexDeclaration->GetDeclaration(vertexElement, &numElements);
5721 
5722 		// Bind vertex data streams
5723 		for(unsigned int i = 0; i < numElements - 1; i++)
5724 		{
5725 			unsigned short stream = vertexElement[i].Stream;
5726 			unsigned short offset = vertexElement[i].Offset;
5727 			unsigned char type = vertexElement[i].Type;
5728 			unsigned char method = vertexElement[i].Method;
5729 			unsigned char usage = vertexElement[i].Usage;
5730 			unsigned char index = vertexElement[i].UsageIndex;
5731 
5732 			ASSERT(method == D3DDECLMETHOD_DEFAULT);	// FIXME: Unimplemented
5733 
5734 			if(!dataStream[stream])
5735 			{
5736 				continue;
5737 			}
5738 
5739 			Direct3DVertexBuffer9 *streamBuffer = dataStream[stream];
5740 			sw::Resource *resource = streamBuffer->getResource();
5741 			const void *buffer = ((char*)resource->data() + streamOffset[stream]) + offset;
5742 
5743 			int stride = streamStride[stream];
5744 
5745 			if(instancing && streamSourceFreq[stream] & D3DSTREAMSOURCE_INSTANCEDATA)
5746 			{
5747 				int instanceFrequency = streamSourceFreq[stream] & ~D3DSTREAMSOURCE_INSTANCEDATA;
5748 				buffer = (char*)buffer + stride * (instance / instanceFrequency);
5749 
5750 				stride = 0;
5751 			}
5752 			else
5753 			{
5754 				buffer = (char*)buffer + stride * base;
5755 			}
5756 
5757 			sw::Stream attribute(resource, buffer, stride);
5758 
5759 			switch(type)
5760 			{
5761 			case D3DDECLTYPE_FLOAT1:    attribute.define(sw::STREAMTYPE_FLOAT, 1, false);  break;
5762 			case D3DDECLTYPE_FLOAT2:    attribute.define(sw::STREAMTYPE_FLOAT, 2, false);  break;
5763 			case D3DDECLTYPE_FLOAT3:    attribute.define(sw::STREAMTYPE_FLOAT, 3, false);  break;
5764 			case D3DDECLTYPE_FLOAT4:    attribute.define(sw::STREAMTYPE_FLOAT, 4, false);  break;
5765 			case D3DDECLTYPE_D3DCOLOR:  attribute.define(sw::STREAMTYPE_COLOR, 4, false);  break;
5766 			case D3DDECLTYPE_UBYTE4:    attribute.define(sw::STREAMTYPE_BYTE, 4, false);   break;
5767 			case D3DDECLTYPE_SHORT2:    attribute.define(sw::STREAMTYPE_SHORT, 2, false);  break;
5768 			case D3DDECLTYPE_SHORT4:    attribute.define(sw::STREAMTYPE_SHORT, 4, false);  break;
5769 			case D3DDECLTYPE_UBYTE4N:   attribute.define(sw::STREAMTYPE_BYTE, 4, true);    break;
5770 			case D3DDECLTYPE_SHORT2N:   attribute.define(sw::STREAMTYPE_SHORT, 2, true);   break;
5771 			case D3DDECLTYPE_SHORT4N:   attribute.define(sw::STREAMTYPE_SHORT, 4, true);   break;
5772 			case D3DDECLTYPE_USHORT2N:  attribute.define(sw::STREAMTYPE_USHORT, 2, true);  break;
5773 			case D3DDECLTYPE_USHORT4N:  attribute.define(sw::STREAMTYPE_USHORT, 4, true);  break;
5774 			case D3DDECLTYPE_UDEC3:     attribute.define(sw::STREAMTYPE_UDEC3, 3, false);  break;
5775 			case D3DDECLTYPE_DEC3N:     attribute.define(sw::STREAMTYPE_DEC3N, 3, true);   break;
5776 			case D3DDECLTYPE_FLOAT16_2: attribute.define(sw::STREAMTYPE_HALF, 2, false);   break;
5777 			case D3DDECLTYPE_FLOAT16_4: attribute.define(sw::STREAMTYPE_HALF, 4, false);   break;
5778 			case D3DDECLTYPE_UNUSED:    attribute.defaults();                              break;
5779 			default:
5780 				ASSERT(false);
5781 			}
5782 
5783 			if(vertexShader)
5784 			{
5785 				const sw::VertexShader *shader = vertexShader->getVertexShader();
5786 
5787 				if(!vertexDeclaration->isPreTransformed())
5788 				{
5789 					for(int i = 0; i < MAX_VERTEX_INPUTS; i++)
5790 					{
5791 						const sw::Shader::Semantic& input = shader->getInput(i);
5792 						if((usage == input.usage) && (index == input.index))
5793 						{
5794 							renderer->setInputStream(i, attribute);
5795 
5796 							break;
5797 						}
5798 					}
5799 				}
5800 				else   // Bind directly to the output
5801 				{
5802 					for(int i = 0; i < MAX_VERTEX_OUTPUTS; i++)
5803 					{
5804 						const sw::Shader::Semantic& output = shader->getOutput(i, 0);
5805 						if(((usage == output.usage) || (usage == D3DDECLUSAGE_POSITIONT && output.usage == D3DDECLUSAGE_POSITION)) &&
5806 						   (index == output.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, 0, 0, sw::PUBLIC);
6274 				byte *destBuffer = (byte*)dest->lockStencil(0, 0, 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 			sw::SliceRectF sRectF((float)sRect.x0, (float)sRect.y0, (float)sRect.x1, (float)sRect.y1, 0);
6325 			renderer->blit(source, sRectF, dest, dRect, filter >= D3DTEXF_LINEAR);
6326 		}
6327 	}
6328 
updateVolume(IDirect3DVolume9 * sourceVolume,IDirect3DVolume9 * destinationVolume)6329 	long Direct3DDevice9::updateVolume(IDirect3DVolume9 *sourceVolume, IDirect3DVolume9 *destinationVolume)
6330 	{
6331 		TRACE("IDirect3DVolume9 *sourceVolume = 0x%0.8p, IDirect3DVolume9 *destinationVolume = 0x%0.8p", sourceVolume, destinationVolume);
6332 
6333 		if(!sourceVolume || !destinationVolume)
6334 		{
6335 			return INVALIDCALL();
6336 		}
6337 
6338 		D3DVOLUME_DESC sourceDescription;
6339 		D3DVOLUME_DESC destinationDescription;
6340 
6341 		sourceVolume->GetDesc(&sourceDescription);
6342 		destinationVolume->GetDesc(&destinationDescription);
6343 
6344 		if(sourceDescription.Pool      != D3DPOOL_SYSTEMMEM ||
6345 		   destinationDescription.Pool != D3DPOOL_DEFAULT ||
6346 		   sourceDescription.Format != destinationDescription.Format ||
6347 		   sourceDescription.Width  != destinationDescription.Width ||
6348 		   sourceDescription.Height != destinationDescription.Height ||
6349 		   sourceDescription.Depth  != destinationDescription.Depth)
6350 		{
6351 			return INVALIDCALL();
6352 		}
6353 
6354 		sw::Surface *source = static_cast<Direct3DVolume9*>(sourceVolume);
6355 		sw::Surface *dest = static_cast<Direct3DVolume9*>(destinationVolume);
6356 
6357 		if(source->getExternalPitchB() != dest->getExternalPitchB() ||
6358 		   source->getExternalSliceB() != dest->getExternalSliceB())
6359 		{
6360 			UNIMPLEMENTED();
6361 		}
6362 
6363 		void *sBuffer = source->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
6364 		void *dBuffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
6365 
6366 		memcpy(dBuffer, sBuffer, source->getExternalSliceB() * sourceDescription.Depth);
6367 
6368 		source->unlockExternal();
6369 		dest->unlockExternal();
6370 
6371 		return D3D_OK;
6372 	}
6373 
validRectangle(const RECT * rect,IDirect3DSurface9 * surface)6374 	bool Direct3DDevice9::validRectangle(const RECT *rect, IDirect3DSurface9 *surface)
6375 	{
6376 		if(!rect)
6377 		{
6378 			return true;
6379 		}
6380 
6381 		if(rect->right <= rect->left || rect->bottom <= rect->top)
6382 		{
6383 			return false;
6384 		}
6385 
6386 		if(rect->left < 0 || rect->top < 0)
6387 		{
6388 			return false;
6389 		}
6390 
6391 		D3DSURFACE_DESC description;
6392 		surface->GetDesc(&description);
6393 
6394 		if(rect->right > (int)description.Width || rect->bottom > (int)description.Height)
6395 		{
6396 			return false;
6397 		}
6398 
6399 		return true;
6400 	}
6401 
configureFPU()6402 	void Direct3DDevice9::configureFPU()
6403 	{
6404 	//	_controlfp(_PC_24, _MCW_PC);     // Single-precision
6405 		_controlfp(_MCW_EM, _MCW_EM);    // Mask all exceptions
6406 		_controlfp(_RC_NEAR, _MCW_RC);   // Round to nearest
6407 	}
6408 }
6409