Home | History | Annotate | Download | only in D3D9
      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 {
     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 
     41 	Direct3DSwapChain9::~Direct3DSwapChain9()
     42 	{
     43 		release();
     44 	}
     45 
     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 
     66 	unsigned long Direct3DSwapChain9::AddRef()
     67 	{
     68 		TRACE("");
     69 
     70 		return Unknown::AddRef();
     71 	}
     72 
     73 	unsigned long Direct3DSwapChain9::Release()
     74 	{
     75 		TRACE("");
     76 
     77 		return Unknown::Release();
     78 	}
     79 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    382 	void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate)
    383 	{
    384 		frameBuffer->setGammaRamp(gammaRamp, calibrate);
    385 	}
    386 
    387 	void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp)
    388 	{
    389 		frameBuffer->getGammaRamp(gammaRamp);
    390 	}
    391 
    392 	void *Direct3DSwapChain9::lockBackBuffer(int index)
    393 	{
    394 		return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC);   // FIXME: External
    395 	}
    396 
    397 	void Direct3DSwapChain9::unlockBackBuffer(int index)
    398 	{
    399 		backBuffer[index]->unlockInternal();   // FIXME: External
    400 	}
    401 }
    402