~ubuntu-branches/ubuntu/precise/mesa/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/state_trackers/d3d1x/dxgi/src/dxgi_native.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2011-08-04 16:25:08 UTC
  • mfrom: (1.2.37 upstream)
  • Revision ID: james.westby@ubuntu.com-20110804162508-kujg82moxerjg1kk
Tags: 7.11-0ubuntu1
* Fake merge from Debian experimental, updating previous changelog entries.
  New upstream release fixes infrequent X crash (LP: #800778).
  Remaining Ubuntu changes:
 - debian/control
    + Drop lesstif-dev from Build-Depends; it's in Universe.
    + Comment out GLw libs since it depends on lesstif-dev.
    + Drop i686 swx11 libgl package.
    + Add libdrm-dev to mesa-common-dev Depends.
    + Drop libwayland-dev from Build-Depends; it's in Universe.
    + Update Breaks for Ubuntu versions
    + Enable llvm on armel as well as i386 and amd64
  - debian/rules
    + Use --disable-glw for swx11 targets too.
    + Don't enable motif for swx11 targets.
    + Use lzma compression for binary debs to save CD space.
    + Drop unloved mach64 driver.
    + Use --enable-shared-dricore to claw back CD space.
    + Enable llvmpipe software rasteriser.
    + Enable llvm on armel as well as i386 and amd64
  - debian/patches
    + 100_no_abi_tag.patch
    + 101_ubuntu_hidden_glname.patch
    + 103_savage-expose_fbmodes_with_nonzero_alpha.patch
  - rules, libgl1-mesa-{glx,dev,swx11,swx11-dev}.install.in,
    libgl1-mesa-{glx,swx11}.{postinst,prerm}.in, libgl1-mesa-dev.links.in:
    Install libGL.so* in /usr/lib/mesa to allow things to work with
    alternatives.
  - debian/not-installed:
    + Drop i686 files; we don't build 686-optimised packages in the first
      place.
  - debian/gbp.conf
    + Point at Ubuntu branch to make git-buildpackage less narky.
  - 113_fix_tls.diff: Fix crashes in unrelated code due to TLS usage.
  - debian/patches/111_export_searchdirs_in_dripc.diff:
    + Add drisearchdirs variable to dri.pc so the Xserver can pick up the
      alternate DRI driver dirs.
  - debian/patches/115_llvm_dynamic_linking.diff
    + Dynamically link DRI drivers to libllvm.  Saves ~6MiB per DRI driver.
  - debian/patches/116_use_shared_galliumcore.diff:
  - debian/libgl1-mesa-dri.install.in:
    + Link gallium DRI drivers against shared gallium routines to save CD
      space.
* debian/rules:
* debian/libgl1-mesa-dri-experimental.install.{i386,amd64}.in
  - Explicitly install i915g only when it has been built, matching what is
    done with r300g.
* debian/rules:
* debian/control:
* debian/libegl1-mesa{,-dev}.install.in:
* debian/libegl1-mesa.symbols:
  - Enable the Wayland EGL backend.
* debian/rules:
* debian/libegl1-mesa.{postinst,prerm,install}.in:
* debian/libegl1-mesa-dev.{install,links}.in:
* debian/libgles{1,2}-mesa.install.in:
* debian/libgles{1,2}-mesa-dev.links.in:
* debian/libopenvg1-mesa{,-dev}.install.in:
* debian/libopenvg1-mesa-dev.links.in:
  - Use alternatives for libEGL to match the handling of libGL.
    libEGL (and associated GL|ES and OpenVG libraries) now live in
    /usr/lib/$MULTIARCH/mesa-egl.  (LP: #812639)
* debian/patches/118_fix_24bpp_software_rendering.diff:
  - Cherry pick upstream patch from master fixing graphical corruption when
    using a 24bpp framebuffer and software rendering. (LP: #810339)
* debian/rules:
* debian/clean:
  - Generate xmlpool pot file and clean up other po files for
    pkgbinarymangler's benefit (LP: #410264).
* debian/patches/119_r600g_gnome_shell_rendering_fix.diff:
  - Cherry pick upstream commit fixing rendering corruption in gnome-shell
    (and therefore likely Unity as well).

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
        struct native_event_handler handler;
254
 
 
255
 
        GalliumDXGIAdapter(GalliumDXGIFactory* factory, const struct native_platform* platform, void* dpy)
256
 
        {
257
 
                this->parent = factory;
258
 
 
259
 
                /* FIXME handler should be static */
260
 
                handler.invalid_surface = handle_invalid_surface;
261
 
                handler.new_drm_screen = dxgi_loader_create_drm_screen;
262
 
                handler.new_sw_screen = dxgi_loader_create_sw_screen;
263
 
                platform->set_event_handler(&handler);
264
 
 
265
 
                display = platform->create_display(dpy, FALSE, this);
266
 
                if(!display)
267
 
                   display = platform->create_display(dpy, TRUE, this);
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.flatshade = 1;
758
 
                rasterizer = pipe->create_rasterizer_state(pipe, &rs_state);
759
 
 
760
 
                struct pipe_blend_state blendd;
761
 
                memset(&blendd, 0, sizeof(blendd));
762
 
                blendd.rt[0].colormask = PIPE_MASK_RGBA;
763
 
                blend = pipe->create_blend_state(pipe, &blendd);
764
 
 
765
 
                struct pipe_depth_stencil_alpha_state zsad;
766
 
                memset(&zsad, 0, sizeof(zsad));
767
 
                zsa = pipe->create_depth_stencil_alpha_state(pipe, &zsad);
768
 
 
769
 
                struct pipe_vertex_element velem[2];
770
 
                memset(&velem[0], 0, sizeof(velem[0]) * 2);
771
 
                velem[0].src_offset = 0;
772
 
                velem[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
773
 
                velem[1].src_offset = 8;
774
 
                velem[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
775
 
                elements = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
776
 
 
777
 
                for(unsigned stretch = 0; stretch < 2; ++stretch)
778
 
                {
779
 
                        struct pipe_sampler_state sampler_state;
780
 
                        memset(&sampler_state, 0, sizeof(sampler_state));
781
 
                        sampler_state.min_img_filter = stretch ? PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
782
 
                        sampler_state.mag_img_filter = stretch ? PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
783
 
                        sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
784
 
                        sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
785
 
                        sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
786
 
                        sampler_state.normalized_coords = normalized;
787
 
 
788
 
                        sampler[stretch] = pipe->create_sampler_state(pipe, &sampler_state);
789
 
                }
790
 
 
791
 
                fs = util_make_fragment_tex_shader(pipe, normalized ? TGSI_TEXTURE_2D : TGSI_TEXTURE_RECT, TGSI_INTERPOLATE_LINEAR);
792
 
 
793
 
                const unsigned semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC };
794
 
                const unsigned semantic_indices[] = { 0, 0 };
795
 
                vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names, semantic_indices);
796
 
 
797
 
                vbuf.buffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
798
 
                                                 PIPE_USAGE_STREAM, sizeof(quad_data));
799
 
                vbuf.buffer_offset = 0;
800
 
                vbuf.stride = 4 * sizeof(float);
801
 
                pipe_buffer_write(pipe, vbuf.buffer, 0, sizeof(quad_data), quad_data);
802
 
 
803
 
                memset(&clip, 0, sizeof(clip));
804
 
 
805
 
                memset(&draw, 0, sizeof(draw));
806
 
                draw.mode = PIPE_PRIM_QUADS;
807
 
                draw.count = 4;
808
 
                draw.instance_count = 1;
809
 
                draw.max_index = ~0;
810
 
        }
811
 
 
812
 
        void blit(struct pipe_surface* surf, struct pipe_sampler_view* view, unsigned x, unsigned y, unsigned w, unsigned h)
813
 
        {
814
 
                struct pipe_framebuffer_state fb;
815
 
                memset(&fb, 0, sizeof(fb));
816
 
                fb.nr_cbufs = 1;
817
 
                fb.cbufs[0] = surf;
818
 
                fb.width = surf->width;
819
 
                fb.height = surf->height;
820
 
 
821
 
                struct pipe_viewport_state viewport;
822
 
                float half_width = w * 0.5f;
823
 
                float half_height = h * 0.5f;
824
 
                viewport.scale[0] = half_width;
825
 
                viewport.scale[1] = half_height;
826
 
                viewport.scale[2] = 1.0f;
827
 
                viewport.scale[3] = 1.0f;
828
 
                viewport.translate[0] = x + half_width;
829
 
                viewport.translate[1] = y + half_height;
830
 
                viewport.translate[2] = 0.0f;
831
 
                viewport.translate[3] = 1.0f;
832
 
 
833
 
                bool stretch = view->texture->width0 != w || view->texture->height0 != h;
834
 
                if(pipe->render_condition)
835
 
                        pipe->render_condition(pipe, 0, 0);
836
 
                pipe->set_framebuffer_state(pipe, &fb);
837
 
                pipe->bind_fragment_sampler_states(pipe, 1, &sampler[stretch]);
838
 
                pipe->set_viewport_state(pipe, &viewport);
839
 
                pipe->set_clip_state(pipe, &clip);
840
 
                pipe->bind_rasterizer_state(pipe, rasterizer);
841
 
                pipe->bind_depth_stencil_alpha_state(pipe, zsa);
842
 
                pipe->bind_blend_state(pipe, blend);
843
 
                pipe->bind_vertex_elements_state(pipe, elements);
844
 
                pipe->set_vertex_buffers(pipe, 1, &vbuf);
845
 
                pipe->bind_fs_state(pipe, fs);
846
 
                pipe->bind_vs_state(pipe, vs);
847
 
                if(pipe->bind_gs_state)
848
 
                        pipe->bind_gs_state(pipe, 0);
849
 
                if(pipe->bind_stream_output_state)
850
 
                        pipe->bind_stream_output_state(pipe, 0);
851
 
                pipe->set_fragment_sampler_views(pipe, 1, &view);
852
 
 
853
 
                pipe->draw_vbo(pipe, &draw);
854
 
        }
855
 
 
856
 
        ~dxgi_blitter()
857
 
        {
858
 
                pipe->delete_blend_state(pipe, blend);
859
 
                pipe->delete_rasterizer_state(pipe, rasterizer);
860
 
                pipe->delete_depth_stencil_alpha_state(pipe, zsa);
861
 
                pipe->delete_sampler_state(pipe, sampler[0]);
862
 
                pipe->delete_sampler_state(pipe, sampler[1]);
863
 
                pipe->delete_vertex_elements_state(pipe, elements);
864
 
                pipe->delete_vs_state(pipe, vs);
865
 
                pipe->delete_fs_state(pipe, fs);
866
 
                pipe->screen->resource_destroy(pipe->screen, vbuf.buffer);
867
 
        }
868
 
};
869
 
 
870
 
struct GalliumDXGISwapChain : public GalliumDXGIObject<IDXGISwapChain, GalliumDXGIFactory>
871
 
{
872
 
        ComPtr<IDXGIDevice>dxgi_device;
873
 
        ComPtr<IGalliumDevice>gallium_device;
874
 
        ComPtr<GalliumDXGIAdapter> adapter;
875
 
        ComPtr<IDXGIOutput> target;
876
 
 
877
 
        DXGI_SWAP_CHAIN_DESC desc;
878
 
 
879
 
        struct native_surface* surface;
880
 
        const struct native_config* config;
881
 
 
882
 
        void* window;
883
 
        struct pipe_resource* resources[NUM_NATIVE_ATTACHMENTS];
884
 
        int width;
885
 
        int height;
886
 
        unsigned seq_num;
887
 
        bool ever_validated;
888
 
        bool needs_validation;
889
 
        unsigned present_count;
890
 
 
891
 
        ComPtr<IDXGISurface> buffer0;
892
 
        struct pipe_resource* gallium_buffer0;
893
 
        struct pipe_sampler_view* gallium_buffer0_view;
894
 
 
895
 
        struct pipe_context* pipe;
896
 
        bool owns_pipe;
897
 
 
898
 
        BOOL fullscreen;
899
 
 
900
 
        std::auto_ptr<dxgi_blitter> blitter;
901
 
        bool formats_compatible;
902
 
 
903
 
        GalliumDXGISwapChain(GalliumDXGIFactory* factory, IUnknown* p_device, const DXGI_SWAP_CHAIN_DESC& p_desc)
904
 
        : GalliumDXGIObject<IDXGISwapChain, GalliumDXGIFactory>(factory), desc(p_desc), surface(0)
905
 
        {
906
 
                HRESULT hr;
907
 
 
908
 
                hr = p_device->QueryInterface(IID_IGalliumDevice, (void**)&gallium_device);
909
 
                if(!SUCCEEDED(hr))
910
 
                        throw hr;
911
 
 
912
 
                hr = p_device->QueryInterface(IID_IDXGIDevice, (void**)&dxgi_device);
913
 
                if(!SUCCEEDED(hr))
914
 
                        throw hr;
915
 
 
916
 
                hr = dxgi_device->GetAdapter((IDXGIAdapter**)&adapter);
917
 
                if(!SUCCEEDED(hr))
918
 
                        throw hr;
919
 
 
920
 
                memset(resources, 0, sizeof(resources));
921
 
 
922
 
                if(desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL && desc.BufferCount != 1)
923
 
                {
924
 
                        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;
925
 
                        // change the returned desc, so that the application might perhaps notice what we did and react well
926
 
                        desc.BufferCount = 1;
927
 
                }
928
 
 
929
 
                pipe = gallium_device->GetGalliumContext();
930
 
                owns_pipe = false;
931
 
                if(!pipe)
932
 
                {
933
 
                        pipe = adapter->display->screen->context_create(adapter->display->screen, 0);
934
 
                        owns_pipe = true;
935
 
                }
936
 
 
937
 
                blitter.reset(new dxgi_blitter(pipe));
938
 
                window = 0;
939
 
 
940
 
                hr = resolve_zero_width_height(true);
941
 
                if(!SUCCEEDED(hr))
942
 
                        throw hr;
943
 
        }
944
 
 
945
 
        void init_for_window()
946
 
        {
947
 
                if(surface)
948
 
                {
949
 
                        surface->destroy(surface);
950
 
                        surface = 0;
951
 
                }
952
 
 
953
 
                unsigned config_num;
954
 
                if(!strcmp(parent->platform->name, "X11"))
955
 
                {
956
 
                        XWindowAttributes xwa;
957
 
                        XGetWindowAttributes((Display*)parent->display, (Window)window, &xwa);
958
 
                        assert(adapter->configs_by_native_visual_id.count(xwa.visual->visualid));
959
 
                        config_num = adapter->configs_by_native_visual_id[xwa.visual->visualid];
960
 
                }
961
 
                else
962
 
                {
963
 
                        enum pipe_format format = dxgi_to_pipe_format[desc.BufferDesc.Format];
964
 
                        if(!adapter->configs_by_pipe_format.count(format))
965
 
                        {
966
 
                                if(adapter->configs_by_pipe_format.empty())
967
 
                                        throw E_FAIL;
968
 
                                // TODO: choose the best match
969
 
                                format = (pipe_format)adapter->configs_by_pipe_format.begin()->first;
970
 
                        }
971
 
                        // TODO: choose the best config
972
 
                        config_num = adapter->configs_by_pipe_format.find(format)->second;
973
 
                }
974
 
 
975
 
                config = adapter->configs[config_num];
976
 
                surface = adapter->display->create_window_surface(adapter->display, (EGLNativeWindowType)window, config);
977
 
                surface->user_data = this;
978
 
 
979
 
                width = 0;
980
 
                height = 0;
981
 
                seq_num = 0;
982
 
                present_count = 0;
983
 
                needs_validation = true;
984
 
                ever_validated = false;
985
 
 
986
 
                formats_compatible = util_is_format_compatible(
987
 
                                util_format_description(dxgi_to_pipe_format[desc.BufferDesc.Format]),
988
 
                                util_format_description(config->color_format));
989
 
        }
990
 
 
991
 
        ~GalliumDXGISwapChain()
992
 
        {
993
 
                if(owns_pipe)
994
 
                        pipe->destroy(pipe);
995
 
        }
996
 
 
997
 
        virtual HRESULT STDMETHODCALLTYPE GetDevice(
998
 
                REFIID riid,
999
 
                void **pdevice)
1000
 
        {
1001
 
                return dxgi_device->QueryInterface(riid, pdevice);
1002
 
        }
1003
 
 
1004
 
        HRESULT create_buffer0()
1005
 
        {
1006
 
                HRESULT hr;
1007
 
                ComPtr<IDXGISurface> new_buffer0;
1008
 
                DXGI_USAGE usage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT;
1009
 
                if(desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD)
1010
 
                        usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
1011
 
                // for our blitter
1012
 
                usage |= DXGI_USAGE_SHADER_INPUT;
1013
 
 
1014
 
                DXGI_SURFACE_DESC surface_desc;
1015
 
                surface_desc.Format = desc.BufferDesc.Format;
1016
 
                surface_desc.Width = desc.BufferDesc.Width;
1017
 
                surface_desc.Height = desc.BufferDesc.Height;
1018
 
                surface_desc.SampleDesc = desc.SampleDesc;
1019
 
                hr = dxgi_device->CreateSurface(&surface_desc, 1, usage, 0, &new_buffer0);
1020
 
                if(!SUCCEEDED(hr))
1021
 
                        return hr;
1022
 
 
1023
 
                ComPtr<IGalliumResource> gallium_resource;
1024
 
                hr = new_buffer0->QueryInterface(IID_IGalliumResource, (void**)&gallium_resource);
1025
 
                if(!SUCCEEDED(hr))
1026
 
                        return hr;
1027
 
 
1028
 
                struct pipe_resource* new_gallium_buffer0 = gallium_resource->GetGalliumResource();
1029
 
                if(!new_gallium_buffer0)
1030
 
                        return E_FAIL;
1031
 
 
1032
 
                buffer0.reset(new_buffer0.steal());
1033
 
                gallium_buffer0 = new_gallium_buffer0;
1034
 
                struct pipe_sampler_view templat;
1035
 
                memset(&templat, 0, sizeof(templat));
1036
 
                templat.texture = gallium_buffer0;
1037
 
                templat.swizzle_r = 0;
1038
 
                templat.swizzle_g = 1;
1039
 
                templat.swizzle_b = 2;
1040
 
                templat.swizzle_a = 3;
1041
 
                templat.format = gallium_buffer0->format;
1042
 
                gallium_buffer0_view = pipe->create_sampler_view(pipe, gallium_buffer0, &templat);
1043
 
                return S_OK;
1044
 
        }
1045
 
 
1046
 
        bool validate()
1047
 
        {
1048
 
                unsigned new_seq_num;
1049
 
                needs_validation = false;
1050
 
 
1051
 
                if(!surface->validate(surface, (1 << NATIVE_ATTACHMENT_BACK_LEFT) | (1 << NATIVE_ATTACHMENT_FRONT_LEFT), &new_seq_num, resources, &width, &height))
1052
 
                        return false;
1053
 
 
1054
 
                if(!ever_validated || seq_num != new_seq_num)
1055
 
                {
1056
 
                        seq_num = new_seq_num;
1057
 
                        ever_validated = true;
1058
 
                }
1059
 
                return true;
1060
 
        }
1061
 
 
1062
 
        HRESULT resolve_zero_width_height(bool force = false)
1063
 
        {
1064
 
                if(!force && desc.BufferDesc.Width && desc.BufferDesc.Height)
1065
 
                        return S_OK;
1066
 
 
1067
 
                unsigned width, height;
1068
 
                HRESULT hr = parent->backend->GetPresentSize(desc.OutputWindow, &width, &height);
1069
 
                if(!SUCCEEDED(hr))
1070
 
                        return hr;
1071
 
 
1072
 
                // On Windows, 8 is used, and a debug message saying so gets printed
1073
 
                if(!width)
1074
 
                        width = 8;
1075
 
                if(!height)
1076
 
                        height = 8;
1077
 
 
1078
 
                if(!desc.BufferDesc.Width)
1079
 
                        desc.BufferDesc.Width = width;
1080
 
                if(!desc.BufferDesc.Height)
1081
 
                        desc.BufferDesc.Height = height;
1082
 
                return S_OK;
1083
 
        }
1084
 
 
1085
 
        virtual HRESULT STDMETHODCALLTYPE Present(
1086
 
                UINT sync_interval,
1087
 
                UINT flags)
1088
 
        {
1089
 
                HRESULT hr;
1090
 
                if(flags & DXGI_PRESENT_TEST)
1091
 
                        return parent->backend->TestPresent(desc.OutputWindow);
1092
 
 
1093
 
                if(!buffer0)
1094
 
                {
1095
 
                        HRESULT hr = create_buffer0();
1096
 
                        if(!SUCCEEDED(hr))
1097
 
                                return hr;
1098
 
                }
1099
 
 
1100
 
                void* cur_window = 0;
1101
 
                RECT rect;
1102
 
                RGNDATA* rgndata;
1103
 
                BOOL preserve_aspect_ratio;
1104
 
                unsigned dst_w, dst_h;
1105
 
                bool db;
1106
 
                struct pipe_resource* dst;
1107
 
                struct pipe_resource* src;
1108
 
                struct pipe_surface* dst_surface;
1109
 
                enum native_attachment att;
1110
 
 
1111
 
                void* present_cookie;
1112
 
                hr = parent->backend->BeginPresent(desc.OutputWindow, &present_cookie, &cur_window, &rect, &rgndata, &preserve_aspect_ratio);
1113
 
                if(hr != S_OK)
1114
 
                        return hr;
1115
 
 
1116
 
                if(!cur_window || rect.left >= rect.right || rect.top >= rect.bottom)
1117
 
                        goto end_present;
1118
 
 
1119
 
                if(cur_window != window)
1120
 
                {
1121
 
                        window = cur_window;
1122
 
                        init_for_window();
1123
 
                }
1124
 
 
1125
 
                if(needs_validation)
1126
 
                {
1127
 
                        if(!validate())
1128
 
                                return DXGI_ERROR_DEVICE_REMOVED;
1129
 
                }
1130
 
 
1131
 
                db = !!(config->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT));
1132
 
                dst = resources[db ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT];
1133
 
                src = gallium_buffer0;
1134
 
                dst_surface = 0;
1135
 
 
1136
 
                assert(src);
1137
 
                assert(dst);
1138
 
 
1139
 
                /* TODO: sharing the context for blitting won't work correctly if queries are active
1140
 
                 * Hopefully no one is crazy enough to keep queries active while presenting, expecting
1141
 
                 * sensible results.
1142
 
                 * We could alternatively force using another context, but that might cause inefficiency issues
1143
 
                 */
1144
 
 
1145
 
                if((unsigned)rect.right > dst->width0)
1146
 
                        rect.right = dst->width0;
1147
 
                if((unsigned)rect.bottom > dst->height0)
1148
 
                        rect.bottom = dst->height0;
1149
 
                if(rect.left > rect.right)
1150
 
                        rect.left = rect.right;
1151
 
                if(rect.top > rect.bottom)
1152
 
                        rect.top = rect.bottom;
1153
 
 
1154
 
                if(rect.left >= rect.right && rect.top >= rect.bottom)
1155
 
                        goto end_present;
1156
 
 
1157
 
                dst_w = rect.right - rect.left;
1158
 
                dst_h = rect.bottom - rect.top;
1159
 
 
1160
 
                // TODO: add support for rgndata
1161
 
//              if(preserve_aspect_ratio || !rgndata)
1162
 
                if(1)
1163
 
                {
1164
 
                        unsigned blit_x, blit_y, blit_w, blit_h;
1165
 
                        float black[4] = {0, 0, 0, 0};
1166
 
 
1167
 
                        if(!formats_compatible || src->width0 != dst_w || src->height0 != dst_h) {
1168
 
                                struct pipe_surface templat;
1169
 
                                templat.usage = PIPE_BIND_RENDER_TARGET;
1170
 
                                templat.format = dst->format;
1171
 
                                templat.u.tex.level = 0;
1172
 
                                templat.u.tex.first_layer = 0;
1173
 
                                templat.u.tex.last_layer = 0;
1174
 
                                dst_surface = pipe->create_surface(pipe, dst, &templat);
1175
 
                        }
1176
 
 
1177
 
                        if(preserve_aspect_ratio)
1178
 
                        {
1179
 
                                int delta = src->width0 * dst_h - dst_w * src->height0;
1180
 
                                if(delta > 0)
1181
 
                                {
1182
 
                                        blit_w = dst_w;
1183
 
                                        blit_h = dst_w * src->height0 / src->width0;
1184
 
                                }
1185
 
                                else if(delta < 0)
1186
 
                                {
1187
 
                                        blit_w = dst_h * src->width0 / src->height0;
1188
 
                                        blit_h = dst_h;
1189
 
                                }
1190
 
                                else
1191
 
                                {
1192
 
                                        blit_w = dst_w;
1193
 
                                        blit_h = dst_h;
1194
 
                                }
1195
 
 
1196
 
                                blit_x = (dst_w - blit_w) >> 1;
1197
 
                                blit_y = (dst_h - blit_h) >> 1;
1198
 
                        }
1199
 
                        else
1200
 
                        {
1201
 
                                blit_x = 0;
1202
 
                                blit_y = 0;
1203
 
                                blit_w = dst_w;
1204
 
                                blit_h = dst_h;
1205
 
                        }
1206
 
 
1207
 
                        if(blit_x)
1208
 
                                pipe->clear_render_target(pipe, dst_surface, black, rect.left, rect.top, blit_x, dst_h);
1209
 
                        if(blit_y)
1210
 
                                pipe->clear_render_target(pipe, dst_surface, black, rect.left, rect.top, dst_w, blit_y);
1211
 
 
1212
 
                        if(formats_compatible && blit_w == src->width0 && blit_h == src->height0)
1213
 
                        {
1214
 
                                pipe_box box;
1215
 
                                box.x = box.y = box.z;
1216
 
                                box.width = blit_w;
1217
 
                                box.height = blit_h;
1218
 
                                box.z = 1;
1219
 
                                pipe->resource_copy_region(pipe, dst, 0, rect.left, rect.top, 0, src, 0, &box);
1220
 
                        }
1221
 
                        else
1222
 
                        {
1223
 
                                blitter->blit(dst_surface, gallium_buffer0_view, rect.left + blit_x, rect.top + blit_y, blit_w, blit_h);
1224
 
                                if(!owns_pipe)
1225
 
                                        gallium_device->RestoreGalliumState();
1226
 
                        }
1227
 
 
1228
 
                        if(blit_w != dst_w)
1229
 
                                pipe->clear_render_target(pipe, dst_surface, black, rect.left + blit_x + blit_w, rect.top, dst_w - blit_x - blit_w, dst_h);
1230
 
                        if(blit_h != dst_h)
1231
 
                                pipe->clear_render_target(pipe, dst_surface, black, rect.left, rect.top + blit_y + blit_h, dst_w, dst_h - blit_y - blit_h);
1232
 
                }
1233
 
 
1234
 
                if(dst_surface)
1235
 
                        pipe->surface_destroy(pipe, dst_surface);
1236
 
 
1237
 
                pipe->flush(pipe, 0);
1238
 
 
1239
 
                att = (db) ? NATIVE_ATTACHMENT_BACK_LEFT : NATIVE_ATTACHMENT_FRONT_LEFT;
1240
 
                if(!surface->present(surface, att, FALSE, 0))
1241
 
                        return DXGI_ERROR_DEVICE_REMOVED;
1242
 
 
1243
 
end_present:
1244
 
                parent->backend->EndPresent(desc.OutputWindow, present_cookie);
1245
 
 
1246
 
                ++present_count;
1247
 
                return S_OK;
1248
 
        }
1249
 
 
1250
 
        virtual HRESULT STDMETHODCALLTYPE GetBuffer(
1251
 
                        UINT Buffer,
1252
 
                        REFIID riid,
1253
 
                        void **ppSurface)
1254
 
        {
1255
 
                if(Buffer > 0)
1256
 
                {
1257
 
                        if(desc.SwapEffect == DXGI_SWAP_EFFECT_SEQUENTIAL)
1258
 
                                std::cerr << "DXGI unimplemented: GetBuffer(n) with n > 0 not supported, returning buffer 0 instead!" << std::endl;
1259
 
                        else
1260
 
                                std::cerr << "DXGI error: in GetBuffer(n), n must be 0 for DXGI_SWAP_EFFECT_DISCARD\n" << std::endl;
1261
 
                }
1262
 
 
1263
 
                if(!buffer0)
1264
 
                {
1265
 
                        HRESULT hr = create_buffer0();
1266
 
                        if(!SUCCEEDED(hr))
1267
 
                                return hr;
1268
 
                }
1269
 
                return buffer0->QueryInterface(riid, ppSurface);
1270
 
        }
1271
 
 
1272
 
        /* TODO: implement somehow */
1273
 
        virtual HRESULT STDMETHODCALLTYPE SetFullscreenState(
1274
 
                BOOL fullscreen,
1275
 
                IDXGIOutput *target)
1276
 
        {
1277
 
                fullscreen = fullscreen;
1278
 
                target = target;
1279
 
                return S_OK;
1280
 
        }
1281
 
 
1282
 
        virtual HRESULT STDMETHODCALLTYPE GetFullscreenState(
1283
 
                BOOL *out_fullscreen,
1284
 
                IDXGIOutput **out_target)
1285
 
        {
1286
 
                if(out_fullscreen)
1287
 
                        *out_fullscreen = fullscreen;
1288
 
                if(out_target)
1289
 
                        *out_target = target.ref();
1290
 
                return S_OK;
1291
 
        }
1292
 
 
1293
 
        virtual HRESULT STDMETHODCALLTYPE GetDesc(
1294
 
                DXGI_SWAP_CHAIN_DESC *out_desc)
1295
 
        {
1296
 
                *out_desc = desc;
1297
 
                return S_OK;
1298
 
        }
1299
 
 
1300
 
        virtual HRESULT STDMETHODCALLTYPE ResizeBuffers(
1301
 
                UINT buffer_count,
1302
 
                UINT width,
1303
 
                UINT height,
1304
 
                DXGI_FORMAT new_format,
1305
 
                UINT swap_chain_flags)
1306
 
        {
1307
 
                if(buffer0)
1308
 
                {
1309
 
                        buffer0.p->AddRef();
1310
 
                        ULONG v = buffer0.p->Release();
1311
 
                        // we must fail if there are any references to buffer0 other than ours
1312
 
                        if(v > 1)
1313
 
                                return E_FAIL;
1314
 
                        pipe_sampler_view_reference(&gallium_buffer0_view, 0);
1315
 
                        buffer0 = (IUnknown*)NULL;
1316
 
                        gallium_buffer0 = 0;
1317
 
                }
1318
 
 
1319
 
                if(desc.SwapEffect != DXGI_SWAP_EFFECT_SEQUENTIAL)
1320
 
                        desc.BufferCount = buffer_count;
1321
 
                desc.BufferDesc.Format = new_format;
1322
 
                desc.BufferDesc.Width = width;
1323
 
                desc.BufferDesc.Height = height;
1324
 
                desc.Flags = swap_chain_flags;
1325
 
                return resolve_zero_width_height();
1326
 
        }
1327
 
 
1328
 
        virtual HRESULT STDMETHODCALLTYPE ResizeTarget(
1329
 
                const DXGI_MODE_DESC *out_new_target_parameters)
1330
 
        {
1331
 
                /* TODO: implement */
1332
 
                return S_OK;
1333
 
        }
1334
 
 
1335
 
        virtual HRESULT STDMETHODCALLTYPE GetContainingOutput(
1336
 
                IDXGIOutput **out_output)
1337
 
        {
1338
 
                *out_output = adapter->outputs[0].ref();
1339
 
                return S_OK;
1340
 
        }
1341
 
 
1342
 
        virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics(
1343
 
                DXGI_FRAME_STATISTICS *out_stats)
1344
 
        {
1345
 
                memset(out_stats, 0, sizeof(*out_stats));
1346
 
#ifdef _WIN32
1347
 
                QueryPerformanceCounter(&out_stats->SyncQPCTime);
1348
 
#endif
1349
 
                out_stats->PresentCount = present_count;
1350
 
                out_stats->PresentRefreshCount = present_count;
1351
 
                out_stats->SyncRefreshCount = present_count;
1352
 
                return S_OK;
1353
 
        }
1354
 
 
1355
 
        virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount(
1356
 
                UINT *last_present_count)
1357
 
        {
1358
 
                *last_present_count = present_count;
1359
 
                return S_OK;
1360
 
        }
1361
 
};
1362
 
 
1363
 
