• 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 		void *source = backBuffer[0]->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);   // FIXME: External
153 		sw::Format format = backBuffer[0]->getInternalFormat();
154 		int stride = backBuffer[0]->getInternalPitchB();
155 
156 		POINT point;
157 		GetCursorPos(&point);
158 		ScreenToClient(window, &point);
159 
160 		frameBuffer->setCursorPosition(point.x, point.y);
161 
162 		if(!sourceRect && !destRect)   // FIXME: More cases?
163 		{
164 			frameBuffer->flip(window, source, format, stride);
165 		}
166 		else   // FIXME: Check for SWAPEFFECT_COPY
167 		{
168 			sw::Rect sRect(0, 0, 0, 0);
169 			sw::Rect dRect(0, 0, 0, 0);
170 
171 			if(sourceRect)
172 			{
173 				sRect.x0 = sourceRect->left;
174 				sRect.y0 = sourceRect->top;
175 				sRect.x1 = sourceRect->right;
176 				sRect.y1 = sourceRect->bottom;
177 			}
178 
179 			if(destRect)
180 			{
181 				dRect.x0 = destRect->left;
182 				dRect.y0 = destRect->top;
183 				dRect.x1 = destRect->right;
184 				dRect.y1 = destRect->bottom;
185 			}
186 
187 			frameBuffer->blit(window, source, sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr, format, stride);
188 		}
189 
190 		backBuffer[0]->unlockInternal();   // FIXME: External
191 
192 		return D3D_OK;
193 	}
194 
GetFrontBufferData(IDirect3DSurface9 * destSurface)195 	long Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *destSurface)
196 	{
197 		CriticalSection cs(device);
198 
199 		TRACE("");
200 
201 		if(!destSurface)
202 		{
203 			return INVALIDCALL();
204 		}
205 
206 		sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface);
207 		void *buffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PRIVATE);
208 
209 		frameBuffer->screenshot(buffer);
210 
211 		dest->unlockExternal();
212 
213 		return D3D_OK;
214 	}
215 
GetBackBuffer(unsigned int index,D3DBACKBUFFER_TYPE type,IDirect3DSurface9 ** backBuffer)216 	long Direct3DSwapChain9::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer)
217 	{
218 		CriticalSection cs(device);
219 
220 		TRACE("");
221 
222 		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
223 		{
224 			return INVALIDCALL();
225 		}
226 
227 		*backBuffer = 0;
228 
229 		if(index >= 3 || this->backBuffer[index] == 0)
230 		{
231 			return INVALIDCALL();
232 		}
233 
234 		*backBuffer = this->backBuffer[index];
235 		this->backBuffer[index]->AddRef();
236 
237 		return D3D_OK;
238 	}
239 
GetRasterStatus(D3DRASTER_STATUS * rasterStatus)240 	long Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *rasterStatus)
241 	{
242 		CriticalSection cs(device);
243 
244 		TRACE("");
245 
246 		if(!rasterStatus)
247 		{
248 			return INVALIDCALL();
249 		}
250 
251 		bool inVerticalBlank;
252 		unsigned int scanline;
253 		bool supported = frameBuffer->getScanline(inVerticalBlank, scanline);
254 
255 		if(supported)
256 		{
257 			rasterStatus->InVBlank = inVerticalBlank;
258 			rasterStatus->ScanLine = scanline;
259 		}
260 		else
261 		{
262 			return INVALIDCALL();
263 		}
264 
265 		return D3D_OK;
266 	}
267 
GetDisplayMode(D3DDISPLAYMODE * displayMode)268 	long Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *displayMode)
269 	{
270 		CriticalSection cs(device);
271 
272 		TRACE("");
273 
274 		if(!displayMode)
275 		{
276 			return INVALIDCALL();
277 		}
278 
279 		device->getAdapterDisplayMode(D3DADAPTER_DEFAULT, displayMode);
280 
281 		return D3D_OK;
282 	}
283 
GetDevice(IDirect3DDevice9 ** device)284 	long Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **device)
285 	{
286 		CriticalSection cs(this->device);
287 
288 		TRACE("");
289 
290 		if(!device)
291 		{
292 			return INVALIDCALL();
293 		}
294 
295 		this->device->AddRef();
296 		*device = this->device;
297 
298 		return D3D_OK;
299 	}
300 
GetPresentParameters(D3DPRESENT_PARAMETERS * presentParameters)301 	long Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *presentParameters)
302 	{
303 		CriticalSection cs(device);
304 
305 		TRACE("");
306 
307 		if(!presentParameters)
308 		{
309 			return INVALIDCALL();
310 		}
311 
312 		*presentParameters = this->presentParameters;
313 
314 		return D3D_OK;
315 	}
316 
reset(D3DPRESENT_PARAMETERS * presentParameters)317 	void Direct3DSwapChain9::reset(D3DPRESENT_PARAMETERS *presentParameters)
318 	{
319 		release();
320 
321 		ASSERT(presentParameters->BackBufferCount <= 3);   // Maximum of three back buffers
322 
323 		if(presentParameters->BackBufferCount == 0)
324 		{
325 			presentParameters->BackBufferCount = 1;
326 		}
327 
328 		if(presentParameters->BackBufferFormat == D3DFMT_UNKNOWN)
329 		{
330 			D3DDISPLAYMODE displayMode;
331 			GetDisplayMode(&displayMode);
332 
333 			presentParameters->BackBufferFormat = displayMode.Format;
334 		}
335 
336 		D3DDEVICE_CREATION_PARAMETERS creationParameters;
337 		device->GetCreationParameters(&creationParameters);
338 
339 		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow;
340 
341 		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
342 		{
343 			RECT rectangle;
344 			GetClientRect(windowHandle, &rectangle);
345 
346 			presentParameters->BackBufferWidth = rectangle.right - rectangle.left;
347 			presentParameters->BackBufferHeight = rectangle.bottom - rectangle.top;
348 		}
349 
350 		frameBuffer = createFrameBufferWin(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE, true);
351 
352 		lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
353 
354 		backBuffer[0] = 0;
355 		backBuffer[1] = 0;
356 		backBuffer[2] = 0;
357 
358 		for(int i = 0; i < (int)presentParameters->BackBufferCount; i++)
359 		{
360 			backBuffer[i] = new Direct3DSurface9(device, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_RENDERTARGET);
361 			backBuffer[i]->bind();
362 		}
363 
364 		this->presentParameters = *presentParameters;
365 	}
366 
release()367 	void Direct3DSwapChain9::release()
368 	{
369 		delete frameBuffer;
370 		frameBuffer = 0;
371 
372 		for(int i = 0; i < 3; i++)
373 		{
374 			if(backBuffer[i])
375 			{
376 				backBuffer[i]->unbind();
377 				backBuffer[i] = 0;
378 			}
379 		}
380 	}
381 
setGammaRamp(sw::GammaRamp * gammaRamp,bool calibrate)382 	void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate)
383 	{
384 		frameBuffer->setGammaRamp(gammaRamp, calibrate);
385 	}
386 
getGammaRamp(sw::GammaRamp * gammaRamp)387 	void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp)
388 	{
389 		frameBuffer->getGammaRamp(gammaRamp);
390 	}
391 
lockBackBuffer(int index)392 	void *Direct3DSwapChain9::lockBackBuffer(int index)
393 	{
394 		return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC);   // FIXME: External
395 	}
396 
unlockBackBuffer(int index)397 	void Direct3DSwapChain9::unlockBackBuffer(int index)
398 	{
399 		backBuffer[index]->unlockInternal();   // FIXME: External
400 	}
401 }
402