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
;
254 GalliumDXGIAdapter(GalliumDXGIFactory
* factory
, const struct native_platform
* platform
, void* dpy
)
256 this->parent
= factory
;
258 display
= platform
->create_display(dpy
, FALSE
);
260 display
= platform
->create_display(dpy
, TRUE
);
262 display
->user_data
= this;
263 if (!display
->init_screen(display
)) {
264 display
->destroy(display
);
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
);
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
];
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;
282 // TODO: we should actually use an unique ID instead
283 *(void**)&desc
.AdapterLuid
= dpy
;
285 configs
= display
->get_configs(display
, (int*)&num_configs
);
286 for(unsigned i
= 0; i
< num_configs
; ++i
)
288 if(configs
[i
]->window_bit
)
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
;
302 connectors
= display
->modeset
->get_connectors(display
, &num_outputs
, &num_crtcs
);
305 else if(!num_outputs
)
315 static void handle_invalid_surface(struct native_display
*ndpy
, struct native_surface
*nsurf
, unsigned int seq_num
)
317 GalliumDXGISwapChainRevalidate((IDXGISwapChain
*)nsurf
->user_data
);
320 ~GalliumDXGIAdapter()
322 display
->destroy(display
);
327 virtual HRESULT STDMETHODCALLTYPE
EnumOutputs(
329 IDXGIOutput
**out_output
)
331 if(output
>= (unsigned)num_outputs
)
332 return DXGI_ERROR_NOT_FOUND
;
336 std::ostringstream ss
;
337 ss
<< "output #" << output
;
338 return GalliumDXGIOutputCreate(this, ss
.str(), connectors
[output
], out_output
);
341 return GalliumDXGIOutputCreate(this, "Unique output", NULL
, out_output
);
344 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
345 DXGI_ADAPTER_DESC
*desc
)
347 memcpy(desc
, &desc
, sizeof(*desc
));
351 virtual HRESULT STDMETHODCALLTYPE
GetDesc1(
352 DXGI_ADAPTER_DESC1
*desc
)
354 memcpy(desc
, &desc
, sizeof(*desc
));
358 virtual HRESULT STDMETHODCALLTYPE
CheckInterfaceSupport(
359 REFGUID interface_name
,
360 LARGE_INTEGER
*u_m_d_version
)
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
)
365 u_m_d_version
->QuadPart
= 0x00080011000a0411ULL
;
368 return DXGI_ERROR_UNSUPPORTED
;
371 pipe_screen
* STDMETHODCALLTYPE
GetGalliumScreen()
373 return display
->screen
;
376 pipe_screen
* STDMETHODCALLTYPE
GetGalliumReferenceSoftwareScreen()
378 // TODO: give a softpipe screen
379 return display
->screen
;
382 pipe_screen
* STDMETHODCALLTYPE
GetGalliumFastSoftwareScreen()
384 // TODO: give an llvmpipe screen
385 return display
->screen
;
390 struct GalliumDXGIOutput
: public GalliumDXGIObject
<IDXGIOutput
, GalliumDXGIAdapter
>
392 DXGI_OUTPUT_DESC desc
;
393 const struct native_mode
** modes
;
394 DXGI_MODE_DESC
* dxgi_modes
;
396 const struct native_connector
* connector
;
397 DXGI_GAMMA_CONTROL
* gamma
;
399 GalliumDXGIOutput(GalliumDXGIAdapter
* adapter
, std::string name
, const struct native_connector
* connector
= 0)
400 : GalliumDXGIObject
<IDXGIOutput
, GalliumDXGIAdapter
>(adapter
), connector(connector
)
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 */
413 modes
= parent
->display
->modeset
->get_modes(parent
->display
, connector
, (int*)&num_modes
);
414 if(modes
&& num_modes
)
416 dxgi_modes
= new DXGI_MODE_DESC
[num_modes
];
417 for(unsigned i
= 0; i
< num_modes
; ++i
)
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
;
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
;
452 delete [] dxgi_modes
;
458 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
459 DXGI_OUTPUT_DESC
*out_desc
)
465 virtual HRESULT STDMETHODCALLTYPE
GetDisplayModeList(
466 DXGI_FORMAT enum_format
,
469 DXGI_MODE_DESC
*desc
)
471 /* TODO: should we return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE when we don't
472 * support modesetting instead of fake modes?
474 pipe_format format
= dxgi_to_pipe_format
[enum_format
];
475 if(parent
->configs_by_pipe_format
.count(format
))
483 unsigned copy_modes
= std::min(num_modes
, *pcount
);
484 for(unsigned i
= 0; i
< copy_modes
; ++i
)
486 desc
[i
] = dxgi_modes
[i
];
487 desc
[i
].Format
= enum_format
;
491 if(copy_modes
< num_modes
)
492 return DXGI_ERROR_MORE_DATA
;
503 virtual HRESULT STDMETHODCALLTYPE
FindClosestMatchingMode(
504 const DXGI_MODE_DESC
*pModeToMatch
,
505 DXGI_MODE_DESC
*closest_match
,
506 IUnknown
*concerned_device
)
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
))
514 if(!concerned_device
)
518 format
= parent
->configs
[0]->color_format
;
519 dxgi_format
= pipe_to_dxgi_format
[format
];
523 *closest_match
= dxgi_modes
[0];
524 closest_match
->Format
= dxgi_format
;
528 virtual HRESULT STDMETHODCALLTYPE
WaitForVBlank( void)
533 virtual HRESULT STDMETHODCALLTYPE
TakeOwnership(
540 virtual void STDMETHODCALLTYPE
ReleaseOwnership( void)
544 virtual HRESULT STDMETHODCALLTYPE
GetGammaControlCapabilities(
545 DXGI_GAMMA_CONTROL_CAPABILITIES
*gamma_caps
)
547 memset(gamma_caps
, 0, sizeof(*gamma_caps
));
551 virtual HRESULT STDMETHODCALLTYPE
SetGammaControl(
552 const DXGI_GAMMA_CONTROL
*pArray
)
555 gamma
= new DXGI_GAMMA_CONTROL
;
560 virtual HRESULT STDMETHODCALLTYPE
GetGammaControl(
561 DXGI_GAMMA_CONTROL
*pArray
)
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;
579 virtual HRESULT STDMETHODCALLTYPE
SetDisplaySurface(
580 IDXGISurface
*scanout_surface
)
585 virtual HRESULT STDMETHODCALLTYPE
GetDisplaySurfaceData(
586 IDXGISurface
*destination
)
591 virtual HRESULT STDMETHODCALLTYPE
GetFrameStatistics(
592 DXGI_FRAME_STATISTICS
*stats
)
594 memset(stats
, 0, sizeof(*stats
));
596 QueryPerformanceCounter(&stats
->SyncQPCTime
);
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
607 * There are two modes (called "swap effects") that a swap chain can operate in:
608 * discard and sequential.
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.
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
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().
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.
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.
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
657 * How does Microsoft implement the rotation behavior?
658 * It turns out that it does it by calling RotateResourceIdentitiesDXGI in the user-mode
660 * This will rotate the kernel buffer handle, or possibly rotate the GPU virtual memory
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.
668 * OK, so how do we implement this in Gallium?
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.
681 * (2) is not acceptable since it prevents an optimal implementation.
682 * (3) is the ideal solution, but it is complicated.
684 * Hence, we implement (1) for now, and will switch to (3) later.
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..
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.
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.
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
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
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.
718 * "DXGI Overview" in MSDN
719 * IDXGISwapChain documentation on MSDN
720 * "RotateResourceIdentitiesDXGI" on MSDN
721 * http://forums.xna.com/forums/p/42362/266016.aspx
724 static float quad_data
[] = {
742 struct pipe_clip_state clip
;
743 struct pipe_vertex_buffer vbuf
;
744 struct pipe_draw_info draw
;
746 dxgi_blitter(pipe_context
* pipe
)
749 //normalized = !!pipe->screen->get_param(pipe, PIPE_CAP_NPOT_TEXTURES);
750 // TODO: need to update buffer in unnormalized case
753 struct pipe_rasterizer_state rs_state
;
754 memset(&rs_state
, 0, sizeof(rs_state
));
755 rs_state
.cull_face
= PIPE_FACE_NONE
;
756 rs_state
.gl_rasterization_rules
= 1;
757 rs_state
.depth_clip
= 1;
758 rs_state
.flatshade
= 1;
759 rasterizer
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
761 struct pipe_blend_state blendd
;
762 memset(&blendd
, 0, sizeof(blendd
));
763 blendd
.rt
[0].colormask
= PIPE_MASK_RGBA
;
764 blend
= pipe
->create_blend_state(pipe
, &blendd
);
766 struct pipe_depth_stencil_alpha_state zsad
;
767 memset(&zsad
, 0, sizeof(zsad
));
768 zsa
= pipe
->create_depth_stencil_alpha_state(pipe
, &zsad
);
770 struct pipe_vertex_element velem
[2];
771 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
772 velem
[0].src_offset
= 0;
773 velem
[0].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
774 velem
[1].src_offset
= 8;
775 velem
[1].src_format
= PIPE_FORMAT_R32G32_FLOAT
;
776 elements
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
778 for(unsigned stretch
= 0; stretch
< 2; ++stretch
)
780 struct pipe_sampler_state sampler_state
;
781 memset(&sampler_state
, 0, sizeof(sampler_state
));
782 sampler_state
.min_img_filter
= stretch
? PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
783 sampler_state
.mag_img_filter
= stretch
? PIPE_TEX_FILTER_LINEAR
: PIPE_TEX_FILTER_NEAREST
;
784 sampler_state
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
785 sampler_state
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
786 sampler_state
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
787 sampler_state
.normalized_coords
= normalized
;
789 sampler
[stretch
] = pipe
->create_sampler_state(pipe
, &sampler_state
);
792 fs
= util_make_fragment_tex_shader(pipe
, normalized
? TGSI_TEXTURE_2D
: TGSI_TEXTURE_RECT
, TGSI_INTERPOLATE_LINEAR
);
794 const unsigned semantic_names
[] = { TGSI_SEMANTIC_POSITION
, TGSI_SEMANTIC_GENERIC
};
795 const unsigned semantic_indices
[] = { 0, 0 };
796 vs
= util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
, semantic_indices
);
798 vbuf
.buffer
= pipe_buffer_create(pipe
->screen
, PIPE_BIND_VERTEX_BUFFER
,
799 PIPE_USAGE_STREAM
, sizeof(quad_data
));
800 vbuf
.buffer_offset
= 0;
801 vbuf
.stride
= 4 * sizeof(float);
802 pipe_buffer_write(pipe
, vbuf
.buffer
, 0, sizeof(quad_data
), quad_data
);
804 memset(&clip
, 0, sizeof(clip
));
806 memset(&draw
, 0, sizeof(draw
));
807 draw
.mode
= PIPE_PRIM_QUADS
;
809 draw
.instance_count
= 1;
813 void blit(struct pipe_surface
* surf
, struct pipe_sampler_view
* view
, unsigned x
, unsigned y
, unsigned w
, unsigned h
)
815 struct pipe_framebuffer_state fb
;
816 memset(&fb
, 0, sizeof(fb
));
819 fb
.width
= surf
->width
;
820 fb
.height
= surf
->height
;
822 struct pipe_viewport_state viewport
;
823 float half_width
= w
* 0.5f
;
824 float half_height
= h
* 0.5f
;
825 viewport
.scale
[0] = half_width
;
826 viewport
.scale
[1] = half_height
;
827 viewport
.scale
[2] = 1.0f
;
828 viewport
.scale
[3] = 1.0f
;
829 viewport
.translate
[0] = x
+ half_width
;
830 viewport
.translate
[1] = y
+ half_height
;
831 viewport
.translate
[2] = 0.0f
;
832 viewport
.translate
[3] = 1.0f
;
834 bool stretch
= view
->texture
->width0
!= w
|| view
->texture
->height0
!= h
;
835 if(pipe
->render_condition
)
836 pipe
->render_condition(pipe
, 0, 0);
837 pipe
->set_framebuffer_state(pipe
, &fb
);
838 pipe
->bind_fragment_sampler_states(pipe
, 1, &sampler
[stretch
]);
839 pipe
->set_viewport_state(pipe
, &viewport
);
840 pipe
->set_clip_state(pipe
, &clip
);
841 pipe
->bind_rasterizer_state(pipe
, rasterizer
);
842 pipe
->bind_depth_stencil_alpha_state(pipe
, zsa
);
843 pipe
->bind_blend_state(pipe
, blend
);
844 pipe
->bind_vertex_elements_state(pipe
, elements
);
845 pipe
->set_vertex_buffers(pipe
, 0, 1, &vbuf
);
846 pipe
->bind_fs_state(pipe
, fs
);
847 pipe
->bind_vs_state(pipe
, vs
);
848 if(pipe
->bind_gs_state
)
849 pipe
->bind_gs_state(pipe
, 0);
850 if(pipe
->set_stream_output_targets
)
851 pipe
->set_stream_output_targets(pipe
, 0, NULL
, 0);
852 pipe
->set_fragment_sampler_views(pipe
, 1, &view
);
854 pipe
->draw_vbo(pipe
, &draw
);
859 pipe
->delete_blend_state(pipe
, blend
);
860 pipe
->delete_rasterizer_state(pipe
, rasterizer
);
861 pipe
->delete_depth_stencil_alpha_state(pipe
, zsa
);
862 pipe
->delete_sampler_state(pipe
, sampler
[0]);
863 pipe
->delete_sampler_state(pipe
, sampler
[1]);
864 pipe
->delete_vertex_elements_state(pipe
, elements
);
865 pipe
->delete_vs_state(pipe
, vs
);
866 pipe
->delete_fs_state(pipe
, fs
);
867 pipe
->screen
->resource_destroy(pipe
->screen
, vbuf
.buffer
);
871 struct GalliumDXGISwapChain
: public GalliumDXGIObject
<IDXGISwapChain
, GalliumDXGIFactory
>
873 ComPtr
<IDXGIDevice
>dxgi_device
;
874 ComPtr
<IGalliumDevice
>gallium_device
;
875 ComPtr
<GalliumDXGIAdapter
> adapter
;
876 ComPtr
<IDXGIOutput
> target
;
878 DXGI_SWAP_CHAIN_DESC desc
;
880 struct native_surface
* surface
;
881 const struct native_config
* config
;
884 struct pipe_resource
* resources
[NUM_NATIVE_ATTACHMENTS
];
889 bool needs_validation
;
890 unsigned present_count
;
892 ComPtr
<IDXGISurface
> buffer0
;
893 struct pipe_resource
* gallium_buffer0
;
894 struct pipe_sampler_view
* gallium_buffer0_view
;
896 struct pipe_context
* pipe
;
901 std::auto_ptr
<dxgi_blitter
> blitter
;
902 bool formats_compatible
;
904 GalliumDXGISwapChain(GalliumDXGIFactory
* factory
, IUnknown
* p_device
, const DXGI_SWAP_CHAIN_DESC
& p_desc
)
905 : GalliumDXGIObject
<IDXGISwapChain
, GalliumDXGIFactory
>(factory
), desc(p_desc
), surface(0)
909 hr
= p_device
->QueryInterface(IID_IGalliumDevice
, (void**)&gallium_device
);
913 hr
= p_device
->QueryInterface(IID_IDXGIDevice
, (void**)&dxgi_device
);
917 hr
= dxgi_device
->GetAdapter((IDXGIAdapter
**)&adapter
);
921 memset(resources
, 0, sizeof(resources
));
923 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_SEQUENTIAL
&& desc
.BufferCount
!= 1)
925 std::cerr
<< "Gallium DXGI: if DXGI_SWAP_EFFECT_SEQUENTIAL is specified, only buffer_count == 1 is implemented, but " << desc
.BufferCount
<< " was specified: ignoring this" << std::endl
;
926 // change the returned desc, so that the application might perhaps notice what we did and react well
927 desc
.BufferCount
= 1;
930 pipe
= gallium_device
->GetGalliumContext();
934 pipe
= adapter
->display
->screen
->context_create(adapter
->display
->screen
, 0);
938 blitter
.reset(new dxgi_blitter(pipe
));
941 hr
= resolve_zero_width_height(true);
946 void init_for_window()
950 surface
->destroy(surface
);
955 if(!strcmp(parent
->platform
->name
, "X11"))
957 XWindowAttributes xwa
;
958 XGetWindowAttributes((Display
*)parent
->display
, (Window
)window
, &xwa
);
959 assert(adapter
->configs_by_native_visual_id
.count(xwa
.visual
->visualid
));
960 config_num
= adapter
->configs_by_native_visual_id
[xwa
.visual
->visualid
];
964 enum pipe_format format
= dxgi_to_pipe_format
[desc
.BufferDesc
.Format
];
965 if(!adapter
->configs_by_pipe_format
.count(format
))
967 if(adapter
->configs_by_pipe_format
.empty())
969 // TODO: choose the best match
970 format
= (pipe_format
)adapter
->configs_by_pipe_format
.begin()->first
;
972 // TODO: choose the best config
973 config_num
= adapter
->configs_by_pipe_format
.find(format
)->second
;
976 config
= adapter
->configs
[config_num
];
977 surface
= adapter
->display
->create_window_surface(adapter
->display
, (EGLNativeWindowType
)window
, config
);
978 surface
->user_data
= this;
984 needs_validation
= true;
985 ever_validated
= false;
987 formats_compatible
= util_is_format_compatible(
988 util_format_description(dxgi_to_pipe_format
[desc
.BufferDesc
.Format
]),
989 util_format_description(config
->color_format
));
992 ~GalliumDXGISwapChain()
998 virtual HRESULT STDMETHODCALLTYPE
GetDevice(
1002 return dxgi_device
->QueryInterface(riid
, pdevice
);
1005 HRESULT
create_buffer0()
1008 ComPtr
<IDXGISurface
> new_buffer0
;
1009 DXGI_USAGE usage
= DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1010 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_DISCARD
)
1011 usage
|= DXGI_USAGE_DISCARD_ON_PRESENT
;
1013 usage
|= DXGI_USAGE_SHADER_INPUT
;
1015 DXGI_SURFACE_DESC surface_desc
;
1016 surface_desc
.Format
= desc
.BufferDesc
.Format
;
1017 surface_desc
.Width
= desc
.BufferDesc
.Width
;
1018 surface_desc
.Height
= desc
.BufferDesc
.Height
;
1019 surface_desc
.SampleDesc
= desc
.SampleDesc
;
1020 hr
= dxgi_device
->CreateSurface(&surface_desc
, 1, usage
, 0, &new_buffer0
);
1024 ComPtr
<IGalliumResource
> gallium_resource
;
1025 hr
= new_buffer0
->QueryInterface(IID_IGalliumResource
, (void**)&gallium_resource
);
1029 struct pipe_resource
* new_gallium_buffer0
= gallium_resource
->GetGalliumResource();
1030 if(!new_gallium_buffer0
)
1033 buffer0
.reset(new_buffer0
.steal());
1034 gallium_buffer0
= new_gallium_buffer0
;
1035 struct pipe_sampler_view templat
;
1036 memset(&templat
, 0, sizeof(templat
));
1037 templat
.texture
= gallium_buffer0
;
1038 templat
.swizzle_r
= 0;
1039 templat
.swizzle_g
= 1;
1040 templat
.swizzle_b
= 2;
1041 templat
.swizzle_a
= 3;
1042 templat
.format
= gallium_buffer0
->format
;
1043 gallium_buffer0_view
= pipe
->create_sampler_view(pipe
, gallium_buffer0
, &templat
);
1049 unsigned new_seq_num
;
1050 needs_validation
= false;
1052 if(!surface
->validate(surface
, (1 << NATIVE_ATTACHMENT_BACK_LEFT
) | (1 << NATIVE_ATTACHMENT_FRONT_LEFT
), &new_seq_num
, resources
, &width
, &height
))
1055 if(!ever_validated
|| seq_num
!= new_seq_num
)
1057 seq_num
= new_seq_num
;
1058 ever_validated
= true;
1063 HRESULT
resolve_zero_width_height(bool force
= false)
1065 if(!force
&& desc
.BufferDesc
.Width
&& desc
.BufferDesc
.Height
)
1068 unsigned width
, height
;
1069 HRESULT hr
= parent
->backend
->GetPresentSize(desc
.OutputWindow
, &width
, &height
);
1073 // On Windows, 8 is used, and a debug message saying so gets printed
1079 if(!desc
.BufferDesc
.Width
)
1080 desc
.BufferDesc
.Width
= width
;
1081 if(!desc
.BufferDesc
.Height
)
1082 desc
.BufferDesc
.Height
= height
;
1086 virtual HRESULT STDMETHODCALLTYPE
Present(
1091 if(flags
& DXGI_PRESENT_TEST
)
1092 return parent
->backend
->TestPresent(desc
.OutputWindow
);
1096 HRESULT hr
= create_buffer0();
1101 void* cur_window
= 0;
1104 BOOL preserve_aspect_ratio
;
1105 unsigned dst_w
, dst_h
;
1107 struct pipe_resource
* dst
;
1108 struct pipe_resource
* src
;
1109 struct pipe_surface
* dst_surface
;
1110 struct native_present_control ctrl
;
1112 void* present_cookie
;
1113 hr
= parent
->backend
->BeginPresent(desc
.OutputWindow
, &present_cookie
, &cur_window
, &rect
, &rgndata
, &preserve_aspect_ratio
);
1117 if(!cur_window
|| rect
.left
>= rect
.right
|| rect
.top
>= rect
.bottom
)
1120 if(cur_window
!= window
)
1122 window
= cur_window
;
1126 if(needs_validation
)
1129 return DXGI_ERROR_DEVICE_REMOVED
;
1132 db
= !!(config
->buffer_mask
& (1 << NATIVE_ATTACHMENT_BACK_LEFT
));
1133 dst
= resources
[db
? NATIVE_ATTACHMENT_BACK_LEFT
: NATIVE_ATTACHMENT_FRONT_LEFT
];
1134 src
= gallium_buffer0
;
1140 /* TODO: sharing the context for blitting won't work correctly if queries are active
1141 * Hopefully no one is crazy enough to keep queries active while presenting, expecting
1143 * We could alternatively force using another context, but that might cause inefficiency issues
1146 if((unsigned)rect
.right
> dst
->width0
)
1147 rect
.right
= dst
->width0
;
1148 if((unsigned)rect
.bottom
> dst
->height0
)
1149 rect
.bottom
= dst
->height0
;
1150 if(rect
.left
> rect
.right
)
1151 rect
.left
= rect
.right
;
1152 if(rect
.top
> rect
.bottom
)
1153 rect
.top
= rect
.bottom
;
1155 if(rect
.left
>= rect
.right
&& rect
.top
>= rect
.bottom
)
1158 dst_w
= rect
.right
- rect
.left
;
1159 dst_h
= rect
.bottom
- rect
.top
;
1161 // TODO: add support for rgndata
1162 // if(preserve_aspect_ratio || !rgndata)
1165 unsigned blit_x
, blit_y
, blit_w
, blit_h
;
1166 static const union pipe_color_union black
= { { 0, 0, 0, 0 } };
1168 if(!formats_compatible
|| src
->width0
!= dst_w
|| src
->height0
!= dst_h
) {
1169 struct pipe_surface templat
;
1170 templat
.usage
= PIPE_BIND_RENDER_TARGET
;
1171 templat
.format
= dst
->format
;
1172 templat
.u
.tex
.level
= 0;
1173 templat
.u
.tex
.first_layer
= 0;
1174 templat
.u
.tex
.last_layer
= 0;
1175 dst_surface
= pipe
->create_surface(pipe
, dst
, &templat
);
1178 if(preserve_aspect_ratio
)
1180 int delta
= src
->width0
* dst_h
- dst_w
* src
->height0
;
1184 blit_h
= dst_w
* src
->height0
/ src
->width0
;
1188 blit_w
= dst_h
* src
->width0
/ src
->height0
;
1197 blit_x
= (dst_w
- blit_w
) >> 1;
1198 blit_y
= (dst_h
- blit_h
) >> 1;
1209 pipe
->clear_render_target(pipe
, dst_surface
, &black
, rect
.left
, rect
.top
, blit_x
, dst_h
);
1211 pipe
->clear_render_target(pipe
, dst_surface
, &black
, rect
.left
, rect
.top
, dst_w
, blit_y
);
1213 if(formats_compatible
&& blit_w
== src
->width0
&& blit_h
== src
->height0
)
1216 box
.x
= box
.y
= box
.z
= 0;
1218 box
.height
= blit_h
;
1220 pipe
->resource_copy_region(pipe
, dst
, 0, rect
.left
, rect
.top
, 0, src
, 0, &box
);
1224 blitter
->blit(dst_surface
, gallium_buffer0_view
, rect
.left
+ blit_x
, rect
.top
+ blit_y
, blit_w
, blit_h
);
1226 gallium_device
->RestoreGalliumState();
1230 pipe
->clear_render_target(pipe
, dst_surface
, &black
, rect
.left
+ blit_x
+ blit_w
, rect
.top
, dst_w
- blit_x
- blit_w
, dst_h
);
1232 pipe
->clear_render_target(pipe
, dst_surface
, &black
, rect
.left
, rect
.top
+ blit_y
+ blit_h
, dst_w
, dst_h
- blit_y
- blit_h
);
1236 pipe
->surface_destroy(pipe
, dst_surface
);
1238 pipe
->flush(pipe
, 0);
1240 memset(&ctrl
, 0, sizeof(ctrl
));
1241 ctrl
.natt
= (db
) ? NATIVE_ATTACHMENT_BACK_LEFT
: NATIVE_ATTACHMENT_FRONT_LEFT
;
1242 if(!surface
->present(surface
, &ctrl
))
1243 return DXGI_ERROR_DEVICE_REMOVED
;
1246 parent
->backend
->EndPresent(desc
.OutputWindow
, present_cookie
);
1252 virtual HRESULT STDMETHODCALLTYPE
GetBuffer(
1259 if(desc
.SwapEffect
== DXGI_SWAP_EFFECT_SEQUENTIAL
)
1260 std::cerr
<< "DXGI unimplemented: GetBuffer(n) with n > 0 not supported, returning buffer 0 instead!" << std::endl
;
1262 std::cerr
<< "DXGI error: in GetBuffer(n), n must be 0 for DXGI_SWAP_EFFECT_DISCARD\n" << std::endl
;
1267 HRESULT hr
= create_buffer0();
1271 return buffer0
->QueryInterface(riid
, ppSurface
);
1274 /* TODO: implement somehow */
1275 virtual HRESULT STDMETHODCALLTYPE
SetFullscreenState(
1277 IDXGIOutput
*target
)
1279 fullscreen
= fullscreen
;
1284 virtual HRESULT STDMETHODCALLTYPE
GetFullscreenState(
1285 BOOL
*out_fullscreen
,
1286 IDXGIOutput
**out_target
)
1289 *out_fullscreen
= fullscreen
;
1291 *out_target
= target
.ref();
1295 virtual HRESULT STDMETHODCALLTYPE
GetDesc(
1296 DXGI_SWAP_CHAIN_DESC
*out_desc
)
1302 virtual HRESULT STDMETHODCALLTYPE
ResizeBuffers(
1306 DXGI_FORMAT new_format
,
1307 UINT swap_chain_flags
)
1311 buffer0
.p
->AddRef();
1312 ULONG v
= buffer0
.p
->Release();
1313 // we must fail if there are any references to buffer0 other than ours
1316 pipe_sampler_view_reference(&gallium_buffer0_view
, 0);
1317 buffer0
= (IUnknown
*)NULL
;
1318 gallium_buffer0
= 0;
1321 if(desc
.SwapEffect
!= DXGI_SWAP_EFFECT_SEQUENTIAL
)
1322 desc
.BufferCount
= buffer_count
;
1323 desc
.BufferDesc
.Format
= new_format
;
1324 desc
.BufferDesc
.Width
= width
;
1325 desc
.BufferDesc
.Height
= height
;
1326 desc
.Flags
= swap_chain_flags
;
1327 return resolve_zero_width_height();
1330 virtual HRESULT STDMETHODCALLTYPE
ResizeTarget(
1331 const DXGI_MODE_DESC
*out_new_target_parameters
)
1333 /* TODO: implement */
1337 virtual HRESULT STDMETHODCALLTYPE
GetContainingOutput(
1338 IDXGIOutput
**out_output
)
1340 *out_output
= adapter
->outputs
[0].ref();
1344 virtual HRESULT STDMETHODCALLTYPE
GetFrameStatistics(
1345 DXGI_FRAME_STATISTICS
*out_stats
)
1347 memset(out_stats
, 0, sizeof(*out_stats
));
1349 QueryPerformanceCounter(&out_stats
->SyncQPCTime
);
1351 out_stats
->PresentCount
= present_count
;
1352 out_stats
->PresentRefreshCount
= present_count
;
1353 out_stats
->SyncRefreshCount
= present_count
;
1357 virtual HRESULT STDMETHODCALLTYPE
GetLastPresentCount(
1358 UINT
*last_present_count
)
1360 *last_present_count
= present_count
;
1365 static void GalliumDXGISwapChainRevalidate(IDXGISwapChain
* swap_chain
)
1367 ((GalliumDXGISwapChain
*)swap_chain
)->needs_validation
= true;
1370 static HRESULT
GalliumDXGIAdapterCreate(GalliumDXGIFactory
* factory
, const struct native_platform
* platform
, void* dpy
, IDXGIAdapter1
** out_adapter
)
1374 *out_adapter
= new GalliumDXGIAdapter(factory
, platform
, dpy
);
1383 static HRESULT
GalliumDXGIOutputCreate(GalliumDXGIAdapter
* adapter
, const std::string
& name
, const struct native_connector
* connector
, IDXGIOutput
** out_output
)
1387 *out_output
= new GalliumDXGIOutput(adapter
, name
, connector
);
1396 static HRESULT
GalliumDXGISwapChainCreate(GalliumDXGIFactory
* factory
, IUnknown
* device
, const DXGI_SWAP_CHAIN_DESC
& desc
, IDXGISwapChain
** out_swap_chain
)
1400 *out_swap_chain
= new GalliumDXGISwapChain(factory
, device
, desc
);
1411 const struct native_platform
* platform
;
1413 IGalliumDXGIBackend
* backend
;
1416 static dxgi_binding dxgi_default_binding
;
1417 static __thread dxgi_binding dxgi_thread_binding
;
1418 static const struct native_event_handler dxgi_event_handler
= {
1419 GalliumDXGIAdapter::handle_invalid_surface
,
1420 dxgi_loader_create_drm_screen
,
1421 dxgi_loader_create_sw_screen
1424 void STDMETHODCALLTYPE
GalliumDXGIUseNothing()
1426 dxgi_thread_binding
.platform
= 0;
1427 dxgi_thread_binding
.display
= 0;
1428 if(dxgi_thread_binding
.backend
)
1429 dxgi_thread_binding
.backend
->Release();
1430 dxgi_thread_binding
.backend
= 0;
1433 #ifdef GALLIUM_DXGI_USE_X11
1434 void STDMETHODCALLTYPE
GalliumDXGIUseX11Display(Display
* dpy
, IGalliumDXGIBackend
* backend
)
1436 GalliumDXGIUseNothing();
1437 dxgi_thread_binding
.platform
= native_get_x11_platform(&dxgi_event_handler
);
1438 dxgi_thread_binding
.display
= dpy
;
1442 dxgi_thread_binding
.backend
= backend
;
1449 #ifdef GALLIUM_DXGI_USE_DRM
1450 void STDMETHODCALLTYPE GalliumDXGIUseDRMCard(int fd)
1452 GalliumDXGIUseNothing();
1453 dxgi_thread_binding.platform = native_get_drm_platform(&dxgi_event_handler);
1454 dxgi_thread_binding.display = (void*)fd;
1455 dxgi_thread_binding.backend = 0;
1459 #ifdef GALLIUM_DXGI_USE_FBDEV
1460 void STDMETHODCALLTYPE GalliumDXGIUseFBDev(int fd)
1462 GalliumDXGIUseNothing();
1463 dxgi_thread_binding.platform = native_get_fbdev_platform(&dxgi_event_handler);
1464 dxgi_thread_binding.display = (void*)fd;
1465 dxgi_thread_binding.backend = 0;
1469 #ifdef GALLIUM_DXGI_USE_GDI
1470 void STDMETHODCALLTYPE GalliumDXGIUseHDC(HDC hdc, PFNHWNDRESOLVER resolver, void* resolver_cookie)
1472 GalliumDXGIUseNothing();
1473 dxgi_thread_binding.platform = native_get_gdi_platform(&dxgi_event_handler);
1474 dxgi_thread_binding.display = (void*)hdc;
1475 dxgi_thread_binding.backend = 0;
1479 void STDMETHODCALLTYPE
GalliumDXGIMakeDefault()
1481 if(dxgi_default_binding
.backend
)
1482 dxgi_default_binding
.backend
->Release();
1483 dxgi_default_binding
= dxgi_thread_binding
;
1484 if(dxgi_default_binding
.backend
)
1485 dxgi_default_binding
.backend
->AddRef();
1488 /* TODO: why did Microsoft add this? should we do something different for DXGI 1.0 and 1.1?
1489 * Or perhaps what they actually mean is "only create a single factory in your application"?
1490 * TODO: should we use a singleton here, so we never have multiple DXGI objects for the same thing? */
1491 HRESULT STDMETHODCALLTYPE
CreateDXGIFactory1(
1496 GalliumDXGIFactory
* factory
;
1498 if(dxgi_thread_binding
.platform
)
1499 factory
= new GalliumDXGIFactory(dxgi_thread_binding
.platform
, dxgi_thread_binding
.display
, dxgi_thread_binding
.backend
);
1500 else if(dxgi_default_binding
.platform
)
1501 factory
= new GalliumDXGIFactory(dxgi_default_binding
.platform
, dxgi_default_binding
.display
, dxgi_default_binding
.backend
);
1503 factory
= new GalliumDXGIFactory(native_get_x11_platform(&dxgi_event_handler
), NULL
, NULL
);
1504 HRESULT hres
= factory
->QueryInterface(riid
, out_factory
);
1509 HRESULT STDMETHODCALLTYPE
CreateDXGIFactory(
1514 return CreateDXGIFactory1(riid
, out_factor
);