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