static void GalliumDXGISwapChainRevalidate(IDXGISwapChain* swap_chain)
1364
 
{
1365
 
        ((GalliumDXGISwapChain*)swap_chain)->needs_validation = true;
1366
 
}
1367
 
 
1368
 
static HRESULT GalliumDXGIAdapterCreate(GalliumDXGIFactory* factory, const struct native_platform* platform, void* dpy, IDXGIAdapter1** out_adapter)
1369
 
{
1370
 
        try
1371
 
        {
1372
 
                *out_adapter = new GalliumDXGIAdapter(factory, platform, dpy);
1373
 
                return S_OK;
1374
 
        }
1375
 
        catch(HRESULT hr)
1376
 
        {
1377
 
                return hr;
1378
 
        }
1379
 
}
1380
 
 
1381
 
static HRESULT GalliumDXGIOutputCreate(GalliumDXGIAdapter* adapter, const std::string& name, const struct native_connector* connector, IDXGIOutput** out_output)
1382
 
{
1383
 
        try
1384
 
        {
1385
 
                *out_output = new GalliumDXGIOutput(adapter, name, connector);
1386
 
                return S_OK;
1387
 
        }
1388
 
        catch(HRESULT hr)
1389
 
        {
1390
 
                return hr;
1391
 
        }
1392
 
}
1393
 
 
1394
 
