Commit 94c51a83 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

d2d1/commandlist: Implement basic state recording commands.

parent f0185275
......@@ -20,6 +20,58 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
enum d2d_command_type
{
D2D_COMMAND_SET_ANTIALIAS_MODE,
D2D_COMMAND_SET_TAGS,
D2D_COMMAND_SET_TEXT_ANTIALIAS_MODE,
D2D_COMMAND_SET_TRANSFORM,
D2D_COMMAND_SET_PRIMITIVE_BLEND,
D2D_COMMAND_SET_UNIT_MODE,
};
struct d2d_command
{
enum d2d_command_type op;
size_t size;
};
struct d2d_command_set_antialias_mode
{
struct d2d_command c;
D2D1_ANTIALIAS_MODE mode;
};
struct d2d_command_set_tags
{
struct d2d_command c;
D2D1_TAG tag1, tag2;
};
struct d2d_command_set_text_antialias_mode
{
struct d2d_command c;
D2D1_TEXT_ANTIALIAS_MODE mode;
};
struct d2d_command_set_transform
{
struct d2d_command c;
D2D1_MATRIX_3X2_F transform;
};
struct d2d_command_set_primitive_blend
{
struct d2d_command c;
D2D1_PRIMITIVE_BLEND primitive_blend;
};
struct d2d_command_set_unit_mode
{
struct d2d_command c;
D2D1_UNIT_MODE mode;
};
static inline struct d2d_command_list *impl_from_ID2D1CommandList(ID2D1CommandList *iface)
{
return CONTAINING_RECORD(iface, struct d2d_command_list, ID2D1CommandList_iface);
......@@ -65,6 +117,7 @@ static ULONG STDMETHODCALLTYPE d2d_command_list_Release(ID2D1CommandList *iface)
if (!refcount)
{
ID2D1Factory_Release(command_list->factory);
free(command_list->data);
free(command_list);
}
......@@ -82,16 +135,88 @@ static void STDMETHODCALLTYPE d2d_command_list_GetFactory(ID2D1CommandList *ifac
static HRESULT STDMETHODCALLTYPE d2d_command_list_Stream(ID2D1CommandList *iface, ID2D1CommandSink *sink)
{
FIXME("iface %p, sink %p stub.\n", iface, sink);
struct d2d_command_list *command_list = impl_from_ID2D1CommandList(iface);
const void *data, *end;
HRESULT hr;
TRACE("iface %p, sink %p.\n", iface, sink);
if (command_list->state != D2D_COMMAND_LIST_STATE_CLOSED) return S_OK;
if (FAILED(hr = ID2D1CommandSink_BeginDraw(sink)))
return hr;
data = command_list->data;
end = (char *)command_list->data + command_list->size;
while (data < end)
{
const struct d2d_command *command = data;
return E_NOTIMPL;
switch (command->op)
{
case D2D_COMMAND_SET_ANTIALIAS_MODE:
{
const struct d2d_command_set_antialias_mode *c = data;
hr = ID2D1CommandSink_SetAntialiasMode(sink, c->mode);
break;
}
case D2D_COMMAND_SET_TAGS:
{
const struct d2d_command_set_tags *c = data;
hr = ID2D1CommandSink_SetTags(sink, c->tag1, c->tag2);
break;
}
case D2D_COMMAND_SET_TEXT_ANTIALIAS_MODE:
{
const struct d2d_command_set_text_antialias_mode *c = data;
hr = ID2D1CommandSink_SetTextAntialiasMode(sink, c->mode);
break;
}
case D2D_COMMAND_SET_TRANSFORM:
{
const struct d2d_command_set_transform *c = data;
hr = ID2D1CommandSink_SetTransform(sink, &c->transform);
break;
}
case D2D_COMMAND_SET_PRIMITIVE_BLEND:
{
const struct d2d_command_set_primitive_blend *c = data;
hr = ID2D1CommandSink_SetPrimitiveBlend(sink, c->primitive_blend);
break;
}
case D2D_COMMAND_SET_UNIT_MODE:
{
const struct d2d_command_set_unit_mode *c = data;
hr = ID2D1CommandSink_SetUnitMode(sink, c->mode);
break;
}
default:
FIXME("Unhandled command %u.\n", command->op);
hr = E_UNEXPECTED;
}
if (FAILED(hr)) return hr;
data = (char *)data + command->size;
}
return ID2D1CommandSink_EndDraw(sink);
}
static HRESULT STDMETHODCALLTYPE d2d_command_list_Close(ID2D1CommandList *iface)
{
struct d2d_command_list *command_list = impl_from_ID2D1CommandList(iface);
FIXME("iface %p stub.\n", iface);
return E_NOTIMPL;
if (command_list->state != D2D_COMMAND_LIST_STATE_OPEN)
return D2DERR_WRONG_STATE;
command_list->state = D2D_COMMAND_LIST_STATE_CLOSED;
/* FIXME: reset as a target */
return S_OK;
}
static const ID2D1CommandListVtbl d2d_command_list_vtbl =
......@@ -125,3 +250,96 @@ struct d2d_command_list *unsafe_impl_from_ID2D1CommandList(ID2D1CommandList *ifa
assert(iface->lpVtbl == (ID2D1CommandListVtbl *)&d2d_command_list_vtbl);
return CONTAINING_RECORD(iface, struct d2d_command_list, ID2D1CommandList_iface);
}
static void * d2d_command_list_require_space(struct d2d_command_list *command_list, size_t size)
{
struct d2d_command *command;
if (!d2d_array_reserve(&command_list->data, &command_list->capacity, command_list->size + size, 1))
return NULL;
command = (struct d2d_command *)((char *)command_list->data + command_list->size);
command->size = size;
command_list->size += size;
return command;
}
void d2d_command_list_set_antialias_mode(struct d2d_command_list *command_list,
D2D1_ANTIALIAS_MODE mode)
{
struct d2d_command_set_antialias_mode *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_ANTIALIAS_MODE;
command->mode = mode;
}
void d2d_command_list_set_primitive_blend(struct d2d_command_list *command_list,
D2D1_PRIMITIVE_BLEND primitive_blend)
{
struct d2d_command_set_primitive_blend *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_PRIMITIVE_BLEND;
command->primitive_blend = primitive_blend;
}
void d2d_command_list_set_unit_mode(struct d2d_command_list *command_list, D2D1_UNIT_MODE mode)
{
struct d2d_command_set_unit_mode *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_UNIT_MODE;
command->mode = mode;
}
void d2d_command_list_set_text_antialias_mode(struct d2d_command_list *command_list,
D2D1_TEXT_ANTIALIAS_MODE mode)
{
struct d2d_command_set_text_antialias_mode *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_TEXT_ANTIALIAS_MODE;
command->mode = mode;
}
void d2d_command_list_set_tags(struct d2d_command_list *command_list, D2D1_TAG tag1, D2D1_TAG tag2)
{
struct d2d_command_set_tags *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_TAGS;
command->tag1 = tag1;
command->tag2 = tag2;
}
void d2d_command_list_set_transform(struct d2d_command_list *command_list,
const D2D1_MATRIX_3X2_F *transform)
{
struct d2d_command_set_transform *command;
command = d2d_command_list_require_space(command_list, sizeof(*command));
command->c.op = D2D_COMMAND_SET_TRANSFORM;
command->transform = *transform;
}
void d2d_command_list_begin_draw(struct d2d_command_list *command_list,
const struct d2d_device_context *context)
{
if (command_list->state != D2D_COMMAND_LIST_STATE_INITIAL)
{
command_list->state = D2D_COMMAND_LIST_STATE_ERROR;
return;
}
d2d_command_list_set_antialias_mode(command_list, context->drawing_state.antialiasMode);
d2d_command_list_set_primitive_blend(command_list, context->drawing_state.primitiveBlend);
d2d_command_list_set_unit_mode(command_list, context->drawing_state.unitMode);
d2d_command_list_set_text_antialias_mode(command_list, context->drawing_state.textAntialiasMode);
d2d_command_list_set_tags(command_list, context->drawing_state.tag1, context->drawing_state.tag2);
d2d_command_list_set_transform(command_list, &context->drawing_state.transform);
command_list->state = D2D_COMMAND_LIST_STATE_OPEN;
}
......@@ -705,16 +705,39 @@ struct d2d_effect_property * d2d_effect_properties_get_property_by_name(
const struct d2d_effect_properties *properties, const WCHAR *name) DECLSPEC_HIDDEN;
void d2d_effect_properties_cleanup(struct d2d_effect_properties *props) DECLSPEC_HIDDEN;
enum d2d_command_list_state
{
D2D_COMMAND_LIST_STATE_INITIAL = 0,
D2D_COMMAND_LIST_STATE_ERROR,
D2D_COMMAND_LIST_STATE_OPEN,
D2D_COMMAND_LIST_STATE_CLOSED,
};
struct d2d_command_list
{
ID2D1CommandList ID2D1CommandList_iface;
LONG refcount;
ID2D1Factory *factory;
enum d2d_command_list_state state;
size_t size;
size_t capacity;
void *data;
};
HRESULT d2d_command_list_create(ID2D1Factory *factory, struct d2d_command_list **command_list) DECLSPEC_HIDDEN;
struct d2d_command_list *unsafe_impl_from_ID2D1CommandList(ID2D1CommandList *iface) DECLSPEC_HIDDEN;
void d2d_command_list_begin_draw(struct d2d_command_list *command_list, const struct d2d_device_context *context) DECLSPEC_HIDDEN;
void d2d_command_list_set_antialias_mode(struct d2d_command_list *command_list, D2D1_ANTIALIAS_MODE mode) DECLSPEC_HIDDEN;
void d2d_command_list_set_primitive_blend(struct d2d_command_list *command_list,
D2D1_PRIMITIVE_BLEND primitive_blend) DECLSPEC_HIDDEN;
void d2d_command_list_set_unit_mode(struct d2d_command_list *command_list, D2D1_UNIT_MODE mode) DECLSPEC_HIDDEN;
void d2d_command_list_set_text_antialias_mode(struct d2d_command_list *command_list,
D2D1_TEXT_ANTIALIAS_MODE mode) DECLSPEC_HIDDEN;
void d2d_command_list_set_tags(struct d2d_command_list *command_list, D2D1_TAG tag1, D2D1_TAG tag2) DECLSPEC_HIDDEN;
void d2d_command_list_set_transform(struct d2d_command_list *command_list,
const D2D1_MATRIX_3X2_F *transform) DECLSPEC_HIDDEN;
static inline BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
{
......
......@@ -1474,10 +1474,7 @@ static void STDMETHODCALLTYPE d2d_device_context_SetTransform(ID2D1DeviceContext
TRACE("iface %p, transform %p.\n", iface, transform);
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
d2d_command_list_set_transform(context->target.command_list, transform);
context->drawing_state.transform = *transform;
}
......@@ -1500,10 +1497,7 @@ static void STDMETHODCALLTYPE d2d_device_context_SetAntialiasMode(ID2D1DeviceCon
TRACE("iface %p, antialias_mode %#x stub!\n", iface, antialias_mode);
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
d2d_command_list_set_antialias_mode(context->target.command_list, antialias_mode);
context->drawing_state.antialiasMode = antialias_mode;
}
......@@ -1525,10 +1519,7 @@ static void STDMETHODCALLTYPE d2d_device_context_SetTextAntialiasMode(ID2D1Devic
TRACE("iface %p, antialias_mode %#x.\n", iface, antialias_mode);
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
d2d_command_list_set_text_antialias_mode(context->target.command_list, antialias_mode);
context->drawing_state.textAntialiasMode = antialias_mode;
}
......@@ -1580,10 +1571,7 @@ static void STDMETHODCALLTYPE d2d_device_context_SetTags(ID2D1DeviceContext1 *if
TRACE("iface %p, tag1 %s, tag2 %s.\n", iface, wine_dbgstr_longlong(tag1), wine_dbgstr_longlong(tag2));
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
d2d_command_list_set_tags(context->target.command_list, tag1, tag2);
context->drawing_state.tag1 = tag1;
context->drawing_state.tag2 = tag2;
......@@ -1791,10 +1779,7 @@ static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext1 *
TRACE("iface %p.\n", iface);
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
d2d_command_list_begin_draw(context->target.command_list, context);
memset(&context->error, 0, sizeof(context->error));
}
......@@ -2351,18 +2336,15 @@ static void STDMETHODCALLTYPE d2d_device_context_SetUnitMode(ID2D1DeviceContext1
TRACE("iface %p, unit_mode %#x.\n", iface, unit_mode);
if (context->target.type == D2D_TARGET_COMMAND_LIST)
{
FIXME("Unimplemented for command list target.\n");
return;
}
if (unit_mode != D2D1_UNIT_MODE_DIPS && unit_mode != D2D1_UNIT_MODE_PIXELS)
{
WARN("Unknown unit mode %#x.\n", unit_mode);
return;
}
if (context->target.type == D2D_TARGET_COMMAND_LIST)
d2d_command_list_set_unit_mode(context->target.command_list, unit_mode);
context->drawing_state.unitMode = unit_mode;
}
......
......@@ -9641,7 +9641,6 @@ static void test_command_list(BOOL d3d11)
ID2D1Image_Release(target);
hr = ID2D1CommandList_Close(command_list);
todo_wine
ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
ID2D1DeviceContext_GetTarget(device_context, &target);
......@@ -9650,7 +9649,6 @@ static void test_command_list(BOOL d3d11)
if (target) ID2D1Image_Release(target);
hr = ID2D1CommandList_Close(command_list);
todo_wine
ok(hr == D2DERR_WRONG_STATE, "Got unexpected hr %#lx.\n", hr);
ID2D1CommandList_Release(command_list);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment