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