static HRESULT GalliumDXGISwapChainCreate(GalliumDXGIFactory* factory, IUnknown* device, const DXGI_SWAP_CHAIN_DESC& desc, IDXGISwapChain** out_swap_chain)
1395
 
{
1396
 
        try
1397
 
        {
1398
 
                *out_swap_chain = new GalliumDXGISwapChain(factory, device, desc);
1399
 
                return S_OK;
1400
 
        }
1401
 
        catch(HRESULT hr)
1402
 
        {
1403
 
                return hr;
1404
 
        }
1405
 
}
1406
 
 
1407
 
struct dxgi_binding
1408
 
{
1409
 
        const struct native_platform* platform;
1410
 
        void* display;
1411
 
        IGalliumDXGIBackend* backend;
1412
 
};
1413
 
 
1414
 
static dxgi_binding dxgi_default_binding;
1415
 
static __thread dxgi_binding dxgi_thread_binding;
1416
 
 
1417
 
void STDMETHODCALLTYPE GalliumDXGIUseNothing()
1418
 
{
1419
 
        dxgi_thread_binding.platform = 0;
1420
 
        dxgi_thread_binding.display = 0;
1421
 
        if(dxgi_thread_binding.backend)
1422
 
                dxgi_thread_binding.backend->Release();
1423
 
        dxgi_thread_binding.backend = 0;
1424
 
}
1425
 
 
1426
 
