diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index bb9b915a598..76316e008f4 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -48,6 +48,7 @@ enum wined3d_cs_op WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW, WINED3D_CS_OP_SET_SAMPLER, WINED3D_CS_OP_SET_SHADER, + WINED3D_CS_OP_SET_BLEND_STATE, WINED3D_CS_OP_SET_RASTERIZER_STATE, WINED3D_CS_OP_SET_RENDER_STATE, WINED3D_CS_OP_SET_TEXTURE_STATE, @@ -256,6 +257,12 @@ struct wined3d_cs_set_shader struct wined3d_shader *shader; }; +struct wined3d_cs_set_blend_state +{ + enum wined3d_cs_op opcode; + struct wined3d_blend_state *state; +}; + struct wined3d_cs_set_rasterizer_state { enum wined3d_cs_op opcode; @@ -1432,6 +1439,25 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); } +static void wined3d_cs_exec_set_blend_state(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_set_blend_state *op = data; + + cs->state.blend_state = op->state; + device_invalidate_state(cs->device, STATE_BLEND); +} + +void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) +{ + struct wined3d_cs_set_blend_state *op; + + op = cs->ops->require_space(cs, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_BLEND_STATE; + op->state = state; + + cs->ops->submit(cs, WINED3D_CS_QUEUE_DEFAULT); +} + static void wined3d_cs_exec_set_rasterizer_state(struct wined3d_cs *cs, const void *data) { const struct wined3d_cs_set_rasterizer_state *op = data; @@ -2397,6 +2423,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view, /* WINED3D_CS_OP_SET_SAMPLER */ wined3d_cs_exec_set_sampler, /* WINED3D_CS_OP_SET_SHADER */ wined3d_cs_exec_set_shader, + /* WINED3D_CS_OP_SET_BLEND_STATE */ wined3d_cs_exec_set_blend_state, /* WINED3D_CS_OP_SET_RASTERIZER_STATE */ wined3d_cs_exec_set_rasterizer_state, /* WINED3D_CS_OP_SET_RENDER_STATE */ wined3d_cs_exec_set_render_state, /* WINED3D_CS_OP_SET_TEXTURE_STATE */ wined3d_cs_exec_set_texture_state, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2d1603f0b09..78610fc9036 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1948,6 +1948,31 @@ static void resolve_depth_buffer(struct wined3d_state *state) src_view->sub_resource_idx, &src_rect, 0, NULL, WINED3D_TEXF_POINT); } +void CDECL wined3d_device_set_blend_state(struct wined3d_device *device, struct wined3d_blend_state *blend_state) +{ + struct wined3d_blend_state *prev; + + TRACE("device %p, blend_state %p.\n", device, blend_state); + + prev = device->update_state->blend_state; + if (prev == blend_state) + return; + + if (blend_state) + wined3d_blend_state_incref(blend_state); + device->update_state->blend_state = blend_state; + wined3d_cs_emit_set_blend_state(device->cs, blend_state); + if (prev) + wined3d_blend_state_decref(prev); +} + +struct wined3d_blend_state * CDECL wined3d_device_get_blend_state(const struct wined3d_device *device) +{ + TRACE("device %p.\n", device); + + return device->state.blend_state; +} + void CDECL wined3d_device_set_rasterizer_state(struct wined3d_device *device, struct wined3d_rasterizer_state *rasterizer_state) { diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index db1711ef76c..aa1a2ae5b31 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -38,6 +38,67 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); +ULONG CDECL wined3d_blend_state_incref(struct wined3d_blend_state *state) +{ + ULONG refcount = InterlockedIncrement(&state->refcount); + + TRACE("%p increasing refcount to %u.\n", state, refcount); + + return refcount; +} + +static void wined3d_blend_state_destroy_object(void *object) +{ + HeapFree(GetProcessHeap(), 0, object); +} + +ULONG CDECL wined3d_blend_state_decref(struct wined3d_blend_state *state) +{ + ULONG refcount = InterlockedDecrement(&state->refcount); + struct wined3d_device *device = state->device; + + TRACE("%p decreasing refcount to %u.\n", state, refcount); + + if (!refcount) + { + state->parent_ops->wined3d_object_destroyed(state->parent); + wined3d_cs_destroy_object(device->cs, wined3d_blend_state_destroy_object, state); + } + + return refcount; +} + +void * CDECL wined3d_blend_state_get_parent(const struct wined3d_blend_state *state) +{ + TRACE("state %p.\n", state); + + return state->parent; +} + +HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device, + const struct wined3d_blend_state_desc *desc, void *parent, + const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state) +{ + struct wined3d_blend_state *object; + + TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n", + device, desc, parent, parent_ops, state); + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->refcount = 1; + object->desc = *desc; + object->parent = parent; + object->parent_ops = parent_ops; + object->device = device; + + TRACE("Created blend state %p.\n", object); + *state = object; + + return WINED3D_OK; +} + ULONG CDECL wined3d_rasterizer_state_incref(struct wined3d_rasterizer_state *state) { ULONG refcount = InterlockedIncrement(&state->refcount); @@ -81,7 +142,8 @@ HRESULT CDECL wined3d_rasterizer_state_create(struct wined3d_device *device, { struct wined3d_rasterizer_state *object; - TRACE("device %p, desc %p, state %p.\n", device, desc, state); + TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n", + device, desc, parent, parent_ops, state); if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) return E_OUTOFMEMORY; @@ -553,6 +615,28 @@ static void state_blendfactor(struct wined3d_context *context, const struct wine checkGLcall("glBlendColor"); } +static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + BOOL alpha_to_coverage = FALSE; + + if (!gl_info->supported[ARB_MULTISAMPLE]) + return; + + if (state->blend_state) + { + struct wined3d_blend_state_desc *desc = &state->blend_state->desc; + alpha_to_coverage = desc->alpha_to_coverage; + } + + if (alpha_to_coverage) + gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + else + gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + checkGLcall("blend state"); +} + void state_alpha_test(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = context->gl_info; @@ -5024,6 +5108,7 @@ const struct StateEntryTemplate misc_state_template[] = { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_BLENDOPALPHA), { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE), NULL }, WINED3D_GL_EXT_NONE }, + { STATE_BLEND, { STATE_BLEND, state_blend_object }, WINED3D_GL_EXT_NONE }, { STATE_STREAMSRC, { STATE_STREAMSRC, streamsrc }, WINED3D_GL_EXT_NONE }, { STATE_VDECL, { STATE_VDECL, vdecl_miscpart }, WINED3D_GL_EXT_NONE }, { STATE_FRONTFACE, { STATE_FRONTFACE, frontface_cc }, ARB_CLIP_CONTROL }, @@ -5973,6 +6058,7 @@ static void validate_state_table(struct StateEntry *state_table) STATE_FRAMEBUFFER, STATE_POINT_ENABLE, STATE_COLOR_KEY, + STATE_BLEND, }; unsigned int i, current; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 606ba0b3525..f65cc85be3f 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -22,6 +22,11 @@ @ cdecl wined3d_register_software_device(ptr ptr) @ cdecl wined3d_set_adapter_display_mode(ptr long ptr) +@ cdecl wined3d_blend_state_create(ptr ptr ptr ptr ptr) +@ cdecl wined3d_blend_state_decref(ptr) +@ cdecl wined3d_blend_state_get_parent(ptr) +@ cdecl wined3d_blend_state_incref(ptr) + @ cdecl wined3d_buffer_create(ptr ptr ptr ptr ptr ptr) @ cdecl wined3d_buffer_create_vb(ptr long long long ptr ptr ptr) @ cdecl wined3d_buffer_decref(ptr) @@ -53,6 +58,7 @@ @ cdecl wined3d_device_evict_managed_resources(ptr) @ cdecl wined3d_device_get_available_texture_mem(ptr) @ cdecl wined3d_device_get_base_vertex_index(ptr) +@ cdecl wined3d_device_get_blend_state(ptr) @ cdecl wined3d_device_get_clip_plane(ptr long ptr) @ cdecl wined3d_device_get_clip_status(ptr ptr) @ cdecl wined3d_device_get_compute_shader(ptr) @@ -126,6 +132,7 @@ @ cdecl wined3d_device_reset(ptr ptr ptr ptr long) @ cdecl wined3d_device_restore_fullscreen_window(ptr ptr ptr) @ cdecl wined3d_device_set_base_vertex_index(ptr long) +@ cdecl wined3d_device_set_blend_state(ptr ptr) @ cdecl wined3d_device_set_clip_plane(ptr long ptr) @ cdecl wined3d_device_set_clip_status(ptr ptr) @ cdecl wined3d_device_set_compute_shader(ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 334724514df..e2527f2a224 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1642,7 +1642,10 @@ enum wined3d_pipeline #define STATE_STREAM_OUTPUT (STATE_COLOR_KEY + 1) #define STATE_IS_STREAM_OUTPUT(a) ((a) == STATE_STREAM_OUTPUT) -#define STATE_COMPUTE_OFFSET (STATE_STREAM_OUTPUT + 1) +#define STATE_BLEND (STATE_STREAM_OUTPUT + 1) +#define STATE_IS_BLEND(a) ((a) == STATE_BLEND) + +#define STATE_COMPUTE_OFFSET (STATE_BLEND + 1) #define STATE_COMPUTE_SHADER (STATE_COMPUTE_OFFSET) #define STATE_IS_COMPUTE_SHADER(a) ((a) == STATE_COMPUTE_SHADER) @@ -2763,6 +2766,17 @@ HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) DECLSPEC_HIDDEN; BOOL wined3d_register_window(HWND window, struct wined3d_device *device) DECLSPEC_HIDDEN; void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN; +struct wined3d_blend_state +{ + LONG refcount; + struct wined3d_blend_state_desc desc; + + void *parent; + const struct wined3d_parent_ops *parent_ops; + + struct wined3d_device *device; +}; + struct wined3d_rasterizer_state { LONG refcount; @@ -2841,6 +2855,7 @@ struct wined3d_state const struct wined3d_light_info *lights[MAX_ACTIVE_LIGHTS]; DWORD render_states[WINEHIGHEST_RENDER_STATE + 1]; + struct wined3d_blend_state *blend_state; struct wined3d_rasterizer_state *rasterizer_state; }; @@ -3519,6 +3534,7 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_query_issue(struct wined3d_cs *cs, struct wined3d_query *query, DWORD flags) DECLSPEC_HIDDEN; void wined3d_cs_emit_reset_state(struct wined3d_cs *cs) DECLSPEC_HIDDEN; +void wined3d_cs_emit_set_blend_state(struct wined3d_cs *cs, struct wined3d_blend_state *state) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_clip_plane(struct wined3d_cs *cs, UINT plane_idx, const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_color_key(struct wined3d_cs *cs, struct wined3d_texture *texture, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 2a796029098..f6ffdba67c8 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1976,6 +1976,11 @@ struct wined3d_buffer_desc unsigned int structure_byte_stride; }; +struct wined3d_blend_state_desc +{ + BOOL alpha_to_coverage; +}; + struct wined3d_rasterizer_state_desc { BOOL front_ccw; @@ -2086,6 +2091,7 @@ struct wined3d_buffer; struct wined3d_device; struct wined3d_palette; struct wined3d_query; +struct wined3d_blend_state; struct wined3d_rasterizer_state; struct wined3d_rendertarget_view; struct wined3d_resource; @@ -2238,6 +2244,7 @@ HRESULT __cdecl wined3d_device_end_stateblock(struct wined3d_device *device, str void __cdecl wined3d_device_evict_managed_resources(struct wined3d_device *device); UINT __cdecl wined3d_device_get_available_texture_mem(const struct wined3d_device *device); INT __cdecl wined3d_device_get_base_vertex_index(const struct wined3d_device *device); +struct wined3d_blend_state * __cdecl wined3d_device_get_blend_state(const struct wined3d_device *device); HRESULT __cdecl wined3d_device_get_clip_plane(const struct wined3d_device *device, UINT plane_idx, struct wined3d_vec4 *plane); HRESULT __cdecl wined3d_device_get_clip_status(const struct wined3d_device *device, @@ -2348,6 +2355,7 @@ HRESULT __cdecl wined3d_device_reset(struct wined3d_device *device, void __cdecl wined3d_device_restore_fullscreen_window(struct wined3d_device *device, HWND window, const RECT *window_rect); void __cdecl wined3d_device_set_base_vertex_index(struct wined3d_device *device, INT base_index); +void __cdecl wined3d_device_set_blend_state(struct wined3d_device *device, struct wined3d_blend_state *blend_state); HRESULT __cdecl wined3d_device_set_clip_plane(struct wined3d_device *device, UINT plane_idx, const struct wined3d_vec4 *plane); HRESULT __cdecl wined3d_device_set_clip_status(struct wined3d_device *device, @@ -2550,6 +2558,13 @@ static inline HRESULT wined3d_private_store_set_private_data(struct wined3d_priv return WINED3D_OK; } +HRESULT __cdecl wined3d_blend_state_create(struct wined3d_device *device, + const struct wined3d_blend_state_desc *desc, void *parent, + const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state); +ULONG __cdecl wined3d_blend_state_decref(struct wined3d_blend_state *state); +void * __cdecl wined3d_blend_state_get_parent(const struct wined3d_blend_state *state); +ULONG __cdecl wined3d_blend_state_incref(struct wined3d_blend_state *state); + HRESULT __cdecl wined3d_rasterizer_state_create(struct wined3d_device *device, const struct wined3d_rasterizer_state_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_rasterizer_state **state);