Home | History | Annotate | Download | only in src
      1 /**************************************************************************
      2  *
      3  * Copyright 2010 Luca Barbieri
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the
     14  * next paragraph) shall be included in all copies or substantial
     15  * portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  *
     25  **************************************************************************/
     26 
     27 #include "dxgi_private.h"
     28 extern "C" {
     29 #include "native.h"
     30 #include "util/u_format.h"
     31 #include "util/u_inlines.h"
     32 #include "util/u_simple_shaders.h"
     33 #include "pipe/p_shader_tokens.h"
     34 }
     35 #include <iostream>
     36 #include <memory>
     37 
     38 struct GalliumDXGIOutput;
     39 struct GalliumDXGIAdapter;
     40 struct GalliumDXGISwapChain;
     41 struct GalliumDXGIFactory;
     42 
     43 static HRESULT GalliumDXGISwapChainCreate(GalliumDXGIFactory* factory, IUnknown* device, const DXGI_SWAP_CHAIN_DESC& desc, IDXGISwapChain** out_swap_chain);
     44 static HRESULT GalliumDXGIAdapterCreate(GalliumDXGIFactory* adapter, const struct native_platform* platform, void* dpy, IDXGIAdapter1** out_adapter);
     45 static HRESULT GalliumDXGIOutputCreate(GalliumDXGIAdapter* adapter, const std::string& name, const struct native_connector* connector, IDXGIOutput** out_output);
     46 static void GalliumDXGISwapChainRevalidate(IDXGISwapChain* swap_chain);
     47 
     48 template<typename Base = IDXGIObject, typename Parent = IDXGIObject>
     49 struct GalliumDXGIObject : public GalliumPrivateDataComObject<Base>
     50 {
     51 	ComPtr<Parent> parent;
     52 
     53 	GalliumDXGIObject(Parent* p_parent = 0)
     54 	{
     55 		this->parent = p_parent;
     56 	}
     57 
     58 	virtual HRESULT STDMETHODCALLTYPE GetParent(
     59 		REFIID riid,
     60 		void **out_parent)
     61 	{
     62 		return parent->QueryInterface(riid, out_parent);
     63 	}
     64 };
     65 
     66 COM_INTERFACE(IGalliumDXGIBackend, IUnknown)
     67 
     68 // TODO: somehow check whether the window is fully obscured or not
     69 struct GalliumDXGIIdentityBackend : public GalliumComObject<IGalliumDXGIBackend>
     70 {
     71 	virtual HRESULT STDMETHODCALLTYPE BeginPresent(
     72 		HWND hwnd,
     73 		void** present_cookie,
     74 		void** window,
     75 		RECT *rect,
     76 		RGNDATA **rgndata,
     77 		BOOL* preserve_aspect_ratio
     78 	)
     79 	{
     80 		*window = (void*)hwnd;
     81 		rect->left = 0;
     82 		rect->top = 0;
     83 		rect->right = INT_MAX;
     84 		rect->bottom = INT_MAX;
     85 		*rgndata = 0;
     86 
     87 		// yes, because we like things looking good
     88 		*preserve_aspect_ratio = TRUE;
     89 		*present_cookie = 0;
     90 		return S_OK;
     91 	}
     92 
     93 	virtual void STDMETHODCALLTYPE EndPresent(
     94 		HWND hwnd,
     95 		void* present_cookie
     96 	)
     97 	{}
     98 
     99 	virtual HRESULT STDMETHODCALLTYPE TestPresent(HWND hwnd)
    100 	{
    101 		return S_OK;
    102 	}
    103 
    104         virtual HRESULT STDMETHODCALLTYPE GetPresentSize(
    105                 HWND hwnd,
    106                 unsigned* width,
    107                 unsigned* height
    108         )
    109         {
    110                 *width = 0;
    111                 *height = 0;
    112                 return S_OK;
    113         }
    114 };
    115 
    116 // TODO: maybe install an X11 error hook, so we can return errors properly
    117 struct GalliumDXGIX11IdentityBackend : public GalliumDXGIIdentityBackend
    118 {
    119 	Display* dpy;
    120 
    121 	GalliumDXGIX11IdentityBackend(Display* dpy)
    122 	: dpy(dpy)
    123 	{}
    124 
    125 	virtual HRESULT STDMETHODCALLTYPE GetPresentSize(
    126 		HWND hwnd,
    127 		unsigned* width,
    128 		unsigned* height
    129 	)
    130         {
    131 		XWindowAttributes xwa;
    132 		XGetWindowAttributes(dpy, (Window)hwnd, &xwa);
    133 		*width = xwa.width;
    134 		*height = xwa.height;
    135 		return S_OK;
    136         }
    137 };
    138 
    139 struct GalliumDXGIFactory : public GalliumDXGIObject<IDXGIFactory1, IUnknown>
    140 {
    141 	HWND associated_window;
    142 	const struct native_platform* platform;
    143 	void* display;
    144 	ComPtr<IGalliumDXGIBackend> backend;
    145 	void* resolver_cookie;
    146 
    147 	GalliumDXGIFactory(const struct native_platform* platform, void* display, IGalliumDXGIBackend* p_backend)
    148 	: GalliumDXGIObject<IDXGIFactory1, IUnknown>((IUnknown*)NULL), platform(platform), display(display)
    149 	 {
    150 		if(p_backend)
    151 			backend = p_backend;
    152 		else if(!strcmp(platform->name, "X11"))
    153 			backend.reset(new GalliumDXGIX11IdentityBackend((Display*)display));
    154 		else
    155 			backend.reset(new GalliumDXGIIdentityBackend());
    156 	}
    157 
    158 	virtual HRESULT STDMETHODCALLTYPE EnumAdapters(
    159 		UINT adapter,
    160 		IDXGIAdapter **out_adapter)
    161 	{
    162 		return EnumAdapters1(adapter, (IDXGIAdapter1**)out_adapter);
    163 	}
    164 
    165 	virtual HRESULT STDMETHODCALLTYPE EnumAdapters1(
    166 		UINT adapter,
    167 		IDXGIAdapter1 **out_adapter)
    168 	{
    169 		*out_adapter = 0;
    170 		if(adapter == 0)
    171 		{
    172 			return GalliumDXGIAdapterCreate(this, platform, display, out_adapter);
    173 		}
    174 #if 0
    175 		// TODO: enable this
    176 		if(platform == native_get_x11_platform())
    177 		{
    178 			unsigned nscreens = ScreenCount((Display*)display);
    179 			if(adapter < nscreens)
    180 			{
    181 				unsigned def_screen = DefaultScreen(display);
    182 				if(adapter <= def_screen)
    183 					--adapter;
    184 				*out_adapter = GalliumDXGIAdapterCreate(this, platform, display, adapter);
    185 				return S_OK;
    186 			}
    187 		}
    188 #endif
    189 		return DXGI_ERROR_NOT_FOUND;
    190 	}
    191 
    192 	/* TODO: this is a mysterious underdocumented magic API
    193 	 * Can we have multiple windows associated?
    194 	 * Can we have multiple windows associated if we use multiple factories?
    195 	 * If so, what should GetWindowAssociation return?
    196 	 * If not, does a new swapchain steal the association?
    197 	 * Does this act for existing swapchains? For new swapchains?
    198 	 */
    199 	virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation(
    200 		HWND window_handle,
    201 		UINT flags)
    202 	{
    203 		/* TODO: actually implement, for Wine, X11 and KMS*/
    204 		associated_window = window_handle;
    205 		return S_OK;
    206 	}
    207 
    208 	virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation(
    209 		HWND *pwindow_handle)
    210 	{
    211 		*pwindow_handle = associated_window;
    212 		return S_OK;
    213 	}
    214 
    215 	virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(
    216 		IUnknown *device,
    217 		DXGI_SWAP_CHAIN_DESC *desc,
    218 		IDXGISwapChain **out_swap_chain)
    219 	{
    220 		return GalliumDXGISwapChainCreate(this, device, *desc, out_swap_chain);
    221 	}
    222 
    223 	virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter(
    224 		HMODULE module,
    225 		IDXGIAdapter **out_adapter)
    226 	{
    227 		/* TODO: ignore the module, and just create a Gallium software screen */
    228 		*out_adapter = 0;
    229 		return E_NOTIMPL;
    230 	}
    231 
    232 	/* TODO: support hotplug */
    233 	virtual BOOL STDMETHODCALLTYPE IsCurrent( void)
    234 	{
    235 		return TRUE;
    236 	}
    237 };
    238 
    239 struct GalliumDXGIAdapter
    240 	: public GalliumMultiComObject<
    241 		 GalliumDXGIObject<IDXGIAdapter1, GalliumDXGIFactory>,
    242 		 IGalliumAdapter>
    243 {
    244 	struct native_display* display;
    245 	const struct native_config** configs;
    246 	std::unordered_multimap<unsigned, unsigned> configs_by_pipe_format;
    247 	std::unordered_map<unsigned, unsigned> configs_by_native_visual_id;
    248 	const struct native_connector** connectors;
    249 	unsigned num_configs;
    250 	DXGI_ADAPTER_DESC1 desc;
    251 	std::vector<ComPtr<IDXGIOutput> > outputs;
    252 	int num_outputs;
    253 
    254 	GalliumDXGIAdapter(GalliumDXGIFactory* factory, const struct native_platform* platform, void* dpy)
    255 	{
    256 		this->parent = factory;
    257 
    258 		display = platform->create_display(dpy, FALSE);
    259 		if(!display)
    260                    display = platform->create_display(dpy, TRUE);
    261                 if (display) {
    262                    display->user_data = this;
    263                    if (!display->init_screen(display)) {
    264                       display->destroy(display);
    265                       display = NULL;
    266                    }
    267                 }
    268                 if(!display)
    269 			throw E_FAIL;
    270 		memset(&desc, 0, sizeof(desc));
    271 		std::string s = std::string("GalliumD3D on ") + display->screen->get_name(display->screen) + " by " + display->screen->get_vendor(display->screen);
    272 
    273 		/* hopefully no one will decide to use UTF-8 in Gallium name/vendor strings */
    274 		for(int i = 0; i < std::min((int)s.size(), 127); ++i)
    275 			desc.Description[i] = (WCHAR)s[i];
    276 
    277 		// TODO: add an interface to get these; for now, return mid/low values
    278 		desc.DedicatedVideoMemory = 256 << 20;
    279 		desc.DedicatedSystemMemory = 256 << 20;
    280 		desc.SharedSystemMemory = 1024 << 20;
    281 
    282 		// TODO: we should actually use an unique ID instead
    283 		*(void**)&desc.AdapterLuid = dpy;
    284 
    285 		configs = display->get_configs(display, (int*)&num_configs);
    286 		for(unsigned i = 0; i < num_configs; ++i)
    287 		{
    288 			if(configs[i]->window_bit)
    289 			{
    290 				configs_by_pipe_format.insert(std::make_pair(configs[i]->color_format, i));
    291 				configs_by_native_visual_id[configs[i]->native_visual_id] = i;
    292 			}
    293 		}
    294 
    295 		connectors = 0;
    296 		num_outputs = 0;
    297 
    298 		if(display->modeset)
    299 		{
    300 			int num_crtcs;
    301 
    302 			connectors = display->modeset->get_connectors(display, &num_outputs, &num_crtcs);
    303 			if(!connectors)
    304 				num_outputs = 0;
    305 			else if(!num_outputs)
    306 			{
    307 				free(connectors);
    308 				connectors = 0;
    309 			}
    310 		}
    311 		if(!num_outputs)
    312 			num_outputs = 1;
    313 	}
    314 
    315 	static void handle_invalid_surface(struct native_display *ndpy, struct native_surface *nsurf, unsigned int seq_num)
    316 	{
    317 		GalliumDXGISwapChainRevalidate((IDXGISwapChain*)nsurf->user_data);
    318 	}
    319 
    320 	~GalliumDXGIAdapter()
    321 	{
    322 		display->destroy(display);
    323 		free(configs);
    324 		free(connectors);
    325 	}
    326 
    327 	virtual HRESULT STDMETHODCALLTYPE EnumOutputs(
    328 		UINT output,
    329 		IDXGIOutput **out_output)
    330 	{
    331 		if(output >= (unsigned)num_outputs)
    332 			return DXGI_ERROR_NOT_FOUND;
    333 
    334 		if(connectors)
    335 		{
    336 			std::ostringstream ss;
    337 			ss << "output #" << output;
    338 			return GalliumDXGIOutputCreate(this, ss.str(), connectors[output], out_output);
    339 		}
    340 		else
    341 			return GalliumDXGIOutputCreate(this, "Unique output", NULL, out_output);
    342 	}
    343 
    344 	virtual HRESULT STDMETHODCALLTYPE GetDesc(
    345 		DXGI_ADAPTER_DESC *desc)
    346 	{
    347 		memcpy(desc, &desc, sizeof(*desc));
    348 		return S_OK;
    349 	}
    350 
    351 	virtual HRESULT STDMETHODCALLTYPE GetDesc1(
    352 		DXGI_ADAPTER_DESC1 *desc)
    353 	{
    354 		memcpy(desc, &desc, sizeof(*desc));
    355 		return S_OK;
    356 	}
    357 
    358 	virtual HRESULT STDMETHODCALLTYPE CheckInterfaceSupport(
    359 		REFGUID interface_name,
    360 		LARGE_INTEGER *u_m_d_version)
    361 	{
    362 		// these number was taken from Windows 7 with Catalyst 10.8: its meaning is unclear
    363 		if(interface_name == IID_ID3D11Device || interface_name == IID_ID3D10Device1 || interface_name == IID_ID3D10Device)
    364 		{
    365 			u_m_d_version->QuadPart = 0x00080011000a0411ULL;
    366 			return S_OK;
    367 		}
    368 		return DXGI_ERROR_UNSUPPORTED;
    369 	}
    370 
    371 	pipe_screen* STDMETHODCALLTYPE GetGalliumScreen()
    372 	{
    373 		return display->screen;
    374 	}
    375 
    376 	pipe_screen* STDMETHODCALLTYPE GetGalliumReferenceSoftwareScreen()
    377 	{
    378 		// TODO: give a softpipe screen
    379 		return display->screen;
    380 	}
    381 
    382 	pipe_screen* STDMETHODCALLTYPE GetGalliumFastSoftwareScreen()
    383 	{
    384 		// TODO: give an llvmpipe screen
    385 		return display->screen;
    386 	}
    387 };
    388 
    389 
    390 struct GalliumDXGIOutput : public GalliumDXGIObject<IDXGIOutput, GalliumDXGIAdapter>
    391 {
    392 	DXGI_OUTPUT_DESC desc;
    393 	const struct native_mode** modes;
    394 	DXGI_MODE_DESC* dxgi_modes;
    395 	unsigned num_modes;
    396 	const struct native_connector* connector;
    397 	DXGI_GAMMA_CONTROL* gamma;
    398 
    399 	GalliumDXGIOutput(GalliumDXGIAdapter* adapter, std::string name, const struct native_connector* connector = 0)
    400 	: GalliumDXGIObject<IDXGIOutput, GalliumDXGIAdapter>(adapter), connector(connector)
    401 	{
    402 		memset(&desc, 0, sizeof(desc));
    403 		for(unsigned i = 0; i < std::min(name.size(), sizeof(desc.DeviceName) - 1); ++i)
    404 			desc.DeviceName[i] = name[i];
    405 		desc.AttachedToDesktop = TRUE;
    406 		/* TODO: should put an HMONITOR in desc.Monitor */
    407 
    408 		gamma = 0;
    409 		num_modes = 0;
    410 		modes = 0;
    411 		if(connector)
    412 		{
    413 			modes = parent->display->modeset->get_modes(parent->display, connector, (int*)&num_modes);
    414 			if(modes && num_modes)
    415 			{
    416 				dxgi_modes = new DXGI_MODE_DESC[num_modes];
    417 				for(unsigned i = 0; i < num_modes; ++i)
    418 				{
    419 					dxgi_modes[i].Width = modes[i]->width;
    420 					dxgi_modes[i].Height = modes[i]->height;
    421 					dxgi_modes[i].RefreshRate.Numerator = modes[i]->refresh_rate;
    422 					dxgi_modes[i].RefreshRate.Denominator = 1;
    423 					dxgi_modes[i].Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    424 					dxgi_modes[i].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    425 				}
    426 			}
    427 			else
    428 			{
    429 				if(modes)
    430 				{
    431 					free(modes);
    432 					modes = 0;
    433 				}
    434 				goto use_fake_mode;
    435 			}
    436 		}
    437 		else
    438 		{
    439 use_fake_mode:
    440 			dxgi_modes = new DXGI_MODE_DESC[1];
    441 			dxgi_modes[0].Width = 1920;
    442 			dxgi_modes[0].Height = 1200;
    443 			dxgi_modes[0].RefreshRate.Numerator = 60;
    444 			dxgi_modes[0].RefreshRate.Denominator = 1;
    445 			dxgi_modes[0].Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    446 			dxgi_modes[0].ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    447 		}
    448 	}
    449 
    450 	~GalliumDXGIOutput()
    451 	{
    452 		delete [] dxgi_modes;
    453 		free(modes);
    454 		if(gamma)
    455 			delete gamma;
    456 	}
    457 
    458 	virtual HRESULT STDMETHODCALLTYPE GetDesc(
    459 		DXGI_OUTPUT_DESC *out_desc)
    460 	{
    461 		*out_desc = desc;
    462 		return S_OK;
    463 	}
    464 
    465 	virtual HRESULT STDMETHODCALLTYPE GetDisplayModeList(
    466 		DXGI_FORMAT enum_format,
    467 		UINT flags,
    468 		UINT *pcount,
    469 		DXGI_MODE_DESC *desc)
    470 	{
    471 		/* TODO: should we return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE when we don't
    472 		 * support modesetting instead of fake modes?
    473 		 */
    474 		pipe_format format = dxgi_to_pipe_format[enum_format];
    475 		if(parent->configs_by_pipe_format.count(format))
    476 		{
    477 			if(!desc)
    478 			{
    479 				*pcount = num_modes;
    480 				return S_OK;
    481 			}
    482 
    483 			unsigned copy_modes = std::min(num_modes, *pcount);
    484 			for(unsigned i = 0; i < copy_modes; ++i)
    485 			{
    486 				desc[i] = dxgi_modes[i];
    487 				desc[i].Format = enum_format;
    488 			}
    489 			*pcount = num_modes;
    490 
    491 			if(copy_modes < num_modes)
    492 				return DXGI_ERROR_MORE_DATA;
    493 			else
    494 				return S_OK;
    495 		}
    496 		else
    497 		{
    498 			*pcount = 0;
    499 			return S_OK;
    500 		}
    501 	}
    502 
    503 	virtual HRESULT STDMETHODCALLTYPE FindClosestMatchingMode(
    504 		const DXGI_MODE_DESC *pModeToMatch,
    505 		DXGI_MODE_DESC *closest_match,
    506 		IUnknown *concerned_device)
    507 	{
    508 		/* TODO: actually implement this */
    509 		DXGI_FORMAT dxgi_format = pModeToMatch->Format;
    510 		enum pipe_format format = dxgi_to_pipe_format[dxgi_format];
    511 		init_pipe_to_dxgi_format();
    512 		if(!parent->configs_by_pipe_format.count(format))
    513 		{
    514 			if(!concerned_device)
    515 				return E_FAIL;
    516 			else
    517 			{
    518 				format = parent->configs[0]->color_format;
    519 				dxgi_format = pipe_to_dxgi_format[format];
    520 			}
    521 		}
    522 
    523 		*closest_match = dxgi_modes[0];
    524 		closest_match->Format = dxgi_format;
    525 		return S_OK;
    526 	}
    527 
    528 	virtual HRESULT STDMETHODCALLTYPE WaitForVBlank( void)
    529 	{
    530 		return S_OK;
    531 	}
    532 
    533 	virtual HRESULT STDMETHODCALLTYPE TakeOwnership(
    534 		IUnknown *device,
    535 		BOOL exclusive)
    536 	{
    537 		return S_OK;
    538 	}
    539 
    540 	virtual void STDMETHODCALLTYPE ReleaseOwnership( void)
    541 	{
    542 	}
    543 
    544 	virtual HRESULT STDMETHODCALLTYPE GetGammaControlCapabilities(
    545 		DXGI_GAMMA_CONTROL_CAPABILITIES *gamma_caps)
    546 	{
    547 		memset(gamma_caps, 0, sizeof(*gamma_caps));
    548 		return S_OK;
    549 	}
    550 
    551 	virtual HRESULT STDMETHODCALLTYPE SetGammaControl(
    552 			const DXGI_GAMMA_CONTROL *pArray)
    553 	{
    554 		if(!gamma)
    555 			gamma = new DXGI_GAMMA_CONTROL;
    556 		*gamma = *pArray;
    557 		return S_OK;
    558 	}
    559 
    560 	virtual HRESULT STDMETHODCALLTYPE GetGammaControl(
    561 			DXGI_GAMMA_CONTROL *pArray)
    562 	{
    563 		if(gamma)
    564 			*pArray = *gamma;
    565 		else
    566 		{
    567 			pArray->Scale.Red = 1;
    568 			pArray->Scale.Green = 1;
    569 			pArray->Scale.Blue = 1;
    570 			pArray->Offset.Red = 0;
    571 			pArray->Offset.Green = 0;
    572 			pArray->Offset.Blue = 0;
    573 			for(unsigned i = 0; i <= 1024; ++i)
    574 				pArray->GammaCurve[i].Red = pArray->GammaCurve[i].Green = pArray->GammaCurve[i].Blue = (float)i / 1024.0;
    575 		}
    576 		return S_OK;
    577 	}
    578 
    579 	virtual HRESULT STDMETHODCALLTYPE SetDisplaySurface(
    580 		IDXGISurface *scanout_surface)
    581 	{
    582 		return E_NOTIMPL;
    583 	}
    584 
    585 	virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData(
    586 		IDXGISurface *destination)
    587 	{
    588 		return E_NOTIMPL;
    589 	}
    590 
    591 	virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(
    592 		DXGI_FRAME_STATISTICS *stats)
    593 	{
    594 		memset(stats, 0, sizeof(*stats));
    595 #ifdef _WIN32
    596 		QueryPerformanceCounter(&stats->SyncQPCTime);
    597 #endif
    598 		return E_NOTIMPL;
    599 	}
    600 };
    601 
    602 /* Swap chain are rather complex, and Microsoft's documentation is rather
    603  * lacking. As far as I know, this is the most thorough publicly available
    604  * description of how swap chains work, based on multiple sources and
    605  * experimentation.
    606  *
    607  * There are two modes (called "swap effects") that a swap chain can operate in:
    608  * discard and sequential.
    609  *
    610  * In discard mode, things always look as if there is a single buffer, which
    611  * you can get with GetBuffers(0).
    612  * The 2D texture returned by GetBuffers(0) and can only be
    613  * used as a render target view and for resource copies, since no CPU access
    614  * flags are set and only the D3D11_BIND_RENDER_TARGET bind flag is set.
    615  * On Present, it is copied to the actual display
    616  * surface and the contents become undefined.
    617  * D3D may internally use multiple buffers, but you can't observe this, except
    618  * by looking at the buffer contents after Present (but those are undefined).
    619  * If it uses multiple buffers internally, then it will normally use buffer_count buffers
    620  * (this has latency implications).
    621  * Discard mode seems to internally use a single buffer in windowed mode,
    622  * even if DWM is enabled, and buffer_count buffers in fullscreen mode.
    623  *
    624  * In sequential mode, the runtime alllocates buffer_count buffers.
    625  * You can get each with GetBuffers(n).
    626  * GetBuffers(0) ALWAYS points to the backbuffer to be presented and has the
    627  * same usage constraints as the discard mode.
    628  * GetBuffer(n) with n > 0 points to resources that are identical to buffer 0, but
    629  * are classified as "read-only resources" (due to DXGI_USAGE_READ_ONLY),
    630  * meaning that you can't create render target views on them, or use them as
    631  * a CopyResource/CopySubresourceRegion destination.
    632  * It appears the only valid operation is to use them as a source for CopyResource
    633  * and CopySubresourceRegion as well as just waiting for them to become
    634  * buffer 0 again.
    635  * Buffer n - 1 is always displayed on screen.
    636  * When you call Present(), the contents of the buffers are rotated, so that buffer 0
    637  * goes to buffer n - 1, and is thus displayed, and buffer 1 goes to buffer 0, becomes
    638  * the accessible back buffer.
    639  * The resources themselves are NOT rotated, so that you can still render on the
    640  * same ID3D11Texture2D*, and views based on it, that you got before Present().
    641  *
    642  * Present seems to happen by either copying the relevant buffer into the window,
    643  * or alternatively making it the current one, either by programming the CRTC or
    644  * by sending the resource name to the DWM compositor.
    645  *
    646  * Hence, you can call GetBuffer(0) once and keep using the same ID3D11Texture2D*
    647  * and ID3D11RenderTargetView* (and other views if needed) you got from it.
    648  *
    649  * If the window gets resized, DXGI will then "emulate" all successive presentations,
    650  * by using a stretched blit automatically.
    651  * Thus, you should handle WM_SIZE and call ResizeBuffers to update the DXGI
    652  * swapchain buffers size to the new window size.
    653  * Doing so requires you to release all GetBuffers() results and anything referencing
    654  * them, including views and Direct3D11 deferred context command lists (this is
    655  * documented).
    656  *
    657  * How does Microsoft implement the rotation behavior?
    658  * It turns out that it does it by calling RotateResourceIdentitiesDXGI in the user-mode
    659  * DDI driver.
    660  * This will rotate the kernel buffer handle, or possibly rotate the GPU virtual memory
    661  * mappings.
    662  *
    663  * The reason this is done by driver instead of by the runtime appears to be that
    664  * this is necessary to support driver-provided command list support, since otherwise
    665  * the command list would not always target the current backbuffer, since it would
    666  * be done at the driver level, while only the runtime knows about the rotation.
    667  *
    668  * OK, so how do we implement this in Gallium?
    669  *
    670  * There are three strategies:
    671  * 1. Use a single buffer, and always copy it to a window system provided buffer, or
    672  *	just give the buffer to the window system if it supports that
    673  * 2. Rotate the buffers in the D3D1x implementation, and recreate and rebind the views.
    674  *	 Don't support driver-provided command lists
    675  * 3. Add this rotation functionality to the Gallium driver, with the idea that it would rotate
    676  *	remap GPU virtual memory, so that virtual address are unchanged, but the physical
    677  *	ones are rotated (so that pushbuffers remain valid).
    678  *	If the driver does not support this, either fall back to (1), or have a layer doing this,
    679  *	putting a deferred context layer over this intermediate layer.
    680  *
    681  * (2) is not acceptable since it prevents an optimal implementation.
    682  * (3) is the ideal solution, but it is complicated.
    683  *
    684  * Hence, we implement (1) for now, and will switch to (3) later.
    685  *
    686  * Note that (1) doesn't really work for DXGI_SWAP_EFFECT_SEQUENTIAL with more
    687  * than one buffer, so we just pretend we got asked for a single buffer in that case
    688  * Fortunately, no one seems to rely on that, so we'll just not implement it at first, and
    689  * later perform the rotation with blits.
    690  * Once we switch to (3), we'll just use real rotation to do it..
    691  *
    692  * DXGI_SWAP_EFFECT_SEQUENTIAL with more than one buffer is of dubious use
    693  * anyway, since you can only render or write to buffer 0, and other buffers can apparently
    694  * be used only as sources for copies.
    695  * I was unable to find any code using it either in DirectX SDK examples, or on the web.
    696  *
    697  * It seems the only reason you would use it is to not have to redraw from scratch, while
    698  * also possibly avoid a copy compared to buffer_count == 1, assuming that your
    699  * application is OK with having to redraw starting not from the last frame, but from
    700  * one/two/more frames behind it.
    701  *
    702  * A better design would forbid the user specifying buffer_count explicitly, and
    703  * would instead let the application give an upper bound on how old the buffer can
    704  * become after presentation, with "infinite" being equivalent to discard.
    705  * The runtime would then tell the application with frame number the buffer switched to
    706  * after present.
    707  * In addition, in a better design, the application would be allowed to specify the
    708  * number of buffers available, having all them usable for rendering, so that things
    709  * like video players could efficiently decode frames in parallel.
    710  * Present would in such a better design gain a way to specify the number of buffers
    711  * to present.
    712  *
    713  * Other miscellaneous info:
    714  * DXGI_PRESENT_DO_NOT_SEQUENCE causes DXGI to hold the frame for another
    715  * vblank interval without rotating the resource data.
    716  *
    717  * References:
    718  * "DXGI Overview" in MSDN
    719  * IDXGISwapChain documentation on MSDN
    720  * "RotateResourceIdentitiesDXGI" on MSDN
    721  * http://forums.xna.com/forums/p/42362/266016.aspx
    722  */
    723 
    724 static float quad_data[] = {
    725 	-1, -1, 0, 0,
    726 	-1, 1, 0, 1,
    727 	1, 1, 1, 1,
    728 	1, -1, 1, 0,
    729 };
    730 
    731 struct dxgi_blitter
    732 {
    733 	pipe_context* pipe;
    734 	bool normalized;
    735 	void* fs;
    736 	void* vs;
    737 	void* sampler[2];
    738 	void* elements;
    739 	void* blend;
    740 	void* rasterizer;
    741 	void* zsa;
    742 	struct pipe_clip_state clip;
    743 	struct pipe_vertex_buffer vbuf;
    744 	struct pipe_draw_info draw;
    745 
    746 	dxgi_blitter(pipe_context* pipe)
    747 	: pipe(pipe)
    748 	{
    749 		//normalized = !!pipe->screen->get_param(pipe, PIPE_CAP_NPOT_TEXTURES);
    750 		// TODO: need to update buffer in unnormalized case
    751 		normalized = true;
    752 
    753 		struct pipe_rasterizer_state rs_state;
    754 		memset(&rs_state, 0, sizeof(rs_state));
    755 		rs_state.cull_face = PIPE_FACE_NONE;
    756 		rs_state.gl_rasterization_rules = 1;
    757 		rs_state.depth_clip = 1;
    758 		rs_state.flatshade = 1;
    759 		rasterizer = pipe->create_rasterizer_state(pipe, &rs_state);
    760 
    761 		struct pipe_blend_state blendd;
    762 		memset(&blendd, 0, sizeof(blendd));
    763 		blendd.rt[0].colormask = PIPE_MASK_RGBA;
    764 		blend = pipe->create_blend_state(pipe, &blendd);
    765 
    766 		struct pipe_depth_stencil_alpha_state zsad;
    767 		memset(&zsad, 0, sizeof(zsad));
    768 		zsa = pipe->create_depth_stencil_alpha_state(pipe, &zsad);
    769 
    770 		struct pipe_vertex_element velem[2];
    771 		memset(&velem[0], 0, sizeof(velem[0]) * 2);
    772 		velem[0].src_offset = 0;
    773 		velem[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
    774 		velem[1].src_offset = 8;
    775 		velem[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
    776 		elements = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
    777 
    778 		for(unsigned stretch = 0; stretch < 2; ++stretch)
    779 		{
    780 			struct pipe_sampler_state sampler_state;
    781 			memset(&sampler_state, 0, sizeof(sampler_state));
    782 			sampler_state.min_img_filter = stretch ? PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
    783 			sampler_state.mag_img_filter = stretch ? PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
    784 			sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    785 			sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    786 			sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    787 			sampler_state.normalized_coords = normalized;
    788 
    789 			sampler[stretch] = pipe->create_sampler_state(pipe, &sampler_state);
    790 		}
    791 
    792 		fs = util_make_fragment_tex_shader(pipe, normalized ? TGSI_TEXTURE_2D : TGSI_TEXTURE_RECT, TGSI_INTERPOLATE_LINEAR);
    793 
    794 		const unsigned semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC };
    795 		const unsigned semantic_indices[] = { 0, 0 };
    796 		vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices);
    797 
    798 		vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
    799 						 PIPE_USAGE_STREAM, sizeof(quad_data));
    800 		vbuf.buffer_offset = 0;
    801 		vbuf.stride = 4 * sizeof(float);
    802 		pipe_buffer_write(pipe, vbuf.buffer, 0, sizeof(quad_data), quad_data);
    803 
    804 		memset(&clip, 0, sizeof(clip));
    805 
    806 		memset(&draw, 0, sizeof(draw));
    807 		draw.mode = PIPE_PRIM_QUADS;
    808 		draw.count = 4;
    809 		draw.instance_count = 1;
    810 		draw.max_index = ~0;
    811 	}
    812 
    813 	void blit(struct pipe_surface* surf, struct pipe_sampler_view* view, unsigned x, unsigned y, unsigned w, unsigned h)
    814 	{
    815 		struct pipe_framebuffer_state fb;
    816 		memset(&fb, 0, sizeof(fb));
    817 		fb.nr_cbufs = 1;
    818 		fb.cbufs[0] = surf;
    819 		fb.width = surf->width;
    820 		fb.height = surf->height;
    821 
    822 		struct pipe_viewport_state viewport;
    823 		float half_width = w * 0.5f;
    824 		float half_height = h * 0.5f;
    825 		viewport.scale[0] = half_width;
    826 		viewport.scale[1] = half_height;
    827 		viewport.scale[2] = 1.0f;
    828 		viewport.scale[3] = 1.0f;
    829 		viewport.translate[0] = x + half_width;
    830 		viewport.translate[1] = y + half_height;
    831 		viewport.translate[2] = 0.0f;
    832 		viewport.translate[3] = 1.0f;
    833 
    834 		bool stretch = view->texture->width0 != w || view->texture->height0 != h;
    835 		if(pipe->render_condition)
    836 			pipe->render_condition(pipe, 0, 0);
    837 		pipe->set_framebuffer_state(pipe, &fb);
    838 		pipe->bind_fragment_sampler_states(pipe, 1, &sampler[stretch]);
    839 		pipe->set_viewport_state(pipe, &viewport);
    840 		pipe->set_clip_state(pipe, &clip);
    841 		pipe->bind_rasterizer_state(pipe, rasterizer);
    842 		pipe->bind_depth_stencil_alpha_state(pipe, zsa);
    843 		pipe->bind_blend_state(pipe, blend);
    844 		pipe->bind_vertex_elements_state(pipe, elements);
    845 		pipe->set_vertex_buffers(pipe, 1, &vbuf);
    846 		pipe->bind_fs_state(pipe, fs);
    847 		pipe->bind_vs_state(pipe, vs);
    848 		if(pipe->bind_gs_state)
    849 			pipe->bind_gs_state(pipe, 0);
    850 		if(pipe->set_stream_output_targets)
    851 			pipe->set_stream_output_targets(pipe, 0, NULL, 0);
    852 		pipe->set_fragment_sampler_views(pipe, 1, &view);
    853 
    854 		pipe->draw_vbo(pipe, &draw);
    855 	}
    856 
    857 	~dxgi_blitter()
    858 	{
    859 		pipe->delete_blend_state(pipe, blend);
    860 		pipe->delete_rasterizer_state(pipe, rasterizer);
    861 		pipe->delete_depth_stencil_alpha_state(pipe, zsa);
    862 		pipe->delete_sampler_state(pipe, sampler[0]);
    863 		pipe->delete_sampler_state(pipe, sampler[1]);
    864 		pipe->delete_vertex_elements_state(pipe, elements);
    865 		pipe->delete_vs_state(pipe, vs);
    866 		pipe->delete_fs_state(pipe, fs);
    867 		pipe->screen->resource_destroy(pipe->screen, vbuf.buffer);
    868 	}
    869 };
    870 
    871 struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDXGIFactory>
    872 {
    873 	ComPtr<IDXGIDevice>dxgi_device;
    874 	ComPtr<IGalliumDevice>gallium_device;
    875 	ComPtr<GalliumDXGIAdapter> adapter;
    876 	ComPtr<IDXGIOutput> target;
    877 
    878 	DXGI_SWAP_CHAIN_DESC desc;
    879 
    880 	struct native_surface* surface;
    881 	const struct native_config* config;
    882 
    883 	void* window;
    884 	struct pipe_resource* resources[NUM_NATIVE_ATTACHMENTS];
    885 	int width;
    886 	int height;
    887 	unsigned seq_num;
    888 	bool ever_validated;
    889 	bool needs_validation;
    890 	unsigned present_count;
    891 
    892 	ComPtr<IDXGISurface> buffer0;
    893 	struct pipe_resource* gallium_buffer0;
    894 	struct pipe_sampler_view* gallium_buffer0_view;
    895 
    896 	struct pipe_context* pipe;
    897 	bool owns_pipe;
    898 
    899 	BOOL fullscreen;
    900 
    901 	std::auto_ptr<dxgi_blitter> blitter;
    902 	bool formats_compatible;
    903 
    904 	GalliumDXGISwapChain(GalliumDXGIFactory* factory, IUnknown* p_device, const DXGI_SWAP_CHAIN_DESC& p_desc)
    905 	: GalliumDXGIObject<IDXGISwapChain, GalliumDXGIFactory>(factory), desc(p_desc), surface(0)
    906 	{
    907 		HRESULT hr;
    908 
    909 		hr = p_device->QueryInterface(IID_IGalliumDevice, (void**)&gallium_device);
    910 		if(!SUCCEEDED(hr))
    911 			throw hr;
    912 
    913 		hr = p_device->QueryInterface(IID_IDXGIDevice, (void**)&dxgi_device);
    914 		if(!SUCCEEDED(hr))
    915 			throw hr;
    916 
    917 		hr = dxgi_device->GetAdapter((IDXGIAdapter**)&adapter);
    918 		if(!SUCCEEDED(hr))
    919 			throw hr;
    920 
    921 		memset(resources, 0, sizeof(resources));
    922 
    923 		if(desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL && desc.BufferCount != 1)
    924 		{
    925 			std::cerr << "Gallium DXGI: if DXGI_SWAP_EFFECT_SEQUENTIAL is specified, only buffer_count == 1 is implemented, but " << desc.BufferCount << " was specified: ignoring this" << std::endl;
    926 			// change the returned desc, so that the application might perhaps notice what we did and react well
    927 			desc.BufferCount = 1;
    928 		}
    929 
    930 		pipe = gallium_device->GetGalliumContext();
    931 		owns_pipe = false;
    932 		if(!pipe)
    933 		{
    934 			pipe = adapter->display->screen->context_create(adapter->display->screen, 0);
    935 			owns_pipe = true;
    936 		}
    937 
    938 		blitter.reset(new dxgi_blitter(pipe));
    939 		window = 0;
    940 
    941 		hr = resolve_zero_width_height(true);
    942 		if(!SUCCEEDED(hr))
    943 			throw hr;
    944 	}
    945 
    946 	void init_for_window()
    947 	{
    948 		if(surface)
    949 		{
    950 			surface->destroy(surface);
    951 			surface = 0;
    952 		}
    953 
    954 		unsigned config_num;
    955 		if(!strcmp(parent->platform->name, "X11"))
    956 		{
    957 			XWindowAttributes xwa;
    958 			XGetWindowAttributes((Display*)parent->display, (Window)window, &xwa);
    959 			assert(adapter->configs_by_native_visual_id.count(xwa.visual->visualid));
    960 			config_num = adapter->configs_by_native_visual_id[xwa.visual->visualid];
    961 		}
    962 		else
    963 		{
    964 			enum pipe_format format = dxgi_to_pipe_format[desc.BufferDesc.Format];
    965 			if(!adapter->configs_by_pipe_format.count(format))
    966 			{
    967 				if(adapter->configs_by_pipe_format.empty())
    968 					throw E_FAIL;
    969 				// TODO: choose the best match
    970 				format = (pipe_format)adapter->configs_by_pipe_format.begin()->first;
    971 			}
    972 			// TODO: choose the best config
    973 			config_num = adapter->configs_by_pipe_format.find(format)->second;
    974 		}
    975 
    976 		config = adapter->configs[config_num];
    977 		surface = adapter->display->create_window_surface(adapter->display, (EGLNativeWindowType)window, config);
    978 		surface->user_data = this;
    979 
    980 		width = 0;
    981 		height = 0;
    982 		seq_num = 0;
    983 		present_count = 0;
    984 		needs_validation = true;
    985 		ever_validated = false;
    986 
    987 		formats_compatible = util_is_format_compatible(
    988 				util_format_description(dxgi_to_pipe_format[desc.BufferDesc.Format]),
    989 				util_format_description(config->color_format));
    990 	}
    991 
    992 	~GalliumDXGISwapChain()
    993 	{
    994 		if(owns_pipe)
    995 			pipe->destroy(pipe);
    996 	}
    997 
    998 	virtual HRESULT STDMETHODCALLTYPE GetDevice(
    999 		REFIID riid,
   1000 		void **pdevice)
   1001 	{
   1002 		return dxgi_device->QueryInterface(riid, pdevice);
   1003 	}
   1004 
   1005 	HRESULT create_buffer0()
   1006 	{
   1007 		HRESULT hr;
   1008 		ComPtr<IDXGISurface> new_buffer0;
   1009 		DXGI_USAGE usage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT;
   1010 		if(desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD)
   1011 			usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
   1012 		// for our blitter
   1013 		usage |= DXGI_USAGE_SHADER_INPUT;
   1014 
   1015 		DXGI_SURFACE_DESC surface_desc;
   1016 		surface_desc.Format = desc.BufferDesc.Format;
   1017 		surface_desc.Width = desc.BufferDesc.Width;
   1018 		surface_desc.Height = desc.BufferDesc.Height;
   1019 		surface_desc.SampleDesc = desc.SampleDesc;
   1020 		hr = dxgi_device->CreateSurface(&surface_desc, 1, usage, 0, &new_buffer0);
   1021 		if(!SUCCEEDED(hr))
   1022 			return hr;
   1023 
   1024 		ComPtr<IGalliumResource> gallium_resource;
   1025 		hr = new_buffer0->QueryInterface(IID_IGalliumResource, (void**)&gallium_resource);
   1026 		if(!SUCCEEDED(hr))
   1027 			return hr;
   1028 
   1029 		struct pipe_resource* new_gallium_buffer0 = gallium_resource->GetGalliumResource();
   1030 		if(!new_gallium_buffer0)
   1031 			return E_FAIL;
   1032 
   1033 		buffer0.reset(new_buffer0.steal());
   1034 		gallium_buffer0 = new_gallium_buffer0;
   1035 		struct pipe_sampler_view templat;
   1036 		memset(&templat, 0, sizeof(templat));
   1037 		templat.texture = gallium_buffer0;
   1038 		templat.swizzle_r = 0;
   1039 		templat.swizzle_g = 1;
   1040 		templat.swizzle_b = 2;
   1041 		templat.swizzle_a = 3;
   1042 		templat.format = gallium_buffer0->format;
   1043 		gallium_buffer0_view = pipe->create_sampler_view(pipe, gallium_buffer0, &templat);
   1044 		return S_OK;
   1045 	}
   1046 
   1047 	bool validate()
   1048 	{
   1049 		unsigned new_seq_num;
   1050 		needs_validation = false;
   1051 
   1052 		if(!surface->validate(surface, (1 << NATIVE_ATTACHMENT_BACK_LEFT) | (1 << NATIVE_ATTACHMENT_FRONT_LEFT), &new_seq_num, resources, &width, &height))
   1053 			return false;
   1054 
   1055 		if(!ever_validated || seq_num != new_seq_num)
   1056 		{
   1057 			seq_num = new_seq_num;
   1058 			ever_validated = true;
   1059 		}
   1060 		return true;
   1061 	}
   1062 
   1063 	HRESULT resolve_zero_width_height(bool force = false)
   1064 	{
   1065 		if(!force && desc.BufferDesc.Width && desc.BufferDesc.Height)
   1066 			return S_OK;
   1067 
   1068 		unsigned width, height;
   1069 		HRESULT hr = parent->backend->GetPresentSize(desc.OutputWindow, &width, &height);
   1070 		if(!SUCCEEDED(hr))
   1071 			return hr;
   1072 
   1073 		// On Windows, 8 is used, and a debug message saying so gets printed
   1074 		if(!width)
   1075 			width = 8;
   1076 		if(!height)
   1077 			height = 8;
   1078 
   1079 		if(!desc.BufferDesc.Width)
   1080 			desc.BufferDesc.Width = width;
   1081 		if(!desc.BufferDesc.Height)
   1082 			desc.BufferDesc.Height = height;
   1083 		return S_OK;
   1084 	}
   1085 
   1086 	virtual HRESULT STDMETHODCALLTYPE Present(
   1087 		UINT sync_interval,
   1088 		UINT flags)
   1089 	{
   1090 		HRESULT hr;
   1091 		if(flags & DXGI_PRESENT_TEST)
   1092 			return parent->backend->TestPresent(desc.OutputWindow);
   1093 
   1094 		if(!buffer0)
   1095 		{
   1096 			HRESULT hr = create_buffer0();
   1097 			if(!SUCCEEDED(hr))
   1098 				return hr;
   1099 		}
   1100 
   1101 		void* cur_window = 0;
   1102 		RECT rect;
   1103 		RGNDATA* rgndata;
   1104 		BOOL preserve_aspect_ratio;
   1105 		unsigned dst_w, dst_h;
   1106 		bool db;
   1107 		struct pipe_resource* dst;
   1108 		struct pipe_resource* src;
   1109 		struct pipe_surface* dst_surface;
   1110 		struct native_present_control ctrl;
   1111 
   1112 		void* present_cookie;
   1113 		hr = parent->backend->BeginPresent(desc.OutputWindow, &present_cookie, &cur_window, &rect, &rgndata, &preserve_aspect_ratio);
   1114 		if(hr != S_OK)
   1115 			return hr;
   1116 
   1117 		if(!cur_window || rect.left >= rect.right || rect.top >= rect.bottom)
   1118 			goto end_present;
   1119 
   1120 		if(cur_window != window)
   1121 		{
   1122 			window = cur_window;
   1123 			init_for_window();
   1124 		}
   1125 
   1126 		if(needs_validation)
   1127 		{
   1128 			if(!validate())
   1129 				return DXGI_ERROR_DEVICE_REMOVED;
   1130 		}
   1131 
   1132 		db = !!(config->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT));
   1133 		dst = resources[db ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT];
   1134 		src = gallium_buffer0;
   1135 		dst_surface = 0;
   1136 
   1137 		assert(src);
   1138 		assert(dst);
   1139 
   1140 		/* TODO: sharing the context for blitting won't work correctly if queries are active
   1141 		 * Hopefully no one is crazy enough to keep queries active while presenting, expecting
   1142 		 * sensible results.
   1143 		 * We could alternatively force using another context, but that might cause inefficiency issues
   1144 		 */
   1145 
   1146 		if((unsigned)rect.right > dst->width0)
   1147 			rect.right = dst->width0;
   1148 		if((unsigned)rect.bottom > dst->height0)
   1149 			rect.bottom = dst->height0;
   1150 		if(rect.left > rect.right)
   1151 			rect.left = rect.right;
   1152 		if(rect.top > rect.bottom)
   1153 			rect.top = rect.bottom;
   1154 
   1155 		if(rect.left >= rect.right && rect.top >= rect.bottom)
   1156 			goto end_present;
   1157 
   1158 		dst_w = rect.right - rect.left;
   1159 		dst_h = rect.bottom - rect.top;
   1160 
   1161 		// TODO: add support for rgndata
   1162 //		if(preserve_aspect_ratio || !rgndata)
   1163 		if(1)
   1164 		{
   1165 			unsigned blit_x, blit_y, blit_w, blit_h;
   1166 			static const union pipe_color_union black = { { 0, 0, 0, 0 } };
   1167 
   1168 			if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h) {
   1169 				struct pipe_surface templat;
   1170 				templat.usage = PIPE_BIND_RENDER_TARGET;
   1171 				templat.format = dst->format;
   1172 				templat.u.tex.level = 0;
   1173 				templat.u.tex.first_layer = 0;
   1174 				templat.u.tex.last_layer = 0;
   1175 				dst_surface = pipe->create_surface(pipe, dst, &templat);
   1176 			}
   1177 
   1178 			if(preserve_aspect_ratio)
   1179 			{
   1180 				int delta = src->width0 * dst_h - dst_w * src->height0;
   1181 				if(delta > 0)
   1182 				{
   1183 					blit_w = dst_w;
   1184 					blit_h = dst_w * src->height0 / src->width0;
   1185 				}
   1186 				else if(delta < 0)
   1187 				{
   1188 					blit_w = dst_h * src->width0 / src->height0;
   1189 					blit_h = dst_h;
   1190 				}
   1191 				else
   1192 				{
   1193 					blit_w = dst_w;
   1194 					blit_h = dst_h;
   1195 				}
   1196 
   1197 				blit_x = (dst_w - blit_w) >> 1;
   1198 				blit_y = (dst_h - blit_h) >> 1;
   1199 			}
   1200 			else
   1201 			{
   1202 				blit_x = 0;
   1203 				blit_y = 0;
   1204 				blit_w = dst_w;
   1205 				blit_h = dst_h;
   1206 			}
   1207 
   1208 			if(blit_x)
   1209 				pipe->clear_render_target(pipe, dst_surface, &black, rect.left, rect.top, blit_x, dst_h);
   1210 			if(blit_y)
   1211 				pipe->clear_render_target(pipe, dst_surface, &black, rect.left, rect.top, dst_w, blit_y);
   1212 
   1213 			if(formats_compatible && blit_w == src->width0 && blit_h == src->height0)
   1214 			{
   1215 				pipe_box box;
   1216 				box.x = box.y = box.z = 0;
   1217 				box.width = blit_w;
   1218 				box.height = blit_h;
   1219 				box.depth = 1;
   1220 				pipe->resource_copy_region(pipe, dst, 0, rect.left, rect.top, 0, src, 0, &box);
   1221 			}
   1222 			else
   1223 			{
   1224 				blitter->blit(dst_surface, gallium_buffer0_view, rect.left + blit_x, rect.top + blit_y, blit_w, blit_h);
   1225 				if(!owns_pipe)
   1226 					gallium_device->RestoreGalliumState();
   1227 			}
   1228 
   1229 			if(blit_w != dst_w)
   1230 				pipe->clear_render_target(pipe, dst_surface, &black, rect.left + blit_x + blit_w, rect.top, dst_w - blit_x - blit_w, dst_h);
   1231 			if(blit_h != dst_h)
   1232 				pipe->clear_render_target(pipe, dst_surface, &black, rect.left, rect.top + blit_y + blit_h, dst_w, dst_h - blit_y - blit_h);
   1233 		}
   1234 
   1235 		if(dst_surface)
   1236 			pipe->surface_destroy(pipe, dst_surface);
   1237 
   1238                 pipe->flush(pipe, 0);
   1239 
   1240 		memset(&ctrl, 0, sizeof(ctrl));
   1241 		ctrl.natt = (db) ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT;
   1242 		if(!surface->present(surface, &ctrl))
   1243 			return DXGI_ERROR_DEVICE_REMOVED;
   1244 
   1245 end_present:
   1246 		parent->backend->EndPresent(desc.OutputWindow, present_cookie);
   1247 
   1248 		++present_count;
   1249 		return S_OK;
   1250 	}
   1251 
   1252 	virtual HRESULT STDMETHODCALLTYPE GetBuffer(
   1253 			UINT Buffer,
   1254 			REFIID riid,
   1255 			void **ppSurface)
   1256 	{
   1257 		if(Buffer > 0)
   1258 		{
   1259 			if(desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL)
   1260 				std::cerr << "DXGI unimplemented: GetBuffer(n) with n > 0 not supported, returning buffer 0 instead!" << std::endl;
   1261 			else
   1262 				std::cerr << "DXGI error: in GetBuffer(n), n must be 0 for DXGI_SWAP_EFFECT_DISCARD\n" << std::endl;
   1263 		}
   1264 
   1265 		if(!buffer0)
   1266 		{
   1267 			HRESULT hr = create_buffer0();
   1268 			if(!SUCCEEDED(hr))
   1269 				return hr;
   1270 		}
   1271 		return buffer0->QueryInterface(riid, ppSurface);
   1272 	}
   1273 
   1274 	/* TODO: implement somehow */
   1275 	virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(
   1276 		BOOL fullscreen,
   1277 		IDXGIOutput *target)
   1278 	{
   1279 		fullscreen = fullscreen;
   1280 		target = target;
   1281 		return S_OK;
   1282 	}
   1283 
   1284 	virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(
   1285 		BOOL *out_fullscreen,
   1286 		IDXGIOutput **out_target)
   1287 	{
   1288 		if(out_fullscreen)
   1289 			*out_fullscreen = fullscreen;
   1290 		if(out_target)
   1291 			*out_target = target.ref();
   1292 		return S_OK;
   1293 	}
   1294 
   1295 	virtual HRESULT STDMETHODCALLTYPE GetDesc(
   1296 		DXGI_SWAP_CHAIN_DESC *out_desc)
   1297 	{
   1298 		*out_desc = desc;
   1299 		return S_OK;
   1300 	}
   1301 
   1302 	virtual HRESULT STDMETHODCALLTYPE ResizeBuffers(
   1303 		UINT buffer_count,
   1304 		UINT width,
   1305 		UINT height,
   1306 		DXGI_FORMAT new_format,
   1307 		UINT swap_chain_flags)
   1308 	{
   1309 		if(buffer0)
   1310 		{
   1311 			buffer0.p->AddRef();
   1312 			ULONG v = buffer0.p->Release();
   1313 			// we must fail if there are any references to buffer0 other than ours
   1314 			if(v > 1)
   1315 				return E_FAIL;
   1316 			pipe_sampler_view_reference(&gallium_buffer0_view, 0);
   1317 			buffer0 = (IUnknown*)NULL;
   1318 			gallium_buffer0 = 0;
   1319 		}
   1320 
   1321 		if(desc.SwapEffect != DXGI_SWAP_EFFECT_SEQUENTIAL)
   1322 			desc.BufferCount = buffer_count;
   1323 		desc.BufferDesc.Format = new_format;
   1324 		desc.BufferDesc.Width = width;
   1325 		desc.BufferDesc.Height = height;
   1326 		desc.Flags = swap_chain_flags;
   1327 		return resolve_zero_width_height();
   1328 	}
   1329 
   1330 	virtual HRESULT STDMETHODCALLTYPE ResizeTarget(
   1331 		const DXGI_MODE_DESC *out_new_target_parameters)
   1332 	{
   1333 		/* TODO: implement */
   1334 		return S_OK;
   1335 	}
   1336 
   1337 	virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(
   1338 		IDXGIOutput **out_output)
   1339 	{
   1340 		*out_output = adapter->outputs[0].ref();
   1341 		return S_OK;
   1342 	}
   1343 
   1344 	virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(
   1345 		DXGI_FRAME_STATISTICS *out_stats)
   1346 	{
   1347 		memset(out_stats, 0, sizeof(*out_stats));
   1348 #ifdef _WIN32
   1349 		QueryPerformanceCounter(&out_stats->SyncQPCTime);
   1350 #endif
   1351 		out_stats->PresentCount = present_count;
   1352 		out_stats->PresentRefreshCount = present_count;
   1353 		out_stats->SyncRefreshCount = present_count;
   1354 		return S_OK;
   1355 	}
   1356 
   1357 	virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(
   1358 		UINT *last_present_count)
   1359 	{
   1360 		*last_present_count = present_count;
   1361 		return S_OK;
   1362 	}
   1363 };
   1364 
   1365 static void GalliumDXGISwapChainRevalidate(IDXGISwapChain* swap_chain)
   1366 {
   1367 	((GalliumDXGISwapChain*)swap_chain)->needs_validation = true;
   1368 }
   1369 
   1370 static HRESULT GalliumDXGIAdapterCreate(GalliumDXGIFactory* factory, const struct native_platform* platform, void* dpy, IDXGIAdapter1** out_adapter)
   1371 {
   1372 	try
   1373 	{
   1374 		*out_adapter = new GalliumDXGIAdapter(factory, platform, dpy);
   1375 		return S_OK;
   1376 	}
   1377 	catch(HRESULT hr)
   1378 	{
   1379 		return hr;
   1380 	}
   1381 }
   1382 
   1383 static HRESULT GalliumDXGIOutputCreate(GalliumDXGIAdapter* adapter, const std::string& name, const struct native_connector* connector, IDXGIOutput** out_output)
   1384 {
   1385 	try
   1386 	{
   1387 		*out_output = new GalliumDXGIOutput(adapter, name, connector);
   1388 		return S_OK;
   1389 	}
   1390 	catch(HRESULT hr)
   1391 	{
   1392 		return hr;
   1393 	}
   1394 }
   1395 
   1396 static HRESULT GalliumDXGISwapChainCreate(GalliumDXGIFactory* factory, IUnknown* device, const DXGI_SWAP_CHAIN_DESC& desc, IDXGISwapChain** out_swap_chain)
   1397 {
   1398 	try
   1399 	{
   1400 		*out_swap_chain = new GalliumDXGISwapChain(factory, device, desc);
   1401 		return S_OK;
   1402 	}
   1403 	catch(HRESULT hr)
   1404 	{
   1405 		return hr;
   1406 	}
   1407 }
   1408 
   1409 struct dxgi_binding
   1410 {
   1411 	const struct native_platform* platform;
   1412 	void* display;
   1413 	IGalliumDXGIBackend* backend;
   1414 };
   1415 
   1416 static dxgi_binding dxgi_default_binding;
   1417 static __thread dxgi_binding dxgi_thread_binding;
   1418 static const struct native_event_handler dxgi_event_handler = {
   1419    GalliumDXGIAdapter::handle_invalid_surface,
   1420    dxgi_loader_create_drm_screen,
   1421    dxgi_loader_create_sw_screen
   1422 };
   1423 
   1424 void STDMETHODCALLTYPE GalliumDXGIUseNothing()
   1425 {
   1426 	dxgi_thread_binding.platform = 0;
   1427 	dxgi_thread_binding.display = 0;
   1428 	if(dxgi_thread_binding.backend)
   1429 		dxgi_thread_binding.backend->Release();
   1430 	dxgi_thread_binding.backend = 0;
   1431 }
   1432 
   1433 #ifdef GALLIUM_DXGI_USE_X11
   1434 void STDMETHODCALLTYPE GalliumDXGIUseX11Display(Display* dpy, IGalliumDXGIBackend* backend)
   1435 {
   1436 	GalliumDXGIUseNothing();
   1437 	dxgi_thread_binding.platform = native_get_x11_platform(&dxgi_event_handler);
   1438 	dxgi_thread_binding.display = dpy;
   1439 
   1440 	if(backend)
   1441 	{
   1442 		dxgi_thread_binding.backend = backend;
   1443 		backend->AddRef();
   1444 	}
   1445 }
   1446 #endif
   1447 
   1448 /*
   1449 #ifdef GALLIUM_DXGI_USE_DRM
   1450 void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd)
   1451 {
   1452 	GalliumDXGIUseNothing();
   1453 	dxgi_thread_binding.platform = native_get_drm_platform(&dxgi_event_handler);
   1454 	dxgi_thread_binding.display = (void*)fd;
   1455 	dxgi_thread_binding.backend = 0;
   1456 }
   1457 #endif
   1458 
   1459 #ifdef GALLIUM_DXGI_USE_FBDEV
   1460 void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd)
   1461 {
   1462 	GalliumDXGIUseNothing();
   1463 	dxgi_thread_binding.platform = native_get_fbdev_platform(&dxgi_event_handler);
   1464 	dxgi_thread_binding.display = (void*)fd;
   1465 	dxgi_thread_binding.backend = 0;
   1466 }
   1467 #endif
   1468 
   1469 #ifdef GALLIUM_DXGI_USE_GDI
   1470 void STDMETHODCALLTYPE GalliumDXGIUseHDC(HDC hdc, PFNHWNDRESOLVER resolver, void* resolver_cookie)
   1471 {
   1472 	GalliumDXGIUseNothing();
   1473 	dxgi_thread_binding.platform = native_get_gdi_platform(&dxgi_event_handler);
   1474 	dxgi_thread_binding.display = (void*)hdc;
   1475 	dxgi_thread_binding.backend = 0;
   1476 }
   1477 #endif
   1478 */
   1479 void STDMETHODCALLTYPE GalliumDXGIMakeDefault()
   1480 {
   1481 	if(dxgi_default_binding.backend)
   1482 		dxgi_default_binding.backend->Release();
   1483 	dxgi_default_binding = dxgi_thread_binding;
   1484 	if(dxgi_default_binding.backend)
   1485 		dxgi_default_binding.backend->AddRef();
   1486 }
   1487 
   1488  /* TODO: why did Microsoft add this? should we do something different for DXGI 1.0 and 1.1?
   1489  * Or perhaps what they actually mean is "only create a single factory in your application"?
   1490  * TODO: should we use a singleton here, so we never have multiple DXGI objects for the same thing? */
   1491  HRESULT STDMETHODCALLTYPE CreateDXGIFactory1(
   1492 		REFIID riid,
   1493 		void **out_factory
   1494 )
   1495  {
   1496 	 GalliumDXGIFactory* factory;
   1497 	 *out_factory = 0;
   1498 	 if(dxgi_thread_binding.platform)
   1499 		 factory = new GalliumDXGIFactory(dxgi_thread_binding.platform, dxgi_thread_binding.display, dxgi_thread_binding.backend);
   1500 	 else if(dxgi_default_binding.platform)
   1501 		 factory = new GalliumDXGIFactory(dxgi_default_binding.platform, dxgi_default_binding.display, dxgi_default_binding.backend);
   1502 	 else
   1503 		 factory = new GalliumDXGIFactory(native_get_x11_platform(&dxgi_event_handler), NULL, NULL);
   1504 	 HRESULT hres = factory->QueryInterface(riid, out_factory);
   1505 	 factory->Release();
   1506 	 return hres;
   1507  }
   1508 
   1509  HRESULT STDMETHODCALLTYPE CreateDXGIFactory(
   1510 		 REFIID riid,
   1511 		 void **out_factor
   1512 )
   1513  {
   1514 	 return CreateDXGIFactory1(riid, out_factor);
   1515  }
   1516