#ifdef GALLIUM_DXGI_USE_X11
1427
 
void STDMETHODCALLTYPE GalliumDXGIUseX11Display(Display* dpy, IGalliumDXGIBackend* backend)
1428
 
{
1429
 
        GalliumDXGIUseNothing();
1430
 
        dxgi_thread_binding.platform = native_get_x11_platform();
1431
 
        dxgi_thread_binding.display = dpy;
1432
 
 
1433
 
        if(backend)
1434
 
        {
1435
 
                dxgi_thread_binding.backend = backend;
1436
 
                backend->AddRef();
1437
 
        }
1438
 
}
1439
 
#endif
1440
 
 
1441
 
/*
1442
 
#ifdef GALLIUM_DXGI_USE_DRM
1443
 
void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd)
1444
 
{
1445
 
        GalliumDXGIUseNothing();
1446
 
        dxgi_thread_binding.platform = native_get_drm_platform();
1447
 
        dxgi_thread_binding.display = (void*)fd;
1448
 
        dxgi_thread_binding.backend = 0;
1449
 
}
1450
 
#endif
1451
 
 
1452
 
#ifdef GALLIUM_DXGI_USE_FBDEV
1453
 
void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd)
1454
 
{
1455
 
        GalliumDXGIUseNothing();
1456
 
        dxgi_thread_binding.platform = native_get_fbdev_platform();
1457
 
        dxgi_thread_binding.display = (void*)fd;
1458
 
        dxgi_thread_binding.backend = 0;
1459
 
}
1460
 
#endif
1461
 
 
1462
 
#ifdef GALLIUM_DXGI_USE_GDI
1463
 
void STDMETHODCALLTYPE GalliumDXGIUseHDC(HDC hdc, PFNHWNDRESOLVER resolver, void* resolver_cookie)
1464
 
{
1465
 
        GalliumDXGIUseNothing();
1466
 
        dxgi_thread_binding.platform = native_get_gdi_platform();
1467
 
        dxgi_thread_binding.display = (void*)hdc;
1468
 
        dxgi_thread_binding.backend = 0;
1469
 
}
1470
 
#endif
1471
 
*/
1472
 
