Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2018
- 70 participants
- 1549 messages
[PATCH 3/6] quartz/tests: Add some tests for filter states.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 276 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 268 insertions(+), 8 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 54afb8a..8dc7341 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -1133,6 +1133,8 @@ struct testfilter
IFilterGraph *graph;
WCHAR *name;
IReferenceClock *clock;
+ FILTER_STATE state;
+ REFERENCE_TIME start_time;
IEnumPins IEnumPins_iface;
struct testpin *pins;
@@ -1255,28 +1257,73 @@ static HRESULT WINAPI testfilter_GetClassID(IBaseFilter *iface, CLSID *clsid)
return S_OK;
}
+/* Downstream filters are always stopped before any filters they are connected
+ * to upstream. Native actually implements this by topologically sorting filters
+ * as they are connected. */
+static void check_state_transition(struct testfilter *filter, FILTER_STATE expect)
+{
+ FILTER_STATE state;
+ unsigned int i;
+ PIN_INFO info;
+
+ for (i = 0; i < filter->pin_count; ++i)
+ {
+ if (filter->pins[i].peer)
+ {
+ IPin_QueryPinInfo(filter->pins[i].peer, &info);
+ IBaseFilter_GetState(info.pFilter, 0, &state);
+ if (filter->pins[i].dir == PINDIR_OUTPUT)
+ ok(state == expect, "Expected state %d for downstream filter %p, got %d.\n",
+ expect, info.pFilter, state);
+ else
+ ok(state == filter->state, "Expected state %d for upstream filter %p, got %d.\n",
+ filter->state, info.pFilter, state);
+ IBaseFilter_Release(info.pFilter);
+ }
+ }
+}
+
static HRESULT WINAPI testfilter_Stop(IBaseFilter *iface)
{
- if (winetest_debug > 1) trace("%p->Stop()\n", iface);
- return E_NOTIMPL;
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->Stop()\n", filter);
+
+ check_state_transition(filter, State_Stopped);
+
+ filter->state = State_Stopped;
+ return S_OK;
}
static HRESULT WINAPI testfilter_Pause(IBaseFilter *iface)
{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->Pause()\n", filter);
+
+ check_state_transition(filter, State_Paused);
+
+ filter->state = State_Paused;
+ return S_OK;
}
static HRESULT WINAPI testfilter_Run(IBaseFilter *iface, REFERENCE_TIME start)
{
- ok(0, "Unexpected call.\n");
- return E_NOTIMPL;
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->Run(%s)\n", filter, wine_dbgstr_longlong(start));
+
+ check_state_transition(filter, State_Running);
+
+ filter->state = State_Running;
+ filter->start_time = start;
+ return S_OK;
}
static HRESULT WINAPI testfilter_GetState(IBaseFilter *iface, DWORD timeout, FILTER_STATE *state)
{
- if (winetest_debug > 1) trace("%p->GetState()\n", iface);
- return E_NOTIMPL;
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->GetState(%u)\n", filter, timeout);
+
+ *state = filter->state;
+ return S_OK;
}
static HRESULT WINAPI testfilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
@@ -1389,6 +1436,7 @@ static void testfilter_init(struct testfilter *filter, struct testpin *pins, int
filter->pin_count = pin_count;
for (i = 0; i < pin_count; i++)
pins[i].filter = &filter->IBaseFilter_iface;
+ filter->state = State_Stopped;
}
static HRESULT WINAPI testfilter_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
@@ -2512,6 +2560,217 @@ todo_wine
ok(filter2.ref == 1, "Got outstanding refcount %d.\n", filter2.ref);
}
+#define check_filter_state(a, b) check_filter_state_(__LINE__, a, b)
+static void check_filter_state_(unsigned int line, IFilterGraph2 *graph, FILTER_STATE expect)
+{
+ IMediaFilter *mediafilter;
+ IEnumFilters *filterenum;
+ IMediaControl *control;
+ OAFilterState oastate;
+ IBaseFilter *filter;
+ FILTER_STATE state;
+ HRESULT hr;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&mediafilter);
+ hr = IMediaFilter_GetState(mediafilter, 1000, &state);
+ ok_(__FILE__, line)(hr == S_OK, "IMediaFilter_GetState() returned %#x.\n", hr);
+ ok_(__FILE__, line)(state == expect, "Expected state %u, got %u.\n", expect, state);
+ IMediaFilter_Release(mediafilter);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+ hr = IMediaControl_GetState(control, 1000, &oastate);
+ ok_(__FILE__, line)(hr == S_OK, "IMediaControl_GetState() returned %#x.\n", hr);
+ ok_(__FILE__, line)(state == expect, "Expected state %u, got %u.\n", expect, state);
+ IMediaControl_Release(control);
+
+ IFilterGraph2_EnumFilters(graph, &filterenum);
+ while (IEnumFilters_Next(filterenum, 1, &filter, NULL) == S_OK)
+ {
+ hr = IBaseFilter_GetState(filter, 1000, &state);
+ ok_(__FILE__, line)(hr == S_OK, "IBaseFilter_GetState() returned %#x.\n", hr);
+ ok_(__FILE__, line)(state == expect, "Expected state %u, got %u.\n", expect, state);
+ IBaseFilter_Release(filter);
+ }
+ IEnumFilters_Release(filterenum);
+}
+
+
+static void test_filter_state(void)
+{
+ struct testpin source_pin, sink_pin;
+ struct testfilter source, sink;
+
+ IFilterGraph2 *graph = create_graph();
+ REFERENCE_TIME start_time;
+ IReferenceClock *clock;
+ IMediaControl *control;
+ IMediaFilter *filter;
+ HRESULT hr;
+ ULONG ref;
+
+ testsource_init(&source_pin, NULL, 0);
+ testsink_init(&sink_pin);
+ testfilter_init(&source, &source_pin, 1);
+ testfilter_init(&sink, &sink_pin, 1);
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&filter);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ source_pin.filter = &source.IBaseFilter_iface;
+ sink_pin.filter = &sink.IBaseFilter_iface;
+
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
+
+ check_filter_state(graph, State_Stopped);
+
+ hr = IMediaControl_Pause(control);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Paused);
+
+ /* Pausing sets the default sync source, if it's not already set. */
+
+ hr = IMediaFilter_GetSyncSource(filter, &clock);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!clock, "Reference clock not set.\n");
+ ok(source.clock == clock, "Expected %p, got %p.\n", clock, source.clock);
+ ok(sink.clock == clock, "Expected %p, got %p.\n", clock, sink.clock);
+
+ hr = IReferenceClock_GetTime(clock, &start_time);
+ ok(SUCCEEDED(hr), "Got hr %#x.\n", hr);
+ hr = IMediaControl_Run(control);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+ ok(source.start_time >= start_time && source.start_time < start_time + 500 * 10000,
+ "Expected time near %s, got %s.\n",
+ wine_dbgstr_longlong(start_time), wine_dbgstr_longlong(source.start_time));
+ ok(sink.start_time == source.start_time, "Expected time %s, got %s.\n",
+ wine_dbgstr_longlong(source.start_time), wine_dbgstr_longlong(sink.start_time));
+
+ hr = IMediaControl_Pause(control);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Paused);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Stopped);
+
+ hr = IMediaControl_Run(control);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Stopped);
+
+ IReferenceClock_Release(clock);
+ IMediaFilter_Release(filter);
+ IMediaControl_Release(control);
+ IFilterGraph2_Release(graph);
+
+ /* Test same methods using IMediaFilter. */
+
+ graph = create_graph();
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&filter);
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
+
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL);
+ IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL);
+
+ hr = IMediaFilter_Pause(filter);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Paused);
+
+ hr = IMediaFilter_GetSyncSource(filter, &clock);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!!clock, "Reference clock not set.\n");
+ ok(source.clock == clock, "Expected %p, got %p.\n", clock, source.clock);
+ ok(sink.clock == clock, "Expected %p, got %p.\n", clock, sink.clock);
+
+ hr = IMediaFilter_Run(filter, 0xdeadbeef);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+todo_wine {
+ ok(source.start_time == 0xdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(source.start_time));
+ ok(sink.start_time == 0xdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(sink.start_time));
+}
+
+ hr = IMediaFilter_Pause(filter);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Paused);
+
+ hr = IMediaFilter_Stop(filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Stopped);
+
+ hr = IReferenceClock_GetTime(clock, &start_time);
+ ok(SUCCEEDED(hr), "Got hr %#x.\n", hr);
+ hr = IMediaFilter_Run(filter, 0);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+ ok(source.start_time >= start_time && source.start_time < start_time + 500 * 10000,
+ "Expected time near %s, got %s.\n",
+ wine_dbgstr_longlong(start_time), wine_dbgstr_longlong(source.start_time));
+ ok(sink.start_time == source.start_time, "Expected time %s, got %s.\n",
+ wine_dbgstr_longlong(source.start_time), wine_dbgstr_longlong(sink.start_time));
+
+ hr = IMediaFilter_Stop(filter);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Stopped);
+
+ /* Test removing the sync source. */
+
+ IReferenceClock_Release(clock);
+ IMediaFilter_SetSyncSource(filter, NULL);
+
+ hr = IMediaControl_Run(control);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+todo_wine
+ ok(source.start_time > 0 && source.start_time < 500 * 10000,
+ "Got time %s.\n", wine_dbgstr_longlong(source.start_time));
+ ok(sink.start_time == source.start_time, "Expected time %s, got %s.\n",
+ wine_dbgstr_longlong(source.start_time), wine_dbgstr_longlong(sink.start_time));
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Stopped);
+
+ /* Destroying the graph while it's running stops all filters. */
+
+ hr = IMediaFilter_Run(filter, 0);
+todo_wine
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ check_filter_state(graph, State_Running);
+todo_wine
+ ok(source.start_time > 0 && source.start_time < 500 * 10000,
+ "Got time %s.\n", wine_dbgstr_longlong(source.start_time));
+ ok(sink.start_time == source.start_time, "Expected time %s, got %s.\n",
+ wine_dbgstr_longlong(source.start_time), wine_dbgstr_longlong(sink.start_time));
+
+ IMediaFilter_Release(filter);
+ IMediaControl_Release(control);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
+ ok(sink.ref == 1, "Got outstanding refcount %d.\n", sink.ref);
+ ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
+ ok(sink_pin.ref == 1, "Got outstanding refcount %d.\n", sink_pin.ref);
+ ok(source.state == State_Stopped, "Got state %u.\n", source.state);
+ ok(sink.state == State_Stopped, "Got state %u.\n", sink.state);
+}
+
START_TEST(filtergraph)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -2527,6 +2786,7 @@ START_TEST(filtergraph)
test_add_remove_filter();
test_connect_direct();
test_sync_source();
+ test_filter_state();
CoUninitialize();
test_render_with_multithread();
--
2.7.4
Sept. 26, 2018
[PATCH 2/6] quartz/filtergraph: Also set the default sync source if necessary in IMediaControl_Pause().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index a5cfe2d..e721388 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -2307,6 +2307,9 @@ static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
if (This->state == State_Paused)
goto out;
+ if (This->defaultclock && !This->refClock)
+ IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface);
+
if (This->state == State_Running && This->refClock && This->start_time >= 0)
IReferenceClock_GetTime(This->refClock, &This->pause_time);
else
--
2.7.4
Sept. 26, 2018
[PATCH 1/6] quartz/tests: Add some tests for IMediaFilter_SetSyncSource() and IMediaFilter_GetSyncSource().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 53 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 5693c86..54afb8a 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -2460,6 +2460,58 @@ todo_wine
ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
}
+static void test_sync_source(void)
+{
+ struct testfilter filter1, filter2;
+
+ IFilterGraph2 *graph = create_graph();
+ IReferenceClock *systemclock, *clock;
+ IMediaFilter *filter;
+ HRESULT hr;
+ ULONG ref;
+
+ IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&filter);
+
+ testfilter_init(&filter1, NULL, 0);
+ testfilter_init(&filter2, NULL, 0);
+
+ IFilterGraph2_AddFilter(graph, &filter1.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &filter2.IBaseFilter_iface, NULL);
+
+ ok(!filter1.clock, "Got clock %p.\n", filter1.clock);
+ ok(!filter2.clock, "Got clock %p.\n", filter2.clock);
+
+ CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IReferenceClock, (void **)&systemclock);
+
+ hr = IMediaFilter_SetSyncSource(filter, systemclock);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(filter1.clock == systemclock, "Got clock %p.\n", filter1.clock);
+ ok(filter2.clock == systemclock, "Got clock %p.\n", filter2.clock);
+
+ hr = IMediaFilter_GetSyncSource(filter, &clock);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(clock == systemclock, "Got clock %p.\n", clock);
+ IReferenceClock_Release(clock);
+
+ hr = IMediaFilter_SetSyncSource(filter, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(!filter1.clock, "Got clock %p.\n", filter1.clock);
+ ok(!filter2.clock, "Got clock %p.\n", filter2.clock);
+
+ hr = IMediaFilter_GetSyncSource(filter, &clock);
+todo_wine
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(!clock, "Got clock %p.\n", clock);
+
+ IReferenceClock_Release(systemclock);
+ IMediaFilter_Release(filter);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d\n", ref);
+ ok(filter1.ref == 1, "Got outstanding refcount %d.\n", filter1.ref);
+ ok(filter2.ref == 1, "Got outstanding refcount %d.\n", filter2.ref);
+}
+
START_TEST(filtergraph)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -2474,6 +2526,7 @@ START_TEST(filtergraph)
test_control_delegation();
test_add_remove_filter();
test_connect_direct();
+ test_sync_source();
CoUninitialize();
test_render_with_multithread();
--
2.7.4
Sept. 26, 2018
[PATCH 2/2] msvcrt: Use isfinite instead of finitef
by Alex Henrie
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
This one wasn't causing any problems in practice that I know of, but
it's less confusing to just use the standard macro.
---
configure.ac | 1 -
dlls/msvcrt/math.c | 42 +++++++++++++++++++-----------------------
2 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2cc481630c..ff8c98fde6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2146,7 +2146,6 @@ AC_CHECK_FUNCS(\
dlopen \
epoll_create \
ffs \
- finitef \
fnmatch \
fork \
fpclass \
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index dbfaa24756..a98defd868 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -34,10 +34,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
-#ifndef HAVE_FINITEF
-#define finitef(x) isfinite(x)
-#endif
-
/* FIXME: Does not work with -NAN and -0. */
#ifndef signbit
#define signbit(x) ((x) < 0)
@@ -159,7 +155,7 @@ float CDECL MSVCRT__copysignf( float num, float sign )
*/
float CDECL MSVCRT__nextafterf( float num, float next )
{
- if (!finitef(num) || !finitef(next)) *MSVCRT__errno() = MSVCRT_EDOM;
+ if (!isfinite(num) || !isfinite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
return nextafterf( num, next );
}
@@ -171,7 +167,7 @@ float CDECL MSVCRT__nextafterf( float num, float next )
*/
int CDECL MSVCRT__finitef( float num )
{
- return finitef(num) != 0; /* See comment for _isnan() */
+ return isfinite(num) != 0; /* See comment for _isnan() */
}
/*********************************************************************
@@ -207,7 +203,7 @@ float CDECL MSVCRT_acosf( float x )
* cancellation. The sqrt() makes things worse. A safer way to calculate
* acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
float ret = atan2f(sqrtf((1 - x) * (1 + x)), x);
- if (x < -1.0 || x > 1.0 || !finitef(x)) math_error(_DOMAIN, "acosf", x, 0, ret);
+ if (x < -1.0 || x > 1.0 || !isfinite(x)) math_error(_DOMAIN, "acosf", x, 0, ret);
return ret;
}
@@ -217,7 +213,7 @@ float CDECL MSVCRT_acosf( float x )
float CDECL MSVCRT_asinf( float x )
{
float ret = atan2f(x, sqrtf((1 - x) * (1 + x)));
- if (x < -1.0 || x > 1.0 || !finitef(x)) math_error(_DOMAIN, "asinf", x, 0, ret);
+ if (x < -1.0 || x > 1.0 || !isfinite(x)) math_error(_DOMAIN, "asinf", x, 0, ret);
return ret;
}
@@ -227,7 +223,7 @@ float CDECL MSVCRT_asinf( float x )
float CDECL MSVCRT_atanf( float x )
{
float ret = atanf(x);
- if (!finitef(x)) math_error(_DOMAIN, "atanf", x, 0, ret);
+ if (!isfinite(x)) math_error(_DOMAIN, "atanf", x, 0, ret);
return ret;
}
@@ -247,7 +243,7 @@ float CDECL MSVCRT_atan2f( float x, float y )
float CDECL MSVCRT_cosf( float x )
{
float ret = cosf(x);
- if (!finitef(x)) math_error(_DOMAIN, "cosf", x, 0, ret);
+ if (!isfinite(x)) math_error(_DOMAIN, "cosf", x, 0, ret);
return ret;
}
@@ -268,8 +264,8 @@ float CDECL MSVCRT_expf( float x )
{
float ret = expf(x);
if (isnan(x)) math_error(_DOMAIN, "expf", x, 0, ret);
- else if (finitef(x) && !ret) math_error(_UNDERFLOW, "expf", x, 0, ret);
- else if (finitef(x) && !finitef(ret)) math_error(_OVERFLOW, "expf", x, 0, ret);
+ else if (isfinite(x) && !ret) math_error(_UNDERFLOW, "expf", x, 0, ret);
+ else if (isfinite(x) && !isfinite(ret)) math_error(_OVERFLOW, "expf", x, 0, ret);
return ret;
}
@@ -279,7 +275,7 @@ float CDECL MSVCRT_expf( float x )
float CDECL MSVCRT_fmodf( float x, float y )
{
float ret = fmodf(x, y);
- if (!finitef(x) || !finitef(y)) math_error(_DOMAIN, "fmodf", x, 0, ret);
+ if (!isfinite(x) || !isfinite(y)) math_error(_DOMAIN, "fmodf", x, 0, ret);
return ret;
}
@@ -312,9 +308,9 @@ float CDECL MSVCRT_powf( float x, float y )
{
float z = powf(x,y);
if (x < 0 && y != floorf(y)) math_error(_DOMAIN, "powf", x, y, z);
- else if (!x && finitef(y) && y < 0) math_error(_SING, "powf", x, y, z);
- else if (finitef(x) && finitef(y) && !finitef(z)) math_error(_OVERFLOW, "powf", x, y, z);
- else if (x && finitef(x) && finitef(y) && !z) math_error(_UNDERFLOW, "powf", x, y, z);
+ else if (!x && isfinite(y) && y < 0) math_error(_SING, "powf", x, y, z);
+ else if (isfinite(x) && isfinite(y) && !isfinite(z)) math_error(_OVERFLOW, "powf", x, y, z);
+ else if (x && isfinite(x) && isfinite(y) && !z) math_error(_UNDERFLOW, "powf", x, y, z);
return z;
}
@@ -324,7 +320,7 @@ float CDECL MSVCRT_powf( float x, float y )
float CDECL MSVCRT_sinf( float x )
{
float ret = sinf(x);
- if (!finitef(x)) math_error(_DOMAIN, "sinf", x, 0, ret);
+ if (!isfinite(x)) math_error(_DOMAIN, "sinf", x, 0, ret);
return ret;
}
@@ -354,7 +350,7 @@ float CDECL MSVCRT_sqrtf( float x )
float CDECL MSVCRT_tanf( float x )
{
float ret = tanf(x);
- if (!finitef(x)) math_error(_DOMAIN, "tanf", x, 0, ret);
+ if (!isfinite(x)) math_error(_DOMAIN, "tanf", x, 0, ret);
return ret;
}
@@ -364,7 +360,7 @@ float CDECL MSVCRT_tanf( float x )
float CDECL MSVCRT_tanhf( float x )
{
float ret = tanhf(x);
- if (!finitef(x)) math_error(_DOMAIN, "tanhf", x, 0, ret);
+ if (!isfinite(x)) math_error(_DOMAIN, "tanhf", x, 0, ret);
return ret;
}
@@ -2468,7 +2464,7 @@ float CDECL MSVCR120_exp2f(float x)
{
#ifdef HAVE_EXP2F
float ret = exp2f(x);
- if (finitef(x) && !finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
+ if (isfinite(x) && !isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
return ret;
#else
return MSVCR120_exp2(x);
@@ -2507,7 +2503,7 @@ float CDECL MSVCR120_expm1f(float x)
#else
float ret = exp(x) - 1;
#endif
- if (finitef(x) && !finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
+ if (isfinite(x) && !isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
return ret;
}
@@ -3152,7 +3148,7 @@ float CDECL MSVCR120_atanhf(float x)
ret = atanhf(x);
- if (!finitef(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
+ if (!isfinite(ret)) *MSVCRT__errno() = MSVCRT_ERANGE;
return ret;
#else
return MSVCR120_atanh(x);
@@ -3223,7 +3219,7 @@ float CDECL MSVCR120_remainderf(float x, float y)
{
#ifdef HAVE_REMAINDERF
/* this matches 64-bit Windows. 32-bit Windows is slightly different */
- if(!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
+ if(!isfinite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
if(isnan(y) || y==0.0f) *MSVCRT__errno() = MSVCRT_EDOM;
return remainderf(x, y);
#else
--
2.19.0
Sept. 26, 2018
[PATCH 1/2] msvcrt: Use isnan instead of isnanf
by Alex Henrie
This resolves several warnings when compiling with MinGW because isnanf
is not in MinGW's math.h (it's not a standard C function). On the other
hand, isnan is a widely available C99 macro designed for both floats and
doubles. We also have an isnan implementation in libs/port/isnan.c for
pre-C99 compilers.
Signed-off-by: Alex Henrie <alexhenrie24(a)gmail.com>
---
configure.ac | 1 -
dlls/msvcrt/math.c | 30 +++++++++++-------------------
2 files changed, 11 insertions(+), 20 deletions(-)
diff --git a/configure.ac b/configure.ac
index 6936a71b6f..2cc481630c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2163,7 +2163,6 @@ AC_CHECK_FUNCS(\
getpwuid \
gettimeofday \
getuid \
- isnanf \
kqueue \
lstat \
memmove \
diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c
index a1ba552632..dbfaa24756 100644
--- a/dlls/msvcrt/math.c
+++ b/dlls/msvcrt/math.c
@@ -38,14 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
#define finitef(x) isfinite(x)
#endif
-#ifndef HAVE_ISNANF
-#ifdef HAVE_ISNAN
-#define isnanf(x) isnan(x)
-#else
-#define isnanf(x) 0
-#endif
-#endif
-
/* FIXME: Does not work with -NAN and -0. */
#ifndef signbit
#define signbit(x) ((x) < 0)
@@ -190,7 +182,7 @@ INT CDECL MSVCRT__isnanf( float num )
/* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
* Do the same, as the result may be used in calculations
*/
- return isnanf(num) != 0;
+ return isnan(num) != 0;
}
/*********************************************************************
@@ -199,7 +191,7 @@ INT CDECL MSVCRT__isnanf( float num )
float CDECL MSVCRT__logbf( float num )
{
float ret = logbf(num);
- if (isnanf(num)) math_error(_DOMAIN, "_logbf", num, 0, ret);
+ if (isnan(num)) math_error(_DOMAIN, "_logbf", num, 0, ret);
else if (!num) math_error(_SING, "_logbf", num, 0, ret);
return ret;
}
@@ -245,7 +237,7 @@ float CDECL MSVCRT_atanf( float x )
float CDECL MSVCRT_atan2f( float x, float y )
{
float ret = atan2f(x, y);
- if (isnanf(x)) math_error(_DOMAIN, "atan2f", x, y, ret);
+ if (isnan(x)) math_error(_DOMAIN, "atan2f", x, y, ret);
return ret;
}
@@ -265,7 +257,7 @@ float CDECL MSVCRT_cosf( float x )
float CDECL MSVCRT_coshf( float x )
{
float ret = coshf(x);
- if (isnanf(x)) math_error(_DOMAIN, "coshf", x, 0, ret);
+ if (isnan(x)) math_error(_DOMAIN, "coshf", x, 0, ret);
return ret;
}
@@ -275,7 +267,7 @@ float CDECL MSVCRT_coshf( float x )
float CDECL MSVCRT_expf( float x )
{
float ret = expf(x);
- if (isnanf(x)) math_error(_DOMAIN, "expf", x, 0, ret);
+ if (isnan(x)) math_error(_DOMAIN, "expf", x, 0, ret);
else if (finitef(x) && !ret) math_error(_UNDERFLOW, "expf", x, 0, ret);
else if (finitef(x) && !finitef(ret)) math_error(_OVERFLOW, "expf", x, 0, ret);
return ret;
@@ -342,7 +334,7 @@ float CDECL MSVCRT_sinf( float x )
float CDECL MSVCRT_sinhf( float x )
{
float ret = sinhf(x);
- if (isnanf(x)) math_error(_DOMAIN, "sinhf", x, 0, ret);
+ if (isnan(x)) math_error(_DOMAIN, "sinhf", x, 0, ret);
return ret;
}
@@ -2943,9 +2935,9 @@ LDOUBLE CDECL MSVCR120_erfcl(LDOUBLE x)
*/
float CDECL MSVCR120_fmaxf(float x, float y)
{
- if(isnanf(x))
+ if(isnan(x))
return y;
- if(isnanf(y))
+ if(isnan(y))
return x;
if(x==0 && y==0)
return signbit(x) ? y : x;
@@ -3008,9 +3000,9 @@ int CDECL MSVCR120__fdpcomp(float x, float y)
*/
float CDECL MSVCR120_fminf(float x, float y)
{
- if(isnanf(x))
+ if(isnan(x))
return y;
- if(isnanf(y))
+ if(isnan(y))
return x;
if(x==0 && y==0)
return signbit(x) ? x : y;
@@ -3232,7 +3224,7 @@ float CDECL MSVCR120_remainderf(float x, float y)
#ifdef HAVE_REMAINDERF
/* this matches 64-bit Windows. 32-bit Windows is slightly different */
if(!finitef(x)) *MSVCRT__errno() = MSVCRT_EDOM;
- if(isnanf(y) || y==0.0f) *MSVCRT__errno() = MSVCRT_EDOM;
+ if(isnan(y) || y==0.0f) *MSVCRT__errno() = MSVCRT_EDOM;
return remainderf(x, y);
#else
FIXME( "not implemented\n" );
--
2.19.0
Sept. 26, 2018
Re: [PATCH 1/2] ntoskrnl.exe: Implement IoRegisterDeviceInterface
by Zebediah Figura
On 17/09/18 13:39, Zebediah Figura wrote:
> On 17/09/18 13:20, Aric Stewart wrote:
>> On 9/17/18 11:55 AM, Zebediah Figura wrote:
>>> On 17/09/18 11:44, Aric Stewart wrote:
>>>>
>>>>
>>>> On 9/14/18 2:02 PM, Zebediah Figura wrote:
>>>>> On 14/09/18 13:59, Aric Stewart wrote:
>>>>>> Signed-off-by: Aric Stewart <aric(a)codeweavers.com>
>>>>>> ---
>>>>>> dlls/ntoskrnl.exe/ntoskrnl.c | 216 ++++++++++++++++++++++++++++++++++++
>>>>>> dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +-
>>>>>> include/ddk/wdm.h | 1 +
>>>>>> 3 files changed, 218 insertions(+), 1 deletion(-)
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> Can this go directly through setupapi instead?
>>>>>
>>>>>
>>>>
>>>> Sorry, I dont know if I understand your question...
>>>>
>>>> What do you mean go through setupapi? Not that we have or enforce this in any way, but technically setupapi is user level and IoRegisterDeviceInterface is kernel level.
>>>>
>>>> -aric
>>>>
>>>>
>>>
>>> I mean that we could implement this on top of setupapi routines instead
>>> of essentially reimplementing them here. I know that it's
>>> architecturally upside-down, but we call call user-mode functions
>>> elsewhere in ntoskrnl, and as long as we're going to keep drivers in
>>> user-mode I don't see any reason to avoid that.
>>>
>>>
>>
>> Yeah, Looking at the SetupDiCreateDeviceInterfaceW APIs in setupapi I can see how you think that. They where clearly the inspiration and base for my work. However the top level entry points vary quite a bit.
>> BOOL WINAPI SetupDiCreateDeviceInterfaceW(HDEVINFO DeviceInfoSet,
>> PSP_DEVINFO_DATA DeviceInfoData,
>> const GUID *InterfaceClassGuid,
>> PCWSTR ReferenceString,
>> DWORD CreationFlags,
>> SP_DEVICE_INTERFACE_DATA *iface_data)
>> vs
>> NTSTATUS WINAPI IoRegisterDeviceInterface(DEVICE_OBJECT *device,
>> const GUID *class_guid,
>> UNICODE_STRING *reference_string,
>> UNICODE_STRING *symbolic_link)
>>
>> Because creating WINE custom entry points into existing dlls is frowned upon I felt it easier to reimplement instead of try to shoehorn. However if you are seeing something I did not then maybe it should be done differently!
>>
>> -aric
>>
>>
>
> Hmm, right, I see that setupapi doesn't expose a way to specify the
> symbolic link.
>
> Another alternative is to implement some of setupapi on top of ntoskrnl,
> though I'm not sure to what degree that's worth doing.
>
>
Actually, now that I actually look at the documentation for this
function, symbolic_link is an output parameter. So it should be
perfectly possible to use SetupDiCreateDeviceInterface() to register the
interface and SetupDiGetDeviceInterfaceDetail() to retrieve the symbolic
link.
Sept. 26, 2018
[PATCH 4/4] d2d1: Implement CreateDeviceContext().
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d2d1/device.c | 23 +++++++++++++++++++++--
dlls/d2d1/tests/d2d1.c | 16 +++++++---------
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index 212e9c0df9..b1b719e2eb 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -3865,9 +3865,28 @@ static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **fact
static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options,
ID2D1DeviceContext **context)
{
- FIXME("iface %p, options %#x, context %p stub!\n", iface, options, context);
+ struct d2d_device_context *object;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("iface %p, options %#x, context %p.\n", iface, options, context);
+
+ if (options)
+ FIXME("Options are ignored %#x.\n", options);
+
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ if (FAILED(hr = d2d_device_context_init(object, iface, NULL, NULL)))
+ {
+ WARN("Failed to initialize device context, hr %#x.\n", hr);
+ heap_free(object);
+ return hr;
+ }
+
+ TRACE("Created device context %p.\n", object);
+ *context = &object->ID2D1DeviceContext_iface;
+
+ return S_OK;
}
static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory,
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index c2e0ab2a08..e6320e51b0 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -6962,11 +6962,8 @@ static void test_bitmap_surface(void)
ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr);
hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
-todo_wine
ok(SUCCEEDED(hr), "Failed to create device context, hr %#x.\n", hr);
-if (SUCCEEDED(hr))
-{
for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
{
D2D1_PIXEL_FORMAT pixel_format;
@@ -6976,9 +6973,10 @@ if (SUCCEEDED(hr))
bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, &bitmap_desc, &bitmap);
+ todo_wine_if(FAILED(bitmap_format_tests[i].hr))
ok(hr == bitmap_format_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(bitmap_format_tests[i].hr))
{
pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
@@ -7005,7 +7003,7 @@ if (SUCCEEDED(hr))
ID2D1DeviceContext_Release(device_context);
ID2D1Bitmap1_Release(bitmap);
-}
+
ID2D1Device_Release(device);
IDXGIDevice_Release(dxgi_device);
IDXGISurface_Release(surface);
@@ -7108,11 +7106,8 @@ static void test_device_context(void)
IDXGIDevice_Release(dxgi_device);
hr = ID2D1Device_CreateDeviceContext(device, D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &device_context);
-todo_wine
ok(SUCCEEDED(hr), "Failed to create device context, hr %#x.\n", hr);
-if (SUCCEEDED(hr))
-{
ID2D1DeviceContext_GetDevice(device_context, &device2);
ok(device2 == device, "Unexpected device instance.\n");
ID2D1Device_Release(device2);
@@ -7190,6 +7185,7 @@ if (SUCCEEDED(hr))
ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW),
"Unexpected bitmap options %#x.\n", options);
hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
+todo_wine
ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
ID2D1Bitmap1_Release(bitmap);
@@ -7238,6 +7234,7 @@ if (SUCCEEDED(hr))
hr = ID2D1DCRenderTarget_QueryInterface(dc_rt, &IID_ID2D1DeviceContext, (void **)&device_context);
ok(SUCCEEDED(hr), "Failed to get device context interface, hr %#x.\n", hr);
ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
+todo_wine
ok(bitmap == NULL, "Unexpected bitmap instance.\n");
hdc = CreateCompatibleDC(NULL);
@@ -7251,6 +7248,7 @@ if (SUCCEEDED(hr))
ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
options = ID2D1Bitmap1_GetOptions(bitmap);
+todo_wine
ok(options == (D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE),
"Unexpected bitmap options %#x.\n", options);
hr = ID2D1Bitmap1_GetSurface(bitmap, &surface);
@@ -7264,7 +7262,7 @@ if (SUCCEEDED(hr))
ID2D1DeviceContext_Release(device_context);
ID2D1DCRenderTarget_Release(dc_rt);
DeleteDC(hdc);
-}
+
ID2D1Device_Release(device);
ID2D1Factory1_Release(factory);
ID3D10Device1_Release(d3d_device);
--
2.19.0
Sept. 26, 2018
[PATCH 3/4] d2d1: Implement SetTarget() for bitmap targets.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d2d1/d2d1_private.h | 14 ++-
dlls/d2d1/device.c | 245 +++++++++++++++++++++++++--------------
dlls/d2d1/tests/d2d1.c | 5 +-
3 files changed, 170 insertions(+), 94 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 726d143d86..ac42f7cf25 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -136,7 +136,6 @@ struct d2d_device_context
ID2D1Factory *factory;
ID2D1Device *device;
ID3D10Device *d3d_device;
- ID3D10RenderTargetView *view;
ID3D10StateBlock *stateblock;
struct d2d_shape_resources shape_resources[D2D_SHAPE_TYPE_COUNT];
ID3D10PixelShader *ps;
@@ -146,6 +145,19 @@ struct d2d_device_context
ID3D10RasterizerState *rs;
ID3D10BlendState *bs;
+ struct
+ {
+ union
+ {
+ ID2D1Image *image;
+ struct
+ {
+ ID2D1Bitmap *bitmap;
+ ID3D10RenderTargetView *view;
+ } bitmap;
+ } u;
+ } target;
+
struct d2d_error_state error;
D2D1_DRAWING_STATE_DESCRIPTION1 drawing_state;
IDWriteRenderingParams *text_rendering_params;
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index be31ecafc8..212e9c0df9 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -43,6 +43,8 @@ static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface)
return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
}
+static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface);
+
static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect)
{
ID2D1Brush *brush = NULL;
@@ -175,7 +177,7 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en
}
ID3D10Device_RSSetScissorRects(device, 1, &scissor_rect);
ID3D10Device_RSSetState(device, render_target->rs);
- ID3D10Device_OMSetRenderTargets(device, 1, &render_target->view, NULL);
+ ID3D10Device_OMSetRenderTargets(device, 1, &render_target->target.u.bitmap.view, NULL);
if (brush)
{
ID3D10Device_OMSetBlendState(device, render_target->bs, blend_factor, D3D10_DEFAULT_SAMPLE_MASK);
@@ -261,7 +263,8 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
IDWriteRenderingParams_Release(context->default_text_rendering_params);
if (context->text_rendering_params)
IDWriteRenderingParams_Release(context->text_rendering_params);
- ID3D10BlendState_Release(context->bs);
+ if (context->bs)
+ ID3D10BlendState_Release(context->bs);
ID3D10RasterizerState_Release(context->rs);
ID3D10Buffer_Release(context->vb);
ID3D10Buffer_Release(context->ib);
@@ -272,8 +275,11 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface)
ID3D10InputLayout_Release(context->shape_resources[i].il);
}
context->stateblock->lpVtbl->Release(context->stateblock);
- ID3D10RenderTargetView_Release(context->view);
ID3D10Device_Release(context->d3d_device);
+ if (context->target.u.bitmap.view)
+ ID3D10RenderTargetView_Release(context->target.u.bitmap.view);
+ if (context->target.u.image)
+ ID2D1Image_Release(context->target.u.image);
ID2D1Factory_Release(context->factory);
ID2D1Device_Release(context->device);
heap_free(context);
@@ -1971,14 +1977,100 @@ static void STDMETHODCALLTYPE d2d_device_context_GetDevice(ID2D1DeviceContext *i
ID2D1Device_AddRef(*device);
}
+static void d2d_device_context_reset_target(struct d2d_device_context *context)
+{
+ if (!context->target.u.image)
+ return;
+
+ ID2D1Image_Release(context->target.u.image);
+ context->target.u.image = NULL;
+
+ context->desc.dpiX = 96.0f;
+ context->desc.dpiY = 96.0f;
+
+ memset(&context->desc.pixelFormat, 0, sizeof(context->desc.pixelFormat));
+ memset(&context->pixel_size, 0, sizeof(context->pixel_size));
+
+ ID3D10BlendState_Release(context->bs);
+ context->bs = NULL;
+
+ ID3D10RenderTargetView_Release(context->target.u.bitmap.view);
+ context->target.u.bitmap.view = NULL;
+}
+
static void STDMETHODCALLTYPE d2d_device_context_SetTarget(ID2D1DeviceContext *iface, ID2D1Image *target)
{
- FIXME("iface %p, target %p stub!\n", iface, target);
+ struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
+ struct d2d_bitmap *bitmap_impl;
+ D3D10_BLEND_DESC blend_desc;
+ ID3D10Resource *resource;
+ ID2D1Bitmap *bitmap;
+ HRESULT hr;
+
+ TRACE("iface %p, target %p.\n", iface, target);
+
+ if (!target)
+ {
+ d2d_device_context_reset_target(context);
+ return;
+ }
+
+ if (FAILED(ID2D1Image_QueryInterface(target, &IID_ID2D1Bitmap1, (void **)&bitmap)))
+ {
+ FIXME("Only bitmap targets are supported.\n");
+ return;
+ }
+
+ d2d_device_context_reset_target(context);
+
+ context->target.u.bitmap.bitmap = bitmap;
+
+ /* Set sizes and pixel format. */
+ ID2D1Bitmap_GetDpi(bitmap, &context->desc.dpiX, &context->desc.dpiY);
+ context->pixel_size = ID2D1Bitmap_GetPixelSize(bitmap);
+ context->desc.pixelFormat = ID2D1Bitmap_GetPixelFormat(bitmap);
+
+ memset(&blend_desc, 0, sizeof(blend_desc));
+ blend_desc.BlendEnable[0] = TRUE;
+ blend_desc.SrcBlend = D3D10_BLEND_ONE;
+ blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
+ blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
+ if (context->desc.pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
+ {
+ blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
+ blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
+ }
+ else
+ {
+ blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
+ blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
+ }
+ blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
+ blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
+ if (FAILED(hr = ID3D10Device_CreateBlendState(context->d3d_device, &blend_desc, &context->bs)))
+ {
+ WARN("Failed to create blend state, hr %#x.\n", hr);
+ return;
+ }
+
+ bitmap_impl = unsafe_impl_from_ID2D1Bitmap(bitmap);
+ ID3D10ShaderResourceView_GetResource(bitmap_impl->view, &resource);
+
+ hr = ID3D10Device_CreateRenderTargetView(context->d3d_device, resource, NULL, &context->target.u.bitmap.view);
+ ID3D10Resource_Release(resource);
+ if (FAILED(hr))
+ WARN("Failed to create rendertarget view, hr %#x.\n", hr);
}
static void STDMETHODCALLTYPE d2d_device_context_GetTarget(ID2D1DeviceContext *iface, ID2D1Image **target)
{
- FIXME("iface %p, target %p stub!\n", iface, target);
+ struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface);
+
+ TRACE("iface %p, target %p.\n", iface, target);
+
+ *target = context->target.u.image;
+ if (*target)
+ ID2D1Image_AddRef(*target);
}
static void STDMETHODCALLTYPE d2d_device_context_SetRenderingControls(ID2D1DeviceContext *iface,
@@ -2530,7 +2622,7 @@ static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_
ID3D10Resource *resource;
HRESULT hr;
- ID3D10RenderTargetView_GetResource(render_target->view, &resource);
+ ID3D10RenderTargetView_GetResource(render_target->target.u.bitmap.view, &resource);
hr = ID3D10Resource_QueryInterface(resource, &IID_IDXGISurface1, (void **)surface);
ID3D10Resource_Release(resource);
if (FAILED(hr))
@@ -2592,17 +2684,14 @@ static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_targe
};
static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Device *device,
- IDXGISurface *surface, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops,
- const D2D1_RENDER_TARGET_PROPERTIES *desc)
+ IUnknown *outer_unknown, const struct d2d_device_context_ops *ops)
{
D3D10_SUBRESOURCE_DATA buffer_data;
D3D10_STATE_BLOCK_MASK state_mask;
- DXGI_SURFACE_DESC surface_desc;
+ struct d2d_device *device_impl;
IDWriteFactory *dwrite_factory;
D3D10_RASTERIZER_DESC rs_desc;
D3D10_BUFFER_DESC buffer_desc;
- D3D10_BLEND_DESC blend_desc;
- ID3D10Resource *resource;
unsigned int i;
HRESULT hr;
@@ -3452,25 +3541,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
{ 1.0f, -1.0f},
};
static const UINT16 indices[] = {0, 1, 2, 2, 1, 3};
- float dpi_x, dpi_y;
-
- dpi_x = desc->dpiX;
- dpi_y = desc->dpiY;
-
- if (dpi_x == 0.0f && dpi_y == 0.0f)
- {
- dpi_x = 96.0f;
- dpi_y = 96.0f;
- }
- else if (dpi_x <= 0.0f || dpi_y <= 0.0f)
- return E_INVALIDARG;
-
- if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
- WARN("Ignoring render target type %#x.\n", desc->type);
- if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
- FIXME("Ignoring render target usage %#x.\n", desc->usage);
- if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
- WARN("Ignoring feature level %#x.\n", desc->minLevel);
render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl;
render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl;
@@ -3484,27 +3554,15 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface;
render_target->ops = ops;
- if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->d3d_device)))
+ device_impl = unsafe_impl_from_ID2D1Device(device);
+ if (FAILED(hr = IDXGIDevice_QueryInterface(device_impl->dxgi_device, &IID_ID3D10Device,
+ (void **)&render_target->d3d_device)))
{
WARN("Failed to get device interface, hr %#x.\n", hr);
ID2D1Factory_Release(render_target->factory);
return hr;
}
- if (FAILED(hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Resource, (void **)&resource)))
- {
- WARN("Failed to get ID3D10Resource interface, hr %#x.\n", hr);
- goto err;
- }
-
- hr = ID3D10Device_CreateRenderTargetView(render_target->d3d_device, resource, NULL, &render_target->view);
- ID3D10Resource_Release(resource);
- if (FAILED(hr))
- {
- WARN("Failed to create rendertarget view, hr %#x.\n", hr);
- goto err;
- }
-
if (FAILED(hr = D3D10StateBlockMaskEnableAll(&state_mask)))
{
WARN("Failed to create stateblock mask, hr %#x.\n", hr);
@@ -3589,29 +3647,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
goto err;
}
- memset(&blend_desc, 0, sizeof(blend_desc));
- blend_desc.BlendEnable[0] = TRUE;
- blend_desc.SrcBlend = D3D10_BLEND_ONE;
- blend_desc.DestBlend = D3D10_BLEND_INV_SRC_ALPHA;
- blend_desc.BlendOp = D3D10_BLEND_OP_ADD;
- if (desc->pixelFormat.alphaMode == D2D1_ALPHA_MODE_IGNORE)
- {
- blend_desc.SrcBlendAlpha = D3D10_BLEND_ZERO;
- blend_desc.DestBlendAlpha = D3D10_BLEND_ONE;
- }
- else
- {
- blend_desc.SrcBlendAlpha = D3D10_BLEND_ONE;
- blend_desc.DestBlendAlpha = D3D10_BLEND_INV_SRC_ALPHA;
- }
- blend_desc.BlendOpAlpha = D3D10_BLEND_OP_ADD;
- blend_desc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
- if (FAILED(hr = ID3D10Device_CreateBlendState(render_target->d3d_device, &blend_desc, &render_target->bs)))
- {
- WARN("Failed to create blend state, hr %#x.\n", hr);
- goto err;
- }
-
if (FAILED(hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
&IID_IDWriteFactory, (IUnknown **)&dwrite_factory)))
{
@@ -3627,15 +3662,6 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
goto err;
}
- if (FAILED(hr = IDXGISurface_GetDesc(surface, &surface_desc)))
- {
- WARN("Failed to get surface desc, hr %#x.\n", hr);
- goto err;
- }
-
- render_target->desc.pixelFormat = desc->pixelFormat;
- render_target->pixel_size.width = surface_desc.Width;
- render_target->pixel_size.height = surface_desc.Height;
render_target->drawing_state.transform = identity;
if (!d2d_clip_stack_init(&render_target->clip_stack))
@@ -3645,16 +3671,14 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target,
goto err;
}
- render_target->desc.dpiX = dpi_x;
- render_target->desc.dpiY = dpi_y;
+ render_target->desc.dpiX = 96.0f;
+ render_target->desc.dpiY = 96.0f;
return S_OK;
err:
if (render_target->default_text_rendering_params)
IDWriteRenderingParams_Release(render_target->default_text_rendering_params);
- if (render_target->bs)
- ID3D10BlendState_Release(render_target->bs);
if (render_target->rs)
ID3D10RasterizerState_Release(render_target->rs);
if (render_target->vb)
@@ -3672,8 +3696,6 @@ err:
}
if (render_target->stateblock)
render_target->stateblock->lpVtbl->Release(render_target->stateblock);
- if (render_target->view)
- ID3D10RenderTargetView_Release(render_target->view);
if (render_target->d3d_device)
ID3D10Device_Release(render_target->d3d_device);
ID2D1Device_Release(render_target->device);
@@ -3684,19 +3706,55 @@ err:
HRESULT d2d_d3d_create_render_target(ID2D1Device *device, IDXGISurface *surface, IUnknown *outer_unknown,
const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target)
{
+ D2D1_BITMAP_PROPERTIES1 bitmap_desc;
struct d2d_device_context *object;
+ ID2D1Bitmap1 *bitmap;
HRESULT hr;
+ if (desc->type != D2D1_RENDER_TARGET_TYPE_DEFAULT && desc->type != D2D1_RENDER_TARGET_TYPE_HARDWARE)
+ WARN("Ignoring render target type %#x.\n", desc->type);
+ if (desc->usage != D2D1_RENDER_TARGET_USAGE_NONE)
+ FIXME("Ignoring render target usage %#x.\n", desc->usage);
+ if (desc->minLevel != D2D1_FEATURE_LEVEL_DEFAULT)
+ WARN("Ignoring feature level %#x.\n", desc->minLevel);
+
+ bitmap_desc.dpiX = desc->dpiX;
+ bitmap_desc.dpiY = desc->dpiY;
+
+ if (bitmap_desc.dpiX == 0.0f && bitmap_desc.dpiY == 0.0f)
+ {
+ bitmap_desc.dpiX = 96.0f;
+ bitmap_desc.dpiY = 96.0f;
+ }
+ else if (bitmap_desc.dpiX <= 0.0f || bitmap_desc.dpiY <= 0.0f)
+ return E_INVALIDARG;
+
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
- if (FAILED(hr = d2d_device_context_init(object, device, surface, outer_unknown, ops, desc)))
+ if (FAILED(hr = d2d_device_context_init(object, device, outer_unknown, ops)))
{
WARN("Failed to initialize render target, hr %#x.\n", hr);
heap_free(object);
return hr;
}
+ bitmap_desc.pixelFormat = desc->pixelFormat;
+ bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
+ bitmap_desc.colorContext = NULL;
+
+ if (FAILED(hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(&object->ID2D1DeviceContext_iface, surface,
+ &bitmap_desc, &bitmap)))
+ {
+ WARN("Failed to create target bitmap, hr %#x.\n", hr);
+ ID2D1DeviceContext_Release(&object->ID2D1DeviceContext_iface);
+ heap_free(object);
+ return hr;
+ }
+
+ ID2D1DeviceContext_SetTarget(&object->ID2D1DeviceContext_iface, (ID2D1Image *)bitmap);
+ ID2D1Bitmap1_Release(bitmap);
+
TRACE("Created render target %p.\n", object);
*render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
@@ -3713,8 +3771,9 @@ HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1
if (!surface)
{
- ID3D10RenderTargetView_Release(render_target->view);
- render_target->view = NULL;
+ if (render_target->target.u.bitmap.view)
+ ID3D10RenderTargetView_Release(render_target->target.u.bitmap.view);
+ render_target->target.u.bitmap.view = NULL;
return S_OK;
}
@@ -3740,9 +3799,9 @@ HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1
render_target->pixel_size.width = surface_desc.Width;
render_target->pixel_size.height = surface_desc.Height;
- if (render_target->view)
- ID3D10RenderTargetView_Release(render_target->view);
- render_target->view = view;
+ if (render_target->target.u.bitmap.view)
+ ID3D10RenderTargetView_Release(render_target->target.u.bitmap.view);
+ render_target->target.u.bitmap.view = view;
return S_OK;
}
@@ -3853,6 +3912,14 @@ static const struct ID2D1DeviceVtbl d2d_device_vtbl =
d2d_device_ClearResources,
};
+static struct d2d_device *unsafe_impl_from_ID2D1Device(ID2D1Device *iface)
+{
+ if (!iface)
+ return NULL;
+ assert(iface->lpVtbl == &d2d_device_vtbl);
+ return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface);
+}
+
void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device)
{
device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl;
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 3005b43e44..c2e0ab2a08 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -6943,14 +6943,11 @@ static void test_bitmap_surface(void)
bitmap = NULL;
ID2D1DeviceContext_GetTarget(device_context, (ID2D1Image **)&bitmap);
-todo_wine
ok(!!bitmap, "Unexpected target.\n");
-if (bitmap)
-{
check_bitmap_surface((ID2D1Bitmap *)bitmap, TRUE, D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW);
ID2D1Bitmap1_Release(bitmap);
-}
+
check_rt_bitmap_surface(rt, TRUE, D2D1_BITMAP_OPTIONS_NONE);
ID2D1DeviceContext_Release(device_context);
--
2.19.0
Sept. 26, 2018
[PATCH 2/4] d2d1: Use surface format for shared bitmap if it wasn't specified.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d2d1/bitmap.c | 4 ++
dlls/d2d1/tests/d2d1.c | 112 ++++++++++++++++++++++++++++++++++++++---
2 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/dlls/d2d1/bitmap.c b/dlls/d2d1/bitmap.c
index c8d099c7df..85514627ca 100644
--- a/dlls/d2d1/bitmap.c
+++ b/dlls/d2d1/bitmap.c
@@ -464,7 +464,11 @@ HRESULT d2d_bitmap_create_shared(struct d2d_device_context *context, REFIID iid,
d.pixelFormat.format = surface_desc.Format;
}
else
+ {
d = *desc;
+ if (d.pixelFormat.format == DXGI_FORMAT_UNKNOWN)
+ d.pixelFormat.format = surface_desc.Format;
+ }
if (d.dpiX == 0.0f || d.dpiY == 0.0f)
{
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index eaa0b64a3d..3005b43e44 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -4123,6 +4123,7 @@ static void test_shared_bitmap(void)
IWICImagingFactory *wic_factory;
ID2D1Bitmap *bitmap1, *bitmap2;
DXGI_SURFACE_DESC surface_desc;
+ D2D1_PIXEL_FORMAT pixel_format;
D2D1_SIZE_U size = {4, 4};
IDXGISurface1 *surface3;
HWND window1, window2;
@@ -4279,6 +4280,32 @@ static void test_shared_bitmap(void)
if (SUCCEEDED(hr))
{
+ static const struct bitmap_format_test
+ {
+ D2D1_PIXEL_FORMAT original;
+ D2D1_PIXEL_FORMAT result;
+ HRESULT hr;
+ }
+ bitmap_format_tests[] =
+ {
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+ };
+ unsigned int i;
+
size = ID2D1Bitmap_GetPixelSize(bitmap2);
hr = IDXGISurface_GetDesc(surface2, &surface_desc);
ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
@@ -4297,6 +4324,26 @@ static void test_shared_bitmap(void)
ID2D1Bitmap_Release(bitmap2);
IDXGISurface1_Release(surface3);
}
+
+ for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
+ {
+ bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
+
+ hr = ID2D1RenderTarget_CreateSharedBitmap(rt2, &IID_IDXGISurface, surface2, &bitmap_desc, &bitmap2);
+ todo_wine_if(i == 2 || i == 3 || i == 5 || i == 6)
+ ok(hr == bitmap_format_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
+
+ if (SUCCEEDED(bitmap_format_tests[i].hr))
+ {
+ pixel_format = ID2D1Bitmap_GetPixelFormat(bitmap2);
+ ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
+ i, pixel_format.format);
+ ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
+ i, pixel_format.alphaMode);
+
+ ID2D1Bitmap_Release(bitmap2);
+ }
+ }
}
ID2D1RenderTarget_Release(rt2);
@@ -6767,7 +6814,15 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B
target = NULL;
}
if (bitmap)
+ {
+ D2D1_PIXEL_FORMAT rt_format, bitmap_format;
+
+ rt_format = ID2D1RenderTarget_GetPixelFormat(rt);
+ bitmap_format = ID2D1Bitmap_GetPixelFormat(bitmap);
+ ok_(__FILE__, line)(!memcmp(&rt_format, &bitmap_format, sizeof(rt_format)), "Unexpected bitmap format.\n");
+
ID2D1Bitmap_Release(bitmap);
+ }
/* Pixel format is not defined until target is set, for DC target it's specified on creation. */
if (target || dc_rt)
@@ -6805,7 +6860,7 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B
hr = ID2D1RenderTarget_CreateCompatibleRenderTarget(rt, NULL, NULL, NULL,
D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS_NONE, (ID2D1BitmapRenderTarget **)&compatible_rt);
todo_wine
- ok_(__FILE__, line)(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, " --- Unexpected hr %#x.\n", hr);
+ ok_(__FILE__, line)(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT, "Unexpected hr %#x.\n", hr);
}
ID2D1DeviceContext_Release(context);
@@ -6817,6 +6872,31 @@ static void check_rt_bitmap_surface_(unsigned int line, ID2D1RenderTarget *rt, B
static void test_bitmap_surface(void)
{
+ static const struct bitmap_format_test
+ {
+ D2D1_PIXEL_FORMAT original;
+ D2D1_PIXEL_FORMAT result;
+ HRESULT hr;
+ }
+ bitmap_format_tests[] =
+ {
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED } },
+
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_IGNORE },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_UNKNOWN }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+
+ { { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE },
+ { DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE } },
+
+ { { DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_STRAIGHT }, { 0 }, WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT },
+ };
D2D1_HWND_RENDER_TARGET_PROPERTIES hwnd_rt_desc;
D2D1_RENDER_TARGET_PROPERTIES rt_desc;
D2D1_BITMAP_PROPERTIES1 bitmap_desc;
@@ -6830,6 +6910,7 @@ static void test_bitmap_surface(void)
ID2D1Bitmap1 *bitmap;
ID2D1Device *device;
ID2D1Image *target;
+ unsigned int i;
HWND window;
HRESULT hr;
@@ -6889,11 +6970,30 @@ todo_wine
if (SUCCEEDED(hr))
{
- memset(&bitmap_desc, 0, sizeof(bitmap_desc));
- bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
- bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
- bitmap_desc.dpiX = 96.0f;
- bitmap_desc.dpiY = 96.0f;
+ for (i = 0; i < ARRAY_SIZE(bitmap_format_tests); ++i)
+ {
+ D2D1_PIXEL_FORMAT pixel_format;
+
+ memset(&bitmap_desc, 0, sizeof(bitmap_desc));
+ bitmap_desc.pixelFormat = bitmap_format_tests[i].original;
+ bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
+
+ hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, &bitmap_desc, &bitmap);
+ ok(hr == bitmap_format_tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
+
+ if (SUCCEEDED(hr))
+ {
+ pixel_format = ID2D1Bitmap1_GetPixelFormat(bitmap);
+
+ ok(pixel_format.format == bitmap_format_tests[i].result.format, "%u: unexpected pixel format %#x.\n",
+ i, pixel_format.format);
+ ok(pixel_format.alphaMode == bitmap_format_tests[i].result.alphaMode, "%u: unexpected alpha mode %d.\n",
+ i, pixel_format.alphaMode);
+
+ ID2D1Bitmap1_Release(bitmap);
+ }
+ }
+
hr = ID2D1DeviceContext_CreateBitmapFromDxgiSurface(device_context, surface, NULL, &bitmap);
ok(SUCCEEDED(hr), "Failed to create a bitmap, hr %#x.\n", hr);
--
2.19.0
Sept. 26, 2018
[v2 PATCH 1/4] d2d1: Add ID2D1Effect stub.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/d2d1/Makefile.in | 1 +
dlls/d2d1/d2d1_private.h | 8 ++
dlls/d2d1/device.c | 12 ++-
dlls/d2d1/effect.c | 215 +++++++++++++++++++++++++++++++++++++++
4 files changed, 235 insertions(+), 1 deletion(-)
create mode 100644 dlls/d2d1/effect.c
diff --git a/dlls/d2d1/Makefile.in b/dlls/d2d1/Makefile.in
index 4bfe3b5953..413571338b 100644
--- a/dlls/d2d1/Makefile.in
+++ b/dlls/d2d1/Makefile.in
@@ -9,6 +9,7 @@ C_SRCS = \
brush.c \
dc_render_target.c \
device.c \
+ effect.c \
factory.c \
geometry.c \
hwnd_render_target.c \
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h
index 9bfbbf2a6c..726d143d86 100644
--- a/dlls/d2d1/d2d1_private.h
+++ b/dlls/d2d1/d2d1_private.h
@@ -503,6 +503,14 @@ struct d2d_device
void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *factory, IDXGIDevice *dxgi_device) DECLSPEC_HIDDEN;
+struct d2d_effect
+{
+ ID2D1Effect ID2D1Effect_iface;
+ LONG refcount;
+};
+
+void d2d_effect_init(struct d2d_effect *effect) DECLSPEC_HIDDEN;
+
static inline BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
{
size_t new_capacity, max_capacity;
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c
index 5e6655feba..be31ecafc8 100644
--- a/dlls/d2d1/device.c
+++ b/dlls/d2d1/device.c
@@ -1858,9 +1858,19 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateBitmapFromDxgiSurface(
static HRESULT STDMETHODCALLTYPE d2d_device_context_CreateEffect(ID2D1DeviceContext *iface,
REFCLSID effect_id, ID2D1Effect **effect)
{
+ struct d2d_effect *object;
+
FIXME("iface %p, effect_id %s, effect %p stub!\n", iface, debugstr_guid(effect_id), effect);
- return E_NOTIMPL;
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ d2d_effect_init(object);
+
+ TRACE("Created effect %p.\n", object);
+ *effect = &object->ID2D1Effect_iface;
+
+ return S_OK;
}
static HRESULT STDMETHODCALLTYPE d2d_device_context_ID2D1DeviceContext_CreateGradientStopCollection(
diff --git a/dlls/d2d1/effect.c b/dlls/d2d1/effect.c
new file mode 100644
index 0000000000..48e2912ab8
--- /dev/null
+++ b/dlls/d2d1/effect.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2018 Nikolay Sivov for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "d2d1_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d2d);
+
+static inline struct d2d_effect *impl_from_ID2D1Effect(ID2D1Effect *iface)
+{
+ return CONTAINING_RECORD(iface, struct d2d_effect, ID2D1Effect_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_QueryInterface(ID2D1Effect *iface, REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_ID2D1Effect)
+ || IsEqualGUID(iid, &IID_ID2D1Properties)
+ || IsEqualGUID(iid, &IID_IUnknown))
+ {
+ ID2D1Effect_AddRef(iface);
+ *out = iface;
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_effect_AddRef(ID2D1Effect *iface)
+{
+ struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
+ ULONG refcount = InterlockedIncrement(&effect->refcount);
+
+ TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d2d_effect_Release(ID2D1Effect *iface)
+{
+ struct d2d_effect *effect = impl_from_ID2D1Effect(iface);
+ ULONG refcount = InterlockedDecrement(&effect->refcount);
+
+ TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+ if (!refcount)
+ heap_free(effect);
+
+ return refcount;
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyCount(ID2D1Effect *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+
+ return 0;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_GetPropertyName(ID2D1Effect *iface, UINT32 index,
+ WCHAR *name, UINT32 name_count)
+{
+ FIXME("iface %p, index %u, name %p, name_count %u stub!\n", iface, index, name, name_count);
+
+ return E_NOTIMPL;
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyNameLength(ID2D1Effect *iface, UINT32 index)
+{
+ FIXME("iface %p, index %u stub!\n", iface, index);
+
+ return 0;
+}
+
+static D2D1_PROPERTY_TYPE STDMETHODCALLTYPE d2d_effect_GetType(ID2D1Effect *iface, UINT32 index)
+{
+ FIXME("iface %p, index %u stub!\n", iface, index);
+
+ return 0;
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_GetPropertyIndex(ID2D1Effect *iface, const WCHAR *name)
+{
+ FIXME("iface %p, name %s stub!\n", iface, debugstr_w(name));
+
+ return 0;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_SetValueByName(ID2D1Effect *iface, const WCHAR *name,
+ D2D1_PROPERTY_TYPE type, const BYTE *value, UINT32 value_size)
+{
+ FIXME("iface %p, name %s, type %#x, value %p, value_size %u stub!\n", iface, debugstr_w(name),
+ type, value, value_size);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_SetValue(ID2D1Effect *iface, UINT32 index, D2D1_PROPERTY_TYPE type,
+ const BYTE *value, UINT32 value_size)
+{
+ FIXME("iface %p, index %u, type %#x, value %p, value_size %u stub!\n", iface, index, type, value, value_size);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_GetValueByName(ID2D1Effect *iface, const WCHAR *name,
+ D2D1_PROPERTY_TYPE type, BYTE *value, UINT32 value_size)
+{
+ FIXME("iface %p, name %s, type %#x, value %p, value_size %u stub!\n", iface, debugstr_w(name), type,
+ value, value_size);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_GetValue(ID2D1Effect *iface, UINT32 index, D2D1_PROPERTY_TYPE type,
+ BYTE *value, UINT32 value_size)
+{
+ FIXME("iface %p, index %u, type %#x, value %p, value_size %u stub!\n", iface, index, type,
+ value, value_size);
+
+ return E_NOTIMPL;
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_GetValueSize(ID2D1Effect *iface, UINT32 index)
+{
+ FIXME("iface %p, index %u stub!\n", iface, index);
+
+ return 0;
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_GetSubProperties(ID2D1Effect *iface, UINT32 index, ID2D1Properties **props)
+{
+ FIXME("iface %p, index %u, props %p stub!\n", iface, index, props);
+
+ return E_NOTIMPL;
+}
+
+static void STDMETHODCALLTYPE d2d_effect_SetInput(ID2D1Effect *iface, UINT32 index, ID2D1Image *input, BOOL invalidate)
+{
+ FIXME("iface %p, index %u, input %p, invalidate %d stub!\n", iface, index, input, invalidate);
+}
+
+static HRESULT STDMETHODCALLTYPE d2d_effect_SetInputCount(ID2D1Effect *iface, UINT32 count)
+{
+ FIXME("iface %p, count %u stub!\n", iface, count);
+
+ return E_NOTIMPL;
+}
+
+static void STDMETHODCALLTYPE d2d_effect_GetInput(ID2D1Effect *iface, UINT32 index, ID2D1Image **input)
+{
+ FIXME("iface %p, index %u, input %p stub!\n", iface, index, input);
+}
+
+static UINT32 STDMETHODCALLTYPE d2d_effect_GetInputCount(ID2D1Effect *iface)
+{
+ FIXME("iface %p stub!\n", iface);
+
+ return 0;
+}
+
+static void STDMETHODCALLTYPE d2d_effect_GetOutput(ID2D1Effect *iface, ID2D1Image **output)
+{
+ FIXME("iface %p, output %p stub!\n", iface, output);
+}
+
+static const ID2D1EffectVtbl d2d_effect_vtbl =
+{
+ d2d_effect_QueryInterface,
+ d2d_effect_AddRef,
+ d2d_effect_Release,
+ d2d_effect_GetPropertyCount,
+ d2d_effect_GetPropertyName,
+ d2d_effect_GetPropertyNameLength,
+ d2d_effect_GetType,
+ d2d_effect_GetPropertyIndex,
+ d2d_effect_SetValueByName,
+ d2d_effect_SetValue,
+ d2d_effect_GetValueByName,
+ d2d_effect_GetValue,
+ d2d_effect_GetValueSize,
+ d2d_effect_GetSubProperties,
+ d2d_effect_SetInput,
+ d2d_effect_SetInputCount,
+ d2d_effect_GetInput,
+ d2d_effect_GetInputCount,
+ d2d_effect_GetOutput,
+};
+
+void d2d_effect_init(struct d2d_effect *effect)
+{
+ effect->ID2D1Effect_iface.lpVtbl = &d2d_effect_vtbl;
+ effect->refcount = 1;
+}
+
--
2.19.0
Sept. 26, 2018