• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Direct3DSwapChain9.hpp"
16 
17 #include "Direct3DDevice9.hpp"
18 #include "Renderer.hpp"
19 #include "Timer.hpp"
20 #include "Resource.hpp"
21 #include "Configurator.hpp"
22 #include "Debug.hpp"
23 
24 #include "FrameBufferDD.hpp"
25 #include "FrameBufferGDI.hpp"
26 
27 namespace D3D9
28 {
Direct3DSwapChain9(Direct3DDevice9 * device,D3DPRESENT_PARAMETERS * presentParameters)29 	Direct3DSwapChain9::Direct3DSwapChain9(Direct3DDevice9 *device, D3DPRESENT_PARAMETERS *presentParameters) : device(device), presentParameters(*presentParameters)
30 	{
31 		frameBuffer = 0;
32 
33 		for(int i = 0; i < 3; i++)
34 		{
35 			backBuffer[i] = 0;
36 		}
37 
38 		reset(presentParameters);
39 	}
40 
~Direct3DSwapChain9()41 	Direct3DSwapChain9::~Direct3DSwapChain9()
42 	{
43 		release();
44 	}
45 
QueryInterface(const IID & iid,void ** object)46 	long Direct3DSwapChain9::QueryInterface(const IID &iid, void **object)
47 	{
48 		CriticalSection cs(device);
49 
50 		TRACE("");
51 
52 		if(iid == IID_IDirect3DSwapChain9 ||
53 		   iid == IID_IUnknown)
54 		{
55 			AddRef();
56 			*object = this;
57 
58 			return S_OK;
59 		}
60 
61 		*object = 0;
62 
63 		return NOINTERFACE(iid);
64 	}
65 
AddRef()66 	unsigned long Direct3DSwapChain9::AddRef()
67 	{
68 		TRACE("");
69 
70 		return Unknown::AddRef();
71 	}
72 
Release()73 	unsigned long Direct3DSwapChain9::Release()
74 	{
75 		TRACE("");
76 
77 		return Unknown::Release();
78 	}
79 
Present(const RECT * sourceRect,const RECT * destRect,HWND destWindowOverride,const RGNDATA * dirtyRegion,unsigned long flags)80 	long Direct3DSwapChain9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion, unsigned long flags)
81 	{
82 		CriticalSection cs(device);
83 
84 		TRACE("");
85 
86 		#if PERF_PROFILE
87 			profiler.nextFrame();
88 		#endif
89 
90 		#if PERF_HUD
91 			sw::Renderer *renderer = device->renderer;
92 
93 			static int64_t frame = sw::Timer::ticks();
94 
95 			int64_t frameTime = sw::Timer::ticks() - frame;
96 			frame = sw::Timer::ticks();
97 
98 			if(frameTime > 0)
99 			{
100 				unsigned int *frameBuffer = (unsigned int*)lockBackBuffer(0);   // FIXME: Don't assume A8R8G8B8 mode
101 				unsigned int stride = backBuffer[0]->getInternalPitchP();
102 
103 				int thread;
104 				for(thread = 0; thread < renderer->getThreadCount(); thread++)
105 				{
106 					int64_t drawTime = renderer->getVertexTime(thread) + renderer->getSetupTime(thread) + renderer->getPixelTime(thread);
107 
108 					int vertexPercentage = sw::clamp((int)(100 * renderer->getVertexTime(thread) / frameTime), 0, 100);
109 					int setupPercentage = sw::clamp((int)(100 * renderer->getSetupTime(thread) / frameTime), 0, 100);
110 					int pixelPercentage = sw::clamp((int)(100 * renderer->getPixelTime(thread) / frameTime), 0, 100);
111 
112 					for(int i = 0; i < 100; i++)
113 					{
114 						frameBuffer[thread * stride + i] = 0x00000000;
115 					}
116 
117 					unsigned int *buffer = frameBuffer;
118 
119 					for(int i = 0; i < vertexPercentage; i++)
120 					{
121 						buffer[thread * stride] = 0x000000FF;
122 						buffer++;
123 					}
124 
125 					for(int i = 0; i < setupPercentage; i++)
126 					{
127 						buffer[thread * stride] = 0x0000FF00;
128 						buffer++;
129 					}
130 
131 					for(int i = 0; i < pixelPercentage; i++)
132 					{
133 						buffer[thread * stride] = 0x00FF0000;
134 						buffer++;
135 					}
136 
137 					frameBuffer[thread * stride + 100] = 0x00FFFFFF;
138 				}
139 
140 				for(int i = 0; i <= 100; i++)
141 				{
142 					frameBuffer[thread * stride + i] = 0x00FFFFFF;
143 				}
144 
145 				unlockBackBuffer(0);
146 			}
147 
148 			renderer->resetTimers();
149 		#endif
150 
151 		HWND window = destWindowOverride ? destWindowOverride : presentParameters.hDeviceWindow;
152 
153 		POINT point;
154 		GetCursorPos(&point);
155 		ScreenToClient(window, &point);
156 
157 		frameBuffer->setCursorPosition(point.x, point.y);
158 
159 		if(!sourceRect && !destRect)   // FIXME: More cases?
160 		{
161 			frameBuffer->flip(window, backBuffer[0]);
162 		}
163 		else   // FIXME: Check for SWAPEFFECT_COPY
164 		{
165 			sw::Rect sRect(0, 0, 0, 0);
166 			sw::Rect dRect(0, 0, 0, 0);
167 
168 			if(sourceRect)
169 			{
170 				sRect.x0 = sourceRect->left;
171 				sRect.y0 = sourceRect->top;
172 				sRect.x1 = sourceRect->right;
173 				sRect.y1 = sourceRect->bottom;
174 			}
175 
176 			if(destRect)
177 			{
178 				dRect.x0 = destRect->left;
179 				dRect.y0 = destRect->top;
180 				dRect.x1 = destRect->right;
181 				dRect.y1 = destRect->bottom;
182 			}
183 
184 			frameBuffer->blit(window, backBuffer[0], sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr);
185 		}
186 
187 		return D3D_OK;
188 	}
189 
GetFrontBufferData(IDirect3DSurface9 * destSurface)190 	long Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *destSurface)
191 	{
192 		CriticalSection cs(device);
193 
194 		TRACE("");
195 
196 		if(!destSurface)
197 		{
198 			return INVALIDCALL();
199 		}
200 
201 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface);
202 		void *buffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PRIVATE);
203 
204 		frameBuffer->screenshot(buffer);
205 
206 		dest->unlockExternal();
207 
208 		return D3D_OK;
209 	}
210 
GetBackBuffer(unsigned int index,D3DBACKBUFFER_TYPE type,IDirect3DSurface9 ** backBuffer)211 	long Direct3DSwapChain9::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer)
212 	{
213 		CriticalSection cs(device);
214 
215 		TRACE("");
216 
217 		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
218 		{
219 			return INVALIDCALL();
220 		}
221 
222 		*backBuffer = 0;
223 
224 		if(index >= 3 || this->backBuffer[index] == 0)
225 		{
226 			return INVALIDCALL();
227 		}
228 
229 		*backBuffer = this->backBuffer[index];
230 		this->backBuffer[index]->AddRef();
231 
232 		return D3D_OK;
233 	}
234 
GetRasterStatus(D3DRASTER_STATUS * rasterStatus)235 	long Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *rasterStatus)
236 	{
237 		CriticalSection cs(device);
238 
239 		TRACE("");
240 
241 		if(!rasterStatus)
242 		{
243 			return INVALIDCALL();
244 		}
245 
246 		bool inVerticalBlank;
247 		unsigned int scanline;
248 		bool supported = frameBuffer->getScanline(inVerticalBlank, scanline);
249 
250 		if(supported)
251 		{
252 			rasterStatus->InVBlank = inVerticalBlank;
253 			rasterStatus->ScanLine = scanline;
254 		}
255 		else
256 		{
257 			return INVALIDCALL();
258 		}
259 
260 		return D3D_OK;
261 	}
262 
GetDisplayMode(D3DDISPLAYMODE * displayMode)263 	long Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *displayMode)
264 	{
265 		CriticalSection cs(device);
266 
267 		TRACE("");
268 
269 		if(!displayMode)
270 		{
271 			return INVALIDCALL();
272 		}
273 
274 		device->getAdapterDisplayMode(D3DADAPTER_DEFAULT, displayMode);
275 
276 		return D3D_OK;
277 	}
278 
GetDevice(IDirect3DDevice9 ** device)279 	long Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **device)
280 	{
281 		CriticalSection cs(this->device);
282 
283 		TRACE("");
284 
285 		if(!device)
286 		{
287 			return INVALIDCALL();
288 		}
289 
290 		this->device->AddRef();
291 		*device = this->device;
292 
293 		return D3D_OK;
294 	}
295 
GetPresentParameters(D3DPRESENT_PARAMETERS * presentParameters)296 	long Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *presentParameters)
297 	{
298 		CriticalSection cs(device);
299 
300 		TRACE("");
301 
302 		if(!presentParameters)
303 		{
304 			return INVALIDCALL();
305 		}
306 
307 		*presentParameters = this->presentParameters;
308 
309 		return D3D_OK;
310 	}
311 
reset(D3DPRESENT_PARAMETERS * presentParameters)312 	void Direct3DSwapChain9::reset(D3DPRESENT_PARAMETERS *presentParameters)
313 	{
314 		release();
315 
316 		ASSERT(presentParameters->BackBufferCount <= 3);   // Maximum of three back buffers
317 
318 		if(presentParameters->BackBufferCount == 0)
319 		{
320 			presentParameters->BackBufferCount = 1;
321 		}
322 
323 		if(presentParameters->BackBufferFormat == D3DFMT_UNKNOWN)
324 		{
325 			D3DDISPLAYMODE displayMode;
326 			GetDisplayMode(&displayMode);
327 
328 			presentParameters->BackBufferFormat = displayMode.Format;
329 		}
330 
331 		D3DDEVICE_CREATION_PARAMETERS creationParameters;
332 		device->GetCreationParameters(&creationParameters);
333 
334 		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow;
335 
336 		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
337 		{
338 			RECT rectangle;
339 			GetClientRect(windowHandle, &rectangle);
340 
341 			presentParameters->BackBufferWidth = rectangle.right - rectangle.left;
342 			presentParameters->BackBufferHeight = rectangle.bottom - rectangle.top;
343 		}
344 
345 		frameBuffer = createFrameBufferWin(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE, true);
346 
347 		lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
348 
349 		backBuffer[0] = 0;
350 		backBuffer[1] = 0;
351 		backBuffer[2] = 0;
352 
353 		for(int i = 0; i < (int)presentParameters->BackBufferCount; i++)
354 		{
355 			backBuffer[i] = new Direct3DSurface9(device, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_RENDERTARGET);
356 			backBuffer[i]->bind();
357 		}
358 
359 		this->presentParameters = *presentParameters;
360 	}
361 
release()362 	void Direct3DSwapChain9::release()
363 	{
364 		delete frameBuffer;
365 		frameBuffer = 0;
366 
367 		for(int i = 0; i < 3; i++)
368 		{
369 			if(backBuffer[i])
370 			{
371 				backBuffer[i]->unbind();
372 				backBuffer[i] = 0;
373 			}
374 		}
375 	}
376 
setGammaRamp(sw::GammaRamp * gammaRamp,bool calibrate)377 	void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate)
378 	{
379 		frameBuffer->setGammaRamp(gammaRamp, calibrate);
380 	}
381 
getGammaRamp(sw::GammaRamp * gammaRamp)382 	void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp)
383 	{
384 		frameBuffer->getGammaRamp(gammaRamp);
385 	}
386 
lockBackBuffer(int index)387 	void *Direct3DSwapChain9::lockBackBuffer(int index)
388 	{
389 		return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC);   // FIXME: External
390 	}
391 
unlockBackBuffer(int index)392 	void Direct3DSwapChain9::unlockBackBuffer(int index)
393 	{
394 		backBuffer[index]->unlockInternal();   // FIXME: External
395 	}
396 }
397