void STDMETHODCALLTYPE GalliumDXGIMakeDefault()
1473
 
{
1474
 
        if(dxgi_default_binding.backend)
1475
 
                dxgi_default_binding.backend->Release();
1476
 
        dxgi_default_binding = dxgi_thread_binding;
1477
 
        if(dxgi_default_binding.backend)
1478
 
                dxgi_default_binding.backend->AddRef();
1479
 
}
1480
 
 
1481
 
 /* TODO: why did Microsoft add this? should we do something different for DXGI 1.0 and 1.1?
1482
 
 * Or perhaps what they actually mean is "only create a single factory in your application"?
1483
 
 * TODO: should we use a singleton here, so we never have multiple DXGI objects for the same thing? */
1484
 
 HRESULT STDMETHODCALLTYPE CreateDXGIFactory1(
1485
 
                REFIID riid,
1486
 
                void **out_factory
1487
 
)
1488
 
 {
1489
 
         GalliumDXGIFactory* factory;
1490
 
         *out_factory = 0;
1491
 
         if(dxgi_thread_binding.platform)
1492
 
                 factory = new GalliumDXGIFactory(dxgi_thread_binding.platform, dxgi_thread_binding.display, dxgi_thread_binding.backend);
1493
 
         else if(dxgi_default_binding.platform)
1494
 
                 factory = new GalliumDXGIFactory(dxgi_default_binding.platform, dxgi_default_binding.display, dxgi_default_binding.backend);
1495
 
         else
1496
 
                 factory = new GalliumDXGIFactory(native_get_x11_platform(), NULL, NULL);
1497
 
         HRESULT hres = factory->QueryInterface(riid, out_factory);
1498
 
         factory->Release();
1499
 
         return hres;
1500
 
 }
1501
 
 
1502
 
 HRESULT STDMETHODCALLTYPE CreateDXGIFactory(
1503
 
                 REFIID riid,
1504
 
                 void **out_factor
1505
 
)
1506
 
 {
1507
 
         return CreateDXGIFactory1(riid, out_factor);
1508
 
 }