1 /**************************************************************************
3 * Copyright 2010 Luca Barbieri
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:
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.
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.
25 **************************************************************************/
27 #include "dxgi_private.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>
38 struct GalliumDXGIOutput
;
39 struct GalliumDXGIAdapter
;
40 struct GalliumDXGISwapChain
;
41 struct GalliumDXGIFactory
;
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
);
48 template<typename Base
= IDXGIObject
, typename Parent
= IDXGIObject
>
49 struct GalliumDXGIObject
: public GalliumPrivateDataComObject
<Base
>
51 ComPtr
<Parent
> parent
;
53 GalliumDXGIObject(Parent
* p_parent
= 0)
55 this->parent
= p_parent
;
58 virtual HRESULT STDMETHODCALLTYPE
GetParent(
62 return parent
->QueryInterface(riid
, out_parent
);
66 COM_INTERFACE(IGalliumDXGIBackend
, IUnknown
)
68 // TODO: somehow check whether the window is fully obscured or not
69 struct GalliumDXGIIdentityBackend
: public GalliumComObject
<IGalliumDXGIBackend
>
71 virtual HRESULT STDMETHODCALLTYPE
BeginPresent(
73 void** present_cookie
,
77 BOOL
* preserve_aspect_ratio
80 *window
= (void*)hwnd
;
83 rect
->right
= INT_MAX
;
84 rect
->bottom
= INT_MAX
;
87 // yes, because we like things looking good
88 *preserve_aspect_ratio
= TRUE
;
93 virtual void STDMETHODCALLTYPE
EndPresent(
99 virtual HRESULT STDMETHODCALLTYPE
TestPresent(HWND hwnd
)
104 virtual HRESULT STDMETHODCALLTYPE
GetPresentSize(
116 // TODO: maybe install an X11 error hook, so we can return errors properly
117 struct GalliumDXGIX11IdentityBackend
: public GalliumDXGIIdentityBackend
121 GalliumDXGIX11IdentityBackend(Display
* dpy
)
125 virtual HRESULT STDMETHODCALLTYPE
GetPresentSize(
131 XWindowAttributes xwa
;
132 XGetWindowAttributes(dpy
, (Window
)hwnd
, &xwa
);
134 *height
= xwa
.height
;
139 struct GalliumDXGIFactory
: public GalliumDXGIObject
<IDXGIFactory1
, IUnknown
>
141 HWND associated_window
;
142 const struct native_platform
* platform
;
144 ComPtr
<IGalliumDXGIBackend
> backend
;
145 void* resolver_cookie
;
147 GalliumDXGIFactory(const struct native_platform
* platform
, void* display
, IGalliumDXGIBackend
* p_backend
)
148 : GalliumDXGIObject
<IDXGIFactory1
, IUnknown
>((IUnknown
*)NULL
), platform(platform
), display(display
)
152 else if(!strcmp(platform
->name
, "X11"))
153 backend
.reset(new GalliumDXGIX11IdentityBackend((Display
*)display
));
155 backend
.reset(new GalliumDXGIIdentityBackend());
158 virtual HRESULT STDMETHODCALLTYPE
EnumAdapters(
160 IDXGIAdapter
**out_adapter
)
162 return EnumAdapters1(adapter
, (IDXGIAdapter1
**)out_adapter
);
165 virtual HRESULT STDMETHODCALLTYPE
EnumAdapters1(
167 IDXGIAdapter1
**out_adapter
)
172 return GalliumDXGIAdapterCreate(this, platform
, display
, out_adapter
);
176 if(platform
== native_get_x11_platform())
178 unsigned nscreens
= ScreenCount((Display
*)display
);
179 if(adapter
< nscreens
)
181 unsigned def_screen
= DefaultScreen(display
);
182 if(adapter
<= def_screen
)
184 *out_adapter
= GalliumDXGIAdapterCreate(this, platform
, display
, adapter
);
189 return DXGI_ERROR_NOT_FOUND
;
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?
199 virtual HRESULT STDMETHODCALLTYPE
MakeWindowAssociation(
203 /* TODO: actually implement, for Wine, X11 and KMS*/
204 associated_window
= window_handle
;
208 virtual HRESULT STDMETHODCALLTYPE
GetWindowAssociation(
209 HWND
*pwindow_handle
)
211 *pwindow_handle
= associated_window
;
215 virtual HRESULT STDMETHODCALLTYPE
CreateSwapChain(
217 DXGI_SWAP_CHAIN_DESC
*desc
,
218 IDXGISwapChain
**out_swap_chain
)
220 return GalliumDXGISwapChainCreate(this, device
, *desc
, out_swap_chain
);
223 virtual HRESULT STDMETHODCALLTYPE
CreateSoftwareAdapter(
225 IDXGIAdapter
**out_adapter
)
227 /* TODO: ignore the module, and just create a Gallium software screen */
232 /* TODO: support hotplug */
233 virtual BOOL STDMETHODCALLTYPE
IsCurrent( void)
239 struct GalliumDXGIAdapter
240 : public GalliumMultiComObject
<
241 GalliumDXGIObject
<IDXGIAdapter1
, GalliumDXGIFactory
>,
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
;
253 struct native_event_handler handler
;
255 GalliumDXGIAdapter(GalliumDXGIFactory
* factory
, const struct native_platform
* platform
, void* dpy
)
257 this->parent
= factory
;
259 handler
.invalid_surface
= handle_invalid_surface
;
260 handler
.new_drm_screen
= dxgi_loader_create_drm_screen
;
261 handler
.new_sw_screen
= dxgi_loader_create_sw_screen
;
262 display
= platform
->create_display(dpy
, &handler
, this);
265 memset(&desc
, 0, sizeof(desc
));
266 std::string s
= std::string("GalliumD3D on ") + display
->screen
->get_name(display
->screen
) + " by " + display
->screen
->get_vendor(display
->screen
);
268 /* hopefully no one will decide to use UTF-8 in Gallium name/vendor strings */
269 for(int i
= 0; i
< std::min((int)s
.size(), 127); ++i
)
270 desc
.Description
[i
] = (WCHAR
)s
[i
];
272 // TODO: add an interface to get these; for now, return mid/low values
273 desc
.DedicatedVideoMemory
= 256 << 20;
274 desc
.DedicatedSystemMemory
= 256 << 20;
275 desc
.SharedSystemMemory
= 1024 << 20;
277 // TODO: we should actually use an unique ID instead
278 *(void**)&desc
.AdapterLuid
= dpy
;
280 configs
= display
->get_configs(display
, (int*)&num_configs
);
281 for(unsigned i
= 0; i
< num_configs
; ++i
)
283 if(configs
[i
]->window_bit
)
285 configs_by_pipe_format
.insert(std::make_pair(configs
[i
]->color_format
, i
));
286 configs_by_native_visual_id
[configs
[i
]->native_visual_id
] = i
;
297 connectors
= display
->modeset
->get_connectors(display
, &num_outputs
, &num_crtcs
);
300 else if(!num_outputs
)
310 static void handle_invalid_surface(struct native_display
*ndpy
, struct native_surface
*nsurf
, unsigned int seq_num
)
312 GalliumDXGISwapChainRevalidate((IDXGISwapChain
*)nsurf
->user_data
);
315 ~GalliumDXGIAdapter()
317 display
->destroy(display
);
322 virtual HRESULT STDMETHODCALLTYPE
EnumOutputs(
324 IDXGIOutput
**out_output
)
326 if(output
>= (unsigned)num_outputs
)
327 return DXGI_ERROR_NOT_FOUND
;
331 std::ostringstream ss
;
332 ss
<< "output #" << output
;
333 return GalliumDXGIOutputCreate(this, ss
.str(), connectors
[output
], out_output
);
336 return GalliumDXGIOutputCreate(this, "Unique output", NULL
, out_output
);
339 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
340 DXGI_ADAPTER_DESC
*desc
)
342 memcpy(desc
, &desc
, sizeof(*desc
));
346 virtual HRESULT STDMETHODCALLTYPE
GetDesc1(
347 DXGI_ADAPTER_DESC1
*desc
)
349 memcpy(desc
, &desc
, sizeof(*desc
));
353 virtual HRESULT STDMETHODCALLTYPE
CheckInterfaceSupport(
354 REFGUID interface_name
,
355 LARGE_INTEGER
*u_m_d_version
)
357 // these number was taken from Windows 7 with Catalyst 10.8: its meaning is unclear
358 if(interface_name
== IID_ID3D11Device
|| interface_name
== IID_ID3D10Device1
|| interface_name
== IID_ID3D10Device
)
360 u_m_d_version
->QuadPart
= 0x00080011000a0411ULL
;
363 return DXGI_ERROR_UNSUPPORTED
;
366 pipe_screen
* STDMETHODCALLTYPE
GetGalliumScreen()
368 return display
->screen
;
371 pipe_screen
* STDMETHODCALLTYPE
GetGalliumReferenceSoftwareScreen()
373 // TODO: give a softpipe screen
374 return display
->screen
;
377 pipe_screen
* STDMETHODCALLTYPE
GetGalliumFastSoftwareScreen()
379 // TODO: give an llvmpipe screen
380 return display
->screen
;
385 struct GalliumDXGIOutput
: public GalliumDXGIObject
<IDXGIOutput
, GalliumDXGIAdapter
>
387 DXGI_OUTPUT_DESC desc
;
388 const struct native_mode
** modes
;
389 DXGI_MODE_DESC
* dxgi_modes
;
391 const struct native_connector
* connector
;
392 DXGI_GAMMA_CONTROL
* gamma
;
394 GalliumDXGIOutput(GalliumDXGIAdapter
* adapter
, std::string name
, const struct native_connector
* connector
= 0)
395 : GalliumDXGIObject
<IDXGIOutput
, GalliumDXGIAdapter
>(adapter
), connector(connector
)
397 memset(&desc
, 0, sizeof(desc
));
398 for(unsigned i
= 0; i
< std::min(name
.size(), sizeof(desc
.DeviceName
) - 1); ++i
)
399 desc
.DeviceName
[i
] = name
[i
];
400 desc
.AttachedToDesktop
= TRUE
;
401 /* TODO: should put an HMONITOR in desc.Monitor */
408 modes
= parent
->display
->modeset
->get_modes(parent
->display
, connector
, (int*)&num_modes
);
409 if(modes
&& num_modes
)
411 dxgi_modes
= new DXGI_MODE_DESC
[num_modes
];
412 for(unsigned i
= 0; i
< num_modes
; ++i
)
414 dxgi_modes
[i
].Width
= modes
[i
]->width
;
415 dxgi_modes
[i
].Height
= modes
[i
]->height
;
416 dxgi_modes
[i
].RefreshRate
.Numerator
= modes
[i
]->refresh_rate
;
417 dxgi_modes
[i
].RefreshRate
.Denominator
= 1;
418 dxgi_modes
[i
].Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
419 dxgi_modes
[i
].ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
435 dxgi_modes
= new DXGI_MODE_DESC
[1];
436 dxgi_modes
[0].Width
= 1920;
437 dxgi_modes
[0].Height
= 1200;
438 dxgi_modes
[0].RefreshRate
.Numerator
= 60;
439 dxgi_modes
[0].RefreshRate
.Denominator
= 1;
440 dxgi_modes
[0].Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
441 dxgi_modes
[0].ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
447 delete [] dxgi_modes
;
453 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
454 DXGI_OUTPUT_DESC
*out_desc
)
460 virtual HRESULT STDMETHODCALLTYPE
GetDisplayModeList(
461 DXGI_FORMAT enum_format
,
464 DXGI_MODE_DESC
*desc
)
466 /* TODO: should we return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE when we don't
467 * support modesetting instead of fake modes?
469 pipe_format format
= dxgi_to_pipe_format
[enum_format
];
470 if(parent
->configs_by_pipe_format
.count(format
))
478 unsigned copy_modes
= std::min(num_modes
, *pcount
);
479 for(unsigned i
= 0; i
< copy_modes
; ++i
)
481 desc
[i
] = dxgi_modes
[i
];
482 desc
[i
].Format
= enum_format
;
486 if(copy_modes
< num_modes
)
487 return DXGI_ERROR_MORE_DATA
;
498 virtual HRESULT STDMETHODCALLTYPE
FindClosestMatchingMode(
499 const DXGI_MODE_DESC
*pModeToMatch
,
500 DXGI_MODE_DESC
*closest_match
,
501 IUnknown
*concerned_device
)
503 /* TODO: actually implement this */
504 DXGI_FORMAT dxgi_format
= pModeToMatch
->Format
;
505 enum pipe_format format
= dxgi_to_pipe_format
[dxgi_format
];
506 init_pipe_to_dxgi_format();
507 if(!parent
->configs_by_pipe_format
.count(format
))
509 if(!concerned_device
)
513 format
= parent
->configs
[0]->color_format
;
514 dxgi_format
= pipe_to_dxgi_format
[format
];
518 *closest_match
= dxgi_modes
[0];
519 closest_match
->Format
= dxgi_format
;
523 virtual HRESULT STDMETHODCALLTYPE
WaitForVBlank( void)
528 virtual HRESULT STDMETHODCALLTYPE
TakeOwnership(
535 virtual void STDMETHODCALLTYPE
ReleaseOwnership( void)
539 virtual HRESULT STDMETHODCALLTYPE
GetGammaControlCapabilities(
540 DXGI_GAMMA_CONTROL_CAPABILITIES
*gamma_caps
)
542 memset(gamma_caps
, 0, sizeof(*gamma_caps
));
546 virtual HRESULT STDMETHODCALLTYPE
SetGammaControl(
547 const DXGI_GAMMA_CONTROL
*pArray
)
550 gamma
= new DXGI_GAMMA_CONTROL
;
555 virtual HRESULT STDMETHODCALLTYPE
GetGammaControl(
556 DXGI_GAMMA_CONTROL
*pArray
)
562 pArray
->Scale
.Red
= 1;
563 pArray
->Scale
.Green
= 1;
564 pArray
->Scale
.Blue
= 1;
565 pArray
->Offset
.Red
= 0;
566 pArray
->Offset
.Green
= 0;
567 pArray
->Offset
.Blue
= 0;
568 for(unsigned i
= 0; i
<= 1024; ++i
)
569 pArray
->GammaCurve
[i
].Red
= pArray
->GammaCurve
[i
].Green
= pArray
->GammaCurve
[i
].Blue
= (float)i
/ 1024.0;
574 virtual HRESULT STDMETHODCALLTYPE
SetDisplaySurface(
575 IDXGISurface
*scanout_surface
)
580 virtual HRESULT STDMETHODCALLTYPE
GetDisplaySurfaceData(
581 IDXGISurface
*destination
)
586 virtual HRESULT STDMETHODCALLTYPE
GetFrameStatistics(
587 DXGI_FRAME_STATISTICS
*stats
)
589 memset(stats
, 0, sizeof(*stats
));
591 QueryPerformanceCounter(&stats
->SyncQPCTime
);
597 /* Swap chain are rather complex, and Microsoft's documentation is rather
598 * lacking. As far as I know, this is the most thorough publicly available
599 * description of how swap chains work, based on multiple sources and
602 * There are two modes (called "swap effects") that a swap chain can operate in:
603 * discard and sequential.
605 * In discard mode, things always look as if there is a single buffer, which
606 * you can get with GetBuffers(0).
607 * The 2D texture returned by GetBuffers(0) and can only be
608 * used as a render target view and for resource copies, since no CPU access
609 * flags are set and only the D3D11_BIND_RENDER_TARGET bind flag is set.
610 * On Present, it is copied to the actual display
611 * surface and the contents become undefined.
612 * D3D may internally use multiple buffers, but you can't observe this, except
613 * by looking at the buffer contents after Present (but those are undefined).
614 * If it uses multiple buffers internally, then it will normally use buffer_count buffers
615 * (this has latency implications).
616 * Discard mode seems to internally use a single buffer in windowed mode,
617 * even if DWM is enabled, and buffer_count buffers in fullscreen mode.
619 * In sequential mode, the runtime alllocates buffer_count buffers.
620 * You can get each with GetBuffers(n).
621 * GetBuffers(0) ALWAYS points to the backbuffer to be presented and has the
622 * same usage constraints as the discard mode.
623 * GetBuffer(n) with n > 0 points to resources that are identical to buffer 0, but
624 * are classified as "read-only resources" (due to DXGI_USAGE_READ_ONLY),
625 * meaning that you can't create render target views on them, or use them as
626 * a CopyResource/CopySubresourceRegion destination.
627 * It appears the only valid operation is to use them as a source for CopyResource
628 * and CopySubresourceRegion as well as just waiting for them to become
630 * Buffer n - 1 is always displayed on screen.
631 * When you call Present(), the contents of the buffers are rotated, so that buffer 0
632 * goes to buffer n - 1, and is thus displayed, and buffer 1 goes to buffer 0, becomes
633 * the accessible back buffer.
634 * The resources themselves are NOT rotated, so that you can still render on the
635 * same ID3D11Texture2D*, and views based on it, that you got before Present().
637 * Present seems to happen by either copying the relevant buffer into the window,
638 * or alternatively making it the current one, either by programming the CRTC or
639 * by sending the resource name to the DWM compositor.
641 * Hence, you can call GetBuffer(0) once and keep using the same ID3D11Texture2D*
642 * and ID3D11RenderTargetView* (and other views if needed) you got from it.
644 * If the window gets resized, DXGI will then "emulate" all successive presentations,
645 * by using a stretched blit automatically.
646 * Thus, you should handle WM_SIZE and call ResizeBuffers to update the DXGI
647 * swapchain buffers size to the new window size.
648 * Doing so requires you to release all GetBuffers() results and anything referencing
649 * them, including views and Direct3D11 deferred context command lists (this is
652 * How does Microsoft implement the rotation behavior?
653 * It turns out that it does it by calling RotateResourceIdentitiesDXGI in the user-mode
655 * This will rotate the kernel buffer handle, or possibly rotate the GPU virtual memory
658 * The reason this is done by driver instead of by the runtime appears to be that
659 * this is necessary to support driver-provided command list support, since otherwise
660 * the command list would not always target the current backbuffer, since it would
661 * be done at the driver level, while only the runtime knows about the rotation.
663 * OK, so how do we implement this in Gallium?
665 * There are three strategies:
666 * 1. Use a single buffer, and always copy it to a window system provided buffer, or
667 * just give the buffer to the window system if it supports that
668 * 2. Rotate the buffers in the D3D1x implementation, and recreate and rebind the views.
669 * Don't support driver-provided command lists
670 * 3. Add this rotation functionality to the Gallium driver, with the idea that it would rotate
671 * remap GPU virtual memory, so that virtual address are unchanged, but the physical
672 * ones are rotated (so that pushbuffers remain valid).
673 * If the driver does not support this, either fall back to (1), or have a layer doing this,
674 * putting a deferred context layer over this intermediate layer.
676 * (2) is not acceptable since it prevents an optimal implementation.
677 * (3) is the ideal solution, but it is complicated.
679 * Hence, we implement (1) for now, and will switch to (3) later.
681 * Note that (1) doesn't really work for DXGI_SWAP_EFFECT_SEQUENTIAL with more
682 * than one buffer, so we just pretend we got asked for a single buffer in that case
683 * Fortunately, no one seems to rely on that, so we'll just not implement it at first, and
684 * later perform the rotation with blits.
685 * Once we switch to (3), we'll just use real rotation to do it..
687 * DXGI_SWAP_EFFECT_SEQUENTIAL with more than one buffer is of dubious use
688 * anyway, since you can only render or write to buffer 0, and other buffers can apparently
689 * be used only as sources for copies.
690 * I was unable to find any code using it either in DirectX SDK examples, or on the web.
692 * It seems the only reason you would use it is to not have to redraw from scratch, while
693 * also possibly avoid a copy compared to buffer_count == 1, assuming that your
694 * application is OK with having to redraw starting not from the last frame, but from
695 * one/two/more frames behind it.
697 * A better design would forbid the user specifying buffer_count explicitly, and
698 * would instead let the application give an upper bound on how old the buffer can
699 * become after presentation, with "infinite" being equivalent to discard.
700 * The runtime would then tell the application with frame number the buffer switched to
702 * In addition, in a better design, the application would be allowed to specify the
703 * number of buffers available, having all them usable for rendering, so that things
704 * like video players could efficiently decode frames in parallel.
705 * Present would in such a better design gain a way to specify the number of buffers
708 * Other miscellaneous info:
709 * DXGI_PRESENT_DO_NOT_SEQUENCE causes DXGI to hold the frame for another
710 * vblank interval without rotating the resource data.
713 * "DXGI Overview" in MSDN
714 * IDXGISwapChain documentation on MSDN
715 * "RotateResourceIdentitiesDXGI" on MSDN
716 * http://forums.xna.com/forums/p/42362/266016.aspx
719 static float quad_data
[] = {
737 struct pipe_clip_state clip
;
738 struct pipe_vertex_buffer vbuf
;
739 struct pipe_draw_info draw
;
741 dxgi_blitter(pipe_context
* pipe
)
744 //normalized = !!pipe->screen->get_param(pipe, PIPE_CAP_NPOT_TEXTURES);
745 // TODO: need to update buffer in unnormalized case
748 struct pipe_rasterizer_state rs_state
;
749 memset(&rs_state
, 0, sizeof(rs_state
));
750 rs_state
.cull_face
= PIPE_FACE_NONE
;
751 rs_state
.gl_rasterization_rules
= 1;
752 rs_state
.flatshade
= 1;
753 rasterizer
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
755 struct pipe_blend_state blendd
;
756 memset(&blendd
, 0, sizeof(blendd
));
757 blendd
.rt
[0].colormask
= PIPE_MASK_RGBA
;
758 blend
= pipe
->create_blend_state(pipe
, &blendd
);
760 struct pipe_depth_stencil_alpha_state zsad
;
761 memset(&zsad
, 0, sizeof(zsad
));
762 zsa
= pipe
->create_depth_stencil_alpha_state(pipe
, &zsad
);
764 struct pipe_vertex_element velem
[2];
765 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
766 velem
[0].src_offset
= 0;
767 velem
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
768 velem
[1].src_offset
= 8;
769 velem
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
770 elements
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
772 for(unsigned stretch
= 0; stretch
< 2; ++stretch
)
774 struct pipe_sampler_state sampler_state
;
775 memset(&sampler_state
, 0, sizeof(sampler_state
));
776 sampler_state
.min_img_filter
= stretch
? PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
777 sampler_state
.mag_img_filter
= stretch
? PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
778 sampler_state
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
779 sampler_state
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
780 sampler_state
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
781 sampler_state
.normalized_coords
= normalized
;
783 sampler
[stretch
] = pipe
->create_sampler_state(pipe
, &sampler_state
);
786 fs
= util_make_fragment_tex_shader(pipe
, normalized
? TGSI_TEXTURE_2D
: TGSI_TEXTURE_RECT
, TGSI_INTERPOLATE_LINEAR
);
788 const unsigned semantic_names
[] = { TGSI_SEMANTIC_POSITION
, TGSI_SEMANTIC_GENERIC
};
789 const unsigned semantic_indices
[] = { 0, 0 };
790 vs
= util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
, semantic_indices
);
792 vbuf
.buffer
= pipe_buffer_create(pipe
->screen
, PIPE_BIND_VERTEX_BUFFER
, sizeof(quad_data
));
793 vbuf
.buffer_offset
= 0;
795 vbuf
.stride
= 4 * sizeof(float);
796 pipe_buffer_write(pipe
, vbuf
.buffer
, 0, sizeof(quad_data
), quad_data
);
798 memset(&clip
, 0, sizeof(clip
));
800 memset(&draw
, 0, sizeof(draw
));
801 draw
.mode
= PIPE_PRIM_QUADS
;
803 draw
.instance_count
= 1;
807 void blit(struct pipe_surface
* surf
, struct pipe_sampler_view
* view
, unsigned x
, unsigned y
, unsigned w
, unsigned h
)
809 struct pipe_framebuffer_state fb
;
810 memset(&fb
, 0, sizeof(fb
));
813 fb
.width
= surf
->width
;
814 fb
.height
= surf
->height
;
816 struct pipe_viewport_state viewport
;
817 float half_width
= w
* 0.5f
;
818 float half_height
= h
* 0.5f
;
819 viewport
.scale
[0] = half_width
;
820 viewport
.scale
[1] = half_height
;
821 viewport
.scale
[2] = 1.0f
;
822 viewport
.scale
[3] = 1.0f
;
823 viewport
.translate
[0] = x
+ half_width
;
824 viewport
.translate
[1] = y
+ half_height
;
825 viewport
.translate
[2] = 0.0f
;
826 viewport
.translate
[3] = 1.0f
;
828 bool stretch
= view
->texture
->width0
!= w
|| view
->texture
->height0
!= h
;
829 if(pipe
->render_condition
)
830 pipe
->render_condition(pipe
, 0, 0);
831 pipe
->set_framebuffer_state(pipe
, &fb
);
832 pipe
->bind_fragment_sampler_states(pipe
, 1, &sampler
[stretch
]);
833 pipe
->set_viewport_state(pipe
, &viewport
);
834 pipe
->set_clip_state(pipe
, &clip
);
835 pipe
->bind_rasterizer_state(pipe
, rasterizer
);
836 pipe
->bind_depth_stencil_alpha_state(pipe
, zsa
);
837 pipe
->bind_blend_state(pipe
, blend
);
838 pipe
->bind_vertex_elements_state(pipe
, elements
);
839 pipe
->set_vertex_buffers(pipe
, 1, &vbuf
);
840 pipe
->bind_fs_state(pipe
, fs
);
841 pipe
->bind_vs_state(pipe
, vs
);
842 if(pipe
->bind_gs_state
)
843 pipe
->bind_gs_state(pipe
, 0);
844 if(pipe
->bind_stream_output_state
)
845 pipe
->bind_stream_output_state(pipe
, 0);
846 pipe
->set_fragment_sampler_views(pipe
, 1, &view
);
848 pipe
->draw_vbo(pipe
, &draw
);
853 pipe
->delete_blend_state(pipe
, blend
);
854 pipe
->delete_rasterizer_state(pipe
, rasterizer
);
855 pipe
->delete_depth_stencil_alpha_state(pipe
, zsa
);
856 pipe
->delete_sampler_state(pipe
, sampler
[0]);
857 pipe
->delete_sampler_state(pipe
, sampler
[1]);
858 pipe
->delete_vertex_elements_state(pipe
, elements
);
859 pipe
->delete_vs_state(pipe
, vs
);
860 pipe
->delete_fs_state(pipe
, fs
);
861 pipe
->screen
->resource_destroy(pipe
->screen
, vbuf
.buffer
);
865 struct GalliumDXGISwapChain
: public GalliumDXGIObject
<IDXGISwapChain
, GalliumDXGIFactory
>
867 ComPtr
<IDXGIDevice
>dxgi_device
;
868 ComPtr
<IGalliumDevice
>gallium_device
;
869 ComPtr
<GalliumDXGIAdapter
> adapter
;
870 ComPtr
<IDXGIOutput
> target
;
872 DXGI_SWAP_CHAIN_DESC desc
;
874 struct native_surface
* surface
;
875 const struct native_config
* config
;
878 struct pipe_resource
* resources
[NUM_NATIVE_ATTACHMENTS
];
883 bool needs_validation
;
884 unsigned present_count
;
886 ComPtr
<IDXGISurface
> buffer0
;
887 struct pipe_resource
* gallium_buffer0
;
888 struct pipe_sampler_view
* gallium_buffer0_view
;
890 struct pipe_context
* pipe
;
895 std::auto_ptr
<dxgi_blitter
> blitter
;
896 bool formats_compatible
;
898 GalliumDXGISwapChain(GalliumDXGIFactory
* factory
, IUnknown
* p_device
, const DXGI_SWAP_CHAIN_DESC
& p_desc
)
899 : GalliumDXGIObject
<IDXGISwapChain
, GalliumDXGIFactory
>(factory
), desc(p_desc
), surface(0)
903 hr
= p_device
->QueryInterface(IID_IGalliumDevice
, (void**)&gallium_device
);
907 hr
= p_device
->QueryInterface(IID_IDXGIDevice
, (void**)&dxgi_device
);
911 hr
= dxgi_device
->GetAdapter((IDXGIAdapter
**)&adapter
);
915 memset(resources
, 0, sizeof(resources
));
917 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_SEQUENTIAL
&& desc
.BufferCount
!= 1)
919 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
;
920 // change the returned desc, so that the application might perhaps notice what we did and react well
921 desc
.BufferCount
= 1;
924 pipe
= gallium_device
->GetGalliumContext();
928 pipe
= adapter
->display
->screen
->context_create(adapter
->display
->screen
, 0);
932 blitter
.reset(new dxgi_blitter(pipe
));
935 hr
= resolve_zero_width_height(true);
940 void init_for_window()
944 surface
->destroy(surface
);
949 if(!strcmp(parent
->platform
->name
, "X11"))
951 XWindowAttributes xwa
;
952 XGetWindowAttributes((Display
*)parent
->display
, (Window
)window
, &xwa
);
953 assert(adapter
->configs_by_native_visual_id
.count(xwa
.visual
->visualid
));
954 config_num
= adapter
->configs_by_native_visual_id
[xwa
.visual
->visualid
];
958 enum pipe_format format
= dxgi_to_pipe_format
[desc
.BufferDesc
.Format
];
959 if(!adapter
->configs_by_pipe_format
.count(format
))
961 if(adapter
->configs_by_pipe_format
.empty())
963 // TODO: choose the best match
964 format
= (pipe_format
)adapter
->configs_by_pipe_format
.begin()->first
;
966 // TODO: choose the best config
967 config_num
= adapter
->configs_by_pipe_format
.find(format
)->second
;
970 config
= adapter
->configs
[config_num
];
971 surface
= adapter
->display
->create_window_surface(adapter
->display
, (EGLNativeWindowType
)window
, config
);
972 surface
->user_data
= this;
978 needs_validation
= true;
979 ever_validated
= false;
981 formats_compatible
= util_is_format_compatible(
982 util_format_description(dxgi_to_pipe_format
[desc
.BufferDesc
.Format
]),
983 util_format_description(config
->color_format
));
986 ~GalliumDXGISwapChain()
992 virtual HRESULT STDMETHODCALLTYPE
GetDevice(
996 return dxgi_device
->QueryInterface(riid
, pdevice
);
999 HRESULT
create_buffer0()
1002 ComPtr
<IDXGISurface
> new_buffer0
;
1003 DXGI_USAGE usage
= DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1004 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_DISCARD
)
1005 usage
|= DXGI_USAGE_DISCARD_ON_PRESENT
;
1007 usage
|= DXGI_USAGE_SHADER_INPUT
;
1009 DXGI_SURFACE_DESC surface_desc
;
1010 surface_desc
.Format
= desc
.BufferDesc
.Format
;
1011 surface_desc
.Width
= desc
.BufferDesc
.Width
;
1012 surface_desc
.Height
= desc
.BufferDesc
.Height
;
1013 surface_desc
.SampleDesc
= desc
.SampleDesc
;
1014 hr
= dxgi_device
->CreateSurface(&surface_desc
, 1, usage
, 0, &new_buffer0
);
1018 ComPtr
<IGalliumResource
> gallium_resource
;
1019 hr
= new_buffer0
->QueryInterface(IID_IGalliumResource
, (void**)&gallium_resource
);
1023 struct pipe_resource
* new_gallium_buffer0
= gallium_resource
->GetGalliumResource();
1024 if(!new_gallium_buffer0
)
1027 buffer0
.reset(new_buffer0
.steal());
1028 gallium_buffer0
= new_gallium_buffer0
;
1029 struct pipe_sampler_view templat
;
1030 memset(&templat
, 0, sizeof(templat
));
1031 templat
.texture
= gallium_buffer0
;
1032 templat
.swizzle_r
= 0;
1033 templat
.swizzle_g
= 1;
1034 templat
.swizzle_b
= 2;
1035 templat
.swizzle_a
= 3;
1036 templat
.format
= gallium_buffer0
->format
;
1037 gallium_buffer0_view
= pipe
->create_sampler_view(pipe
, gallium_buffer0
, &templat
);
1043 unsigned new_seq_num
;
1044 needs_validation
= false;
1046 if(!surface
->validate(surface
, (1 << NATIVE_ATTACHMENT_BACK_LEFT
) | (1 << NATIVE_ATTACHMENT_FRONT_LEFT
), &new_seq_num
, resources
, &width
, &height
))
1049 if(!ever_validated
|| seq_num
!= new_seq_num
)
1051 seq_num
= new_seq_num
;
1052 ever_validated
= true;
1057 HRESULT
resolve_zero_width_height(bool force
= false)
1059 if(!force
&& desc
.BufferDesc
.Width
&& desc
.BufferDesc
.Height
)
1062 unsigned width
, height
;
1063 HRESULT hr
= parent
->backend
->GetPresentSize(desc
.OutputWindow
, &width
, &height
);
1067 // On Windows, 8 is used, and a debug message saying so gets printed
1073 if(!desc
.BufferDesc
.Width
)
1074 desc
.BufferDesc
.Width
= width
;
1075 if(!desc
.BufferDesc
.Height
)
1076 desc
.BufferDesc
.Height
= height
;
1080 virtual HRESULT STDMETHODCALLTYPE
Present(
1085 if(flags
& DXGI_PRESENT_TEST
)
1086 return parent
->backend
->TestPresent(desc
.OutputWindow
);
1090 HRESULT hr
= create_buffer0();
1095 void* cur_window
= 0;
1098 BOOL preserve_aspect_ratio
;
1099 unsigned dst_w
, dst_h
;
1101 struct pipe_resource
* dst
;
1102 struct pipe_resource
* src
;
1103 struct pipe_surface
* dst_surface
;
1105 void* present_cookie
;
1106 hr
= parent
->backend
->BeginPresent(desc
.OutputWindow
, &present_cookie
, &cur_window
, &rect
, &rgndata
, &preserve_aspect_ratio
);
1110 if(!cur_window
|| rect
.left
>= rect
.right
|| rect
.top
>= rect
.bottom
)
1113 if(cur_window
!= window
)
1115 window
= cur_window
;
1119 if(needs_validation
)
1122 return DXGI_ERROR_DEVICE_REMOVED
;
1125 db
= !!(config
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
));
1126 dst
= resources
[db
? NATIVE_ATTACHMENT_BACK_LEFT
: NATIVE_ATTACHMENT_FRONT_LEFT
];
1127 src
= gallium_buffer0
;
1133 /* TODO: sharing the context for blitting won't work correctly if queries are active
1134 * Hopefully no one is crazy enough to keep queries active while presenting, expecting
1136 * We could alternatively force using another context, but that might cause inefficiency issues
1139 if((unsigned)rect
.right
> dst
->width0
)
1140 rect
.right
= dst
->width0
;
1141 if((unsigned)rect
.bottom
> dst
->height0
)
1142 rect
.bottom
= dst
->height0
;
1143 if(rect
.left
> rect
.right
)
1144 rect
.left
= rect
.right
;
1145 if(rect
.top
> rect
.bottom
)
1146 rect
.top
= rect
.bottom
;
1148 if(rect
.left
>= rect
.right
&& rect
.top
>= rect
.bottom
)
1151 dst_w
= rect
.right
- rect
.left
;
1152 dst_h
= rect
.bottom
- rect
.top
;
1154 // TODO: add support for rgndata
1155 // if(preserve_aspect_ratio || !rgndata)
1158 unsigned blit_x
, blit_y
, blit_w
, blit_h
;
1159 float black
[4] = {0, 0, 0, 0};
1161 if(!formats_compatible
|| src
->width0
!= dst_w
|| src
->height0
!= dst_h
)
1162 dst_surface
= pipe
->screen
->get_tex_surface(pipe
->screen
, dst
, 0, 0, 0, PIPE_BIND_RENDER_TARGET
);
1164 if(preserve_aspect_ratio
)
1166 int delta
= src
->width0
* dst_h
- dst_w
* src
->height0
;
1170 blit_h
= dst_w
* src
->height0
/ src
->width0
;
1174 blit_w
= dst_h
* src
->width0
/ src
->height0
;
1183 blit_x
= (dst_w
- blit_w
) >> 1;
1184 blit_y
= (dst_h
- blit_h
) >> 1;
1195 pipe
->clear_render_target(pipe
, dst_surface
, black
, rect
.left
, rect
.top
, blit_x
, dst_h
);
1197 pipe
->clear_render_target(pipe
, dst_surface
, black
, rect
.left
, rect
.top
, dst_w
, blit_y
);
1199 if(formats_compatible
&& blit_w
== src
->width0
&& blit_h
== src
->height0
)
1201 pipe_subresource sr
;
1204 pipe
->resource_copy_region(pipe
, dst
, sr
, rect
.left
, rect
.top
, 0, src
, sr
, 0, 0, 0, blit_w
, blit_h
);
1208 blitter
->blit(dst_surface
, gallium_buffer0_view
, rect
.left
+ blit_x
, rect
.top
+ blit_y
, blit_w
, blit_h
);
1210 gallium_device
->RestoreGalliumState();
1214 pipe
->clear_render_target(pipe
, dst_surface
, black
, rect
.left
+ blit_x
+ blit_w
, rect
.top
, dst_w
- blit_x
- blit_w
, dst_h
);
1216 pipe
->clear_render_target(pipe
, dst_surface
, black
, rect
.left
, rect
.top
+ blit_y
+ blit_h
, dst_w
, dst_h
- blit_y
- blit_h
);
1220 pipe
->screen
->tex_surface_destroy(dst_surface
);
1222 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_FRAME
, 0);
1226 if(!surface
->swap_buffers(surface
))
1227 return DXGI_ERROR_DEVICE_REMOVED
;
1231 if(!surface
->flush_frontbuffer(surface
))
1232 return DXGI_ERROR_DEVICE_REMOVED
;
1236 parent
->backend
->EndPresent(desc
.OutputWindow
, present_cookie
);
1242 virtual HRESULT STDMETHODCALLTYPE
GetBuffer(
1249 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_SEQUENTIAL
)
1250 std::cerr
<< "DXGI unimplemented: GetBuffer(n) with n > 0 not supported, returning buffer 0 instead!" << std::endl
;
1252 std::cerr
<< "DXGI error: in GetBuffer(n), n must be 0 for DXGI_SWAP_EFFECT_DISCARD\n" << std::endl
;
1257 HRESULT hr
= create_buffer0();
1261 return buffer0
->QueryInterface(riid
, ppSurface
);
1264 /* TODO: implement somehow */
1265 virtual HRESULT STDMETHODCALLTYPE
SetFullscreenState(
1267 IDXGIOutput
*target
)
1269 fullscreen
= fullscreen
;
1274 virtual HRESULT STDMETHODCALLTYPE
GetFullscreenState(
1275 BOOL
*out_fullscreen
,
1276 IDXGIOutput
**out_target
)
1279 *out_fullscreen
= fullscreen
;
1281 *out_target
= target
.ref();
1285 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
1286 DXGI_SWAP_CHAIN_DESC
*out_desc
)
1292 virtual HRESULT STDMETHODCALLTYPE
ResizeBuffers(
1296 DXGI_FORMAT new_format
,
1297 UINT swap_chain_flags
)
1301 buffer0
.p
->AddRef();
1302 ULONG v
= buffer0
.p
->Release();
1303 // we must fail if there are any references to buffer0 other than ours
1306 pipe_sampler_view_reference(&gallium_buffer0_view
, 0);
1307 buffer0
= (IUnknown
*)NULL
;
1308 gallium_buffer0
= 0;
1311 if(desc
.SwapEffect
!= DXGI_SWAP_EFFECT_SEQUENTIAL
)
1312 desc
.BufferCount
= buffer_count
;
1313 desc
.BufferDesc
.Format
= new_format
;
1314 desc
.BufferDesc
.Width
= width
;
1315 desc
.BufferDesc
.Height
= height
;
1316 desc
.Flags
= swap_chain_flags
;
1317 return resolve_zero_width_height();
1320 virtual HRESULT STDMETHODCALLTYPE
ResizeTarget(
1321 const DXGI_MODE_DESC
*out_new_target_parameters
)
1323 /* TODO: implement */
1327 virtual HRESULT STDMETHODCALLTYPE
GetContainingOutput(
1328 IDXGIOutput
**out_output
)
1330 *out_output
= adapter
->outputs
[0].ref();
1334 virtual HRESULT STDMETHODCALLTYPE
GetFrameStatistics(
1335 DXGI_FRAME_STATISTICS
*out_stats
)
1337 memset(out_stats
, 0, sizeof(*out_stats
));
1339 QueryPerformanceCounter(&out_stats
->SyncQPCTime
);
1341 out_stats
->PresentCount
= present_count
;
1342 out_stats
->PresentRefreshCount
= present_count
;
1343 out_stats
->SyncRefreshCount
= present_count
;
1347 virtual HRESULT STDMETHODCALLTYPE
GetLastPresentCount(
1348 UINT
*last_present_count
)
1350 *last_present_count
= present_count
;
1355 static void GalliumDXGISwapChainRevalidate(IDXGISwapChain
* swap_chain
)
1357 ((GalliumDXGISwapChain
*)swap_chain
)->needs_validation
= true;
1360 static HRESULT
GalliumDXGIAdapterCreate(GalliumDXGIFactory
* factory
, const struct native_platform
* platform
, void* dpy
, IDXGIAdapter1
** out_adapter
)
1364 *out_adapter
= new GalliumDXGIAdapter(factory
, platform
, dpy
);
1373 static HRESULT
GalliumDXGIOutputCreate(GalliumDXGIAdapter
* adapter
, const std::string
& name
, const struct native_connector
* connector
, IDXGIOutput
** out_output
)
1377 *out_output
= new GalliumDXGIOutput(adapter
, name
, connector
);
1386 static HRESULT
GalliumDXGISwapChainCreate(GalliumDXGIFactory
* factory
, IUnknown
* device
, const DXGI_SWAP_CHAIN_DESC
& desc
, IDXGISwapChain
** out_swap_chain
)
1390 *out_swap_chain
= new GalliumDXGISwapChain(factory
, device
, desc
);
1401 const struct native_platform
* platform
;
1403 IGalliumDXGIBackend
* backend
;
1406 static dxgi_binding dxgi_default_binding
;
1407 static __thread dxgi_binding dxgi_thread_binding
;
1409 void STDMETHODCALLTYPE
GalliumDXGIUseNothing()
1411 dxgi_thread_binding
.platform
= 0;
1412 dxgi_thread_binding
.display
= 0;
1413 if(dxgi_thread_binding
.backend
)
1414 dxgi_thread_binding
.backend
->Release();
1415 dxgi_thread_binding
.backend
= 0;
1418 #ifdef GALLIUM_DXGI_USE_X11
1419 void STDMETHODCALLTYPE
GalliumDXGIUseX11Display(Display
* dpy
, IGalliumDXGIBackend
* backend
)
1421 GalliumDXGIUseNothing();
1422 dxgi_thread_binding
.platform
= native_get_x11_platform();
1423 dxgi_thread_binding
.display
= dpy
;
1427 dxgi_thread_binding
.backend
= backend
;
1434 #ifdef GALLIUM_DXGI_USE_DRM
1435 void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd)
1437 GalliumDXGIUseNothing();
1438 dxgi_thread_binding.platform = native_get_drm_platform();
1439 dxgi_thread_binding.display = (void*)fd;
1440 dxgi_thread_binding.backend = 0;
1444 #ifdef GALLIUM_DXGI_USE_FBDEV
1445 void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd)
1447 GalliumDXGIUseNothing();
1448 dxgi_thread_binding.platform = native_get_fbdev_platform();
1449 dxgi_thread_binding.display = (void*)fd;
1450 dxgi_thread_binding.backend = 0;
1454 #ifdef GALLIUM_DXGI_USE_GDI
1455 void STDMETHODCALLTYPE GalliumDXGIUseHDC(HDC hdc, PFNHWNDRESOLVER resolver, void* resolver_cookie)
1457 GalliumDXGIUseNothing();
1458 dxgi_thread_binding.platform = native_get_gdi_platform();
1459 dxgi_thread_binding.display = (void*)hdc;
1460 dxgi_thread_binding.backend = 0;
1464 void STDMETHODCALLTYPE
GalliumDXGIMakeDefault()
1466 if(dxgi_default_binding
.backend
)
1467 dxgi_default_binding
.backend
->Release();
1468 dxgi_default_binding
= dxgi_thread_binding
;
1469 if(dxgi_default_binding
.backend
)
1470 dxgi_default_binding
.backend
->AddRef();
1473 /* TODO: why did Microsoft add this? should we do something different for DXGI 1.0 and 1.1?
1474 * Or perhaps what they actually mean is "only create a single factory in your application"?
1475 * TODO: should we use a singleton here, so we never have multiple DXGI objects for the same thing? */
1476 HRESULT STDMETHODCALLTYPE
CreateDXGIFactory1(
1481 GalliumDXGIFactory
* factory
;
1483 if(dxgi_thread_binding
.platform
)
1484 factory
= new GalliumDXGIFactory(dxgi_thread_binding
.platform
, dxgi_thread_binding
.display
, dxgi_thread_binding
.backend
);
1485 else if(dxgi_default_binding
.platform
)
1486 factory
= new GalliumDXGIFactory(dxgi_default_binding
.platform
, dxgi_default_binding
.display
, dxgi_default_binding
.backend
);
1488 factory
= new GalliumDXGIFactory(native_get_x11_platform(), NULL
, NULL
);
1489 HRESULT hres
= factory
->QueryInterface(riid
, out_factory
);
1494 HRESULT STDMETHODCALLTYPE
CreateDXGIFactory(
1499 return CreateDXGIFactory1(riid
, out_factor
);