1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Direct3DSwapChain8.hpp"
16 
17 #include "Direct3DDevice8.hpp"
18 #include "Config.hpp"
19 #include "Configurator.hpp"
20 #include "Debug.hpp"
21 
22 #include "FrameBufferDD.hpp"
23 #include "FrameBufferGDI.hpp"
24 
25 namespace D3D8
26 {
Direct3DSwapChain8(Direct3DDevice8 * device,D3DPRESENT_PARAMETERS * presentParameters)27 	Direct3DSwapChain8::Direct3DSwapChain8(Direct3DDevice8 *device, D3DPRESENT_PARAMETERS *presentParameters) : device(device), presentParameters(*presentParameters)
28 	{
29 		frameBuffer = 0;
30 
31 		for(int i = 0; i < 3; i++)
32 		{
33 			backBuffer[i] = 0;
34 		}
35 
36 		reset(presentParameters);
37 	}
38 
~Direct3DSwapChain8()39 	Direct3DSwapChain8::~Direct3DSwapChain8()
40 	{
41 		release();
42 	}
43 
QueryInterface(const IID & iid,void ** object)44 	long Direct3DSwapChain8::QueryInterface(const IID &iid, void **object)
45 	{
46 		TRACE("");
47 
48 		if(iid == IID_IDirect3DSwapChain8 ||
49 		   iid == IID_IUnknown)
50 		{
51 			AddRef();
52 			*object = this;
53 
54 			return S_OK;
55 		}
56 
57 		*object = 0;
58 
59 		return NOINTERFACE(iid);
60 	}
61 
AddRef()62 	unsigned long Direct3DSwapChain8::AddRef()
63 	{
64 		TRACE("");
65 
66 		return Unknown::AddRef();
67 	}
68 
Release()69 	unsigned long Direct3DSwapChain8::Release()
70 	{
71 		TRACE("");
72 
73 		return Unknown::Release();
74 	}
75 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion)76 	long Direct3DSwapChain8::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion)
77 	{
78 		TRACE("");
79 
80 		#if PERF_PROFILE
81 			profiler.nextFrame();
82 		#endif
83 
84 		if(!sourceRect && !destRect)   // FIXME: More cases?
85 		{
86 			frameBuffer->flip(destWindowOverride, backBuffer[0]);
87 		}
88 		else   // TODO: Check for SWAPEFFECT_COPY
89 		{
90 			sw::Rect sRect(0, 0, 0, 0);
91 			sw::Rect dRect(0, 0, 0, 0);
92 
93 			if(sourceRect)
94 			{
95 				sRect.x0 = sourceRect->left;
96 				sRect.y0 = sourceRect->top;
97 				sRect.x1 = sourceRect->right;
98 				sRect.y1 = sourceRect->bottom;
99 			}
100 
101 			if(destRect)
102 			{
103 				dRect.x0 = destRect->left;
104 				dRect.y0 = destRect->top;
105 				dRect.x1 = destRect->right;
106 				dRect.y1 = destRect->bottom;
107 			}
108 
109 			frameBuffer->blit(destWindowOverride, backBuffer[0], sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr);
110 		}
111 
112 		return D3D_OK;
113 	}
114 
GetBackBuffer(unsigned int index,D3DBACKBUFFER_TYPE type,IDirect3DSurface8 ** backBuffer)115 	long Direct3DSwapChain8::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface8 **backBuffer)
116 	{
117 		TRACE("");
118 
119 		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
120 		{
121 			return INVALIDCALL();
122 		}
123 
124 		if(index >= 3 || this->backBuffer[index] == 0)
125 		{
126 			return INVALIDCALL();
127 		}
128 
129 		this->backBuffer[index]->AddRef();
130 		*backBuffer = this->backBuffer[index];
131 
132 		return D3D_OK;
133 	}
134 
reset(D3DPRESENT_PARAMETERS * presentParameters)135 	void Direct3DSwapChain8::reset(D3DPRESENT_PARAMETERS *presentParameters)
136 	{
137 		release();
138 
139 		this->presentParameters = *presentParameters;
140 
141 		ASSERT(presentParameters->BackBufferCount <= 3);   // Maximum of three back buffers
142 
143 		if(presentParameters->BackBufferCount == 0)
144 		{
145 			presentParameters->BackBufferCount = 1;
146 		}
147 
148 		D3DDEVICE_CREATION_PARAMETERS creationParameters;
149 		device->GetCreationParameters(&creationParameters);
150 
151 		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow;
152 
153 		int width = 0;
154 		int height = 0;
155 
156 		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
157 		{
158 			RECT rectangle;
159 			GetClientRect(windowHandle, &rectangle);
160 
161 			width = rectangle.right - rectangle.left;
162 			height = rectangle.bottom - rectangle.top;
163 		}
164 		else
165 		{
166 			width = presentParameters->BackBufferWidth;
167 			height = presentParameters->BackBufferHeight;
168 		}
169 
170 		frameBuffer = createFrameBufferWin(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE, true);
171 
172 		lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
173 
174 		backBuffer[0] = 0;
175 		backBuffer[1] = 0;
176 		backBuffer[2] = 0;
177 
178 		for(int i = 0; i < (int)presentParameters->BackBufferCount; i++)
179 		{
180 			backBuffer[i] = new Direct3DSurface8(device, this, width, height, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, lockable, D3DUSAGE_RENDERTARGET);
181 			backBuffer[i]->bind();
182 		}
183 	}
184 
release()185 	void Direct3DSwapChain8::release()
186 	{
187 		delete frameBuffer;
188 		frameBuffer = 0;
189 
190 		for(int i = 0; i < 3; i++)
191 		{
192 			if(backBuffer[i])
193 			{
194 				backBuffer[i]->unbind();
195 				backBuffer[i] = 0;
196 			}
197 		}
198 	}
199 
screenshot(void * destBuffer)200 	void Direct3DSwapChain8::screenshot(void *destBuffer)
201 	{
202 		frameBuffer->screenshot(destBuffer);
203 	}
204 
setGammaRamp(sw::GammaRamp * gammaRamp,bool calibrate)205 	void Direct3DSwapChain8::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate)
206 	{
207 		frameBuffer->setGammaRamp(gammaRamp, calibrate);
208 	}
209 
getGammaRamp(sw::GammaRamp * gammaRamp)210 	void Direct3DSwapChain8::getGammaRamp(sw::GammaRamp *gammaRamp)
211 	{
212 		frameBuffer->getGammaRamp(gammaRamp);
213 	}
214 
lockBackBuffer(int index)215 	void *Direct3DSwapChain8::lockBackBuffer(int index)
216 	{
217 		return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC);   // FIXME: External
218 	}
219 
unlockBackBuffer(int index)220 	void Direct3DSwapChain8::unlockBackBuffer(int index)
221 	{
222 		backBuffer[index]->unlockInternal();   // FIXME: External
223 	}
224 }
225