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