summaryrefslogtreecommitdiff
path: root/src/gallium/state_trackers/d3d1x/gd3d11
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/d3d1x/gd3d11')
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/Makefile6
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/d3d11.cpp236
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h2033
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h715
-rw-r--r--src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h1447
5 files changed, 4437 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/Makefile b/src/gallium/state_trackers/d3d1x/gd3d11/Makefile
new file mode 100644
index 0000000000..650c11d3d0
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/Makefile
@@ -0,0 +1,6 @@
+LIBNAME=gd3d11
+CPP_SOURCES=d3d11.cpp
+LIBRARY_INCLUDES=-I../gd3d1x -I../gd3dapi -I../d3dapi -I../w32api -I../d3d1xstutil/include -I../d3d1xshader/include -I../../../include -I../../../auxiliary -I../../../state_trackers/egl/common
+
+include ../Makefile.inc
+
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11.cpp b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11.cpp
new file mode 100644
index 0000000000..22cbf150fe
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11.cpp
@@ -0,0 +1,236 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "d3d1x_private.h"
+
+extern "C"
+{
+#include "util/u_gen_mipmap.h"
+#include "tgsi/tgsi_ureg.h"
+#include "cso_cache/cso_context.h"
+}
+
+
+// the perl script will change this to 10 for d3d10, and also do s/D3D11/D3D10 in the whole file
+#define API 11
+
+#if API >= 11
+#define DX10_ONLY(x)
+#else
+#define DX10_ONLY(x) x
+#endif
+
+typedef D3D10_MAPPED_TEXTURE3D D3D10_MAPPED_SUBRESOURCE;
+
+// used to make QueryInterface know the IIDs of the interface and its ancestors
+COM_INTERFACE(ID3D11DeviceChild, IUnknown)
+COM_INTERFACE(ID3D11InputLayout, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11DepthStencilState, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11BlendState, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11RasterizerState, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11SamplerState, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11Resource, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11Buffer, ID3D11Resource)
+COM_INTERFACE(ID3D11Texture1D, ID3D11Resource)
+COM_INTERFACE(ID3D11Texture2D, ID3D11Resource)
+COM_INTERFACE(ID3D11Texture3D, ID3D11Resource)
+COM_INTERFACE(ID3D11View, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11ShaderResourceView, ID3D11View)
+COM_INTERFACE(ID3D11RenderTargetView, ID3D11View)
+COM_INTERFACE(ID3D11DepthStencilView, ID3D11View)
+COM_INTERFACE(ID3D11VertexShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11GeometryShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11PixelShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11Asynchronous, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11Query, ID3D11Asynchronous)
+COM_INTERFACE(ID3D11Predicate, ID3D11Query)
+COM_INTERFACE(ID3D11Counter, ID3D11Asynchronous)
+COM_INTERFACE(ID3D11Device, IUnknown)
+
+#if API >= 11
+COM_INTERFACE(ID3D11UnorderedAccessView, ID3D11View)
+COM_INTERFACE(ID3D11HullShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11DomainShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11ComputeShader, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11ClassInstance, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11ClassLinkage, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11CommandList, ID3D11DeviceChild)
+COM_INTERFACE(ID3D11DeviceContext, ID3D11DeviceChild)
+#else
+COM_INTERFACE(ID3D10BlendState1, ID3D10BlendState)
+COM_INTERFACE(ID3D10ShaderResourceView1, ID3D10ShaderResourceView)
+COM_INTERFACE(ID3D10Device1, ID3D10Device)
+#endif
+
+struct GalliumD3D11Screen;
+
+#if API >= 11
+static ID3D11DeviceContext* GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen* device, struct pipe_context* pipe, bool owns_pipe);
+static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext* context);
+static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext* context);
+static void GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext* device);
+#endif
+
+static inline pipe_box d3d11_to_pipe_box(struct pipe_resource* resource, unsigned level, const D3D11_BOX* pBox)
+{
+ pipe_box box;
+ if(pBox)
+ {
+ box.x = pBox->left;
+ box.y = pBox->top;
+ box.z = pBox->front;
+ box.width = pBox->right - pBox->left;
+ box.height = pBox->bottom - pBox->top;
+ box.depth = pBox->back - pBox->front;
+ }
+ else
+ {
+ box.x = box.y = box.z = 0;
+ box.width = u_minify(resource->width0, level);
+ box.height = u_minify(resource->height0, level);
+ box.depth = u_minify(resource->depth0, level);
+ }
+ return box;
+}
+
+struct GalliumD3D11Caps
+{
+ bool so;
+ bool gs;
+ bool queries;
+ bool render_condition;
+ unsigned constant_buffers[D3D11_STAGES];
+ unsigned stages;
+};
+
+// used to avoid needing to have forward declarations of functions
+// this is called "screen" because in the D3D10 case it's only part of the device
+struct GalliumD3D11Screen
+ : public GalliumDXGIDevice<
+ GalliumMultiComObject<
+#if API >= 11
+ GalliumPrivateDataComObject<ID3D11Device>,
+#else
+ GalliumPrivateDataComObject<ID3D10Device1>,
+#endif
+ IGalliumDevice
+ >
+ >
+{
+ pipe_screen* screen;
+ pipe_context* immediate_pipe;
+ GalliumD3D11Caps screen_caps;
+
+#if API >= 11
+ ID3D11DeviceContext* immediate_context;
+ ID3D11DeviceContext* get_immediate_context()
+ {
+ return immediate_context;
+ }
+#else
+ GalliumD3D11Screen* get_immediate_context()
+ {
+ return this;
+ }
+#endif
+
+
+ GalliumD3D11Screen(pipe_screen* screen, struct pipe_context* immediate_pipe, IDXGIAdapter* adapter)
+ : GalliumDXGIDevice(adapter), screen(screen), immediate_pipe(immediate_pipe)
+ {
+ }
+
+#if API < 11
+ // we use a D3D11-like API internally
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in ID3D11Resource *pResource,
+ __in unsigned Subresource,
+ __in D3D11_MAP MapType,
+ __in unsigned MapFlags,
+ __out D3D11_MAPPED_SUBRESOURCE *pMappedResource) = 0;
+ virtual void STDMETHODCALLTYPE Unmap(
+ __in ID3D11Resource *pResource,
+ __in unsigned Subresource) = 0;
+ virtual void STDMETHODCALLTYPE Begin(
+ __in ID3D11Asynchronous *pAsync) = 0;
+ virtual void STDMETHODCALLTYPE End(
+ __in ID3D11Asynchronous *pAsync) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetData(
+ __in ID3D11Asynchronous *pAsync,
+ __out_bcount_opt(DataSize) void *pData,
+ __in unsigned DataSize,
+ __in unsigned GetDataFlags) = 0;
+
+ // TODO: maybe we should use function overloading, but that might risk silent errors,
+ // and cannot be exported to a C interface
+ virtual void UnbindBlendState(ID3D11BlendState* state) = 0;
+ virtual void UnbindRasterizerState(ID3D11RasterizerState* state) = 0;
+ virtual void UnbindDepthStencilState(ID3D11DepthStencilState* state) = 0;
+ virtual void UnbindInputLayout(ID3D11InputLayout* state) = 0;
+ virtual void UnbindPixelShader(ID3D11PixelShader* state) = 0;
+ virtual void UnbindVertexShader(ID3D11VertexShader* state) = 0;
+ virtual void UnbindGeometryShader(ID3D11GeometryShader* state) = 0;
+ virtual void UnbindPredicate(ID3D11Predicate* predicate) = 0;
+ virtual void UnbindSamplerState(ID3D11SamplerState* state) = 0;
+ virtual void UnbindBuffer(ID3D11Buffer* buffer) = 0;
+ virtual void UnbindDepthStencilView(ID3D11DepthStencilView* view) = 0;
+ virtual void UnbindRenderTargetView(ID3D11RenderTargetView* view) = 0;
+ virtual void UnbindShaderResourceView(ID3D11ShaderResourceView* view) = 0;
+
+ void UnbindBlendState1(ID3D11BlendState1* state)
+ {
+ UnbindBlendState(state);
+ }
+ void UnbindShaderResourceView1(ID3D11ShaderResourceView1* view)
+ {
+ UnbindShaderResourceView(view);
+ }
+#endif
+};
+
+#include "d3d11_objects.h"
+#include "d3d11_screen.h"
+#include "d3d11_context.h"
+
+#if API >= 11
+HRESULT STDMETHODCALLTYPE GalliumD3D11DeviceCreate(struct pipe_screen* screen, struct pipe_context* context, BOOL owns_context, unsigned creation_flags, IDXGIAdapter* adapter, ID3D11Device** ppDevice)
+{
+ if(creation_flags & D3D11_CREATE_DEVICE_SINGLETHREADED)
+ *ppDevice = new GalliumD3D11ScreenImpl<false>(screen, context, owns_context, creation_flags, adapter);
+ else
+ *ppDevice = new GalliumD3D11ScreenImpl<true>(screen, context, owns_context, creation_flags, adapter);
+ return S_OK;
+}
+#else
+HRESULT STDMETHODCALLTYPE GalliumD3D10DeviceCreate1(struct pipe_screen* screen, struct pipe_context* context, BOOL owns_context, unsigned creation_flags, IDXGIAdapter* adapter, ID3D10Device1** ppDevice)
+{
+ if(creation_flags & D3D10_CREATE_DEVICE_SINGLETHREADED)
+ *ppDevice = new GalliumD3D10Device<false>(screen, context, owns_context, creation_flags, adapter);
+ else
+ *ppDevice = new GalliumD3D10Device<true>(screen, context, owns_context, creation_flags, adapter);
+ return S_OK;
+}
+#endif
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
new file mode 100644
index 0000000000..a8573cdf68
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_context.h
@@ -0,0 +1,2033 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* used to unbind things, we need 128 due to resources */
+static const void* zero_data[128];
+
+#define UPDATE_VIEWS_SHIFT (D3D11_STAGES * 0)
+#define UPDATE_SAMPLERS_SHIFT (D3D11_STAGES * 1)
+#define UPDATE_VERTEX_BUFFERS (1 << (D3D11_STAGES * 2))
+
+#if API >= 11
+template<typename PtrTraits>
+struct GalliumD3D11DeviceContext :
+ public GalliumD3D11DeviceChild<ID3D11DeviceContext>
+{
+#else
+template<bool threadsafe>
+struct GalliumD3D10Device : public GalliumD3D10ScreenImpl<threadsafe>
+{
+ typedef simple_ptr_traits PtrTraits;
+ typedef GalliumD3D10Device GalliumD3D10DeviceContext;
+#endif
+
+ refcnt_ptr<GalliumD3D11Shader<>, PtrTraits> shaders[D3D11_STAGES];
+ refcnt_ptr<GalliumD3D11InputLayout, PtrTraits> input_layout;
+ refcnt_ptr<GalliumD3D11Buffer, PtrTraits> index_buffer;
+ refcnt_ptr<GalliumD3D11RasterizerState, PtrTraits> rasterizer_state;
+ refcnt_ptr<GalliumD3D11DepthStencilState, PtrTraits> depth_stencil_state;
+ refcnt_ptr<GalliumD3D11BlendState, PtrTraits> blend_state;
+ refcnt_ptr<GalliumD3D11DepthStencilView, PtrTraits> depth_stencil_view;
+ refcnt_ptr<GalliumD3D11Predicate, PtrTraits> render_predicate;
+
+ refcnt_ptr<GalliumD3D11Buffer, PtrTraits> constant_buffers[D3D11_STAGES][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
+ refcnt_ptr<GalliumD3D11ShaderResourceView, PtrTraits> shader_resource_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
+ refcnt_ptr<GalliumD3D11SamplerState, PtrTraits> samplers[D3D11_STAGES][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
+ refcnt_ptr<GalliumD3D11Buffer, PtrTraits> input_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ refcnt_ptr<GalliumD3D11RenderTargetView, PtrTraits> render_target_views[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ refcnt_ptr<GalliumD3D11Buffer, PtrTraits> so_targets[D3D11_SO_BUFFER_SLOT_COUNT];
+
+#if API >= 11
+ refcnt_ptr<ID3D11UnorderedAccessView, PtrTraits> cs_unordered_access_views[D3D11_PS_CS_UAV_REGISTER_COUNT];
+ refcnt_ptr<ID3D11UnorderedAccessView, PtrTraits> om_unordered_access_views[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
+#endif
+
+ D3D11_VIEWPORT viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ D3D11_RECT scissor_rects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
+ unsigned so_offsets[D3D11_SO_BUFFER_SLOT_COUNT];
+ D3D11_PRIMITIVE_TOPOLOGY primitive_topology;
+ DXGI_FORMAT index_format;
+ unsigned index_offset;
+ BOOL render_predicate_value;
+ float blend_color[4];
+ unsigned sample_mask;
+ unsigned stencil_ref;
+ bool depth_clamp;
+
+ void* default_input_layout;
+ void* default_rasterizer;
+ void* default_depth_stencil;
+ void* default_blend;
+ void* default_sampler;
+ void* ld_sampler;
+ void * default_shaders[D3D11_STAGES];
+
+ // derived state
+ int primitive_mode;
+ struct pipe_vertex_buffer vertex_buffers[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ struct pipe_resource* so_buffers[D3D11_SO_BUFFER_SLOT_COUNT];
+ struct pipe_sampler_view* sampler_views[D3D11_STAGES][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
+ struct
+ {
+ void* ld; // accessed with a -1 index from v
+ void* v[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
+ } sampler_csos[D3D11_STAGES];
+ struct pipe_resource * buffers[D3D11_SO_BUFFER_SLOT_COUNT];
+ unsigned num_shader_resource_views[D3D11_STAGES];
+ unsigned num_samplers[D3D11_STAGES];
+ unsigned num_vertex_buffers;
+ unsigned num_render_target_views;
+ unsigned num_viewports;
+ unsigned num_scissor_rects;
+ unsigned num_so_targets;
+
+ struct pipe_context* pipe;
+ unsigned update_flags;
+
+ bool owns_pipe;
+ unsigned context_flags;
+
+ GalliumD3D11Caps caps;
+
+ cso_context* cso_ctx;
+ gen_mipmap_state* gen_mipmap;
+
+#if API >= 11
+#define SYNCHRONIZED do {} while(0)
+
+ GalliumD3D11DeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, bool owns_pipe, unsigned context_flags = 0)
+ : GalliumD3D11DeviceChild(device), pipe(pipe), owns_pipe(owns_pipe), context_flags(context_flags)
+ {
+ caps = device->screen_caps;
+ init_context();
+ }
+
+ ~GalliumD3D11DeviceContext()
+ {
+ destroy_context();
+ }
+#else
+#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(this->mutex)
+
+ GalliumD3D10Device(pipe_screen* screen, pipe_context* pipe, bool owns_pipe, unsigned creation_flags, IDXGIAdapter* adapter)
+ : GalliumD3D10ScreenImpl<threadsafe>(screen, pipe, owns_pipe, creation_flags, adapter), pipe(pipe), owns_pipe(owns_pipe), context_flags(0)
+ {
+ caps = this->screen_caps;
+ init_context();
+ }
+
+ ~GalliumD3D10Device()
+ {
+ destroy_context();
+ }
+#endif
+
+ void init_context()
+ {
+ if(!pipe->begin_query)
+ caps.queries = false;
+ if(!pipe->render_condition)
+ caps.render_condition = false;
+ if(!pipe->bind_gs_state)
+ {
+ caps.gs = false;
+ caps.stages = 2;
+ }
+ if(!pipe->set_stream_output_buffers)
+ caps.so = false;
+
+ update_flags = 0;
+
+ // pipeline state
+ memset(viewports, 0, sizeof(viewports));
+ memset(scissor_rects, 0, sizeof(scissor_rects));
+ memset(so_offsets, 0, sizeof(so_offsets));
+ primitive_topology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ index_format = DXGI_FORMAT_UNKNOWN;
+ index_offset = 0;
+ render_predicate_value = 0;
+ memset(blend_color, 0, sizeof(blend_color));
+ sample_mask = ~0;
+ stencil_ref = 0;
+ depth_clamp = 0;
+
+ // derived state
+ primitive_mode = 0;
+ memset(vertex_buffers, 0, sizeof(vertex_buffers));
+ memset(so_buffers, 0, sizeof(so_buffers));
+ memset(sampler_views, 0, sizeof(sampler_views));
+ memset(sampler_csos, 0, sizeof(sampler_csos));
+ memset(num_shader_resource_views, 0, sizeof(num_shader_resource_views));
+ memset(num_samplers, 0, sizeof(num_samplers));
+ num_vertex_buffers = 0;
+ num_render_target_views = 0;
+ num_viewports = 0;
+ num_scissor_rects = 0;
+ num_so_targets = 0;
+
+ default_input_layout = pipe->create_vertex_elements_state(pipe, 0, 0);
+
+ struct pipe_rasterizer_state rasterizerd;
+ memset(&rasterizerd, 0, sizeof(rasterizerd));
+ rasterizerd.gl_rasterization_rules = 1;
+ rasterizerd.cull_face = PIPE_FACE_BACK;
+ default_rasterizer = pipe->create_rasterizer_state(pipe, &rasterizerd);
+
+ struct pipe_depth_stencil_alpha_state depth_stencild;
+ memset(&depth_stencild, 0, sizeof(depth_stencild));
+ depth_stencild.depth.enabled = TRUE;
+ depth_stencild.depth.writemask = 1;
+ depth_stencild.depth.func = PIPE_FUNC_LESS;
+ default_depth_stencil = pipe->create_depth_stencil_alpha_state(pipe, &depth_stencild);
+
+ struct pipe_blend_state blendd;
+ memset(&blendd, 0, sizeof(blendd));
+ blendd.rt[0].colormask = 0xf;
+ default_blend = pipe->create_blend_state(pipe, &blendd);
+
+ struct pipe_sampler_state samplerd;
+ memset(&samplerd, 0, sizeof(samplerd));
+ samplerd.normalized_coords = 1;
+ samplerd.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ samplerd.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
+ samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ samplerd.border_color[0] = 1.0f;
+ samplerd.border_color[1] = 1.0f;
+ samplerd.border_color[2] = 1.0f;
+ samplerd.border_color[3] = 1.0f;
+ samplerd.min_lod = -FLT_MAX;
+ samplerd.max_lod = FLT_MAX;
+ samplerd.max_anisotropy = 1;
+ default_sampler = pipe->create_sampler_state(pipe, &samplerd);
+
+ memset(&samplerd, 0, sizeof(samplerd));
+ samplerd.normalized_coords = 0;
+ samplerd.min_img_filter = PIPE_TEX_FILTER_NEAREST;
+ samplerd.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
+ samplerd.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ samplerd.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ samplerd.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ samplerd.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ samplerd.min_lod = -FLT_MAX;
+ samplerd.max_lod = FLT_MAX;
+ samplerd.max_anisotropy = 1;
+ ld_sampler = pipe->create_sampler_state(pipe, &samplerd);
+
+ for(unsigned s = 0; s < D3D11_STAGES; ++s)
+ {
+ sampler_csos[s].ld = ld_sampler;
+ for(unsigned i = 0; i < D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i)
+ sampler_csos[s].v[i] = default_sampler;
+ }
+
+ // TODO: should this really be empty shaders, or should they be all-passthrough?
+ memset(default_shaders, 0, sizeof(default_shaders));
+ struct ureg_program *ureg;
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ ureg_END(ureg);
+ default_shaders[PIPE_SHADER_FRAGMENT] = ureg_create_shader_and_destroy(ureg, pipe);
+
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ ureg_END(ureg);
+ default_shaders[PIPE_SHADER_VERTEX] = ureg_create_shader_and_destroy(ureg, pipe);
+
+ cso_ctx = cso_create_context(pipe);
+ gen_mipmap = util_create_gen_mipmap(pipe, cso_ctx);
+
+ RestoreGalliumState();
+ }
+
+ void destroy_context()
+ {
+ util_destroy_gen_mipmap(gen_mipmap);
+ cso_destroy_context(cso_ctx);
+ pipe->delete_vertex_elements_state(pipe, default_input_layout);
+ pipe->delete_rasterizer_state(pipe, default_rasterizer);
+ pipe->delete_depth_stencil_alpha_state(pipe, default_depth_stencil);
+ pipe->delete_blend_state(pipe, default_blend);
+ pipe->delete_sampler_state(pipe, default_sampler);
+ pipe->delete_sampler_state(pipe, ld_sampler);
+ pipe->delete_fs_state(pipe, default_shaders[PIPE_SHADER_FRAGMENT]);
+ pipe->delete_vs_state(pipe, default_shaders[PIPE_SHADER_VERTEX]);
+ if(owns_pipe)
+ pipe->destroy(pipe);
+ }
+
+ virtual unsigned STDMETHODCALLTYPE GetContextFlags(void)
+ {
+ return context_flags;
+ }
+#if API >= 11
+#define SET_SHADER_EXTRA_ARGS , \
+ __in_ecount_opt(NumClassInstances) ID3D11ClassInstance *const *ppClassInstances, \
+ unsigned NumClassInstances
+#define GET_SHADER_EXTRA_ARGS , \
+ __out_ecount_opt(*pNumClassInstances) ID3D11ClassInstance **ppClassInstances, \
+ __inout_opt unsigned *pNumClassInstances
+#else
+#define SET_SHADER_EXTRA_ARGS
+#define GET_SHADER_EXTRA_ARGS
+#endif
+
+/* On Windows D3D11, SetConstantBuffers and SetShaderResources crash if passed a null pointer.
+ * Instead, you have to pass a pointer to nulls to unbind things.
+ * We do the same.
+ * TODO: is D3D10 the same?
+ */
+ template<unsigned s>
+ void xs_set_shader(GalliumD3D11Shader<>* shader)
+ {
+ if(shader != shaders[s].p)
+ {
+ shaders[s] = shader;
+ void* shader_cso = shader ? shader->object : default_shaders[s];
+ switch(s)
+ {
+ case PIPE_SHADER_VERTEX:
+ pipe->bind_vs_state(pipe, shader_cso);
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ pipe->bind_fs_state(pipe, shader_cso);
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ pipe->bind_gs_state(pipe, shader_cso);
+ break;
+ }
+ update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s)) | (1 << (UPDATE_VIEWS_SHIFT + s));
+ }
+ }
+
+ template<unsigned s>
+ void xs_set_constant_buffers(unsigned start, unsigned count, GalliumD3D11Buffer *const *constbufs)
+ {
+ for(unsigned i = 0; i < count; ++i)
+ {
+ if(constbufs[i] != constant_buffers[s][i].p)
+ {
+ constant_buffers[s][i] = constbufs[i];
+ if(s < caps.stages && start + i < caps.constant_buffers[s])
+ pipe->set_constant_buffer(pipe, s, start + i, constbufs[i] ? constbufs[i]->resource : NULL);
+ }
+ }
+ }
+
+ template<unsigned s>
+ void xs_set_shader_resources(unsigned start, unsigned count, GalliumD3D11ShaderResourceView *const *srvs)
+ {
+ int last_different = -1;
+ for(unsigned i = 0; i < count; ++i)
+ {
+ if(shader_resource_views[s][start + i].p != srvs[i])
+ {
+ shader_resource_views[s][start + i] = srvs[i];
+ sampler_views[s][start + i] = srvs[i] ? srvs[i]->object : 0;
+ last_different = i;
+ }
+ }
+ if(last_different >= 0)
+ {
+ num_shader_resource_views[s] = std::max(num_shader_resource_views[s], start + last_different + 1);
+ update_flags |= 1 << (UPDATE_VIEWS_SHIFT + s);
+ }
+ }
+
+ template<unsigned s>
+ void xs_set_samplers(unsigned start, unsigned count, GalliumD3D11SamplerState *const *samps)
+ {
+ int last_different = -1;
+ for(unsigned i = 0; i < count; ++i)
+ {
+ if(samplers[s][start + i].p != samps[i])
+ {
+ samplers[s][start + i] = samps[i];
+ sampler_csos[s].v[start + i] = samps[i] ? samps[i]->object : default_sampler;
+ }
+ if(last_different >= 0)
+ {
+ num_samplers[s] = std::max(num_samplers[s], start + last_different + 1);
+ update_flags |= (UPDATE_SAMPLERS_SHIFT + s);
+ }
+ }
+ }
+
+#define IMPLEMENT_SHADER_STAGE(XS, Stage) \
+ virtual void STDMETHODCALLTYPE XS##SetShader( \
+ __in_opt ID3D11##Stage##Shader *pShader \
+ SET_SHADER_EXTRA_ARGS) \
+ { \
+ SYNCHRONIZED; \
+ xs_set_shader<D3D11_STAGE_##XS>((GalliumD3D11Shader<>*)pShader); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##GetShader(\
+ __out ID3D11##Stage##Shader **ppShader \
+ GET_SHADER_EXTRA_ARGS) \
+ { \
+ SYNCHRONIZED; \
+ *ppShader = (ID3D11##Stage##Shader*)shaders[D3D11_STAGE_##XS].ref(); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##SetConstantBuffers(\
+ __in_range(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) unsigned NumBuffers, \
+ __in_ecount(NumBuffers) ID3D11Buffer *const *ppConstantBuffers) \
+ { \
+ SYNCHRONIZED; \
+ xs_set_constant_buffers<D3D11_STAGE_##XS>(StartSlot, NumBuffers, (GalliumD3D11Buffer *const *)ppConstantBuffers); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##GetConstantBuffers(\
+ __in_range(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - StartSlot) unsigned NumBuffers, \
+ __out_ecount(NumBuffers) ID3D11Buffer **ppConstantBuffers) \
+ { \
+ SYNCHRONIZED; \
+ for(unsigned i = 0; i < NumBuffers; ++i) \
+ ppConstantBuffers[i] = constant_buffers[D3D11_STAGE_##XS][StartSlot + i].ref(); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##SetShaderResources(\
+ __in_range(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) unsigned NumViews, \
+ __in_ecount(NumViews) ID3D11ShaderResourceView *const *ppShaderResourceViews) \
+ { \
+ SYNCHRONIZED; \
+ xs_set_shader_resources<D3D11_STAGE_##XS>(StartSlot, NumViews, (GalliumD3D11ShaderResourceView *const *)ppShaderResourceViews); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##GetShaderResources(\
+ __in_range(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT - StartSlot) unsigned NumViews, \
+ __out_ecount(NumViews) ID3D11ShaderResourceView **ppShaderResourceViews) \
+ { \
+ SYNCHRONIZED; \
+ for(unsigned i = 0; i < NumViews; ++i) \
+ ppShaderResourceViews[i] = shader_resource_views[D3D11_STAGE_##XS][StartSlot + i].ref(); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##SetSamplers(\
+ __in_range(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) unsigned NumSamplers, \
+ __in_ecount(NumSamplers) ID3D11SamplerState *const *ppSamplers) \
+ { \
+ SYNCHRONIZED; \
+ xs_set_samplers<D3D11_STAGE_##XS>(StartSlot, NumSamplers, (GalliumD3D11SamplerState *const *)ppSamplers); \
+ } \
+ virtual void STDMETHODCALLTYPE XS##GetSamplers( \
+ __in_range(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - 1) unsigned StartSlot, \
+ __in_range(0, D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT - StartSlot) unsigned NumSamplers, \
+ __out_ecount(NumSamplers) ID3D11SamplerState **ppSamplers) \
+ { \
+ SYNCHRONIZED; \
+ for(unsigned i = 0; i < NumSamplers; ++i) \
+ ppSamplers[i] = samplers[D3D11_STAGE_##XS][StartSlot + i].ref(); \
+ }
+
+#define DO_VS(x) x
+#define DO_GS(x) do {if(caps.gs) {x;}} while(0)
+#define DO_PS(x) x
+#define DO_HS(x)
+#define DO_DS(x)
+#define DO_CS(x)
+ IMPLEMENT_SHADER_STAGE(VS, Vertex)
+ IMPLEMENT_SHADER_STAGE(GS, Geometry)
+ IMPLEMENT_SHADER_STAGE(PS, Pixel)
+
+#if API >= 11
+ IMPLEMENT_SHADER_STAGE(HS, Hull)
+ IMPLEMENT_SHADER_STAGE(DS, Domain)
+ IMPLEMENT_SHADER_STAGE(CS, Compute)
+
+ virtual void STDMETHODCALLTYPE CSSetUnorderedAccessViews(
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) unsigned StartSlot,
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - StartSlot) unsigned NumUAVs,
+ __in_ecount(NumUAVs) ID3D11UnorderedAccessView *const *ppUnorderedAccessViews,
+ __in_ecount(NumUAVs) const unsigned *pUAVInitialCounts)
+ {
+ SYNCHRONIZED;
+ for(unsigned i = 0; i < NumUAVs; ++i)
+ cs_unordered_access_views[StartSlot + i] = ppUnorderedAccessViews[i];
+ }
+
+ virtual void STDMETHODCALLTYPE CSGetUnorderedAccessViews(
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) unsigned StartSlot,
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - StartSlot) unsigned NumUAVs,
+ __out_ecount(NumUAVs) ID3D11UnorderedAccessView **ppUnorderedAccessViews)
+ {
+ SYNCHRONIZED;
+ for(unsigned i = 0; i < NumUAVs; ++i)
+ ppUnorderedAccessViews[i] = cs_unordered_access_views[StartSlot + i].ref();
+ }
+#endif
+
+ template<unsigned s>
+ void update_stage()
+ {
+ if(update_flags & (1 << (UPDATE_VIEWS_SHIFT + s)))
+ {
+ while(num_shader_resource_views[s] && !sampler_views[s][num_shader_resource_views[s] - 1]) \
+ --num_shader_resource_views[s];
+ if(s < caps.stages)
+ {
+ struct pipe_sampler_view* views_to_bind[PIPE_MAX_SAMPLERS];
+ unsigned num_views_to_bind = shaders[s] ? shaders[s]->slot_to_resource.size() : 0;
+ for(unsigned i = 0; i < num_views_to_bind; ++i)
+ {
+ views_to_bind[i] = sampler_views[s][shaders[s]->slot_to_resource[i]];
+ }
+ switch(s)
+ {
+ case PIPE_SHADER_VERTEX:
+ pipe->set_vertex_sampler_views(pipe, num_views_to_bind, views_to_bind);
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ pipe->set_fragment_sampler_views(pipe, num_views_to_bind, views_to_bind);
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ pipe->set_geometry_sampler_views(pipe, num_views_to_bind, views_to_bind);
+ break;
+ }
+ }
+ }
+
+ if(update_flags & (1 << (UPDATE_SAMPLERS_SHIFT + s)))
+ {
+ while(num_samplers[s] && !sampler_csos[s].v[num_samplers[s] - 1])
+ --num_samplers[s];
+ if(s < caps.stages)
+ {
+ void* samplers_to_bind[PIPE_MAX_SAMPLERS];
+ unsigned num_samplers_to_bind = shaders[s] ? shaders[s]->slot_to_sampler.size() : 0;
+ for(unsigned i = 0; i < num_samplers_to_bind; ++i)
+ {
+ // index can be -1 to access sampler_csos[s].ld
+ samplers_to_bind[i] = *(sampler_csos[s].v + shaders[s]->slot_to_sampler[i]);
+ }
+ switch(s)
+ {
+ case PIPE_SHADER_VERTEX:
+ pipe->bind_vertex_sampler_states(pipe, num_samplers_to_bind, samplers_to_bind);
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ pipe->bind_fragment_sampler_states(pipe, num_samplers_to_bind, samplers_to_bind);
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ pipe->bind_geometry_sampler_states(pipe, num_samplers_to_bind, samplers_to_bind);
+ break;
+ }
+ }
+ }
+ }
+
+ void update_state()
+ {
+ update_stage<D3D11_STAGE_PS>();
+ update_stage<D3D11_STAGE_VS>();
+ update_stage<D3D11_STAGE_GS>();
+#if API >= 11
+ update_stage<D3D11_STAGE_HS>();
+ update_stage<D3D11_STAGE_DS>();
+ update_stage<D3D11_STAGE_CS>();
+#endif
+
+ if(update_flags & UPDATE_VERTEX_BUFFERS)
+ {
+ while(num_vertex_buffers && !vertex_buffers[num_vertex_buffers - 1].buffer)
+ --num_vertex_buffers;
+ pipe->set_vertex_buffers(pipe, num_vertex_buffers, vertex_buffers);
+ }
+
+ update_flags = 0;
+ }
+
+ virtual void STDMETHODCALLTYPE IASetInputLayout(
+ __in_opt ID3D11InputLayout *pInputLayout)
+ {
+ SYNCHRONIZED;
+ if(pInputLayout != input_layout.p)
+ {
+ input_layout = pInputLayout;
+ pipe->bind_vertex_elements_state(pipe, pInputLayout ? ((GalliumD3D11InputLayout*)pInputLayout)->object : default_input_layout);
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE IAGetInputLayout(
+ __out ID3D11InputLayout **ppInputLayout)
+ {
+ SYNCHRONIZED;
+ *ppInputLayout = input_layout.ref();
+ }
+
+ virtual void STDMETHODCALLTYPE IASetVertexBuffers(
+ __in_range(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) unsigned StartSlot,
+ __in_range(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) unsigned NumBuffers,
+ __in_ecount(NumBuffers) ID3D11Buffer *const *ppVertexBuffers,
+ __in_ecount(NumBuffers) const unsigned *pStrides,
+ __in_ecount(NumBuffers) const unsigned *pOffsets)
+ {
+ SYNCHRONIZED;
+ int last_different = -1;
+ for(unsigned i = 0; i < NumBuffers; ++i)
+ {
+ ID3D11Buffer* buffer = ppVertexBuffers[i];
+ if(buffer != input_buffers[StartSlot + i].p
+ || vertex_buffers[StartSlot + i].buffer_offset != pOffsets[i]
+ || vertex_buffers[StartSlot + i].stride != pOffsets[i]
+ )
+ {
+ input_buffers[StartSlot + i] = buffer;
+ vertex_buffers[StartSlot + i].buffer = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0;
+ vertex_buffers[StartSlot + i].buffer_offset = pOffsets[i];
+ vertex_buffers[StartSlot + i].stride = pStrides[i];
+ vertex_buffers[StartSlot + i].max_index = ~0;
+ last_different = i;
+ }
+ }
+ if(last_different >= 0)
+ {
+ num_vertex_buffers = std::max(num_vertex_buffers, StartSlot + NumBuffers);
+ update_flags |= UPDATE_VERTEX_BUFFERS;
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE IAGetVertexBuffers(
+ __in_range(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - 1) unsigned StartSlot,
+ __in_range(0, D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT - StartSlot) unsigned NumBuffers,
+ __out_ecount_opt(NumBuffers) ID3D11Buffer **ppVertexBuffers,
+ __out_ecount_opt(NumBuffers) unsigned *pStrides,
+ __out_ecount_opt(NumBuffers) unsigned *pOffsets)
+ {
+ SYNCHRONIZED;
+ if(ppVertexBuffers)
+ {
+ for(unsigned i = 0; i < NumBuffers; ++i)
+ ppVertexBuffers[i] = input_buffers[StartSlot + i].ref();
+ }
+
+ if(pOffsets)
+ {
+ for(unsigned i = 0; i < NumBuffers; ++i)
+ pOffsets[i] = vertex_buffers[StartSlot + i].buffer_offset;
+ }
+
+ if(pStrides)
+ {
+ for(unsigned i = 0; i < NumBuffers; ++i)
+ pStrides[i] = vertex_buffers[StartSlot + i].stride;
+ }
+ }
+
+ void set_index_buffer()
+ {
+ pipe_index_buffer ib;
+ if(!index_buffer)
+ {
+ memset(&ib, 0, sizeof(ib));
+ }
+ else
+ {
+ if(index_format == DXGI_FORMAT_R32_UINT)
+ ib.index_size = 4;
+ else if(index_format == DXGI_FORMAT_R16_UINT)
+ ib.index_size = 2;
+ else
+ ib.index_size = 1;
+ ib.offset = index_offset;
+ ib.buffer = index_buffer ? ((GalliumD3D11Buffer*)index_buffer.p)->resource : 0;
+ }
+ pipe->set_index_buffer(pipe, &ib);
+ }
+
+ virtual void STDMETHODCALLTYPE IASetIndexBuffer(
+ __in_opt ID3D11Buffer *pIndexBuffer,
+ __in DXGI_FORMAT Format,
+ __in unsigned Offset)
+ {
+ SYNCHRONIZED;
+ if(index_buffer.p != pIndexBuffer || index_format != Format || index_offset != Offset)
+ {
+ index_buffer = pIndexBuffer;
+ index_format = Format;
+ index_offset = Offset;
+
+ set_index_buffer();
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE IAGetIndexBuffer(
+ __out_opt ID3D11Buffer **pIndexBuffer,
+ __out_opt DXGI_FORMAT *Format,
+ __out_opt unsigned *Offset)
+ {
+ SYNCHRONIZED;
+ if(pIndexBuffer)
+ *pIndexBuffer = index_buffer.ref();
+ if(Format)
+ *Format = index_format;
+ if(Offset)
+ *Offset = index_offset;
+ }
+
+ virtual void STDMETHODCALLTYPE IASetPrimitiveTopology(
+ __in D3D11_PRIMITIVE_TOPOLOGY Topology)
+ {
+ SYNCHRONIZED;
+ if(primitive_topology != Topology)
+ {
+ if(Topology < D3D_PRIMITIVE_TOPOLOGY_COUNT)
+ primitive_mode = d3d_to_pipe_prim[Topology];
+ else
+ primitive_mode = 0;
+ primitive_topology = Topology;
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE IAGetPrimitiveTopology(
+ __out D3D11_PRIMITIVE_TOPOLOGY *pTopology)
+ {
+ SYNCHRONIZED;
+ *pTopology = primitive_topology;
+ }
+
+ virtual void STDMETHODCALLTYPE DrawIndexed(
+ __in unsigned IndexCount,
+ __in unsigned StartIndexLocation,
+ __in int BaseVertexLocation)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = TRUE;
+ info.count = IndexCount;
+ info.start = StartIndexLocation;
+ info.index_bias = BaseVertexLocation;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = 0;
+ info.instance_count = 1;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+ virtual void STDMETHODCALLTYPE Draw(
+ __in unsigned VertexCount,
+ __in unsigned StartVertexLocation)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = FALSE;
+ info.count = VertexCount;
+ info.start = StartVertexLocation;
+ info.index_bias = 0;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = 0;
+ info.instance_count = 1;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+ virtual void STDMETHODCALLTYPE DrawIndexedInstanced(
+ __in unsigned IndexCountPerInstance,
+ __in unsigned InstanceCount,
+ __in unsigned StartIndexLocation,
+ __in int BaseVertexLocation,
+ __in unsigned StartInstanceLocation)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = TRUE;
+ info.count = IndexCountPerInstance;
+ info.start = StartIndexLocation;
+ info.index_bias = BaseVertexLocation;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = StartInstanceLocation;
+ info.instance_count = InstanceCount;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+ virtual void STDMETHODCALLTYPE DrawInstanced(
+ __in unsigned VertexCountPerInstance,
+ __in unsigned InstanceCount,
+ __in unsigned StartVertexLocation,
+ __in unsigned StartInstanceLocation)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = FALSE;
+ info.count = VertexCountPerInstance;
+ info.start = StartVertexLocation;
+ info.index_bias = 0;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = StartInstanceLocation;
+ info.instance_count = InstanceCount;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+ virtual void STDMETHODCALLTYPE DrawAuto(void)
+ {
+ if(!caps.so)
+ return;
+
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ pipe->draw_stream_output(pipe, primitive_mode);
+ }
+
+ virtual void STDMETHODCALLTYPE DrawIndexedInstancedIndirect(
+ __in ID3D11Buffer *pBufferForArgs,
+ __in unsigned AlignedByteOffsetForArgs)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ struct {
+ unsigned count;
+ unsigned instance_count;
+ unsigned start;
+ unsigned index_bias;
+ } data;
+
+ pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)pBufferForArgs)->resource, AlignedByteOffsetForArgs, sizeof(data), &data);
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = TRUE;
+ info.start = data.start;
+ info.count = data.count;
+ info.index_bias = data.index_bias;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = 0;
+ info.instance_count = data.instance_count;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+ virtual void STDMETHODCALLTYPE DrawInstancedIndirect(
+ __in ID3D11Buffer *pBufferForArgs,
+ __in unsigned AlignedByteOffsetForArgs)
+ {
+ SYNCHRONIZED;
+ if(update_flags)
+ update_state();
+
+ struct {
+ unsigned count;
+ unsigned instance_count;
+ unsigned start;
+ } data;
+
+ pipe_buffer_read(pipe, ((GalliumD3D11Buffer*)pBufferForArgs)->resource, AlignedByteOffsetForArgs, sizeof(data), &data);
+
+ pipe_draw_info info;
+ info.mode = primitive_mode;
+ info.indexed = FALSE;
+ info.start = data.start;
+ info.count = data.count;
+ info.index_bias = 0;
+ info.min_index = 0;
+ info.max_index = ~0;
+ info.start_instance = 0;
+ info.instance_count = data.instance_count;
+
+ pipe->draw_vbo(pipe, &info);
+ }
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE Dispatch(
+ __in unsigned ThreadGroupCountX,
+ __in unsigned ThreadGroupCountY,
+ __in unsigned ThreadGroupCountZ)
+ {
+// uncomment this when this is implemented
+// SYNCHRONIZED;
+// if(update_flags)
+// update_state();
+ }
+
+ virtual void STDMETHODCALLTYPE DispatchIndirect(
+ __in ID3D11Buffer *pBufferForArgs,
+ __in unsigned AlignedByteOffsetForArgs)
+ {
+// uncomment this when this is implemented
+// SYNCHRONIZED;
+// if(update_flags)
+// update_state();
+ }
+#endif
+
+ void set_clip()
+ {
+ SYNCHRONIZED;
+ pipe_clip_state clip;
+ clip.nr = 0;
+ clip.depth_clamp = depth_clamp;
+ pipe->set_clip_state(pipe, &clip);
+ }
+
+ virtual void STDMETHODCALLTYPE RSSetState(
+ __in_opt ID3D11RasterizerState *pRasterizerState)
+ {
+ SYNCHRONIZED;
+ if(pRasterizerState != rasterizer_state.p)
+ {
+ rasterizer_state = pRasterizerState;
+ pipe->bind_rasterizer_state(pipe, pRasterizerState ? ((GalliumD3D11RasterizerState*)pRasterizerState)->object : default_rasterizer);
+ bool new_depth_clamp = pRasterizerState ? ((GalliumD3D11RasterizerState*)pRasterizerState)->depth_clamp : false;
+ if(depth_clamp != new_depth_clamp)
+ {
+ depth_clamp = new_depth_clamp;
+ set_clip();
+ }
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE RSGetState(
+ __out ID3D11RasterizerState **ppRasterizerState)
+ {
+ SYNCHRONIZED;
+ *ppRasterizerState = rasterizer_state.ref();
+ }
+
+ void set_viewport()
+ {
+ // TODO: is depth correct? it seems D3D10/11 uses a [-1,1]x[-1,1]x[0,1] cube
+ pipe_viewport_state viewport;
+ float half_width = viewports[0].Width * 0.5f;
+ float half_height = viewports[0].Height * 0.5f;
+
+ viewport.scale[0] = half_width;
+ viewport.scale[1] = -half_height;
+ viewport.scale[2] = (viewports[0].MaxDepth - viewports[0].MinDepth);
+ viewport.scale[3] = 1.0f;
+ viewport.translate[0] = half_width + viewports[0].TopLeftX;
+ viewport.translate[1] = half_height + viewports[0].TopLeftY;
+ viewport.translate[2] = viewports[0].MinDepth;
+ viewport.translate[3] = 1.0f;
+ pipe->set_viewport_state(pipe, &viewport);
+ }
+
+ virtual void STDMETHODCALLTYPE RSSetViewports(
+ __in_range(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) unsigned NumViewports,
+ __in_ecount_opt(NumViewports) const D3D11_VIEWPORT *pViewports)
+ {
+ SYNCHRONIZED;
+ if(NumViewports)
+ {
+ if(memcmp(&viewports[0], &pViewports[0], sizeof(viewports[0])))
+ {
+ viewports[0] = pViewports[0];
+ set_viewport();
+ }
+ for(unsigned i = 1; i < NumViewports; ++i)
+ viewports[i] = pViewports[i];
+ }
+ else if(num_viewports)
+ {
+ // TODO: what should we do here?
+ memset(&viewports[0], 0, sizeof(viewports[0]));
+ set_viewport();
+ }
+ num_viewports = NumViewports;
+ }
+
+ virtual void STDMETHODCALLTYPE RSGetViewports(
+ __inout_range(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) unsigned *pNumViewports,
+ __out_ecount_opt(*pNumViewports) D3D11_VIEWPORT *pViewports)
+ {
+ SYNCHRONIZED;
+ if(pViewports)
+ {
+ unsigned i;
+ for(i = 0; i < std::min(*pNumViewports, num_viewports); ++i)
+ pViewports[i] = viewports[i];
+
+ memset(pViewports + i, 0, (*pNumViewports - i) * sizeof(D3D11_VIEWPORT));
+ }
+
+ *pNumViewports = num_viewports;
+ }
+
+ void set_scissor()
+ {
+ pipe_scissor_state scissor;
+ scissor.minx = scissor_rects[0].left;
+ scissor.miny = scissor_rects[0].top;
+ scissor.maxx = scissor_rects[0].right;
+ scissor.maxy = scissor_rects[0].bottom;
+ pipe->set_scissor_state(pipe, &scissor);
+ }
+
+ virtual void STDMETHODCALLTYPE RSSetScissorRects(
+ __in_range(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) unsigned NumRects,
+ __in_ecount_opt(NumRects) const D3D11_RECT *pRects)
+ {
+ SYNCHRONIZED;
+ if(NumRects)
+ {
+ if(memcmp(&scissor_rects[0], &pRects[0], sizeof(scissor_rects[0])))
+ {
+ scissor_rects[0] = pRects[0];
+ set_scissor();
+ }
+ for(unsigned i = 1; i < NumRects; ++i)
+ scissor_rects[i] = pRects[i];
+ }
+ else if(num_scissor_rects)
+ {
+ // TODO: what should we do here?
+ memset(&scissor_rects[0], 0, sizeof(scissor_rects[0]));
+ set_scissor();
+ }
+
+ num_scissor_rects = NumRects;
+ }
+
+ virtual void STDMETHODCALLTYPE RSGetScissorRects(
+ __inout_range(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) unsigned *pNumRects,
+ __out_ecount_opt(*pNumRects) D3D11_RECT *pRects)
+ {
+ SYNCHRONIZED;
+ if(pRects)
+ {
+ unsigned i;
+ for(i = 0; i < std::min(*pNumRects, num_scissor_rects); ++i)
+ pRects[i] = scissor_rects[i];
+
+ memset(pRects + i, 0, (*pNumRects - i) * sizeof(D3D11_RECT));
+ }
+
+ *pNumRects = num_scissor_rects;
+ }
+
+ virtual void STDMETHODCALLTYPE OMSetBlendState(
+ __in_opt ID3D11BlendState *pBlendState,
+ __in_opt const float BlendFactor[ 4 ],
+ __in unsigned SampleMask)
+ {
+ SYNCHRONIZED;
+ float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ if(blend_state.p != pBlendState)
+ {
+ pipe->bind_blend_state(pipe, pBlendState ? ((GalliumD3D11BlendState*)pBlendState)->object : default_blend);
+ blend_state = pBlendState;
+ }
+
+ // Windows D3D11 does this, even though it's apparently undocumented
+ if(!BlendFactor)
+ BlendFactor = white;
+
+ if(memcmp(blend_color, BlendFactor, sizeof(blend_color)))
+ {
+ pipe->set_blend_color(pipe, (struct pipe_blend_color*)BlendFactor);
+ memcpy(blend_color, BlendFactor, sizeof(blend_color));
+ }
+
+ if(sample_mask != SampleMask)
+ {
+ pipe->set_sample_mask(pipe, sample_mask);
+ sample_mask = SampleMask;
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE OMGetBlendState(
+ __out_opt ID3D11BlendState **ppBlendState,
+ __out_opt float BlendFactor[ 4 ],
+ __out_opt unsigned *pSampleMask)
+ {
+ SYNCHRONIZED;
+ if(ppBlendState)
+ *ppBlendState = blend_state.ref();
+ if(BlendFactor)
+ memcpy(BlendFactor, blend_color, sizeof(blend_color));
+ if(pSampleMask)
+ *pSampleMask = sample_mask;
+ }
+
+ void set_stencil_ref()
+ {
+ struct pipe_stencil_ref sref;
+ sref.ref_value[0] = stencil_ref;
+ sref.ref_value[1] = stencil_ref;
+ pipe->set_stencil_ref(pipe, &sref);
+ }
+
+ virtual void STDMETHODCALLTYPE OMSetDepthStencilState(
+ __in_opt ID3D11DepthStencilState *pDepthStencilState,
+ __in unsigned StencilRef)
+ {
+ SYNCHRONIZED;
+ if(pDepthStencilState != depth_stencil_state.p)
+ {
+ pipe->bind_depth_stencil_alpha_state(pipe, pDepthStencilState ? ((GalliumD3D11DepthStencilState*)pDepthStencilState)->object : default_depth_stencil);
+ depth_stencil_state = pDepthStencilState;
+ }
+
+ if(StencilRef != stencil_ref)
+ {
+ stencil_ref = StencilRef;
+ set_stencil_ref();
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE OMGetDepthStencilState(
+ __out_opt ID3D11DepthStencilState **ppDepthStencilState,
+ __out_opt unsigned *pStencilRef)
+ {
+ SYNCHRONIZED;
+ if(*ppDepthStencilState)
+ *ppDepthStencilState = depth_stencil_state.ref();
+ if(pStencilRef)
+ *pStencilRef = stencil_ref;
+ }
+
+ void set_framebuffer()
+ {
+ struct pipe_framebuffer_state fb;
+ memset(&fb, 0, sizeof(fb));
+ if(depth_stencil_view)
+ {
+ struct pipe_surface* surf = ((GalliumD3D11DepthStencilView*)depth_stencil_view.p)->object;
+ fb.zsbuf = surf;
+ if(surf->width > fb.width)
+ fb.width = surf->width;
+ if(surf->height > fb.height)
+ fb.height = surf->height;
+ }
+ fb.nr_cbufs = num_render_target_views;
+ unsigned i;
+ for(i = 0; i < num_render_target_views; ++i)
+ {
+ if(render_target_views[i])
+ {
+ struct pipe_surface* surf = ((GalliumD3D11RenderTargetView*)render_target_views[i].p)->object;
+ fb.cbufs[i] = surf;
+ if(surf->width > fb.width)
+ fb.width = surf->width;
+ if(surf->height > fb.height)
+ fb.height = surf->height;
+ }
+ }
+
+ pipe->set_framebuffer_state(pipe, &fb);
+ }
+
+ /* TODO: the docs say that we should unbind conflicting resources (e.g. those bound for read while we are binding them for write too), but we aren't.
+ * Hopefully nobody relies on this happening
+ */
+
+ virtual void STDMETHODCALLTYPE OMSetRenderTargets(
+ __in_range(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) unsigned NumViews,
+ __in_ecount_opt(NumViews) ID3D11RenderTargetView *const *ppRenderTargetViews,
+ __in_opt ID3D11DepthStencilView *pDepthStencilView)
+ {
+ SYNCHRONIZED;
+ if(!ppRenderTargetViews)
+ NumViews = 0;
+ if(NumViews == num_render_target_views)
+ {
+ for(unsigned i = 0; i < NumViews; ++i)
+ {
+ if(ppRenderTargetViews[i] != render_target_views[i].p)
+ goto changed;
+ }
+ return;
+ }
+changed:
+ depth_stencil_view = pDepthStencilView;
+ unsigned i;
+ for(i = 0; i < NumViews; ++i)
+ {
+ render_target_views[i] = ppRenderTargetViews[i];
+#if API >= 11
+ om_unordered_access_views[i] = (ID3D11UnorderedAccessView*)NULL;
+#endif
+ }
+ for(; i < num_render_target_views; ++i)
+ render_target_views[i] = (ID3D11RenderTargetView*)NULL;
+ num_render_target_views = NumViews;
+ set_framebuffer();
+ }
+
+ virtual void STDMETHODCALLTYPE OMGetRenderTargets(
+ __in_range(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) unsigned NumViews,
+ __out_ecount_opt(NumViews) ID3D11RenderTargetView **ppRenderTargetViews,
+ __out_opt ID3D11DepthStencilView **ppDepthStencilView)
+ {
+ SYNCHRONIZED;
+ if(ppRenderTargetViews)
+ {
+ unsigned i;
+ for(i = 0; i < std::min(num_render_target_views, NumViews); ++i)
+ ppRenderTargetViews[i] = render_target_views[i].ref();
+
+ for(; i < NumViews; ++i)
+ ppRenderTargetViews[i] = 0;
+ }
+
+ if(ppDepthStencilView)
+ *ppDepthStencilView = depth_stencil_view.ref();
+ }
+
+#if API >= 11
+ /* TODO: what is this supposed to do _exactly_? are we doing the right thing? */
+ virtual void STDMETHODCALLTYPE OMSetRenderTargetsAndUnorderedAccessViews(
+ __in unsigned NumRTVs,
+ __in_ecount_opt(NumRTVs) ID3D11RenderTargetView *const *ppRenderTargetViews,
+ __in_opt ID3D11DepthStencilView *pDepthStencilView,
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) unsigned UAVStartSlot,
+ __in unsigned NumUAVs,
+ __in_ecount_opt(NumUAVs) ID3D11UnorderedAccessView *const *ppUnorderedAccessViews,
+ __in_ecount_opt(NumUAVs) const unsigned *pUAVInitialCounts)
+ {
+ SYNCHRONIZED;
+ if(NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
+ OMSetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView);
+
+ if(NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS)
+ {
+ for(unsigned i = 0; i < NumUAVs; ++i)
+ {
+ om_unordered_access_views[UAVStartSlot + i] = ppUnorderedAccessViews[i];
+ render_target_views[UAVStartSlot + i] = (ID3D11RenderTargetView*)0;
+ }
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE OMGetRenderTargetsAndUnorderedAccessViews(
+ __in_range(0, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT) unsigned NumRTVs,
+ __out_ecount_opt(NumRTVs) ID3D11RenderTargetView **ppRenderTargetViews,
+ __out_opt ID3D11DepthStencilView **ppDepthStencilView,
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - 1) unsigned UAVStartSlot,
+ __in_range(0, D3D11_PS_CS_UAV_REGISTER_COUNT - UAVStartSlot) unsigned NumUAVs,
+ __out_ecount_opt(NumUAVs) ID3D11UnorderedAccessView **ppUnorderedAccessViews)
+ {
+ SYNCHRONIZED;
+ if(ppRenderTargetViews)
+ OMGetRenderTargets(NumRTVs, ppRenderTargetViews, ppDepthStencilView);
+
+ if(ppUnorderedAccessViews)
+ {
+ for(unsigned i = 0; i < NumUAVs; ++i)
+ ppUnorderedAccessViews[i] = om_unordered_access_views[UAVStartSlot + i].ref();
+ }
+ }
+#endif
+
+ virtual void STDMETHODCALLTYPE SOSetTargets(
+ __in_range(0, D3D11_SO_BUFFER_SLOT_COUNT) unsigned NumBuffers,
+ __in_ecount_opt(NumBuffers) ID3D11Buffer *const *ppSOTargets,
+ __in_ecount_opt(NumBuffers) const unsigned *pOffsets)
+ {
+ SYNCHRONIZED;
+ unsigned i;
+ if(!ppSOTargets)
+ NumBuffers = 0;
+ bool changed = false;
+ for(i = 0; i < NumBuffers; ++i)
+ {
+ ID3D11Buffer* buffer = ppSOTargets[i];
+ if(buffer != so_targets[i].p || pOffsets[i] != so_offsets[i])
+ {
+ so_buffers[i] = buffer ? ((GalliumD3D11Buffer*)buffer)->resource : 0;
+ so_targets[i] = buffer;
+ so_offsets[i] = pOffsets[i];
+ changed = true;
+ }
+ }
+ for(; i < D3D11_SO_BUFFER_SLOT_COUNT; ++i)
+ {
+ if(so_targets[i].p || so_offsets[i])
+ {
+ changed = true;
+ so_targets[i] = (ID3D11Buffer*)0;
+ so_offsets[i] = 0;
+ }
+ }
+ num_so_targets = NumBuffers;
+
+ if(changed && caps.so)
+ pipe->set_stream_output_buffers(pipe, so_buffers, (int*)so_offsets, num_so_targets);
+ }
+
+ virtual void STDMETHODCALLTYPE SOGetTargets(
+ __in_range(0, D3D11_SO_BUFFER_SLOT_COUNT) unsigned NumBuffers,
+ __out_ecount(NumBuffers) ID3D11Buffer **ppSOTargets
+#if API < 11
+ , __out_ecount(NumBuffers) UINT *pOffsets
+#endif
+ )
+ {
+ SYNCHRONIZED;
+ for(unsigned i = 0; i < NumBuffers; ++i)
+ {
+ ppSOTargets[i] = so_targets[i].ref();
+#if API < 11
+ pOffsets[i] = so_offsets[i];
+#endif
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE Begin(
+ __in ID3D11Asynchronous *pAsync)
+ {
+ SYNCHRONIZED;
+ if(caps.queries)
+ pipe->begin_query(pipe, ((GalliumD3D11Asynchronous<>*)pAsync)->query);
+ }
+
+ virtual void STDMETHODCALLTYPE End(
+ __in ID3D11Asynchronous *pAsync)
+ {
+ SYNCHRONIZED;
+ if(caps.queries)
+ pipe->end_query(pipe, ((GalliumD3D11Asynchronous<>*)pAsync)->query);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetData(
+ __in ID3D11Asynchronous *pAsync,
+ __out_bcount_opt(DataSize) void *pData,
+ __in unsigned DataSize,
+ __in unsigned GetDataFlags)
+ {
+ SYNCHRONIZED;
+ if(!caps.queries)
+ return E_NOTIMPL;
+
+ GalliumD3D11Asynchronous<>* async = (GalliumD3D11Asynchronous<>*)pAsync;
+ void* data = alloca(async->data_size);
+ boolean ret = pipe->get_query_result(pipe, ((GalliumD3D11Asynchronous<>*)pAsync)->query, !(GetDataFlags & D3D11_ASYNC_GETDATA_DONOTFLUSH), data);
+ if(pData)
+ memcpy(pData, data, std::min(async->data_size, DataSize));
+ return ret ? S_OK : S_FALSE;
+ }
+
+ void set_render_condition()
+ {
+ if(caps.render_condition)
+ {
+ if(!render_predicate)
+ pipe->render_condition(pipe, 0, 0);
+ else
+ {
+ GalliumD3D11Predicate* predicate = (GalliumD3D11Predicate*)render_predicate.p;
+ if(!render_predicate_value && predicate->desc.Query == D3D11_QUERY_OCCLUSION_PREDICATE)
+ {
+ unsigned mode = (predicate->desc.MiscFlags & D3D11_QUERY_MISC_PREDICATEHINT) ? PIPE_RENDER_COND_NO_WAIT : PIPE_RENDER_COND_WAIT;
+ pipe->render_condition(pipe, predicate->query, mode);
+ }
+ else
+ {
+ /* TODO: add inverted predication to Gallium*/
+ pipe->render_condition(pipe, 0, 0);
+ }
+ }
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE SetPredication(
+ __in_opt ID3D11Predicate *pPredicate,
+ __in BOOL PredicateValue)
+ {
+ SYNCHRONIZED;
+ if(render_predicate.p != pPredicate || render_predicate_value != PredicateValue)
+ {
+ render_predicate = pPredicate;
+ render_predicate_value = PredicateValue;
+ set_render_condition();
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE GetPredication(
+ __out_opt ID3D11Predicate **ppPredicate,
+ __out_opt BOOL *pPredicateValue)
+ {
+ SYNCHRONIZED;
+ if(ppPredicate)
+ *ppPredicate = render_predicate.ref();
+ if(pPredicateValue)
+ *pPredicateValue = render_predicate_value;
+ }
+
+ static pipe_subresource d3d11_to_pipe_subresource(struct pipe_resource* resource, unsigned subresource)
+ {
+ pipe_subresource sr;
+ if(subresource <= resource->last_level)
+ {
+ sr.level = subresource;
+ sr.face = 0;
+ }
+ else
+ {
+ unsigned levels = resource->last_level + 1;
+ sr.level = subresource % levels;
+ sr.face = subresource / levels;
+ }
+ return sr;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in ID3D11Resource *pResource,
+ __in unsigned Subresource,
+ __in D3D11_MAP MapType,
+ __in unsigned MapFlags,
+ __out D3D11_MAPPED_SUBRESOURCE *pMappedResource)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)pResource;
+ if(resource->transfers.count(Subresource))
+ return E_FAIL;
+ pipe_subresource sr = d3d11_to_pipe_subresource(resource->resource, Subresource);
+ pipe_box box;
+ d3d11_to_pipe_box(resource->resource, sr.level, 0);
+ unsigned usage = 0;
+ if(MapType == D3D11_MAP_READ)
+ usage = PIPE_TRANSFER_READ;
+ else if(MapType == D3D11_MAP_WRITE)
+ usage = PIPE_TRANSFER_WRITE;
+ else if(MapType == D3D11_MAP_READ_WRITE)
+ usage = PIPE_TRANSFER_READ_WRITE;
+ else if(MapType == D3D11_MAP_WRITE_DISCARD)
+ usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD;
+ else if(MapType == D3D11_MAP_WRITE_NO_OVERWRITE)
+ usage = PIPE_TRANSFER_WRITE | PIPE_TRANSFER_NOOVERWRITE;
+ else
+ return E_INVALIDARG;
+ if(MapType & D3D10_MAP_FLAG_DO_NOT_WAIT)
+ usage |= PIPE_TRANSFER_DONTBLOCK;
+ struct pipe_transfer* transfer = pipe->get_transfer(pipe, resource->resource, sr, usage, &box);
+ if(!transfer) {
+ if(MapType & D3D10_MAP_FLAG_DO_NOT_WAIT)
+ return DXGI_ERROR_WAS_STILL_DRAWING;
+ else
+ return E_FAIL;
+ }
+ resource->transfers[Subresource] = transfer;
+ pipe->transfer_map(pipe, transfer);
+ pMappedResource->pData = transfer->data;
+ pMappedResource->RowPitch = transfer->stride;
+ pMappedResource->DepthPitch = transfer->slice_stride;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE Unmap(
+ __in ID3D11Resource *pResource,
+ __in unsigned Subresource)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)pResource;
+ std::unordered_map<unsigned, pipe_transfer*>::iterator i = resource->transfers.find(Subresource);
+ if(i != resource->transfers.end())
+ {
+ pipe->transfer_unmap(pipe, i->second);
+ pipe->transfer_destroy(pipe, i->second);
+ resource->transfers.erase(i);
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE CopySubresourceRegion(
+ __in ID3D11Resource *pDstResource,
+ __in unsigned DstSubresource,
+ __in unsigned DstX,
+ __in unsigned DstY,
+ __in unsigned DstZ,
+ __in ID3D11Resource *pSrcResource,
+ __in unsigned SrcSubresource,
+ __in_opt const D3D11_BOX *pSrcBox)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)pDstResource;
+ GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)pSrcResource;
+ pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, DstSubresource);
+ pipe_subresource subsrc = d3d11_to_pipe_subresource(src->resource, SrcSubresource);
+ pipe_box box = d3d11_to_pipe_box(src->resource, subsrc.level, pSrcBox);
+ for(unsigned i = 0; i < box.depth; ++i)
+ {
+ pipe->resource_copy_region(pipe,
+ dst->resource, subdst, DstX, DstY, DstZ + i,
+ src->resource, subsrc, box.x, box.y, box.z + i,
+ box.width, box.height);
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE CopyResource(
+ __in ID3D11Resource *pDstResource,
+ __in ID3D11Resource *pSrcResource)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)pDstResource;
+ GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)pSrcResource;
+ pipe_subresource sr;
+ unsigned faces = dst->resource->target == PIPE_TEXTURE_CUBE ? 6 : 1;
+
+ for(sr.face = 0; sr.face < faces; ++sr.face)
+ {
+ for(sr.level = 0; sr.level <= dst->resource->last_level; ++sr.level)
+ {
+ unsigned w = u_minify(dst->resource->width0, sr.level);
+ unsigned h = u_minify(dst->resource->height0, sr.level);
+ unsigned d = u_minify(dst->resource->depth0, sr.level);
+ for(unsigned i = 0; i < d; ++i)
+ {
+ pipe->resource_copy_region(pipe,
+ dst->resource, sr, 0, 0, i,
+ src->resource, sr, 0, 0, i,
+ w, h);
+ }
+ }
+ }
+ }
+
+ virtual void STDMETHODCALLTYPE UpdateSubresource(
+ __in ID3D11Resource *pDstResource,
+ __in unsigned DstSubresource,
+ __in_opt const D3D11_BOX *pDstBox,
+ __in const void *pSrcData,
+ __in unsigned SrcRowPitch,
+ __in unsigned SrcDepthPitch)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)pDstResource;
+ pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, DstSubresource);
+ pipe_box box = d3d11_to_pipe_box(dst->resource, subdst.level, pDstBox);
+ pipe->transfer_inline_write(pipe, dst->resource, subdst, PIPE_TRANSFER_WRITE, &box, pSrcData, SrcRowPitch, SrcDepthPitch);
+ }
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE CopyStructureCount(
+ __in ID3D11Buffer *pDstBuffer,
+ __in unsigned DstAlignedByteOffset,
+ __in ID3D11UnorderedAccessView *pSrcView)
+ {
+ SYNCHRONIZED;
+ }
+#endif
+
+ virtual void STDMETHODCALLTYPE ClearRenderTargetView(
+ __in ID3D11RenderTargetView *pRenderTargetView,
+ __in const float ColorRGBA[4])
+ {
+ SYNCHRONIZED;
+ GalliumD3D11RenderTargetView* view = ((GalliumD3D11RenderTargetView*)pRenderTargetView);
+ pipe->clear_render_target(pipe, view->object, ColorRGBA, 0, 0, view->object->width, view->object->height);
+ }
+
+ virtual void STDMETHODCALLTYPE ClearDepthStencilView(
+ __in ID3D11DepthStencilView *pDepthStencilView,
+ __in unsigned ClearFlags,
+ __in float Depth,
+ __in UINT8 Stencil)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11DepthStencilView* view = ((GalliumD3D11DepthStencilView*)pDepthStencilView);
+ unsigned flags = 0;
+ if(ClearFlags & D3D11_CLEAR_DEPTH)
+ flags |= PIPE_CLEAR_DEPTH;
+ if(ClearFlags & D3D11_CLEAR_STENCIL)
+ flags |= PIPE_CLEAR_STENCIL;
+ pipe->clear_depth_stencil(pipe, view->object, flags, Depth, Stencil, 0, 0, view->object->width, view->object->height);
+ }
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewUint(
+ __in ID3D11UnorderedAccessView *pUnorderedAccessView,
+ __in const unsigned Values[ 4 ])
+ {
+ SYNCHRONIZED;
+ }
+
+ virtual void STDMETHODCALLTYPE ClearUnorderedAccessViewFloat(
+ __in ID3D11UnorderedAccessView *pUnorderedAccessView,
+ __in const float Values[ 4 ])
+ {
+ SYNCHRONIZED;
+ }
+#endif
+
+ virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
+ {
+ pipe->bind_blend_state(pipe, blend_state.p ? blend_state.p->object : default_blend);
+ pipe->bind_depth_stencil_alpha_state(pipe, depth_stencil_state.p ? depth_stencil_state.p->object : default_depth_stencil);
+ pipe->bind_rasterizer_state(pipe, rasterizer_state.p ? rasterizer_state.p->object : default_rasterizer);
+ pipe->bind_vertex_elements_state(pipe, input_layout.p ? input_layout.p->object : default_input_layout);
+ pipe->bind_fs_state(pipe, shaders[D3D11_STAGE_PS].p ? shaders[D3D11_STAGE_PS].p->object : default_shaders[PIPE_SHADER_FRAGMENT]);
+ pipe->bind_vs_state(pipe, shaders[D3D11_STAGE_VS].p ? shaders[D3D11_STAGE_VS].p->object : default_shaders[PIPE_SHADER_VERTEX]);
+ if(caps.gs)
+ pipe->bind_gs_state(pipe, shaders[D3D11_STAGE_GS].p ? shaders[D3D11_STAGE_GS].p->object : default_shaders[PIPE_SHADER_GEOMETRY]);
+ set_framebuffer();
+ set_viewport();
+ set_clip();
+ set_render_condition();
+ // TODO: restore stream output
+
+ update_flags |= UPDATE_VERTEX_BUFFERS | (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_PS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_PS));
+ }
+
+ virtual void STDMETHODCALLTYPE GenerateMips(
+ __in ID3D11ShaderResourceView *pShaderResourceView)
+ {
+ SYNCHRONIZED;
+
+ GalliumD3D11ShaderResourceView* view = (GalliumD3D11ShaderResourceView*)pShaderResourceView;
+ if(caps.gs)
+ pipe->bind_gs_state(pipe, 0);
+ if(caps.so)
+ pipe->bind_stream_output_state(pipe, 0);
+ if(pipe->render_condition)
+ pipe->render_condition(pipe, 0, 0);
+ util_gen_mipmap(gen_mipmap, view->object, 0, 0, view->object->texture->last_level, PIPE_TEX_FILTER_LINEAR);
+ RestoreGalliumStateBlitOnly();
+ }
+
+ virtual void STDMETHODCALLTYPE RestoreGalliumState()
+ {
+ SYNCHRONIZED;
+ RestoreGalliumStateBlitOnly();
+
+ set_index_buffer();
+ set_stencil_ref();
+ pipe->set_blend_color(pipe, (struct pipe_blend_color*)blend_color);
+ pipe->set_sample_mask(pipe, sample_mask);
+
+ for(unsigned s = 0; s < 3; ++s)
+ {
+ unsigned num = std::min(caps.constant_buffers[s], (unsigned)D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
+ for(unsigned i = 0; i < num; ++i)
+ pipe->set_constant_buffer(pipe, s, i, constant_buffers[s][i].p ? constant_buffers[s][i].p->resource : 0);
+ }
+
+ if(caps.so)
+ pipe->set_stream_output_buffers(pipe, so_buffers, (int*)so_offsets, num_so_targets);
+
+ update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_VS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_VS));
+ update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + D3D11_STAGE_GS)) | (1 << (UPDATE_VIEWS_SHIFT + D3D11_STAGE_GS));
+
+ set_scissor();
+ }
+
+#if API >= 11
+ /* TODO: hack SRVs or sampler states to handle this, or add to Gallium */
+ virtual void STDMETHODCALLTYPE SetResourceMinLOD(
+ __in ID3D11Resource *pResource,
+ float MinLOD)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)pResource;
+ if(resource->min_lod != MinLOD)
+ {
+ // TODO: actually do anything?
+ resource->min_lod = MinLOD;
+ }
+ }
+
+ virtual float STDMETHODCALLTYPE GetResourceMinLOD(
+ __in ID3D11Resource *pResource)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* resource = (GalliumD3D11Resource<>*)pResource;
+ return resource->min_lod;
+ }
+#endif
+
+ virtual void STDMETHODCALLTYPE ResolveSubresource(
+ __in ID3D11Resource *pDstResource,
+ __in unsigned DstSubresource,
+ __in ID3D11Resource *pSrcResource,
+ __in unsigned SrcSubresource,
+ __in DXGI_FORMAT Format)
+ {
+ SYNCHRONIZED;
+ GalliumD3D11Resource<>* dst = (GalliumD3D11Resource<>*)pDstResource;
+ GalliumD3D11Resource<>* src = (GalliumD3D11Resource<>*)pSrcResource;
+ pipe_subresource subdst = d3d11_to_pipe_subresource(dst->resource, DstSubresource);
+ pipe_subresource subsrc = d3d11_to_pipe_subresource(src->resource, SrcSubresource);
+ pipe->resource_resolve(pipe, dst->resource, subdst, src->resource, subsrc);
+ }
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE ExecuteCommandList(
+ __in ID3D11CommandList *pCommandList,
+ BOOL RestoreContextState)
+ {
+ SYNCHRONIZED;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE FinishCommandList(
+ BOOL RestoreDeferredContextState,
+ __out_opt ID3D11CommandList **ppCommandList)
+ {
+ SYNCHRONIZED;
+ return E_NOTIMPL;
+ }
+#endif
+
+ virtual void STDMETHODCALLTYPE ClearState(void)
+ {
+ SYNCHRONIZED;
+
+ // we qualify all calls so that we avoid virtual dispatch and might get them inlined
+ // TODO: make sure all this gets inlined, which might require more compiler flags
+ // TODO: optimize this
+#if API >= 11
+ GalliumD3D11DeviceContext::PSSetShader(0, 0, 0);
+ GalliumD3D11DeviceContext::GSSetShader(0, 0, 0);
+ GalliumD3D11DeviceContext::VSSetShader(0, 0, 0);
+ GalliumD3D11DeviceContext::HSSetShader(0, 0, 0);
+ GalliumD3D11DeviceContext::DSSetShader(0, 0, 0);
+ GalliumD3D11DeviceContext::CSSetShader(0, 0, 0);
+#else
+ GalliumD3D11DeviceContext::PSSetShader(0);
+ GalliumD3D11DeviceContext::GSSetShader(0);
+ GalliumD3D11DeviceContext::VSSetShader(0);
+#endif
+
+ GalliumD3D11DeviceContext::IASetInputLayout(0);
+ GalliumD3D11DeviceContext::IASetIndexBuffer(0, DXGI_FORMAT_UNKNOWN, 0);
+ GalliumD3D11DeviceContext::RSSetState(0);
+ GalliumD3D11DeviceContext::OMSetDepthStencilState(0, 0);
+ GalliumD3D11DeviceContext::OMSetBlendState(0, (float*)zero_data, ~0);
+ GalliumD3D11DeviceContext::SetPredication(0, 0);
+ GalliumD3D11DeviceContext::IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED);
+
+ GalliumD3D11DeviceContext::PSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+ GalliumD3D11DeviceContext::GSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+ GalliumD3D11DeviceContext::VSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+#if API >= 11
+ GalliumD3D11DeviceContext::HSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+ GalliumD3D11DeviceContext::DSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+ GalliumD3D11DeviceContext::CSSetConstantBuffers(0, D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, (ID3D11Buffer**)zero_data);
+#endif
+
+ GalliumD3D11DeviceContext::IASetVertexBuffers(0, num_vertex_buffers, (ID3D11Buffer**)zero_data, (unsigned*)zero_data, (unsigned*)zero_data);
+#if API >= 11
+ GalliumD3D11DeviceContext::OMSetRenderTargetsAndUnorderedAccessViews(0, 0, 0 , 0, 0, 0, 0);
+#else
+ GalliumD3D11DeviceContext::OMSetRenderTargets(0, 0, 0 );
+#endif
+ GalliumD3D11DeviceContext::SOSetTargets(0, 0, 0);
+
+ GalliumD3D11DeviceContext::PSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11ShaderResourceView**)zero_data);
+ GalliumD3D11DeviceContext::GSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11ShaderResourceView**)zero_data);
+ GalliumD3D11DeviceContext::VSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11ShaderResourceView**)zero_data);
+#if API >= 11
+ GalliumD3D11DeviceContext::HSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11ShaderResourceView**)zero_data);
+ GalliumD3D11DeviceContext::DSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11ShaderResourceView**)zero_data);
+ GalliumD3D11DeviceContext::CSSetShaderResources(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11ShaderResourceView**)zero_data);
+#endif
+
+ GalliumD3D11DeviceContext::PSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_PS], (ID3D11SamplerState**)zero_data);
+ GalliumD3D11DeviceContext::GSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_GS], (ID3D11SamplerState**)zero_data);
+ GalliumD3D11DeviceContext::VSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_VS], (ID3D11SamplerState**)zero_data);
+#if API >= 11
+ GalliumD3D11DeviceContext::HSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_HS], (ID3D11SamplerState**)zero_data);
+ GalliumD3D11DeviceContext::DSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_DS], (ID3D11SamplerState**)zero_data);
+ GalliumD3D11DeviceContext::CSSetSamplers(0, num_shader_resource_views[D3D11_STAGE_CS], (ID3D11SamplerState**)zero_data);
+#endif
+
+ GalliumD3D11DeviceContext::RSSetViewports(0, 0);
+ GalliumD3D11DeviceContext::RSSetScissorRects(0, 0);
+ }
+
+ virtual void STDMETHODCALLTYPE Flush(void)
+ {
+ SYNCHRONIZED;
+ pipe->flush(pipe, PIPE_FLUSH_FRAME, 0);
+ }
+
+ /* In Direct3D 10, if the reference count of an object drops to 0, it is automatically
+ * cleanly unbound from the pipeline.
+ * In Direct3D 11, the pipeline holds a reference.
+ *
+ * Note that instead of always scanning the pipeline on destruction, we could
+ * maintain the internal reference count on DirectX 10 and use it to check if an
+ * object is still bound.
+ * Presumably, on average, scanning is faster if the application is well written.
+ */
+#if API < 11
+#define IMPLEMENT_SIMPLE_UNBIND(name, member, gallium, def) \
+ void Unbind##name(ID3D11##name* state) \
+ { \
+ SYNCHRONIZED; \
+ if((void*)state == (void*)member.p) \
+ { \
+ member.p = 0; \
+ pipe->bind_##gallium##_state(pipe, default_##def); \
+ } \
+ }
+ IMPLEMENT_SIMPLE_UNBIND(BlendState, blend_state, blend, blend)
+ IMPLEMENT_SIMPLE_UNBIND(RasterizerState, rasterizer_state, rasterizer, rasterizer)
+ IMPLEMENT_SIMPLE_UNBIND(DepthStencilState, depth_stencil_state, depth_stencil_alpha, depth_stencil)
+ IMPLEMENT_SIMPLE_UNBIND(InputLayout, input_layout, vertex_elements, input_layout)
+ IMPLEMENT_SIMPLE_UNBIND(PixelShader, shaders[D3D11_STAGE_PS], fs, shaders[D3D11_STAGE_PS])
+ IMPLEMENT_SIMPLE_UNBIND(VertexShader, shaders[D3D11_STAGE_VS], vs, shaders[D3D11_STAGE_VS])
+ IMPLEMENT_SIMPLE_UNBIND(GeometryShader, shaders[D3D11_STAGE_GS], gs, shaders[D3D11_STAGE_GS])
+
+ void UnbindPredicate(ID3D11Predicate* predicate)
+ {
+ SYNCHRONIZED;
+ if(predicate == render_predicate)
+ {
+ render_predicate.p = NULL;
+ render_predicate_value = 0;
+ pipe->render_condition(pipe, 0, 0);
+ }
+ }
+
+ void UnbindSamplerState(ID3D11SamplerState* state)
+ {
+ SYNCHRONIZED;
+ for(unsigned s = 0; s < D3D11_STAGES; ++s)
+ {
+ for(unsigned i = 0; i < num_samplers[s]; ++i)
+ {
+ if(samplers[s][i] == state)
+ {
+ samplers[s][i].p = NULL;
+ sampler_csos[s].v[i] = NULL;
+ update_flags |= (1 << (UPDATE_SAMPLERS_SHIFT + s));
+ }
+ }
+ }
+ }
+
+ void UnbindBuffer(ID3D11Buffer* buffer)
+ {
+ SYNCHRONIZED;
+ if(buffer == index_buffer)
+ {
+ index_buffer.p = 0;
+ index_format = DXGI_FORMAT_UNKNOWN;
+ index_offset = 0;
+ struct pipe_index_buffer ib;
+ memset(&ib, 0, sizeof(ib));
+ pipe->set_index_buffer(pipe, &ib);
+ }
+
+ for(unsigned i = 0; i < num_vertex_buffers; ++i)
+ {
+ if(buffer == input_buffers[i])
+ {
+ input_buffers[i].p = 0;
+ memset(&vertex_buffers[num_vertex_buffers], 0, sizeof(vertex_buffers[num_vertex_buffers]));
+ update_flags |= UPDATE_VERTEX_BUFFERS;
+ }
+ }
+
+ for(unsigned s = 0; s < D3D11_STAGES; ++s)
+ {
+ for(unsigned i = 0; i < sizeof(constant_buffers) / sizeof(constant_buffers[0]); ++i)
+ {
+ if(constant_buffers[s][i] == buffer)
+ {
+ constant_buffers[s][i] = (ID3D10Buffer*)NULL;
+ pipe->set_constant_buffer(pipe, s, i, NULL);
+ }
+ }
+ }
+ }
+
+ void UnbindDepthStencilView(ID3D11DepthStencilView* view)
+ {
+ SYNCHRONIZED;
+ if(view == depth_stencil_view)
+ {
+ depth_stencil_view.p = NULL;
+ set_framebuffer();
+ }
+ }
+
+ void UnbindRenderTargetView(ID3D11RenderTargetView* view)
+ {
+ SYNCHRONIZED;
+ bool any_bound = false;
+ for(unsigned i = 0; i < num_render_target_views; ++i)
+ {
+ if(render_target_views[i] == view)
+ {
+ render_target_views[i].p = NULL;
+ any_bound = true;
+ }
+ }
+ if(any_bound)
+ set_framebuffer();
+ }
+
+ void UnbindShaderResourceView(ID3D11ShaderResourceView* view)
+ {
+ SYNCHRONIZED;
+ for(unsigned s = 0; s < D3D11_STAGES; ++s)
+ {
+ for(unsigned i = 0; i < num_shader_resource_views[s]; ++i)
+ {
+ if(shader_resource_views[s][i] == view)
+ {
+ shader_resource_views[s][i].p = NULL;
+ sampler_views[s][i] = NULL;
+ update_flags |= (1 << (UPDATE_VIEWS_SHIFT + s));
+ }
+ }
+ }
+ }
+#endif
+
+#undef SYNCHRONIZED
+};
+
+#if API >= 11
+/* This approach serves two purposes.
+ * First, we don't want to do an atomic operation to manipulate the reference
+ * count every time something is bound/unbound to the pipeline, since they are
+ * expensive.
+ * Fortunately, the immediate context can only be used by a single thread, so
+ * we don't have to use them, as long as a separate reference count is used
+ * (see dual_refcnt_t).
+ *
+ * Second, we want to avoid the Device -> DeviceContext -> bound DeviceChild -> Device
+ * garbage cycle.
+ * To avoid it, DeviceChild doesn't hold a reference to Device as usual, but adds
+ * one for each external reference count, while internal nonatomic_add_ref doesn't
+ * add any.
+ *
+ * Note that ideally we would to eliminate the non-atomic op too, but this is more
+ * complicated, since we would either need to use garbage collection and give up
+ * deterministic destruction (especially bad for large textures), or scan the whole
+ * pipeline state every time the reference count of object drops to 0, which risks
+ * pathological slowdowns.
+ *
+ * Since this microoptimization should matter relatively little, let's avoid it for now.
+ *
+ * Note that deferred contexts don't use this, since as a whole, they must thread-safe.
+ * Eliminating the atomic ops for deferred contexts seems substantially harder.
+ * This might be a problem if they are used in a one-shot multithreaded rendering
+ * fashion, where SMP cacheline bouncing on the reference count may be visible.
+ *
+ * The idea would be to attach a structure of reference counts indexed by deferred
+ * context id to each object. Ideally, this should be organized like ext2 block pointers.
+ *
+ * Every deferred context would get a reference count in its own cacheline.
+ * The external count is protected by a lock bit, and there is also a "lock bit" in each
+ * internal count.
+ *
+ * When the external count has to be dropped to 0, the lock bit is taken and all internal
+ * reference counts are scanned, taking a count of them. A flag would also be set on them.
+ * Deferred context manipulation would notice the flag, and update the count.
+ * Once the count goes to zero, the object is freed.
+ *
+ * The problem of this is that if the external reference count ping-pongs between
+ * zero and non-zero, the scans will take a lot of time.
+ *
+ * The idea to solve this is to compute the scans in a binary-tree like fashion, where
+ * each binary tree node would have a "determined bit", which would be invalidated
+ * by manipulations.
+ *
+ * However, all this complexity might actually be a loss in most cases, so let's just
+ * stick to a single atomic refcnt for now.
+ *
+ * Also, we don't even support deferred contexts yet, so this can wait.
+ */
+struct nonatomic_device_child_ptr_traits
+{
+ static void add_ref(void* p)
+ {
+ if(p)
+ ((GalliumD3D11DeviceChild<>*)p)->nonatomic_add_ref();
+ }
+
+ static void release(void* p)
+ {
+ if(p)
+ ((GalliumD3D11DeviceChild<>*)p)->nonatomic_release();
+ }
+};
+
+struct GalliumD3D11ImmediateDeviceContext
+ : public GalliumD3D11DeviceContext<nonatomic_device_child_ptr_traits>
+{
+ GalliumD3D11ImmediateDeviceContext(GalliumD3D11Screen* device, pipe_context* pipe, unsigned context_flags = 0)
+ : GalliumD3D11DeviceContext(device, pipe, context_flags)
+ {
+ // not necessary, but tests that the API at least basically works
+ ClearState();
+ }
+
+ /* we do this since otherwise we would have a garbage cycle between this and the device */
+ virtual ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return this->device->AddRef();
+ }
+
+ virtual ULONG STDMETHODCALLTYPE Release()
+ {
+ return this->device->Release();
+ }
+
+ virtual D3D11_DEVICE_CONTEXT_TYPE STDMETHODCALLTYPE GetType()
+ {
+ return D3D11_DEVICE_CONTEXT_IMMEDIATE;
+ }
+};
+
+static ID3D11DeviceContext* GalliumD3D11ImmediateDeviceContext_Create(GalliumD3D11Screen* device, struct pipe_context* pipe, bool owns_pipe)
+{
+ return new GalliumD3D11ImmediateDeviceContext(device, pipe, owns_pipe);
+}
+
+static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(ID3D11DeviceContext* context)
+{
+ ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumState();
+}
+
+static void GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(ID3D11DeviceContext* context)
+{
+ ((GalliumD3D11ImmediateDeviceContext*)context)->RestoreGalliumStateBlitOnly();
+}
+
+static void GalliumD3D11ImmediateDeviceContext_Destroy(ID3D11DeviceContext* context)
+{
+ delete (GalliumD3D11ImmediateDeviceContext*)context;
+}
+#endif
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h
new file mode 100644
index 0000000000..ad6b28fceb
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_objects.h
@@ -0,0 +1,715 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+template<typename Base = ID3D11DeviceChild>
+struct GalliumD3D11DeviceChild : public GalliumPrivateDataComObject<Base, dual_refcnt_t>
+{
+ GalliumD3D11Screen* device; // must not be null
+
+
+ // if this is called, the subclass constructor must set device itself
+ GalliumD3D11DeviceChild()
+ : device(0)
+ {}
+
+ GalliumD3D11DeviceChild(GalliumD3D11Screen* p_device)
+ {
+ // we store the reference count minus one in refcnt
+ device = p_device;
+ device->AddRef();
+ }
+
+ /* The purpose of this is to avoid cyclic garbage, since this won't hold
+ * a pointer to the device if it is only held by a pipeline binding in the immediate context
+ *
+ * TODO: we could only manipulate the device refcnt when atomic_refcnt == 0 changes,
+ * but this requires more complex atomic ops
+ */
+ inline ULONG add_ref()
+ {
+ device->AddRef();
+ return GalliumPrivateDataComObject<Base, dual_refcnt_t>::add_ref();
+ }
+
+ inline ULONG release()
+ {
+ device->Release();
+ return GalliumPrivateDataComObject<Base, dual_refcnt_t>::release();
+ }
+
+ virtual ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return add_ref();
+ }
+
+ virtual ULONG STDMETHODCALLTYPE Release()
+ {
+ return release();
+ }
+
+ virtual void STDMETHODCALLTYPE GetDevice(
+ __out ID3D11Device **ppDevice
+ )
+ {
+ device->AddRef();
+ *ppDevice = device;
+ }
+};
+
+template<typename Base = ID3D11DeviceChild, typename Object = void>
+struct GalliumD3D11Object : public GalliumD3D11DeviceChild<Base>
+{
+ Object* object;
+ GalliumD3D11Object(GalliumD3D11Screen* device, Object* object)
+ : GalliumD3D11DeviceChild<Base>(device), object(object)
+ {}
+
+ virtual ~GalliumD3D11Object();
+};
+
+#define IMPLEMENT_OBJECT_DTOR(name, gallium) \
+template<> \
+GalliumD3D11Object<ID3D11##name, void>::~GalliumD3D11Object() \
+{ \
+ DX10_ONLY(device->Unbind##name(this)); \
+ device->immediate_pipe->delete_##gallium##_state(device->immediate_pipe, object); \
+}
+
+#define IMPLEMENT_VIEW_DTOR(name, gallium) \
+template<> \
+GalliumD3D11Object<ID3D11##name, struct pipe_##gallium>::~GalliumD3D11Object() \
+{ \
+ DX10_ONLY(device->Unbind##name(this)); \
+ pipe_##gallium##_reference(&object, 0); \
+}
+
+IMPLEMENT_OBJECT_DTOR(InputLayout, vertex_elements)
+IMPLEMENT_OBJECT_DTOR(DepthStencilState, depth_stencil_alpha)
+IMPLEMENT_OBJECT_DTOR(RasterizerState, rasterizer)
+IMPLEMENT_OBJECT_DTOR(SamplerState, sampler)
+IMPLEMENT_OBJECT_DTOR(BlendState, blend)
+IMPLEMENT_OBJECT_DTOR(VertexShader, vs)
+IMPLEMENT_OBJECT_DTOR(PixelShader, fs)
+IMPLEMENT_OBJECT_DTOR(GeometryShader, gs)
+
+IMPLEMENT_VIEW_DTOR(ShaderResourceView, sampler_view)
+IMPLEMENT_VIEW_DTOR(RenderTargetView, surface)
+IMPLEMENT_VIEW_DTOR(DepthStencilView, surface)
+
+#if API >= 11
+// IMPLEMENT_VIEW_DTOR(UnorderedAccessView, surface);
+// IMPLEMENT_OBJECT_DTOR(HullShader, tcs);
+// IMPLEMENT_OBJECT_DTOR(DomainShader, tes);
+// IMPLEMENT_OBJECT_DTOR(ComputeShader, cs);
+#else
+IMPLEMENT_OBJECT_DTOR(BlendState1, blend)
+IMPLEMENT_VIEW_DTOR(ShaderResourceView1, sampler_view)
+#endif
+
+template<typename Base, typename Desc, typename Object = void>
+struct GalliumD3D11DescribedObject : public GalliumD3D11Object<Base, Object>
+{
+ Desc desc;
+ GalliumD3D11DescribedObject(GalliumD3D11Screen* device, Object* object, const Desc& desc)
+ : GalliumD3D11Object<Base, Object>(device, object), desc(desc)
+ {}
+
+ virtual void STDMETHODCALLTYPE GetDesc(Desc *pDesc)
+ {
+ memcpy(pDesc, &desc, sizeof(desc));
+ }
+};
+
+typedef GalliumD3D11Object<ID3D11InputLayout> GalliumD3D11InputLayout;
+typedef GalliumD3D11DescribedObject<ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC> GalliumD3D11DepthStencilState;
+typedef GalliumD3D11DescribedObject<ID3D11RasterizerState, D3D11_RASTERIZER_DESC> GalliumD3D11RasterizerStateBase;
+typedef GalliumD3D11DescribedObject<ID3D11SamplerState, D3D11_SAMPLER_DESC> GalliumD3D11SamplerState;
+
+#if API >= 11
+typedef GalliumD3D11DescribedObject<ID3D11BlendState, D3D11_BLEND_DESC> GalliumD3D11BlendState;
+#else
+typedef GalliumD3D10DescribedObject<ID3D10BlendState1, D3D10_BLEND_DESC> GalliumD3D10BlendStateBase;
+
+struct GalliumD3D10BlendState : public GalliumD3D10BlendStateBase
+{
+ static D3D10_BLEND_DESC convert_to_d3d10(const D3D10_BLEND_DESC1& desc1)
+ {
+ D3D10_BLEND_DESC desc;
+ desc.AlphaToCoverageEnable = desc1.AlphaToCoverageEnable;
+ desc.SrcBlend = desc1.RenderTarget[0].SrcBlend;
+ desc.DestBlend = desc1.RenderTarget[0].DestBlend;
+ desc.BlendOp = desc1.RenderTarget[0].BlendOp;
+ desc.SrcBlendAlpha = desc1.RenderTarget[0].SrcBlendAlpha;
+ desc.DestBlendAlpha = desc1.RenderTarget[0].DestBlendAlpha;
+ desc.BlendOpAlpha = desc1.RenderTarget[0].BlendOpAlpha;
+ for(unsigned i = 0; i < 8; ++i)
+ {
+ desc.BlendEnable[i] = desc1.RenderTarget[i].BlendEnable;
+ desc.RenderTargetWriteMask[i] = desc1.RenderTarget[i].RenderTargetWriteMask;
+ }
+ return desc;
+ }
+
+ D3D10_BLEND_DESC1 desc1;
+
+ GalliumD3D10BlendState(GalliumD3D10Screen* device, void* object, const D3D10_BLEND_DESC& desc)
+ : GalliumD3D10BlendStateBase(device, object, desc)
+ {
+ memset(&desc1, 0, sizeof(desc1));
+ desc1.AlphaToCoverageEnable = desc.AlphaToCoverageEnable;
+ desc1.RenderTarget[0].SrcBlend = desc.SrcBlend;
+ desc1.RenderTarget[0].DestBlend = desc.DestBlend;
+ desc1.RenderTarget[0].BlendOp = desc.BlendOp;
+ desc1.RenderTarget[0].SrcBlendAlpha = desc.SrcBlendAlpha;
+ desc1.RenderTarget[0].DestBlendAlpha = desc.DestBlendAlpha;
+ desc1.RenderTarget[0].BlendOpAlpha = desc.BlendOpAlpha;
+ for(unsigned i = 0; i < 8; ++i)
+ {
+ desc1.RenderTarget[i].BlendEnable = desc.BlendEnable[i];
+ desc1.RenderTarget[i].RenderTargetWriteMask = desc.RenderTargetWriteMask[i];
+ }
+ }
+
+ GalliumD3D10BlendState(GalliumD3D10Screen* device, void* object, const D3D10_BLEND_DESC1& desc)
+ : GalliumD3D10BlendStateBase(device, object, convert_to_d3d10(desc)), desc1(desc1)
+ {}
+
+ virtual void STDMETHODCALLTYPE GetDesc1(D3D10_BLEND_DESC1 *pDesc)
+ {
+ memcpy(pDesc, &desc1, sizeof(desc1));
+ }
+};
+#endif
+
+struct GalliumD3D11RasterizerState : public GalliumD3D11RasterizerStateBase
+{
+ bool depth_clamp;
+
+ GalliumD3D11RasterizerState(GalliumD3D11Screen* device, void* object, const D3D11_RASTERIZER_DESC& desc, bool depth_clamp)
+ : GalliumD3D11RasterizerStateBase(device, object, desc), depth_clamp(depth_clamp)
+ {}
+};
+
+template<typename Base = ID3D11DeviceChild>
+struct GalliumD3D11Shader : public GalliumD3D11Object<Base>
+{
+ std::vector<int> slot_to_resource;
+ std::vector<int> slot_to_sampler;
+
+ GalliumD3D11Shader(GalliumD3D11Screen* device, void* object)
+ : GalliumD3D11Object<Base>(device, object)
+ {}
+};
+
+typedef GalliumD3D11Shader<ID3D11VertexShader> GalliumD3D11VertexShader;
+typedef GalliumD3D11Shader<ID3D11GeometryShader> GalliumD3D11GeometryShader;
+typedef GalliumD3D11Shader<ID3D11PixelShader> GalliumD3D11PixelShader;
+
+#if API >= 11
+/*
+typedef GalliumD3D11Shader<ID3D11HullShader> GalliumD3D11HullShader;
+typedef GalliumD3D11Shader<ID3D11DomainShader> GalliumD3D11DomainShader;
+typedef GalliumD3D11Shader<ID3D11ComputeShader> GalliumD3D11ComputeShader;
+*/
+#endif
+
+template<typename Base = ID3D11Resource>
+struct GalliumD3D11ResourceBase : public GalliumD3D11DeviceChild<Base>
+{
+ unsigned eviction_priority;
+
+ virtual void STDMETHODCALLTYPE SetEvictionPriority(
+ __in unsigned EvictionPriority)
+ {
+ eviction_priority = EvictionPriority;
+ }
+
+ virtual unsigned STDMETHODCALLTYPE GetEvictionPriority()
+ {
+ return eviction_priority;
+ }
+};
+
+template<typename Real>
+struct GalliumDXGIResource : public IDXGIResource
+{
+ virtual HRESULT STDMETHODCALLTYPE SetEvictionPriority(
+ __in unsigned EvictionPriority)
+ {
+ static_cast<Real*>(this)->eviction_priority = EvictionPriority;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetEvictionPriority(unsigned* pEvictionPriority)
+ {
+ *pEvictionPriority = static_cast<Real*>(this)->eviction_priority;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetDevice(
+ __in REFIID riid,
+ __out void **ppParent)
+ {
+ if(!static_cast<Real*>(this)->device)
+ return E_NOINTERFACE;
+ return static_cast<Real*>(this)->device->QueryInterface(riid, ppParent);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetParent(
+ __in REFIID riid,
+ __out void **ppParent)
+ {
+ if(!static_cast<Real*>(this)->device)
+ return E_NOINTERFACE;
+ return static_cast<Real*>(this)->device->QueryInterface(riid, ppParent);
+ }
+};
+
+template<typename T>
+struct com_traits<GalliumDXGIResource<T> > : public com_traits<IDXGIResource>
+{};
+
+template<typename Base = ID3D11Resource>
+struct GalliumD3D11Resource
+ : public GalliumMultiComObject<
+ GalliumMultiPrivateDataComObject<
+ GalliumD3D11ResourceBase<Base>,
+ GalliumDXGIResource<GalliumD3D11Resource<Base> >
+ >,
+ IGalliumResource
+ >
+{
+ struct pipe_resource* resource;
+ std::unordered_map<unsigned, pipe_transfer*> transfers;
+ float min_lod;
+ DXGI_USAGE dxgi_usage;
+
+ GalliumD3D11Resource(GalliumD3D11Screen* device = 0, struct pipe_resource* resource = 0, unsigned dxgi_usage = 0)
+ : resource(resource), min_lod(0), dxgi_usage(dxgi_usage)
+ {
+ this->device = device;
+ if(device)
+ device->AddRef();
+ this->eviction_priority = 0;
+ }
+
+ ~GalliumD3D11Resource()
+ {
+ pipe_resource_reference(&resource, 0);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetUsage(
+ __out DXGI_USAGE *pUsage
+ )
+ {
+ *pUsage = this->dxgi_usage;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetSharedHandle(HANDLE *pSharedHandle)
+ {
+ return E_NOTIMPL;
+ }
+
+ virtual struct pipe_resource* STDMETHODCALLTYPE GetGalliumResource()
+ {
+ return resource;
+ }
+};
+
+template<typename Base, typename Desc, D3D11_RESOURCE_DIMENSION Dim>
+struct GalliumD3D11TypedResource : public GalliumD3D11Resource<Base>
+{
+ Desc desc;
+ GalliumD3D11TypedResource() {}
+ GalliumD3D11TypedResource(GalliumD3D11Screen* device, struct pipe_resource* resource, const Desc& desc, unsigned dxgi_usage)
+ : GalliumD3D11Resource<Base>(device, resource, dxgi_usage), desc(desc)
+ {}
+ virtual void STDMETHODCALLTYPE GetType(
+ __out D3D11_RESOURCE_DIMENSION *pResourceDimension)
+ {
+ *pResourceDimension = Dim;
+ }
+ virtual void STDMETHODCALLTYPE GetDesc(Desc *pDesc)
+ {
+ memcpy(pDesc, &desc, sizeof(desc));
+ }
+};
+
+typedef GalliumD3D11TypedResource<ID3D11Texture1D, D3D11_TEXTURE1D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE1D> GalliumD3D11Texture1DBase;
+typedef GalliumD3D11TypedResource<ID3D11Texture2D, D3D11_TEXTURE2D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE2D> GalliumD3D11Texture2DBase;
+typedef GalliumD3D11TypedResource<ID3D11Texture3D, D3D11_TEXTURE3D_DESC, D3D11_RESOURCE_DIMENSION_TEXTURE3D> GalliumD3D11Texture3DBase;
+typedef GalliumD3D11TypedResource<ID3D11Buffer, D3D11_BUFFER_DESC, D3D11_RESOURCE_DIMENSION_BUFFER> GalliumD3D11BufferBase;
+
+#if API >= 11
+typedef GalliumD3D11BufferBase GalliumD3D11Buffer;
+typedef GalliumD3D11Texture1DBase GalliumD3D11Texture1D;
+typedef GalliumD3D11Texture2DBase GalliumD3D11Texture2D;
+typedef GalliumD3D11Texture3DBase GalliumD3D11Texture3D;
+#else
+struct GalliumD3D10Buffer : public GalliumD3D10BufferBase
+{
+ GalliumD3D10Buffer(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_BUFFER_DESC& desc, unsigned dxgi_usage)
+ : GalliumD3D10BufferBase(device, resource, desc, dxgi_usage)
+ {}
+
+ ~GalliumD3D10Buffer()
+ {
+ device->UnbindBuffer(this);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in D3D10_MAP MapType,
+ __in unsigned MapFlags,
+ __out void **ppData)
+ {
+ D3D10_MAPPED_SUBRESOURCE msr;
+ HRESULT hr = device->Map(this, 0, MapType, MapFlags, &msr);
+ if(!SUCCEEDED(hr))
+ return hr;
+ *ppData = msr.pData;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE Unmap()
+ {
+ device->Unmap(this, 0);
+ }
+};
+
+struct GalliumD3D10Texture1D : public GalliumD3D10Texture1DBase
+{
+ GalliumD3D10Texture1D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE1D_DESC& desc, unsigned dxgi_usage)
+ : GalliumD3D10Texture1DBase(device, resource, desc, dxgi_usage)
+ {}
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in unsigned Subresource,
+ __in D3D10_MAP MapType,
+ __in unsigned MapFlags,
+ __out void **ppData)
+ {
+ D3D10_MAPPED_SUBRESOURCE msr;
+ HRESULT hr = device->Map(this, Subresource, MapType, MapFlags, &msr);
+ if(!SUCCEEDED(hr))
+ return hr;
+ *ppData = msr.pData;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE Unmap(
+ __in unsigned Subresource
+ )
+ {
+ device->Unmap(this, Subresource);
+ }
+};
+
+struct GalliumD3D10Texture2D : public GalliumD3D10Texture2DBase
+{
+ GalliumD3D10Texture2D() {}
+ GalliumD3D10Texture2D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE2D_DESC& desc, unsigned dxgi_usage)
+ : GalliumD3D10Texture2DBase(device, resource, desc, dxgi_usage)
+ {}
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in unsigned Subresource,
+ __in D3D10_MAP MapType,
+ __in unsigned MapFlags,
+ __out D3D10_MAPPED_TEXTURE2D *pMappedTex2D)
+ {
+ D3D10_MAPPED_SUBRESOURCE msr;
+ HRESULT hr = device->Map(this, Subresource, MapType, MapFlags, &msr);
+ if(!SUCCEEDED(hr))
+ return hr;
+ pMappedTex2D->pData = msr.pData;
+ pMappedTex2D->RowPitch = msr.RowPitch;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE Unmap(
+ __in unsigned Subresource
+ )
+ {
+ device->Unmap(this, Subresource);
+ }
+};
+
+
+struct GalliumD3D10Texture3D : public GalliumD3D10Texture3DBase
+{
+ GalliumD3D10Texture3D(GalliumD3D10Screen* device, struct pipe_resource* resource, const D3D10_TEXTURE3D_DESC& desc, unsigned dxgi_usage)
+ : GalliumD3D10Texture3DBase(device, resource, desc, dxgi_usage)
+ {}
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __in unsigned Subresource,
+ __in D3D10_MAP MapType,
+ __in unsigned MapFlags,
+ __out D3D10_MAPPED_TEXTURE3D *pMappedTex3D)
+ {
+ D3D10_MAPPED_SUBRESOURCE msr;
+ HRESULT hr = device->Map(this, Subresource, MapType, MapFlags, &msr);
+ if(!SUCCEEDED(hr))
+ return hr;
+ pMappedTex3D->pData = msr.pData;
+ pMappedTex3D->RowPitch = msr.RowPitch;
+ pMappedTex3D->DepthPitch = msr.DepthPitch;
+ return S_OK;
+ }
+
+ virtual void STDMETHODCALLTYPE Unmap(
+ __in unsigned Subresource
+ )
+ {
+ device->Unmap(this, Subresource);
+ }
+};
+#endif
+
+struct GalliumD3D11Surface : public GalliumMultiPrivateDataComObject<GalliumD3D11Texture2D, IDXGISurface1>
+{
+ GalliumD3D11Surface(GalliumD3D11Screen* device, struct pipe_resource* resource, const D3D11_TEXTURE2D_DESC& desc, unsigned dxgi_usage)
+ {
+ this->device = device;
+ this->device->AddRef();
+ this->resource = resource;
+ this->desc = desc;
+ this->dxgi_usage = dxgi_usage;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetDesc(
+ __out DXGI_SURFACE_DESC *pDesc)
+ {
+ pDesc->Format = this->desc.Format;
+ pDesc->Width = this->desc.Width;
+ pDesc->Height = this->desc.Height;
+ pDesc->SampleDesc = this->desc.SampleDesc;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetParent(
+ __in REFIID riid,
+ __out void **ppParent)
+ {
+ if(!device)
+ return E_NOINTERFACE;
+ return device->QueryInterface(riid, ppParent);
+ }
+
+ /* TODO: somehow implement these */
+ virtual HRESULT STDMETHODCALLTYPE GetDC(
+ BOOL Discard,
+ __out HDC *phdc)
+ {
+ *phdc = 0;
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE ReleaseDC(
+ __in_opt RECT *pDirtyRect)
+ {
+ return E_NOTIMPL;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Map(
+ __out DXGI_MAPPED_RECT *pLockedRect,
+ unsigned MapFlags)
+ {
+ D3D11_MAP d3d_map;
+ if(MapFlags & DXGI_MAP_DISCARD)
+ d3d_map = D3D11_MAP_WRITE_DISCARD;
+ else
+ {
+ if(MapFlags & DXGI_MAP_READ)
+ {
+ if(MapFlags & DXGI_MAP_WRITE)
+ d3d_map = D3D11_MAP_READ_WRITE;
+ else
+ d3d_map = D3D11_MAP_READ;
+ }
+ else
+ d3d_map = D3D11_MAP_WRITE;
+ }
+ D3D11_MAPPED_SUBRESOURCE d3d_mapped;
+ HRESULT hres = this->device->get_immediate_context()->Map(this, 0, d3d_map, 0, &d3d_mapped);
+ pLockedRect->pBits = (uint8_t*)d3d_mapped.pData;
+ pLockedRect->Pitch = d3d_mapped.RowPitch;
+ return hres;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Unmap(void)
+ {
+ this->device->get_immediate_context()->Unmap(this, 0);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetDevice(
+ __in REFIID riid,
+ __out void **ppParent)
+ {
+ if(!device)
+ return E_NOINTERFACE;
+ return device->QueryInterface(riid, ppParent);
+ }
+};
+
+template<typename Base, typename Desc, typename Object>
+struct GalliumD3D11View : public GalliumD3D11DescribedObject<Base, Desc, Object>
+{
+ GalliumD3D11Resource<>* resource;
+ GalliumD3D11View(GalliumD3D11Screen* device, GalliumD3D11Resource<>* resource, Object* object, const Desc& desc)
+ : GalliumD3D11DescribedObject<Base, Desc, Object>(device, object, desc), resource(resource)
+ {
+ resource->AddRef();
+ }
+
+ ~GalliumD3D11View()
+ {
+ resource->Release();
+ }
+
+ virtual void STDMETHODCALLTYPE GetResource(ID3D11Resource** ppResource)
+ {
+ resource->AddRef();
+ *ppResource = resource;
+ }
+};
+
+typedef GalliumD3D11View<ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, struct pipe_surface> GalliumD3D11DepthStencilView;
+typedef GalliumD3D11View<ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, struct pipe_surface> GalliumD3D11RenderTargetView;
+
+#if API >= 11
+typedef GalliumD3D11View<ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, struct pipe_sampler_view> GalliumD3D11ShaderResourceView;
+#else
+typedef GalliumD3D10View<ID3D10ShaderResourceView1, D3D10_SHADER_RESOURCE_VIEW_DESC1, struct pipe_sampler_view> GalliumD3D10ShaderResourceViewBase;
+
+struct GalliumD3D10ShaderResourceView : public GalliumD3D10ShaderResourceViewBase
+{
+ GalliumD3D10ShaderResourceView(GalliumD3D10Screen* device, GalliumD3D10Resource<>* resource, struct pipe_sampler_view* view, const D3D10_SHADER_RESOURCE_VIEW_DESC1& desc)
+ : GalliumD3D10ShaderResourceViewBase(device, resource, view, desc)
+ {}
+
+ virtual void STDMETHODCALLTYPE GetDesc1(D3D10_SHADER_RESOURCE_VIEW_DESC1 *pDesc)
+ {
+ memcpy(pDesc, &desc, sizeof(*pDesc));
+ }
+
+ virtual void STDMETHODCALLTYPE GetDesc(D3D10_SHADER_RESOURCE_VIEW_DESC *pDesc)
+ {
+ memcpy(pDesc, &desc, sizeof(*pDesc));
+ }
+};
+#endif
+
+template<typename Base = ID3D11Asynchronous>
+struct GalliumD3D11Asynchronous : public GalliumD3D11DeviceChild<Base>
+{
+ struct pipe_query* query;
+ unsigned data_size;
+
+ GalliumD3D11Asynchronous(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size)
+ : GalliumD3D11DeviceChild<Base>(device), query(query), data_size(data_size)
+ {}
+
+ ~GalliumD3D11Asynchronous()
+ {
+ this->device->immediate_pipe->destroy_query(this->device->immediate_pipe, query);
+ }
+
+ virtual unsigned STDMETHODCALLTYPE GetDataSize()
+ {
+ return data_size;
+ }
+
+#if API < 11
+ virtual void STDMETHODCALLTYPE Begin()
+ {
+ this->device->Begin(this);
+ }
+
+ virtual void STDMETHODCALLTYPE End()
+ {
+ this->device->End(this);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetData(
+ __out_bcount(DataSize) void *pData,
+ __in unsigned DataSize,
+ __in unsigned GetDataFlags)
+ {
+ return this->device->GetData(this, pData, DataSize, GetDataFlags);
+ }
+#endif
+};
+
+template<typename Base = ID3D11Asynchronous>
+struct GalliumD3D11QueryOrPredicate : public GalliumD3D11Asynchronous<Base>
+{
+ D3D11_QUERY_DESC desc;
+ GalliumD3D11QueryOrPredicate(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
+ : GalliumD3D11Asynchronous<Base>(device, query, data_size), desc(desc)
+ {}
+
+ virtual void STDMETHODCALLTYPE GetDesc(
+ __out D3D11_QUERY_DESC *pDesc)
+ {
+ *pDesc = desc;
+ }
+};
+
+struct GalliumD3D11Query : public GalliumD3D11QueryOrPredicate<ID3D11Query>
+{
+ GalliumD3D11Query(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
+ : GalliumD3D11QueryOrPredicate(device, query, data_size, desc)
+ {}
+};
+
+struct GalliumD3D11Predicate : public GalliumD3D11QueryOrPredicate<ID3D11Predicate>
+{
+ GalliumD3D11Predicate(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_QUERY_DESC& desc)
+ : GalliumD3D11QueryOrPredicate(device, query, data_size, desc)
+ {}
+
+ ~GalliumD3D11Predicate()
+ {
+ DX10_ONLY(device->UnbindPredicate(this));
+ }
+};
+
+struct GalliumD3D11Counter : public GalliumD3D11Asynchronous<ID3D11Counter>
+{
+ D3D11_COUNTER_DESC desc;
+ GalliumD3D11Counter(GalliumD3D11Screen* device, struct pipe_query* query, unsigned data_size, const D3D11_COUNTER_DESC& desc)
+ : GalliumD3D11Asynchronous(device, query, data_size), desc(desc)
+ {}
+
+ virtual void STDMETHODCALLTYPE GetDesc(
+ __out D3D11_COUNTER_DESC *pDesc)
+ {
+ *pDesc = desc;
+ }
+};
diff --git a/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
new file mode 100644
index 0000000000..50039e388d
--- /dev/null
+++ b/src/gallium/state_trackers/d3d1x/gd3d11/d3d11_screen.h
@@ -0,0 +1,1447 @@
+/**************************************************************************
+ *
+ * Copyright 2010 Luca Barbieri
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/* These cap sets are much more correct than the ones in u_caps.c */
+/* TODO: it seems cube levels should be the same as 2D levels */
+
+/* DX 9_1 */
+static unsigned caps_dx_9_1[] = {
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 8), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX 9_2 */
+static unsigned caps_dx_9_2[] = {
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
+ UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
+ UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_TERMINATE
+};
+
+/* DX 9_3 */
+static unsigned caps_dx_9_3[] = {
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
+ UTIL_CHECK_CAP(TEXTURE_MIRROR_CLAMP),
+ UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
+ UTIL_CHECK_CAP(SM3),
+ //UTIL_CHECK_CAP(INSTANCING),
+ UTIL_CHECK_CAP(OCCLUSION_QUERY),
+ UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
+ UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */
+ UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
+ UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
+ UTIL_CHECK_TERMINATE
+};
+
+
+// this is called "screen" because in the D3D10 case it's only part of the device
+template<bool threadsafe>
+struct GalliumD3D11ScreenImpl : public GalliumD3D11Screen
+{
+ D3D_FEATURE_LEVEL feature_level;
+ int format_support[PIPE_FORMAT_COUNT];
+ unsigned creation_flags;
+ unsigned exception_mode;
+ maybe_mutex_t<threadsafe> mutex;
+
+/* TODO: Direct3D 11 specifies that fine-grained locking should be used if the driver supports it.
+ * Right now, I don't trust Gallium drivers to get this right.
+ */
+#define SYNCHRONIZED lock_t<maybe_mutex_t<threadsafe> > lock_(mutex)
+
+ GalliumD3D11ScreenImpl(struct pipe_screen* screen, struct pipe_context* immediate_pipe, BOOL owns_immediate_pipe,unsigned creation_flags, IDXGIAdapter* adapter)
+ : GalliumD3D11Screen(screen, immediate_pipe, adapter), creation_flags(creation_flags)
+ {
+ memset(&screen_caps, 0, sizeof(screen_caps));
+ screen_caps.gs = screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
+ screen_caps.so = !!screen->get_param(screen, PIPE_CAP_STREAM_OUTPUT);
+ screen_caps.queries = screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY);
+ screen_caps.render_condition = screen_caps.queries;
+ for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
+ screen_caps.constant_buffers[i] = screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_CONST_BUFFERS);
+ screen_caps.stages = 0;
+ for(unsigned i = 0; i < PIPE_SHADER_TYPES; ++i)
+ {
+ if(!screen->get_shader_param(screen, i, PIPE_SHADER_CAP_MAX_INSTRUCTIONS))
+ break;
+ screen_caps.stages = i + 1;
+ }
+
+ memset(format_support, 0xff, sizeof(format_support));
+
+ float default_level;
+ /* don't even attempt to autodetect D3D10 level support, since it's just not fully implemented yet */
+ if(util_check_caps(screen, caps_dx_9_3))
+ default_level = 9.3;
+ else if(util_check_caps(screen, caps_dx_9_2))
+ default_level = 9.2;
+ else if(util_check_caps(screen, caps_dx_9_1))
+ default_level = 9.1;
+ else
+ {
+ _debug_printf("Warning: driver does not even meet D3D_FEATURE_LEVEL_9_1 features, advertising it anyway!\n");
+ default_level = 9.1;
+ }
+
+ char default_level_name[64];
+ sprintf(default_level_name, "%.1f", default_level);
+ float feature_level_number = atof(debug_get_option("D3D11_FEATURE_LEVEL", default_level_name));
+ if(!feature_level_number)
+ feature_level_number = default_level;
+
+#if API >= 11
+ if(feature_level_number >= 11.0f)
+ feature_level = D3D_FEATURE_LEVEL_11_0;
+ else
+#endif
+ if(feature_level_number >= 10.1f)
+ feature_level = D3D_FEATURE_LEVEL_10_1;
+ else if(feature_level_number >= 10.0f)
+ feature_level = D3D_FEATURE_LEVEL_10_0;
+ else if(feature_level_number >= 9.3f)
+ feature_level = D3D_FEATURE_LEVEL_9_3;
+ else if(feature_level_number >= 9.2f)
+ feature_level = D3D_FEATURE_LEVEL_9_2;
+ else
+ feature_level = D3D_FEATURE_LEVEL_9_1;
+
+#if API >= 11
+ immediate_context = GalliumD3D11ImmediateDeviceContext_Create(this, immediate_pipe, owns_immediate_pipe);
+#endif
+ }
+
+ ~GalliumD3D11ScreenImpl()
+ {
+#if API >= 11
+ GalliumD3D11ImmediateDeviceContext_Destroy(immediate_context);
+#endif
+ }
+
+ virtual D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void)
+ {
+ return feature_level;
+ }
+
+ virtual unsigned STDMETHODCALLTYPE GetCreationFlags(void)
+ {
+ return creation_flags;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void)
+ {
+ return S_OK;
+ }
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE GetImmediateContext(
+ __out ID3D11DeviceContext **ppImmediateContext)
+ {
+ immediate_context->AddRef();
+ *ppImmediateContext = immediate_context;
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE SetExceptionMode(unsigned RaiseFlags)
+ {
+ exception_mode = RaiseFlags;
+ return S_OK;
+ }
+
+ virtual unsigned STDMETHODCALLTYPE GetExceptionMode(void)
+ {
+ return exception_mode;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CheckCounter(
+ __in const D3D11_COUNTER_DESC *pDesc,
+ __out D3D11_COUNTER_TYPE *pType,
+ __out unsigned *pActiveCounters,
+ __out_ecount_opt(*pNameLength) LPSTR szName,
+ __inout_opt unsigned *pNameLength,
+ __out_ecount_opt(*pUnitsLength) LPSTR szUnits,
+ __inout_opt unsigned *pUnitsLength,
+ __out_ecount_opt(*pDescriptionLength) LPSTR szDescription,
+ __inout_opt unsigned *pDescriptionLength)
+ {
+ return E_NOTIMPL;
+ }
+
+ virtual void STDMETHODCALLTYPE CheckCounterInfo(
+ __out D3D11_COUNTER_INFO *pCounterInfo)
+ {
+ /* none supported at the moment */
+ pCounterInfo->LastDeviceDependentCounter = (D3D11_COUNTER)0;
+ pCounterInfo->NumSimultaneousCounters = 0;
+ pCounterInfo->NumDetectableParallelUnits = 1;
+ }
+
+#if API >= 11
+ virtual HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
+ D3D11_FEATURE Feature,
+ __out_bcount(FeatureSupportDataSize) void *pFeatureSupportData,
+ unsigned FeatureSupportDataSize)
+ {
+ SYNCHRONIZED;
+
+ switch(Feature)
+ {
+ case D3D11_FEATURE_THREADING:
+ {
+ D3D11_FEATURE_DATA_THREADING* data = (D3D11_FEATURE_DATA_THREADING*)pFeatureSupportData;
+ if(FeatureSupportDataSize != sizeof(*data))
+ return E_INVALIDARG;
+
+ data->DriverCommandLists = FALSE;
+ data->DriverConcurrentCreates = FALSE;
+ return S_OK;
+ }
+ case D3D11_FEATURE_DOUBLES:
+ {
+ D3D11_FEATURE_DATA_DOUBLES* data = (D3D11_FEATURE_DATA_DOUBLES*)pFeatureSupportData;
+ if(FeatureSupportDataSize != sizeof(*data))
+ return E_INVALIDARG;
+
+ data->DoublePrecisionFloatShaderOps = FALSE;
+ return S_OK;
+ }
+ case D3D11_FEATURE_FORMAT_SUPPORT:
+ {
+ D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData;
+ if(FeatureSupportDataSize != sizeof(*data))
+ return E_INVALIDARG;
+
+ return this->CheckFormatSupport(data->InFormat, &data->OutFormatSupport);
+ }
+ case D3D11_FEATURE_FORMAT_SUPPORT2:
+ {
+ D3D11_FEATURE_DATA_FORMAT_SUPPORT* data = (D3D11_FEATURE_DATA_FORMAT_SUPPORT*)pFeatureSupportData;
+ if(FeatureSupportDataSize != sizeof(*data))
+ return E_INVALIDARG;
+
+ data->OutFormatSupport = 0;
+ /* TODO: should this be S_OK? */
+ return E_INVALIDARG;
+ }
+ case D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS:
+ {
+ D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS* data = (D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS*)pFeatureSupportData;
+ if(FeatureSupportDataSize != sizeof(*data))
+ return E_INVALIDARG;
+
+ data->ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x = FALSE;
+ return S_OK;
+ }
+ default:
+ return E_INVALIDARG;
+ }
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CheckFormatSupport(
+ DXGI_FORMAT Format,
+ unsigned *pFormatSupport
+ )
+ {
+ SYNCHRONIZED;
+
+ /* TODO: MSAA, advanced features */
+ pipe_format format = dxgi_to_pipe_format[Format];
+ if(!format)
+ return E_INVALIDARG;
+
+ int support = format_support[format];
+ if(support < 0)
+ {
+ support = 0;
+ unsigned buffer = D3D11_FORMAT_SUPPORT_BUFFER | D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER | D3D11_FORMAT_SUPPORT_IA_INDEX_BUFFER;
+ unsigned sampler_view = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ if(util_format_is_depth_or_stencil(format))
+ sampler_view |= D3D11_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON;
+
+ /* TODO: do this properly when Gallium drivers actually support index/vertex format queries */
+ if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER, 0)
+ || (screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_INDEX_BUFFER, 0)
+ || format == PIPE_FORMAT_R8_UNORM))
+ support |= buffer;
+ if(screen->is_format_supported(screen, format, PIPE_BUFFER, 0, PIPE_BIND_STREAM_OUTPUT, 0))
+ support |= buffer | D3D11_FORMAT_SUPPORT_SO_BUFFER;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_1D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE1D | sampler_view;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | sampler_view;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE3D | sampler_view;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_BLENDABLE;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0))
+ support |= D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_DEPTH_STENCIL;
+ if(screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET, 0))
+ support |= D3D11_FORMAT_SUPPORT_DISPLAY;
+ format_support[format] = support;
+ }
+ *pFormatSupport = support;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
+ DXGI_FORMAT Format,
+ unsigned SampleCount,
+ unsigned *pNumQualityLevels
+ )
+ {
+ SYNCHRONIZED;
+
+ *pNumQualityLevels = 0;
+ return S_OK;
+ }
+
+ template<typename T, typename U>
+ bool convert_blend_state(T& to, const U& from, unsigned BlendEnable, unsigned RenderTargetWriteMask)
+ {
+ if(invalid(0
+ || from.SrcBlend >= D3D11_BLEND_COUNT
+ || from.SrcBlendAlpha >= D3D11_BLEND_COUNT
+ || from.DestBlend >= D3D11_BLEND_COUNT
+ || from.DestBlendAlpha >= D3D11_BLEND_COUNT
+ || from.BlendOp >= 6
+ || from.BlendOpAlpha >= 6
+ || !from.BlendOp
+ || !from.BlendOpAlpha
+ ))
+ return false;
+
+ to.blend_enable = BlendEnable;
+
+ to.rgb_func = from.BlendOp - 1;
+ to.alpha_func = from.BlendOpAlpha - 1;
+
+ to.rgb_src_factor = d3d11_to_pipe_blend[from.SrcBlend];
+ to.alpha_src_factor = d3d11_to_pipe_blend[from.SrcBlendAlpha];
+ to.rgb_dst_factor = d3d11_to_pipe_blend[from.DestBlend];
+ to.alpha_dst_factor = d3d11_to_pipe_blend[from.DestBlendAlpha];
+
+ to.colormask = RenderTargetWriteMask & 0xf;
+ return true;
+ }
+
+#if API >= 11
+ virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
+ __in const D3D11_BLEND_DESC *pBlendStateDesc,
+ __out_opt ID3D11BlendState **ppBlendState
+ )
+#else
+ virtual HRESULT STDMETHODCALLTYPE CreateBlendState1(
+ __in const D3D10_BLEND_DESC1 *pBlendStateDesc,
+ __out_opt ID3D10BlendState1 **ppBlendState
+ )
+#endif
+ {
+ SYNCHRONIZED;
+
+ pipe_blend_state state;
+ memset(&state, 0, sizeof(state));
+ state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable;
+ state.independent_blend_enable = !!pBlendStateDesc->IndependentBlendEnable;
+ assert(PIPE_MAX_COLOR_BUFS >= 8);
+ for(unsigned i = 0; i < 8; ++i)
+ {
+ if(!convert_blend_state(
+ state.rt[i],
+ pBlendStateDesc->RenderTarget[i],
+ pBlendStateDesc->RenderTarget[i].BlendEnable,
+ pBlendStateDesc->RenderTarget[i].RenderTargetWriteMask))
+ return E_INVALIDARG;
+ }
+
+ if(!ppBlendState)
+ return S_FALSE;
+
+ void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
+ if(!object)
+ return E_FAIL;
+
+ *ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc);
+ return S_OK;
+ }
+
+#if API < 11
+ virtual HRESULT STDMETHODCALLTYPE CreateBlendState(
+ __in const D3D10_BLEND_DESC *pBlendStateDesc,
+ __out_opt ID3D10BlendState **ppBlendState
+ )
+ {
+ SYNCHRONIZED;
+
+ pipe_blend_state state;
+ memset(&state, 0, sizeof(state));
+ state.alpha_to_coverage = !!pBlendStateDesc->AlphaToCoverageEnable;
+ assert(PIPE_MAX_COLOR_BUFS >= 8);
+ for(unsigned i = 0; i < 8; ++i)
+ {
+ if(!convert_blend_state(
+ state.rt[i],
+ *pBlendStateDesc,
+ pBlendStateDesc->BlendEnable[i],
+ pBlendStateDesc->RenderTargetWriteMask[i]))
+ return E_INVALIDARG;
+ }
+
+ for(unsigned i = 1; i < 8; ++i)
+ {
+ if(memcmp(&state.rt[0], &state.rt[i], sizeof(state.rt[0])))
+ {
+ state.independent_blend_enable = TRUE;
+ break;
+ }
+ }
+
+ void* object = immediate_pipe->create_blend_state(immediate_pipe, &state);
+ if(!object)
+ return E_FAIL;
+
+ *ppBlendState = new GalliumD3D11BlendState(this, object, *pBlendStateDesc);
+ return S_OK;
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
+ __in const D3D11_DEPTH_STENCIL_DESC *pDepthStencilStateDesc,
+ __out_opt ID3D11DepthStencilState **ppDepthStencilState
+ )
+ {
+ SYNCHRONIZED;
+
+ pipe_depth_stencil_alpha_state state;
+ memset(&state, 0, sizeof(state));
+ state.depth.enabled = !!pDepthStencilStateDesc->DepthEnable;
+ state.depth.writemask = pDepthStencilStateDesc->DepthWriteMask;
+ state.depth.func = pDepthStencilStateDesc->DepthFunc - 1;
+ state.stencil[0].enabled = !!pDepthStencilStateDesc->StencilEnable;
+ state.stencil[0].writemask = pDepthStencilStateDesc->StencilWriteMask;
+ state.stencil[0].valuemask = pDepthStencilStateDesc->StencilReadMask;
+ state.stencil[0].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilPassOp];
+ state.stencil[0].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilFailOp];
+ state.stencil[0].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->FrontFace.StencilDepthFailOp];
+ state.stencil[0].func = pDepthStencilStateDesc->FrontFace.StencilFunc - 1;
+ state.stencil[1].enabled = !!pDepthStencilStateDesc->StencilEnable;
+ state.stencil[1].writemask = pDepthStencilStateDesc->StencilWriteMask;
+ state.stencil[1].valuemask = pDepthStencilStateDesc->StencilReadMask;
+ state.stencil[1].zpass_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilPassOp];
+ state.stencil[1].fail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilFailOp];
+ state.stencil[1].zfail_op = d3d11_to_pipe_stencil_op[pDepthStencilStateDesc->BackFace.StencilDepthFailOp];
+ state.stencil[1].func = pDepthStencilStateDesc->BackFace.StencilFunc - 1;
+
+ if(!ppDepthStencilState)
+ return S_FALSE;
+
+ void* object = immediate_pipe->create_depth_stencil_alpha_state(immediate_pipe, &state);
+ if(!object)
+ return E_FAIL;
+
+ *ppDepthStencilState = new GalliumD3D11DepthStencilState(this, object, *pDepthStencilStateDesc);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateRasterizerState(
+ __in const D3D11_RASTERIZER_DESC *pRasterizerDesc,
+ __out_opt ID3D11RasterizerState **ppRasterizerState)
+ {
+ SYNCHRONIZED;
+
+ pipe_rasterizer_state state;
+ memset(&state, 0, sizeof(state));
+ state.gl_rasterization_rules = 1; /* D3D10/11 use GL rules */
+ state.fill_front = state.fill_back = (pRasterizerDesc->FillMode == D3D11_FILL_WIREFRAME) ? PIPE_POLYGON_MODE_LINE : PIPE_POLYGON_MODE_FILL;
+ if(pRasterizerDesc->CullMode == D3D11_CULL_FRONT)
+ state.cull_face = PIPE_FACE_FRONT;
+ else if(pRasterizerDesc->CullMode == D3D11_CULL_BACK)
+ state.cull_face = PIPE_FACE_BACK;
+ else
+ state.cull_face = PIPE_FACE_NONE;
+ state.front_ccw = !!pRasterizerDesc->FrontCounterClockwise;
+ /* TODO: is this correct? */
+ /* TODO: we are ignoring DepthBiasClamp! */
+ state.offset_tri = state.offset_line = state.offset_point = pRasterizerDesc->SlopeScaledDepthBias || pRasterizerDesc->DepthBias;
+ state.offset_scale = pRasterizerDesc->SlopeScaledDepthBias;
+ state.offset_units = pRasterizerDesc->DepthBias;
+ state.scissor = !!pRasterizerDesc->ScissorEnable;
+ state.multisample = !!pRasterizerDesc->MultisampleEnable;
+ state.line_smooth = !!pRasterizerDesc->AntialiasedLineEnable;
+
+ /* TODO: is this correct? */
+ state.point_quad_rasterization = 1;
+
+ if(!ppRasterizerState)
+ return S_FALSE;
+
+ void* object = immediate_pipe->create_rasterizer_state(immediate_pipe, &state);
+ if(!object)
+ return E_FAIL;
+
+ *ppRasterizerState = new GalliumD3D11RasterizerState(this, object, *pRasterizerDesc, !pRasterizerDesc->DepthClipEnable);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSamplerState(
+ __in const D3D11_SAMPLER_DESC *pSamplerDesc,
+ __out_opt ID3D11SamplerState **ppSamplerState)
+ {
+ SYNCHRONIZED;
+
+ pipe_sampler_state state;
+ memset(&state, 0, sizeof(state));
+ state.normalized_coords = 1;
+ state.min_mip_filter = (pSamplerDesc->Filter & 1);
+ state.mag_img_filter = ((pSamplerDesc->Filter >> 2) & 1);
+ state.min_img_filter = ((pSamplerDesc->Filter >> 4) & 1);
+ if(pSamplerDesc->Filter & 0x40)
+ state.max_anisotropy = pSamplerDesc->MaxAnisotropy;
+ if(pSamplerDesc->Filter & 0x80)
+ {
+ state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
+ state.compare_func = pSamplerDesc->ComparisonFunc;
+ }
+ state.wrap_s = d3d11_to_pipe_wrap[pSamplerDesc->AddressU];
+ state.wrap_t = d3d11_to_pipe_wrap[pSamplerDesc->AddressV];
+ state.wrap_r = d3d11_to_pipe_wrap[pSamplerDesc->AddressW];
+ state.lod_bias = pSamplerDesc->MipLODBias;
+ memcpy(state.border_color, pSamplerDesc->BorderColor, sizeof(state.border_color));
+ state.min_lod = pSamplerDesc->MinLOD;
+ state.max_lod = pSamplerDesc->MaxLOD;
+
+ if(!ppSamplerState)
+ return S_FALSE;
+
+ void* object = immediate_pipe->create_sampler_state(immediate_pipe, &state);
+ if(!object)
+ return E_FAIL;
+
+ *ppSamplerState = new GalliumD3D11SamplerState(this, object, *pSamplerDesc);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateInputLayout(
+ __in_ecount(NumElements) const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
+ __in_range(0, D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT) unsigned NumElements,
+ __in const void *pShaderBytecodeWithInputSignature,
+ __in SIZE_T BytecodeLength,
+ __out_opt ID3D11InputLayout **ppInputLayout)
+ {
+ SYNCHRONIZED;
+
+ if(NumElements > D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT)
+ return E_INVALIDARG;
+ assert(D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT <= PIPE_MAX_ATTRIBS);
+
+ // putting semantics matching in the core API seems to be a (minor) design mistake
+
+ struct dxbc_chunk_signature* sig = dxbc_find_signature(pShaderBytecodeWithInputSignature, BytecodeLength, false);
+ D3D11_SIGNATURE_PARAMETER_DESC* params;
+ unsigned num_params = dxbc_parse_signature(sig, &params);
+
+ typedef std::unordered_map<std::pair<c_string, unsigned>, unsigned> semantic_to_idx_map_t;
+ semantic_to_idx_map_t semantic_to_idx_map;
+ for(unsigned i = 0; i < NumElements; ++i)
+ semantic_to_idx_map[std::make_pair(c_string(pInputElementDescs[i].SemanticName), pInputElementDescs[i].SemanticIndex)] = i;
+
+ struct pipe_vertex_element elements[D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
+
+ unsigned num_params_to_use = std::min(num_params, (unsigned)D3D11_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT);
+ for(unsigned i = 0; i < num_params_to_use; ++i)
+ {
+ int idx = -1;
+ semantic_to_idx_map_t::iterator iter = semantic_to_idx_map.find(std::make_pair(c_string(params[i].SemanticName), params[i].SemanticIndex));
+ if(iter != semantic_to_idx_map.end())
+ idx = iter->second;
+
+ // TODO: I kind of doubt Gallium drivers will like null elements; should we do something about it, either here, in the interface, or in the drivers?
+ // TODO: also, in which cases should we return errors? (i.e. duplicate semantics in vs, duplicate semantics in layout, unmatched semantic in vs, unmatched semantic in layout)
+ memset(&elements[i], 0, sizeof(elements[i]));
+ if(idx >= 0)
+ {
+ elements[i].src_format = dxgi_to_pipe_format[pInputElementDescs[idx].Format];
+ elements[i].src_offset = pInputElementDescs[idx].AlignedByteOffset;
+ elements[i].vertex_buffer_index = pInputElementDescs[idx].InputSlot;
+ elements[i].instance_divisor = pInputElementDescs[idx].InstanceDataStepRate;
+ }
+ }
+
+ free(params);
+
+ if(!ppInputLayout)
+ return S_FALSE;
+
+ void* object = immediate_pipe->create_vertex_elements_state(immediate_pipe, num_params_to_use, elements);
+ if(!object)
+ return E_FAIL;
+
+ *ppInputLayout = new GalliumD3D11InputLayout(this, object);
+ return S_OK;
+ }
+
+ static unsigned d3d11_to_pipe_bind_flags(unsigned BindFlags)
+ {
+ unsigned bind = 0;
+ if(BindFlags & D3D11_BIND_VERTEX_BUFFER)
+ bind |= PIPE_BIND_VERTEX_BUFFER;
+ if(BindFlags & D3D11_BIND_INDEX_BUFFER)
+ bind |= PIPE_BIND_INDEX_BUFFER;
+ if(BindFlags & D3D11_BIND_CONSTANT_BUFFER)
+ bind |= PIPE_BIND_CONSTANT_BUFFER;
+ if(BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ bind |= PIPE_BIND_SAMPLER_VIEW;
+ if(BindFlags & D3D11_BIND_STREAM_OUTPUT)
+ bind |= PIPE_BIND_STREAM_OUTPUT;
+ if(BindFlags & D3D11_BIND_RENDER_TARGET)
+ bind |= PIPE_BIND_RENDER_TARGET;
+ if(BindFlags & D3D11_BIND_DEPTH_STENCIL)
+ bind |= PIPE_BIND_DEPTH_STENCIL;
+ return bind;
+ }
+
+ inline HRESULT create_resource(
+ pipe_texture_target target,
+ unsigned Width,
+ unsigned Height,
+ unsigned Depth,
+ unsigned MipLevels,
+ unsigned ArraySize,
+ DXGI_FORMAT Format,
+ const DXGI_SAMPLE_DESC* SampleDesc,
+ D3D11_USAGE Usage,
+ unsigned BindFlags,
+ unsigned CPUAccessFlags,
+ unsigned MiscFlags,
+ const D3D11_SUBRESOURCE_DATA *pInitialData,
+ DXGI_USAGE dxgi_usage,
+ struct pipe_resource** ppresource
+ )
+ {
+ if(invalid(Format >= DXGI_FORMAT_COUNT))
+ return E_INVALIDARG;
+ if(MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE)
+ {
+ if(target != PIPE_TEXTURE_2D)
+ return E_INVALIDARG;
+ target = PIPE_TEXTURE_CUBE;
+
+ if(ArraySize != 6)
+ return E_NOTIMPL;
+ }
+ else
+ {
+ if(ArraySize > 1)
+ return E_NOTIMPL;
+ ArraySize = 1;
+ }
+ /* TODO: msaa */
+ struct pipe_resource templat;
+ memset(&templat, 0, sizeof(templat));
+ templat.target = target;
+ templat.width0 = Width;
+ templat.height0 = Height;
+ templat.depth0 = Depth;
+ templat.last_level = MipLevels ? (MipLevels - 1) : 0;
+ templat.format = dxgi_to_pipe_format[Format];
+ templat.bind = d3d11_to_pipe_bind_flags(BindFlags);
+ if(CPUAccessFlags & D3D11_CPU_ACCESS_READ)
+ templat.bind |= PIPE_BIND_TRANSFER_READ;
+ if(CPUAccessFlags & D3D11_CPU_ACCESS_WRITE)
+ templat.bind |= PIPE_BIND_TRANSFER_WRITE;
+ if(MiscFlags & D3D11_RESOURCE_MISC_SHARED)
+ templat.bind |= PIPE_BIND_SHARED;
+ if(MiscFlags & D3D11_RESOURCE_MISC_GDI_COMPATIBLE)
+ templat.bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE;
+ if(dxgi_usage & DXGI_USAGE_BACK_BUFFER)
+ templat.bind |= PIPE_BIND_DISPLAY_TARGET;
+ templat.usage = d3d11_to_pipe_usage[Usage];
+ if(invalid(!templat.format))
+ return E_NOTIMPL;
+
+ if(!ppresource)
+ return S_FALSE;
+
+ struct pipe_resource* resource = screen->resource_create(screen, &templat);
+ if(!resource)
+ return E_FAIL;
+ if(pInitialData)
+ {
+ for(unsigned slice = 0; slice < ArraySize; ++slice)
+ {
+ for(unsigned level = 0; level <= templat.last_level; ++level)
+ {
+ struct pipe_subresource sr;
+ sr.level = level;
+ sr.face = slice;
+ struct pipe_box box;
+ box.x = box.y = box.z = 0;
+ box.width = u_minify(Width, level);
+ box.height = u_minify(Height, level);
+ box.depth = u_minify(Depth, level);
+ immediate_pipe->transfer_inline_write(immediate_pipe, resource, sr, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | PIPE_TRANSFER_UNSYNCHRONIZED, &box, pInitialData->pSysMem, pInitialData->SysMemPitch, pInitialData->SysMemSlicePitch);
+ ++pInitialData;
+ }
+ }
+ }
+ *ppresource = resource;
+ return S_OK;
+ }
+
+ static unsigned d3d_to_dxgi_usage(unsigned bind, unsigned misc)
+ {
+ unsigned dxgi_usage = 0;
+ if(bind |= D3D11_BIND_RENDER_TARGET)
+ dxgi_usage |= DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ if(bind & D3D11_BIND_SHADER_RESOURCE)
+ dxgi_usage |= DXGI_USAGE_SHADER_INPUT;
+#if API >= 11
+ if(bind & D3D11_BIND_UNORDERED_ACCESS)
+ dxgi_usage |= DXGI_USAGE_UNORDERED_ACCESS;
+#endif
+ if(misc & D3D11_RESOURCE_MISC_SHARED)
+ dxgi_usage |= DXGI_USAGE_SHARED;
+ return dxgi_usage;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateTexture1D(
+ __in const D3D11_TEXTURE1D_DESC *pDesc,
+ __in_xcount_opt(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA *pInitialData,
+ __out_opt ID3D11Texture1D **ppTexture1D)
+ {
+ SYNCHRONIZED;
+
+ struct pipe_resource* resource;
+ DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
+ HRESULT hr = create_resource(PIPE_TEXTURE_1D, pDesc->Width, 1, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture1D ? &resource : 0);
+ if(hr != S_OK)
+ return hr;
+ *ppTexture1D = new GalliumD3D11Texture1D(this, resource, *pDesc, dxgi_usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateTexture2D(
+ __in const D3D11_TEXTURE2D_DESC *pDesc,
+ __in_xcount_opt(pDesc->MipLevels * pDesc->ArraySize) const D3D11_SUBRESOURCE_DATA *pInitialData,
+ __out_opt ID3D11Texture2D **ppTexture2D)
+ {
+ SYNCHRONIZED;
+
+ struct pipe_resource* resource;
+ DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
+ HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, pDesc->MipLevels, pDesc->ArraySize, pDesc->Format, &pDesc->SampleDesc, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture2D ? &resource : 0);
+ if(hr != S_OK)
+ return hr;
+ if(pDesc->MipLevels == 1 && pDesc->ArraySize == 1)
+ *ppTexture2D = new GalliumD3D11Surface(this, resource, *pDesc, dxgi_usage);
+ else
+ *ppTexture2D = new GalliumD3D11Texture2D(this, resource, *pDesc, dxgi_usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateTexture3D(
+ __in const D3D11_TEXTURE3D_DESC *pDesc,
+ __in_xcount_opt(pDesc->MipLevels) const D3D11_SUBRESOURCE_DATA *pInitialData,
+ __out_opt ID3D11Texture3D **ppTexture3D)
+ {
+ SYNCHRONIZED;
+
+ struct pipe_resource* resource;
+ DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
+ HRESULT hr = create_resource(PIPE_TEXTURE_3D, pDesc->Width, pDesc->Height, pDesc->Depth, pDesc->MipLevels, 1, pDesc->Format, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppTexture3D ? &resource : 0);
+ if(hr != S_OK)
+ return hr;
+ *ppTexture3D = new GalliumD3D11Texture3D(this, resource, *pDesc, dxgi_usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateBuffer(
+ __in const D3D11_BUFFER_DESC *pDesc,
+ __in_opt const D3D11_SUBRESOURCE_DATA *pInitialData,
+ __out_opt ID3D11Buffer **ppBuffer)
+ {
+ SYNCHRONIZED;
+
+#if API >= 11
+ if(pDesc->StructureByteStride > 1)
+ return E_NOTIMPL;
+#endif
+ struct pipe_resource* resource;
+ DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(pDesc->BindFlags, pDesc->MiscFlags);
+ HRESULT hr = create_resource(PIPE_BUFFER, pDesc->ByteWidth, 1, 1, 1, 1, DXGI_FORMAT_R8_UNORM, 0, pDesc->Usage, pDesc->BindFlags, pDesc->CPUAccessFlags, pDesc->MiscFlags, pInitialData, dxgi_usage, ppBuffer ? &resource : 0);
+ if(hr != S_OK)
+ return hr;
+ *ppBuffer = new GalliumD3D11Buffer(this, resource, *pDesc, dxgi_usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE OpenGalliumResource(
+ __in struct pipe_resource* resource,
+ __out IUnknown** dxgi_resource)
+ {
+ SYNCHRONIZED;
+
+ /* TODO: maybe support others */
+ assert(resource->target == PIPE_TEXTURE_2D);
+ *dxgi_resource = 0;
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.Width = resource->width0;
+ desc.Height = resource->height0;
+ init_pipe_to_dxgi_format();
+ desc.Format = pipe_to_dxgi_format[resource->format];
+ desc.SampleDesc.Count = resource->nr_samples;
+ desc.SampleDesc.Quality = 0;
+ desc.ArraySize = 1;
+ desc.MipLevels = resource->last_level + 1;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ if(resource->bind & PIPE_BIND_RENDER_TARGET)
+ desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
+ if(resource->bind & PIPE_BIND_DEPTH_STENCIL)
+ desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
+ if(resource->bind & PIPE_BIND_SAMPLER_VIEW)
+ desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+ if(resource->bind & PIPE_BIND_SHARED)
+ desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
+ DXGI_USAGE dxgi_usage = d3d_to_dxgi_usage(desc.BindFlags, desc.MiscFlags);
+ if(desc.MipLevels == 1 && desc.ArraySize == 1)
+ *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Surface(this, resource, desc, dxgi_usage);
+ else
+ *dxgi_resource = (ID3D11Texture2D*)new GalliumD3D11Texture2D(this, resource, desc, dxgi_usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateSurface(
+ __in const DXGI_SURFACE_DESC *pDesc,
+ unsigned NumSurfaces,
+ DXGI_USAGE Usage,
+ __in_opt const DXGI_SHARED_RESOURCE *pSharedResource,
+ __out IDXGISurface **ppSurface)
+ {
+ SYNCHRONIZED;
+
+ D3D11_TEXTURE2D_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+
+ struct pipe_resource* resource;
+ desc.Width = pDesc->Width;
+ desc.Height = pDesc->Height;
+ desc.Format = pDesc->Format;
+ desc.SampleDesc = pDesc->SampleDesc;
+ desc.ArraySize = NumSurfaces;
+ desc.MipLevels = 1;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ if(Usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
+ desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
+ if(Usage & DXGI_USAGE_SHADER_INPUT)
+ desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+#if API >= 11
+ if(Usage & DXGI_USAGE_UNORDERED_ACCESS)
+ desc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+#endif
+ if(Usage & DXGI_USAGE_SHARED)
+ desc.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
+ HRESULT hr = create_resource(PIPE_TEXTURE_2D, pDesc->Width, pDesc->Height, 1, 1, NumSurfaces, pDesc->Format, &pDesc->SampleDesc, D3D11_USAGE_DEFAULT, desc.BindFlags, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE, desc.MiscFlags, 0, Usage, &resource);
+ if(hr != S_OK)
+ return hr;
+ *ppSurface = new GalliumD3D11Surface(this, resource, desc, Usage);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
+ __in ID3D11Resource *pResource,
+ __in_opt const D3D11_SHADER_RESOURCE_VIEW_DESC *pDesc,
+ __out_opt ID3D11ShaderResourceView **ppSRView)
+ {
+#if API >= 11
+ D3D11_SHADER_RESOURCE_VIEW_DESC def_desc;
+#else
+ if(pDesc->ViewDimension == D3D10_1_SRV_DIMENSION_TEXTURECUBEARRAY)
+ return E_INVALIDARG;
+ D3D10_SHADER_RESOURCE_VIEW_DESC1 desc1;
+ memset(&desc1, 0, sizeof(desc1));
+ memcpy(&desc1, pDesc, sizeof(*pDesc));
+ return CreateShaderResourceView1(pResource, &desc1, (ID3D10ShaderResourceView1**)ppSRView);
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
+ __in ID3D11Resource *pResource,
+ __in_opt const D3D10_SHADER_RESOURCE_VIEW_DESC1 *pDesc,
+ __out_opt ID3D10ShaderResourceView1 **ppSRView)
+ {
+ D3D10_SHADER_RESOURCE_VIEW_DESC1 def_desc;
+#endif
+ SYNCHRONIZED;
+
+ if(!pDesc)
+ {
+ struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
+ init_pipe_to_dxgi_format();
+ memset(&def_desc, 0, sizeof(def_desc));
+ def_desc.Format = pipe_to_dxgi_format[resource->format];
+ switch(resource->target)
+ {
+ case PIPE_BUFFER:
+ def_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ def_desc.Buffer.ElementWidth = 1;
+#if API >= 11
+ def_desc.Buffer.NumElements = resource->width0;
+#endif
+ break;
+ case PIPE_TEXTURE_1D:
+ def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D;
+ def_desc.Texture1D.MipLevels = resource->last_level + 1;
+ break;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ def_desc.Texture2D.MipLevels = resource->last_level + 1;
+ break;
+ case PIPE_TEXTURE_3D:
+ def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ def_desc.Texture3D.MipLevels = resource->last_level + 1;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ def_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ def_desc.TextureCube.MipLevels = resource->last_level + 1;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ pDesc = &def_desc;
+ }
+
+ struct pipe_sampler_view templat;
+ memset(&templat, 0, sizeof(templat));
+ if(invalid(Format >= DXGI_FORMAT_COUNT))
+ return E_INVALIDARG;
+ templat.format = dxgi_to_pipe_format[pDesc->Format];
+ if(!templat.format)
+ return E_NOTIMPL;
+ templat.swizzle_r = PIPE_SWIZZLE_RED;
+ templat.swizzle_g = PIPE_SWIZZLE_GREEN;
+ templat.swizzle_b = PIPE_SWIZZLE_BLUE;
+ templat.swizzle_a = PIPE_SWIZZLE_ALPHA;
+
+ templat.texture = ((GalliumD3D11Resource<>*)pResource)->resource;
+ switch(pDesc->ViewDimension)
+ {
+ case D3D11_SRV_DIMENSION_TEXTURE1D:
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ /* yes, this works for all of these types (but TODO: texture arrays) */
+ templat.first_level = pDesc->Texture1D.MostDetailedMip;
+ templat.last_level = templat.first_level + pDesc->Texture1D.MipLevels - 1;
+ break;
+ case D3D11_SRV_DIMENSION_BUFFER:
+ case D3D11_SRV_DIMENSION_TEXTURE2DMS:
+ case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ return E_NOTIMPL;
+ default:
+ return E_INVALIDARG;
+ }
+
+ if(!ppSRView)
+ return S_FALSE;
+
+ struct pipe_sampler_view* view = immediate_pipe->create_sampler_view(immediate_pipe, templat.texture, &templat);
+ if(!view)
+ return E_FAIL;
+ *ppSRView = new GalliumD3D11ShaderResourceView(this, (GalliumD3D11Resource<>*)pResource, view, *pDesc);
+ return S_OK;
+ }
+
+#if API >= 11
+ virtual HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
+ __in ID3D11Resource *pResource,
+ __in_opt const D3D11_UNORDERED_ACCESS_VIEW_DESC *pDesc,
+ __out_opt ID3D11UnorderedAccessView **ppUAView)
+ {
+ SYNCHRONIZED;
+
+ return E_NOTIMPL;
+
+ // remember to return S_FALSE and not crash if ppUAView == 0 and parameters are valid
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
+ __in ID3D11Resource *pResource,
+ __in_opt const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
+ __out_opt ID3D11RenderTargetView **ppRTView)
+ {
+ SYNCHRONIZED;
+
+ D3D11_RENDER_TARGET_VIEW_DESC def_desc;
+ if(!pDesc)
+ {
+ struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
+ init_pipe_to_dxgi_format();
+ memset(&def_desc, 0, sizeof(def_desc));
+ def_desc.Format = pipe_to_dxgi_format[resource->format];
+ switch(resource->target)
+ {
+ case PIPE_BUFFER:
+ def_desc.ViewDimension = D3D11_RTV_DIMENSION_BUFFER;
+ def_desc.Buffer.ElementWidth = 1;
+#if API >= 11
+ def_desc.Buffer.NumElements = resource->width0;
+#endif
+ break;
+ case PIPE_TEXTURE_1D:
+ def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D;
+ break;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ break;
+ case PIPE_TEXTURE_3D:
+ def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ def_desc.Texture3D.WSize = resource->depth0;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ def_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ def_desc.Texture2DArray.ArraySize = 6;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ pDesc = &def_desc;
+ }
+
+ unsigned zslice = 0;
+ unsigned face = 0;
+ unsigned level;
+ enum pipe_format format;
+ if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT))
+ return E_INVALIDARG;
+ format = dxgi_to_pipe_format[pDesc->Format];
+ if(!format)
+ return E_NOTIMPL;
+
+ switch(pDesc->ViewDimension)
+ {
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ level = pDesc->Texture1D.MipSlice;
+ break;
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ level = pDesc->Texture3D.MipSlice;
+ zslice = pDesc->Texture3D.FirstWSlice;
+ break;
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ level = pDesc->Texture1DArray.MipSlice;
+ face = pDesc->Texture1DArray.FirstArraySlice;
+ break;
+ case D3D11_RTV_DIMENSION_BUFFER:
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ return E_NOTIMPL;
+ default:
+ return E_INVALIDARG;
+ }
+
+ if(!ppRTView)
+ return S_FALSE;
+
+ struct pipe_surface* surface = screen->get_tex_surface(screen,
+ ((GalliumD3D11Resource<>*)pResource)->resource,
+ face, level, zslice, PIPE_BIND_RENDER_TARGET);
+ if(!surface)
+ return E_FAIL;
+ /* muhahahahaha, let's hope this actually works */
+ surface->format = format;
+ *ppRTView = new GalliumD3D11RenderTargetView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
+ __in ID3D11Resource *pResource,
+ __in_opt const D3D11_DEPTH_STENCIL_VIEW_DESC *pDesc,
+ __out_opt ID3D11DepthStencilView **ppDepthStencilView)
+ {
+ SYNCHRONIZED;
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC def_desc;
+ if(!pDesc)
+ {
+ struct pipe_resource* resource = ((GalliumD3D11Resource<>*)pResource)->resource;
+ init_pipe_to_dxgi_format();
+ memset(&def_desc, 0, sizeof(def_desc));
+ def_desc.Format = pipe_to_dxgi_format[resource->format];
+ switch(resource->target)
+ {
+ case PIPE_TEXTURE_1D:
+ def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D;
+ break;
+ case PIPE_TEXTURE_2D:
+ case PIPE_TEXTURE_RECT:
+ def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ break;
+ case PIPE_TEXTURE_CUBE:
+ def_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ def_desc.Texture2DArray.ArraySize = 6;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ pDesc = &def_desc;
+ }
+
+ unsigned zslice = 0;
+ unsigned face = 0;
+ unsigned level;
+ enum pipe_format format;
+ if(invalid(pDesc->Format >= DXGI_FORMAT_COUNT))
+ return E_INVALIDARG;
+ format = dxgi_to_pipe_format[pDesc->Format];
+ if(!format)
+ return E_NOTIMPL;
+
+ switch(pDesc->ViewDimension)
+ {
+ case D3D11_DSV_DIMENSION_TEXTURE1D:
+ case D3D11_DSV_DIMENSION_TEXTURE2D:
+ level = pDesc->Texture1D.MipSlice;
+ break;
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ level = pDesc->Texture1DArray.MipSlice;
+ face = pDesc->Texture1DArray.FirstArraySlice;
+ break;
+ case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ return E_NOTIMPL;
+ default:
+ return E_INVALIDARG;
+ }
+
+ if(!ppDepthStencilView)
+ return S_FALSE;
+
+ struct pipe_surface* surface = screen->get_tex_surface(screen,
+ ((GalliumD3D11Resource<>*)pResource)->resource,
+ face, level, zslice, PIPE_BIND_DEPTH_STENCIL);
+ if(!surface)
+ return E_FAIL;
+ /* muhahahahaha, let's hope this actually works */
+ surface->format = format;
+ *ppDepthStencilView = new GalliumD3D11DepthStencilView(this, (GalliumD3D11Resource<>*)pResource, surface, *pDesc);
+ return S_OK;
+ }
+
+ GalliumD3D11Shader<>* create_stage_shader(unsigned type, const void *pShaderBytecode, SIZE_T BytecodeLength
+#if API >= 11
+ , __in_opt ID3D11ClassLinkage *pClassLinkage
+#endif
+ )
+ {
+ dxbc_chunk_header* tpf_chunk = dxbc_find_shader_bytecode(pShaderBytecode, BytecodeLength);
+ if(!tpf_chunk)
+ return 0;
+
+ std::auto_ptr<tpf_program> tpf(tpf_parse(tpf_chunk + 1, bswap_le32(tpf_chunk->size)));
+ if(!tpf.get())
+ return 0;
+
+ struct pipe_shader_state tgsi_shader;
+ memset(&tgsi_shader, 0, sizeof(tgsi_shader));
+ tgsi_shader.tokens = (const tgsi_token*)tpf_to_tgsi(*tpf);
+ if(!tgsi_shader.tokens)
+ return 0;
+
+ void* shader_cso;
+ GalliumD3D11Shader<>* shader;
+
+ switch(type)
+ {
+ case PIPE_SHADER_VERTEX:
+ shader_cso = immediate_pipe->create_vs_state(immediate_pipe, &tgsi_shader);
+ shader = (GalliumD3D11Shader<>*)new GalliumD3D11VertexShader(this, shader_cso);
+ break;
+ case PIPE_SHADER_FRAGMENT:
+ shader_cso = immediate_pipe->create_fs_state(immediate_pipe, &tgsi_shader);
+ shader = (GalliumD3D11Shader<>*)new GalliumD3D11PixelShader(this, shader_cso);
+ break;
+ case PIPE_SHADER_GEOMETRY:
+ shader_cso = immediate_pipe->create_gs_state(immediate_pipe, &tgsi_shader);
+ shader = (GalliumD3D11Shader<>*)new GalliumD3D11GeometryShader(this, shader_cso);
+ break;
+ default:
+ shader_cso = 0;
+ shader = 0;
+ break;
+ }
+
+ if(shader)
+ {
+ shader->slot_to_resource = tpf->slot_to_resource;
+ shader->slot_to_sampler = tpf->slot_to_sampler;
+ }
+
+ free((void*)tgsi_shader.tokens);
+ return shader;
+ }
+
+#if API >= 11
+#define CREATE_SHADER_ARGS \
+ __in const void *pShaderBytecode, \
+ __in SIZE_T BytecodeLength, \
+ __in_opt ID3D11ClassLinkage *pClassLinkage
+#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength, pClassLinkage
+#else
+#define CREATE_SHADER_ARGS \
+ __in const void *pShaderBytecode, \
+ __in SIZE_T BytecodeLength
+#define PASS_SHADER_ARGS pShaderBytecode, BytecodeLength
+#endif
+
+#define IMPLEMENT_CREATE_SHADER(Stage, GALLIUM) \
+ virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
+ CREATE_SHADER_ARGS, \
+ __out_opt ID3D11##Stage##Shader **pp##Stage##Shader) \
+ { \
+ SYNCHRONIZED; \
+ GalliumD3D11##Stage##Shader* shader = (GalliumD3D11##Stage##Shader*)create_stage_shader(PIPE_SHADER_##GALLIUM, PASS_SHADER_ARGS); \
+ if(!shader) \
+ return E_FAIL; \
+ if(pp##Stage##Shader) \
+ { \
+ *pp##Stage##Shader = shader; \
+ return S_OK; \
+ } \
+ else \
+ { \
+ shader->Release(); \
+ return S_FALSE; \
+ } \
+ }
+
+#define IMPLEMENT_NOTIMPL_CREATE_SHADER(Stage) \
+ virtual HRESULT STDMETHODCALLTYPE Create##Stage##Shader( \
+ CREATE_SHADER_ARGS, \
+ __out_opt ID3D11##Stage##Shader **pp##Stage##Shader) \
+ { \
+ return E_NOTIMPL; \
+ }
+
+ IMPLEMENT_CREATE_SHADER(Vertex, VERTEX)
+ IMPLEMENT_CREATE_SHADER(Pixel, FRAGMENT)
+ IMPLEMENT_CREATE_SHADER(Geometry, GEOMETRY)
+#if API >= 11
+ IMPLEMENT_NOTIMPL_CREATE_SHADER(Hull)
+ IMPLEMENT_NOTIMPL_CREATE_SHADER(Domain)
+ IMPLEMENT_NOTIMPL_CREATE_SHADER(Compute)
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
+ __in const void *pShaderBytecode,
+ __in SIZE_T BytecodeLength,
+ __in_ecount_opt(NumEntries) const D3D11_SO_DECLARATION_ENTRY *pSODeclaration,
+ __in_range(0, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT) unsigned NumEntries,
+#if API >= 11
+ __in_ecount_opt(NumStrides) const unsigned *pBufferStrides,
+ __in_range(0, D3D11_SO_BUFFER_SLOT_COUNT) unsigned NumStrides,
+ __in unsigned RasterizedStream,
+ __in_opt ID3D11ClassLinkage *pClassLinkage,
+#else
+ __in UINT OutputStreamStride,
+#endif
+ __out_opt ID3D11GeometryShader **ppGeometryShader)
+ {
+ SYNCHRONIZED;
+
+ if(!ppGeometryShader)
+ return S_FALSE;
+
+ return E_NOTIMPL;
+
+ // remember to return S_FALSE if ppGeometyShader == NULL and the shader is OK
+ }
+
+#if API >= 11
+ virtual HRESULT STDMETHODCALLTYPE CreateClassLinkage(
+ __out ID3D11ClassLinkage **ppLinkage)
+ {
+ SYNCHRONIZED;
+
+ if(!ppLinkage)
+ return S_FALSE;
+
+ return E_NOTIMPL;
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE CreateQuery(
+ __in const D3D11_QUERY_DESC *pQueryDesc,
+ __out_opt ID3D11Query **ppQuery)
+ {
+ SYNCHRONIZED;
+
+ if(invalid(pQueryDesc->Query >= D3D11_QUERY_COUNT))
+ return E_INVALIDARG;
+ unsigned query_type = d3d11_to_pipe_query[pQueryDesc->Query];
+ if(!query_type)
+ return E_NOTIMPL;
+
+ if(ppQuery)
+ return S_FALSE;
+
+ struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
+ if(!query)
+ return E_FAIL;
+
+ *ppQuery = new GalliumD3D11Query(this, query, d3d11_query_size[pQueryDesc->Query], *pQueryDesc);
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE CreatePredicate(
+ __in const D3D11_QUERY_DESC *pPredicateDesc,
+ __out_opt ID3D11Predicate **ppPredicate)
+ {
+ SYNCHRONIZED;
+
+ unsigned query_type;
+ switch(pPredicateDesc->Query)
+ {
+ case D3D11_QUERY_SO_OVERFLOW_PREDICATE:
+ return E_NOTIMPL;
+ case D3D11_QUERY_OCCLUSION_PREDICATE:
+ query_type = PIPE_QUERY_OCCLUSION_COUNTER;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+
+ if(ppPredicate)
+ return S_FALSE;
+
+ struct pipe_query* query = immediate_pipe->create_query(immediate_pipe, query_type);
+ if(!query)
+ return E_FAIL;
+
+ *ppPredicate = new GalliumD3D11Predicate(this, query, sizeof(BOOL), *pPredicateDesc);
+ return S_OK;
+ }
+
+
+ virtual HRESULT STDMETHODCALLTYPE CreateCounter(
+ __in const D3D11_COUNTER_DESC *pCounterDesc,
+ __out_opt ID3D11Counter **ppCounter)
+ {
+ SYNCHRONIZED;
+
+ return E_NOTIMPL;
+
+ // remember to return S_FALSE if ppCounter == NULL and everything is OK
+ }
+
+#if API >= 11
+ virtual HRESULT STDMETHODCALLTYPE CreateDeferredContext(
+ unsigned ContextFlags,
+ __out_opt ID3D11DeviceContext **ppDeferredContext)
+ {
+ SYNCHRONIZED;
+
+ // TODO: this will have to be implemented using a new Gallium util module
+ return E_NOTIMPL;
+
+ // remember to return S_FALSE if ppCounter == NULL and everything is OK
+ }
+#endif
+
+ virtual HRESULT STDMETHODCALLTYPE OpenSharedResource(
+ __in HANDLE hResource,
+ __in REFIID ReturnedInterface,
+ __out_opt void **ppResource)
+ {
+ SYNCHRONIZED;
+
+ // TODO: the problem here is that we need to communicate dimensions somehow
+ return E_NOTIMPL;
+
+ // remember to return S_FALSE if ppCounter == NULL and everything is OK
+#if 0
+ struct pipe_resou rce templat;
+ struct winsys_handle handle;
+ handle.stride = 0;
+ handle.handle = hResource;
+ handle.type = DRM_API_HANDLE_TYPE_SHARED;
+ screen->resource_from_handle(screen, &templat, &handle);
+#endif
+ }
+
+#if API < 11
+ /* these are documented as "Not implemented".
+ * According to the UMDDI documentation, they apparently turn on a
+ * (Width + 1) x (Height + 1) convolution filter for 1-bit textures.
+ * Probably nothing uses these, assuming it has ever been implemented anywhere.
+ */
+ void STDMETHODCALLTYPE SetTextFilterSize(
+ __in UINT Width,
+ __in UINT Height
+ )
+ {}
+
+ virtual void STDMETHODCALLTYPE GetTextFilterSize(
+ __in UINT *Width,
+ __in UINT *Height
+ )
+ {}
+#endif
+
+#if API >= 11
+ virtual void STDMETHODCALLTYPE RestoreGalliumState()
+ {
+ GalliumD3D11ImmediateDeviceContext_RestoreGalliumState(immediate_context);
+ }
+
+ virtual void STDMETHODCALLTYPE RestoreGalliumStateBlitOnly()
+ {
+ GalliumD3D11ImmediateDeviceContext_RestoreGalliumStateBlitOnly(immediate_context);
+ }
+#endif
+
+ virtual struct pipe_context* STDMETHODCALLTYPE GetGalliumContext(void)
+ {
+ return immediate_pipe;
+ }
+
+#undef SYNCHRONIZED
+};