d2d1: Implement D2D1ConvertColorSpace().
Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
12a890329a
commit
2cb681e740
|
@ -3,7 +3,7 @@
|
|||
@ stdcall D2D1MakeSkewMatrix(float float float float ptr)
|
||||
@ stdcall D2D1IsMatrixInvertible(ptr)
|
||||
@ stdcall D2D1InvertMatrix(ptr)
|
||||
@ stub D2D1ConvertColorSpace
|
||||
@ stdcall D2D1ConvertColorSpace(long long ptr)
|
||||
@ stdcall D2D1CreateDevice(ptr ptr ptr)
|
||||
@ stub D2D1CreateDeviceContext
|
||||
@ stdcall D2D1SinCos(float ptr ptr)
|
||||
|
|
|
@ -640,6 +640,13 @@ static inline D2D1_INTERPOLATION_MODE d2d1_1_interp_mode_from_d2d1(D2D1_BITMAP_I
|
|||
return (D2D1_INTERPOLATION_MODE)mode;
|
||||
}
|
||||
|
||||
static inline const char *debug_d2d_color_f(const D2D1_COLOR_F *colour)
|
||||
{
|
||||
if (!colour)
|
||||
return "(null)";
|
||||
return wine_dbg_sprintf("{%.8e, %.8e, %.8e, %.8e}", colour->r, colour->g, colour->b, colour->a);
|
||||
}
|
||||
|
||||
static inline const char *debug_d2d_point_2f(const D2D1_POINT_2F *point)
|
||||
{
|
||||
if (!point)
|
||||
|
|
|
@ -735,6 +735,83 @@ float WINAPI D2D1Vec3Length(float x, float y, float z)
|
|||
return sqrtf(x * x + y * y + z * z);
|
||||
}
|
||||
|
||||
/* See IEC 61966-2-1:1999; also described in the EXT_texture_sRGB OpenGL
|
||||
* extension, among others. */
|
||||
static float srgb_transfer_function(float x)
|
||||
{
|
||||
if (x <= 0.0f)
|
||||
return 0.0f;
|
||||
else if (x >= 1.0f)
|
||||
return 1.0f;
|
||||
else if (x <= 0.0031308f)
|
||||
return 12.92f * x;
|
||||
else
|
||||
return 1.055f * powf(x, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
|
||||
static float srgb_inverse_transfer_function(float x)
|
||||
{
|
||||
if (x <= 0.0f)
|
||||
return 0.0f;
|
||||
else if (x >= 1.0f)
|
||||
return 1.0f;
|
||||
else if (x <= 0.04045f)
|
||||
return x / 12.92f;
|
||||
else
|
||||
return powf((x + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
D2D1_COLOR_F WINAPI D2D1ConvertColorSpace(D2D1_COLOR_SPACE src_colour_space,
|
||||
D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour)
|
||||
{
|
||||
D2D1_COLOR_F ret;
|
||||
|
||||
TRACE("src_colour_space %#x, dst_colour_space %#x, colour %s.\n",
|
||||
src_colour_space, dst_colour_space, debug_d2d_color_f(colour));
|
||||
|
||||
if (src_colour_space == D2D1_COLOR_SPACE_CUSTOM || dst_colour_space == D2D1_COLOR_SPACE_CUSTOM)
|
||||
{
|
||||
ret.r = 0.0f;
|
||||
ret.g = 0.0f;
|
||||
ret.b = 0.0f;
|
||||
ret.a = 0.0f;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (src_colour_space == dst_colour_space)
|
||||
return *colour;
|
||||
|
||||
if (src_colour_space == D2D1_COLOR_SPACE_SRGB && dst_colour_space == D2D1_COLOR_SPACE_SCRGB)
|
||||
{
|
||||
ret.r = srgb_inverse_transfer_function(colour->r);
|
||||
ret.g = srgb_inverse_transfer_function(colour->g);
|
||||
ret.b = srgb_inverse_transfer_function(colour->b);
|
||||
ret.a = colour->a;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (src_colour_space == D2D1_COLOR_SPACE_SCRGB && dst_colour_space == D2D1_COLOR_SPACE_SRGB)
|
||||
{
|
||||
ret.r = srgb_transfer_function(colour->r);
|
||||
ret.g = srgb_transfer_function(colour->g);
|
||||
ret.b = srgb_transfer_function(colour->b);
|
||||
ret.a = colour->a;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FIXME("Unhandled conversion from source colour space %#x to destination colour space %#x.\n",
|
||||
src_colour_space, dst_colour_space);
|
||||
ret.r = 0.0f;
|
||||
ret.g = 0.0f;
|
||||
ret.b = 0.0f;
|
||||
ret.a = 0.0f;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL get_config_key_dword(HKEY default_key, HKEY application_key, const char *name, DWORD *value)
|
||||
{
|
||||
DWORD type, data, size;
|
||||
|
|
|
@ -34,6 +34,8 @@ static HRESULT (WINAPI *pD2D1CreateDevice)(IDXGIDevice *dxgi_device,
|
|||
static void (WINAPI *pD2D1SinCos)(float angle, float *s, float *c);
|
||||
static float (WINAPI *pD2D1Tan)(float angle);
|
||||
static float (WINAPI *pD2D1Vec3Length)(float x, float y, float z);
|
||||
static D2D1_COLOR_F (WINAPI *pD2D1ConvertColorSpace)(D2D1_COLOR_SPACE src_colour_space,
|
||||
D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour);
|
||||
|
||||
static BOOL use_mt = TRUE;
|
||||
|
||||
|
@ -461,6 +463,11 @@ static DWORD get_readback_colour(struct resource_readback *rb, unsigned int x, u
|
|||
return ((DWORD *)((BYTE *)rb->data + y * rb->pitch))[x];
|
||||
}
|
||||
|
||||
static float clamp_float(float f, float lower, float upper)
|
||||
{
|
||||
return f < lower ? lower : f > upper ? upper : f;
|
||||
}
|
||||
|
||||
static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff)
|
||||
{
|
||||
unsigned int diff = x > y ? x - y : y - x;
|
||||
|
@ -492,6 +499,14 @@ static BOOL compare_float(float f, float g, unsigned int ulps)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL compare_colour_f(const D2D1_COLOR_F *colour, float r, float g, float b, float a, unsigned int ulps)
|
||||
{
|
||||
return compare_float(colour->r, r, ulps)
|
||||
&& compare_float(colour->g, g, ulps)
|
||||
&& compare_float(colour->b, b, ulps)
|
||||
&& compare_float(colour->a, a, ulps);
|
||||
}
|
||||
|
||||
static BOOL compare_point(const D2D1_POINT_2F *point, float x, float y, unsigned int ulps)
|
||||
{
|
||||
return compare_float(point->x, x, ulps)
|
||||
|
@ -9466,6 +9481,91 @@ static void test_math(BOOL d3d11)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_colour_space(BOOL d3d11)
|
||||
{
|
||||
D2D1_COLOR_F src_colour, dst_colour, expected;
|
||||
D2D1_COLOR_SPACE src_space, dst_space;
|
||||
unsigned i, j, k;
|
||||
|
||||
static const D2D1_COLOR_SPACE colour_spaces[] =
|
||||
{
|
||||
D2D1_COLOR_SPACE_CUSTOM,
|
||||
D2D1_COLOR_SPACE_SRGB,
|
||||
D2D1_COLOR_SPACE_SCRGB,
|
||||
};
|
||||
static struct
|
||||
{
|
||||
D2D1_COLOR_F srgb;
|
||||
D2D1_COLOR_F scrgb;
|
||||
}
|
||||
const test_data[] =
|
||||
{
|
||||
{{0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}},
|
||||
{{0.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}},
|
||||
{{1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}},
|
||||
/* Samples in the non-linear region. */
|
||||
{{0.2f, 0.4f, 0.6f, 0.8f}, {0.0331047624f, 0.132868335f, 0.318546832f, 0.8f}},
|
||||
{{0.3f, 0.5f, 0.7f, 0.9f}, {0.0732389688f, 0.214041144f, 0.447988421f, 0.9f}},
|
||||
/* Samples in the linear region. */
|
||||
{{0.0002f, 0.0004f, 0.0006f, 0.0008f}, {1.54798763e-005f, 3.09597526e-005f, 4.64396289e-005f, 0.0008f}},
|
||||
{{0.0003f, 0.0005f, 0.0007f, 0.0009f}, {2.32198145e-005f, 3.86996908e-005f, 5.41795634e-005f, 0.0009f}},
|
||||
/* Out of range samples */
|
||||
{{-0.3f, 1.5f, -0.7f, 2.0f}, { 0.0f, 1.0f, 0.0f, 2.0f}},
|
||||
{{ 1.5f, -0.3f, 2.0f, -0.7f}, { 1.0f, 0.0f, 1.0f, -0.7f}},
|
||||
{{ 0.0f, 1.0f, 0.0f, 1.5f}, {-0.7f, 2.0f, -0.3f, 1.5f}},
|
||||
{{ 1.0f, 0.0f, 1.0f, -0.3f}, { 2.0f, -0.7f, 1.5f, -0.3f}},
|
||||
};
|
||||
|
||||
if (!pD2D1ConvertColorSpace)
|
||||
{
|
||||
win_skip("D2D1ConvertColorSpace() not available, skipping test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(colour_spaces); ++i)
|
||||
{
|
||||
src_space = colour_spaces[i];
|
||||
for (j = 0; j < ARRAY_SIZE(colour_spaces); ++j)
|
||||
{
|
||||
dst_space = colour_spaces[j];
|
||||
for (k = 0; k < ARRAY_SIZE(test_data); ++k)
|
||||
{
|
||||
if (src_space == D2D1_COLOR_SPACE_SCRGB)
|
||||
src_colour = test_data[k].scrgb;
|
||||
else
|
||||
src_colour = test_data[k].srgb;
|
||||
|
||||
if (dst_space == D2D1_COLOR_SPACE_SCRGB)
|
||||
expected = test_data[k].scrgb;
|
||||
else
|
||||
expected = test_data[k].srgb;
|
||||
|
||||
if (src_space == D2D1_COLOR_SPACE_CUSTOM || dst_space == D2D1_COLOR_SPACE_CUSTOM)
|
||||
{
|
||||
set_color(&expected, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if (src_space != dst_space)
|
||||
{
|
||||
expected.r = clamp_float(expected.r, 0.0f, 1.0f);
|
||||
expected.g = clamp_float(expected.g, 0.0f, 1.0f);
|
||||
expected.b = clamp_float(expected.b, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
dst_colour = pD2D1ConvertColorSpace(src_space, dst_space, &src_colour);
|
||||
ok(compare_colour_f(&dst_colour, expected.r, expected.g, expected.b, expected.a, 1),
|
||||
"Got unexpected destination colour {%.8e, %.8e, %.8e, %.8e}, "
|
||||
"expected destination colour {%.8e, %.8e, %.8e, %.8e} for "
|
||||
"source colour {%.8e, %.8e, %.8e, %.8e}, "
|
||||
"source colour space %#x, destination colour space %#x.\n",
|
||||
dst_colour.r, dst_colour.g, dst_colour.b, dst_colour.a,
|
||||
expected.r, expected.g, expected.b, expected.a,
|
||||
src_colour.r, src_colour.g, src_colour.b, src_colour.a,
|
||||
src_space, dst_space);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(d2d1)
|
||||
{
|
||||
HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll");
|
||||
|
@ -9476,6 +9576,7 @@ START_TEST(d2d1)
|
|||
pD2D1SinCos = (void *)GetProcAddress(d2d1_dll, "D2D1SinCos");
|
||||
pD2D1Tan = (void *)GetProcAddress(d2d1_dll, "D2D1Tan");
|
||||
pD2D1Vec3Length = (void *)GetProcAddress(d2d1_dll, "D2D1Vec3Length");
|
||||
pD2D1ConvertColorSpace = (void *)GetProcAddress(d2d1_dll, "D2D1ConvertColorSpace");
|
||||
|
||||
use_mt = !getenv("WINETEST_NO_MT_D3D");
|
||||
|
||||
|
@ -9523,6 +9624,7 @@ START_TEST(d2d1)
|
|||
queue_test(test_dpi);
|
||||
queue_test(test_wic_bitmap_format);
|
||||
queue_d3d10_test(test_math);
|
||||
queue_d3d10_test(test_colour_space);
|
||||
|
||||
run_queued_tests();
|
||||
}
|
||||
|
|
|
@ -962,3 +962,5 @@ interface ID2D1Multithread : IUnknown
|
|||
[local] void __stdcall D2D1SinCos(float angle, float *s, float *c);
|
||||
[local] float __stdcall D2D1Tan(float angle);
|
||||
[local] float __stdcall D2D1Vec3Length(float x, float y, float z);
|
||||
[local] D2D1_COLOR_F __stdcall D2D1ConvertColorSpace(D2D1_COLOR_SPACE src_colour_space,
|
||||
D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour);
|
||||
|
|
Loading…
Reference in New Issue