Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
b2b61094
Commit
b2b61094
authored
Feb 05, 2016
by
Henri Verbeet
Committed by
Alexandre Julliard
Feb 06, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ddraw/tests: Rewrite yv12_test().
Signed-off-by:
Henri Verbeet
<
hverbeet@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
0f947567
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
540 additions
and
105 deletions
+540
-105
ddraw1.c
dlls/ddraw/tests/ddraw1.c
+135
-1
ddraw2.c
dlls/ddraw/tests/ddraw2.c
+135
-1
ddraw4.c
dlls/ddraw/tests/ddraw4.c
+135
-1
ddraw7.c
dlls/ddraw/tests/ddraw7.c
+135
-1
overlay.c
dlls/ddraw/tests/overlay.c
+0
-101
No files found.
dlls/ddraw/tests/ddraw1.c
View file @
b2b61094
/*
* Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
* Copyright 2008, 2011, 2012-2013 Stefan Dösinger for CodeWeavers
* Copyright 2011-2014 Henri Verbeet for CodeWeavers
* Copyright 2012-2013 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -45,6 +45,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
return
TRUE
;
}
static
IDirectDrawSurface
*
create_overlay
(
IDirectDraw
*
ddraw
,
unsigned
int
width
,
unsigned
int
height
,
DWORD
format
)
{
IDirectDrawSurface
*
surface
;
DDSURFACEDESC
desc
;
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
desc
.
dwFlags
=
DDSD_CAPS
|
DDSD_HEIGHT
|
DDSD_WIDTH
|
DDSD_PIXELFORMAT
;
desc
.
dwWidth
=
width
;
desc
.
dwHeight
=
height
;
desc
.
ddsCaps
.
dwCaps
=
DDSCAPS_OVERLAY
;
desc
.
ddpfPixelFormat
.
dwSize
=
sizeof
(
desc
.
ddpfPixelFormat
);
desc
.
ddpfPixelFormat
.
dwFlags
=
DDPF_FOURCC
;
desc
.
ddpfPixelFormat
.
dwFourCC
=
format
;
if
(
FAILED
(
IDirectDraw_CreateSurface
(
ddraw
,
&
desc
,
&
surface
,
NULL
)))
return
NULL
;
return
surface
;
}
static
DWORD
WINAPI
create_window_thread_proc
(
void
*
param
)
{
struct
create_window_thread_param
*
p
=
param
;
...
...
@@ -8200,6 +8221,118 @@ done:
DestroyWindow
(
window
);
}
static
void
test_yv12_overlay
(
void
)
{
IDirectDrawSurface
*
src_surface
,
*
dst_surface
;
RECT
rect
=
{
13
,
17
,
14
,
18
};
unsigned
int
offset
,
y
;
unsigned
char
*
base
;
DDSURFACEDESC
desc
;
IDirectDraw
*
ddraw
;
HWND
window
;
HRESULT
hr
;
window
=
CreateWindowA
(
"static"
,
"ddraw_test"
,
WS_OVERLAPPEDWINDOW
,
0
,
0
,
640
,
480
,
0
,
0
,
0
,
0
);
ddraw
=
create_ddraw
();
ok
(
!!
ddraw
,
"Failed to create a ddraw object.
\n
"
);
hr
=
IDirectDraw_SetCooperativeLevel
(
ddraw
,
window
,
DDSCL_NORMAL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to set cooperative level, hr %#x.
\n
"
,
hr
);
if
(
!
(
src_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
skip
(
"Failed to create a YV12 overlay, skipping test.
\n
"
);
goto
done
;
}
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface_Lock
(
src_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
ok
(
desc
.
dwFlags
==
(
DDSD_WIDTH
|
DDSD_HEIGHT
|
DDSD_PIXELFORMAT
|
DDSD_CAPS
|
DDSD_PITCH
),
"Got unexpected flags %#x.
\n
"
,
desc
.
dwFlags
);
ok
(
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
|
DDSCAPS_HWCODEC
)
||
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
),
"Got unexpected caps %#x.
\n
"
,
desc
.
ddsCaps
.
dwCaps
);
ok
(
desc
.
dwWidth
==
256
,
"Got unexpected width %u.
\n
"
,
desc
.
dwWidth
);
ok
(
desc
.
dwHeight
==
256
,
"Got unexpected height %u.
\n
"
,
desc
.
dwHeight
);
/* The overlay pitch seems to have 256 byte alignment. */
ok
(
!
(
U1
(
desc
).
lPitch
&
0xff
),
"Got unexpected pitch %u.
\n
"
,
U1
(
desc
).
lPitch
);
/* Fill the surface with some data for the blit test. */
base
=
desc
.
lpSurface
;
/* Luminance */
for
(
y
=
0
;
y
<
desc
.
dwHeight
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x10
,
desc
.
dwWidth
);
}
/* V */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
4
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x20
,
desc
.
dwWidth
);
}
/* U */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
2
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x30
,
desc
.
dwWidth
);
}
hr
=
IDirectDrawSurface_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
/* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
* other block-based formats like DXT the entire Y channel is stored in
* one big chunk of memory, followed by the chroma channels. So partial
* locks do not really make sense. Show that they are allowed nevertheless
* and the offset points into the luminance data. */
hr
=
IDirectDrawSurface_Lock
(
src_surface
,
&
rect
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
offset
=
((
const
unsigned
char
*
)
desc
.
lpSurface
-
base
);
ok
(
offset
==
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
"Got unexpected offset %u, expected %u.
\n
"
,
offset
,
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
);
hr
=
IDirectDrawSurface_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
if
(
!
(
dst_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
/* Windows XP with a Radeon X1600 GPU refuses to create a second
* overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
skip
(
"Failed to create a second YV12 surface, skipping blit test.
\n
"
);
IDirectDrawSurface_Release
(
src_surface
);
goto
done
;
}
hr
=
IDirectDrawSurface_Blt
(
dst_surface
,
NULL
,
src_surface
,
NULL
,
DDBLT_WAIT
,
NULL
);
/* VMware rejects YV12 blits. This behavior has not been seen on real
* hardware yet, so mark it broken. */
ok
(
SUCCEEDED
(
hr
)
||
broken
(
hr
==
E_NOTIMPL
),
"Failed to blit, hr %#x.
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface_Lock
(
dst_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
base
=
desc
.
lpSurface
;
ok
(
base
[
0
]
==
0x10
,
"Got unexpected Y data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x20
,
"Got unexpected V data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
/
4
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x30
,
"Got unexpected U data 0x%02x.
\n
"
,
base
[
0
]);
hr
=
IDirectDrawSurface_Unlock
(
dst_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
}
IDirectDrawSurface_Release
(
dst_surface
);
IDirectDrawSurface_Release
(
src_surface
);
done:
IDirectDraw_Release
(
ddraw
);
DestroyWindow
(
window
);
}
START_TEST
(
ddraw1
)
{
IDirectDraw
*
ddraw
;
...
...
@@ -8273,4 +8406,5 @@ START_TEST(ddraw1)
test_range_colorkey
();
test_shademode
();
test_lockrect_invalid
();
test_yv12_overlay
();
}
dlls/ddraw/tests/ddraw2.c
View file @
b2b61094
/*
* Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
* Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
* Copyright 2011-2014 Henri Verbeet for CodeWeavers
* Copyright 2012-2014 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -47,6 +47,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
return
TRUE
;
}
static
IDirectDrawSurface
*
create_overlay
(
IDirectDraw2
*
ddraw
,
unsigned
int
width
,
unsigned
int
height
,
DWORD
format
)
{
IDirectDrawSurface
*
surface
;
DDSURFACEDESC
desc
;
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
desc
.
dwFlags
=
DDSD_CAPS
|
DDSD_HEIGHT
|
DDSD_WIDTH
|
DDSD_PIXELFORMAT
;
desc
.
dwWidth
=
width
;
desc
.
dwHeight
=
height
;
desc
.
ddsCaps
.
dwCaps
=
DDSCAPS_OVERLAY
;
desc
.
ddpfPixelFormat
.
dwSize
=
sizeof
(
desc
.
ddpfPixelFormat
);
desc
.
ddpfPixelFormat
.
dwFlags
=
DDPF_FOURCC
;
desc
.
ddpfPixelFormat
.
dwFourCC
=
format
;
if
(
FAILED
(
IDirectDraw2_CreateSurface
(
ddraw
,
&
desc
,
&
surface
,
NULL
)))
return
NULL
;
return
surface
;
}
static
DWORD
WINAPI
create_window_thread_proc
(
void
*
param
)
{
struct
create_window_thread_param
*
p
=
param
;
...
...
@@ -9307,6 +9328,118 @@ done:
DestroyWindow
(
window
);
}
static
void
test_yv12_overlay
(
void
)
{
IDirectDrawSurface
*
src_surface
,
*
dst_surface
;
RECT
rect
=
{
13
,
17
,
14
,
18
};
unsigned
int
offset
,
y
;
unsigned
char
*
base
;
IDirectDraw2
*
ddraw
;
DDSURFACEDESC
desc
;
HWND
window
;
HRESULT
hr
;
window
=
CreateWindowA
(
"static"
,
"ddraw_test"
,
WS_OVERLAPPEDWINDOW
,
0
,
0
,
640
,
480
,
0
,
0
,
0
,
0
);
ddraw
=
create_ddraw
();
ok
(
!!
ddraw
,
"Failed to create a ddraw object.
\n
"
);
hr
=
IDirectDraw2_SetCooperativeLevel
(
ddraw
,
window
,
DDSCL_NORMAL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to set cooperative level, hr %#x.
\n
"
,
hr
);
if
(
!
(
src_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
skip
(
"Failed to create a YV12 overlay, skipping test.
\n
"
);
goto
done
;
}
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface_Lock
(
src_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
ok
(
desc
.
dwFlags
==
(
DDSD_WIDTH
|
DDSD_HEIGHT
|
DDSD_PIXELFORMAT
|
DDSD_CAPS
|
DDSD_PITCH
),
"Got unexpected flags %#x.
\n
"
,
desc
.
dwFlags
);
ok
(
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
|
DDSCAPS_HWCODEC
)
||
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
),
"Got unexpected caps %#x.
\n
"
,
desc
.
ddsCaps
.
dwCaps
);
ok
(
desc
.
dwWidth
==
256
,
"Got unexpected width %u.
\n
"
,
desc
.
dwWidth
);
ok
(
desc
.
dwHeight
==
256
,
"Got unexpected height %u.
\n
"
,
desc
.
dwHeight
);
/* The overlay pitch seems to have 256 byte alignment. */
ok
(
!
(
U1
(
desc
).
lPitch
&
0xff
),
"Got unexpected pitch %u.
\n
"
,
U1
(
desc
).
lPitch
);
/* Fill the surface with some data for the blit test. */
base
=
desc
.
lpSurface
;
/* Luminance */
for
(
y
=
0
;
y
<
desc
.
dwHeight
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x10
,
desc
.
dwWidth
);
}
/* V */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
4
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x20
,
desc
.
dwWidth
);
}
/* U */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
2
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x30
,
desc
.
dwWidth
);
}
hr
=
IDirectDrawSurface_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
/* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
* other block-based formats like DXT the entire Y channel is stored in
* one big chunk of memory, followed by the chroma channels. So partial
* locks do not really make sense. Show that they are allowed nevertheless
* and the offset points into the luminance data. */
hr
=
IDirectDrawSurface_Lock
(
src_surface
,
&
rect
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
offset
=
((
const
unsigned
char
*
)
desc
.
lpSurface
-
base
);
ok
(
offset
==
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
"Got unexpected offset %u, expected %u.
\n
"
,
offset
,
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
);
hr
=
IDirectDrawSurface_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
if
(
!
(
dst_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
/* Windows XP with a Radeon X1600 GPU refuses to create a second
* overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
skip
(
"Failed to create a second YV12 surface, skipping blit test.
\n
"
);
IDirectDrawSurface_Release
(
src_surface
);
goto
done
;
}
hr
=
IDirectDrawSurface_Blt
(
dst_surface
,
NULL
,
src_surface
,
NULL
,
DDBLT_WAIT
,
NULL
);
/* VMware rejects YV12 blits. This behavior has not been seen on real
* hardware yet, so mark it broken. */
ok
(
SUCCEEDED
(
hr
)
||
broken
(
hr
==
E_NOTIMPL
),
"Failed to blit, hr %#x.
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface_Lock
(
dst_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
base
=
desc
.
lpSurface
;
ok
(
base
[
0
]
==
0x10
,
"Got unexpected Y data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x20
,
"Got unexpected V data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
/
4
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x30
,
"Got unexpected U data 0x%02x.
\n
"
,
base
[
0
]);
hr
=
IDirectDrawSurface_Unlock
(
dst_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
}
IDirectDrawSurface_Release
(
dst_surface
);
IDirectDrawSurface_Release
(
src_surface
);
done:
IDirectDraw2_Release
(
ddraw
);
DestroyWindow
(
window
);
}
START_TEST
(
ddraw2
)
{
IDirectDraw2
*
ddraw
;
...
...
@@ -9387,4 +9520,5 @@ START_TEST(ddraw2)
test_range_colorkey
();
test_shademode
();
test_lockrect_invalid
();
test_yv12_overlay
();
}
dlls/ddraw/tests/ddraw4.c
View file @
b2b61094
/*
* Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
* Copyright 2008, 2011, 2012-2014 Stefan Dösinger for CodeWeavers
* Copyright 2011-2014 Henri Verbeet for CodeWeavers
* Copyright 2012-2014 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -86,6 +86,27 @@ static BOOL compare_color(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
return
TRUE
;
}
static
IDirectDrawSurface4
*
create_overlay
(
IDirectDraw4
*
ddraw
,
unsigned
int
width
,
unsigned
int
height
,
DWORD
format
)
{
IDirectDrawSurface4
*
surface
;
DDSURFACEDESC2
desc
;
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
desc
.
dwFlags
=
DDSD_CAPS
|
DDSD_HEIGHT
|
DDSD_WIDTH
|
DDSD_PIXELFORMAT
;
desc
.
dwWidth
=
width
;
desc
.
dwHeight
=
height
;
desc
.
ddsCaps
.
dwCaps
=
DDSCAPS_OVERLAY
;
U4
(
desc
).
ddpfPixelFormat
.
dwSize
=
sizeof
(
U4
(
desc
).
ddpfPixelFormat
);
U4
(
desc
).
ddpfPixelFormat
.
dwFlags
=
DDPF_FOURCC
;
U4
(
desc
).
ddpfPixelFormat
.
dwFourCC
=
format
;
if
(
FAILED
(
IDirectDraw4_CreateSurface
(
ddraw
,
&
desc
,
&
surface
,
NULL
)))
return
NULL
;
return
surface
;
}
static
DWORD
WINAPI
create_window_thread_proc
(
void
*
param
)
{
struct
create_window_thread_param
*
p
=
param
;
...
...
@@ -10482,6 +10503,118 @@ done:
DestroyWindow
(
window
);
}
static
void
test_yv12_overlay
(
void
)
{
IDirectDrawSurface4
*
src_surface
,
*
dst_surface
;
RECT
rect
=
{
13
,
17
,
14
,
18
};
unsigned
int
offset
,
y
;
DDSURFACEDESC2
desc
;
unsigned
char
*
base
;
IDirectDraw4
*
ddraw
;
HWND
window
;
HRESULT
hr
;
window
=
CreateWindowA
(
"static"
,
"ddraw_test"
,
WS_OVERLAPPEDWINDOW
,
0
,
0
,
640
,
480
,
0
,
0
,
0
,
0
);
ddraw
=
create_ddraw
();
ok
(
!!
ddraw
,
"Failed to create a ddraw object.
\n
"
);
hr
=
IDirectDraw4_SetCooperativeLevel
(
ddraw
,
window
,
DDSCL_NORMAL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to set cooperative level, hr %#x.
\n
"
,
hr
);
if
(
!
(
src_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
skip
(
"Failed to create a YV12 overlay, skipping test.
\n
"
);
goto
done
;
}
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface4_Lock
(
src_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
ok
(
desc
.
dwFlags
==
(
DDSD_WIDTH
|
DDSD_HEIGHT
|
DDSD_PIXELFORMAT
|
DDSD_CAPS
|
DDSD_PITCH
),
"Got unexpected flags %#x.
\n
"
,
desc
.
dwFlags
);
ok
(
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
|
DDSCAPS_HWCODEC
)
||
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
),
"Got unexpected caps %#x.
\n
"
,
desc
.
ddsCaps
.
dwCaps
);
ok
(
desc
.
dwWidth
==
256
,
"Got unexpected width %u.
\n
"
,
desc
.
dwWidth
);
ok
(
desc
.
dwHeight
==
256
,
"Got unexpected height %u.
\n
"
,
desc
.
dwHeight
);
/* The overlay pitch seems to have 256 byte alignment. */
ok
(
!
(
U1
(
desc
).
lPitch
&
0xff
),
"Got unexpected pitch %u.
\n
"
,
U1
(
desc
).
lPitch
);
/* Fill the surface with some data for the blit test. */
base
=
desc
.
lpSurface
;
/* Luminance */
for
(
y
=
0
;
y
<
desc
.
dwHeight
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x10
,
desc
.
dwWidth
);
}
/* V */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
4
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x20
,
desc
.
dwWidth
);
}
/* U */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
2
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x30
,
desc
.
dwWidth
);
}
hr
=
IDirectDrawSurface4_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
/* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
* other block-based formats like DXT the entire Y channel is stored in
* one big chunk of memory, followed by the chroma channels. So partial
* locks do not really make sense. Show that they are allowed nevertheless
* and the offset points into the luminance data. */
hr
=
IDirectDrawSurface4_Lock
(
src_surface
,
&
rect
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
offset
=
((
const
unsigned
char
*
)
desc
.
lpSurface
-
base
);
ok
(
offset
==
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
"Got unexpected offset %u, expected %u.
\n
"
,
offset
,
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
);
hr
=
IDirectDrawSurface4_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
if
(
!
(
dst_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
/* Windows XP with a Radeon X1600 GPU refuses to create a second
* overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
skip
(
"Failed to create a second YV12 surface, skipping blit test.
\n
"
);
IDirectDrawSurface4_Release
(
src_surface
);
goto
done
;
}
hr
=
IDirectDrawSurface4_Blt
(
dst_surface
,
NULL
,
src_surface
,
NULL
,
DDBLT_WAIT
,
NULL
);
/* VMware rejects YV12 blits. This behavior has not been seen on real
* hardware yet, so mark it broken. */
ok
(
SUCCEEDED
(
hr
)
||
broken
(
hr
==
E_NOTIMPL
),
"Failed to blit, hr %#x.
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface4_Lock
(
dst_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
base
=
desc
.
lpSurface
;
ok
(
base
[
0
]
==
0x10
,
"Got unexpected Y data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x20
,
"Got unexpected V data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
/
4
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x30
,
"Got unexpected U data 0x%02x.
\n
"
,
base
[
0
]);
hr
=
IDirectDrawSurface4_Unlock
(
dst_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
}
IDirectDrawSurface4_Release
(
dst_surface
);
IDirectDrawSurface4_Release
(
src_surface
);
done:
IDirectDraw4_Release
(
ddraw
);
DestroyWindow
(
window
);
}
START_TEST
(
ddraw4
)
{
IDirectDraw4
*
ddraw
;
...
...
@@ -10569,4 +10702,5 @@ START_TEST(ddraw4)
test_range_colorkey
();
test_shademode
();
test_lockrect_invalid
();
test_yv12_overlay
();
}
dlls/ddraw/tests/ddraw7.c
View file @
b2b61094
/*
* Copyright 2005 Antoine Chavasse (a.chavasse@gmail.com)
* Copyright 2006, 2012-2014 Stefan Dösinger for CodeWeavers
* Copyright 2006, 20
08, 2011, 20
12-2014 Stefan Dösinger for CodeWeavers
* Copyright 2011-2014 Henri Verbeet for CodeWeavers
*
* This library is free software; you can redistribute it and/or
...
...
@@ -100,6 +100,27 @@ static ULONG get_refcount(IUnknown *iface)
return
IUnknown_Release
(
iface
);
}
static
IDirectDrawSurface7
*
create_overlay
(
IDirectDraw7
*
ddraw
,
unsigned
int
width
,
unsigned
int
height
,
DWORD
format
)
{
IDirectDrawSurface7
*
surface
;
DDSURFACEDESC2
desc
;
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
desc
.
dwFlags
=
DDSD_CAPS
|
DDSD_HEIGHT
|
DDSD_WIDTH
|
DDSD_PIXELFORMAT
;
desc
.
dwWidth
=
width
;
desc
.
dwHeight
=
height
;
desc
.
ddsCaps
.
dwCaps
=
DDSCAPS_OVERLAY
;
U4
(
desc
).
ddpfPixelFormat
.
dwSize
=
sizeof
(
U4
(
desc
).
ddpfPixelFormat
);
U4
(
desc
).
ddpfPixelFormat
.
dwFlags
=
DDPF_FOURCC
;
U4
(
desc
).
ddpfPixelFormat
.
dwFourCC
=
format
;
if
(
FAILED
(
IDirectDraw7_CreateSurface
(
ddraw
,
&
desc
,
&
surface
,
NULL
)))
return
NULL
;
return
surface
;
}
static
DWORD
WINAPI
create_window_thread_proc
(
void
*
param
)
{
struct
create_window_thread_param
*
p
=
param
;
...
...
@@ -10761,6 +10782,118 @@ done:
DestroyWindow
(
window
);
}
static
void
test_yv12_overlay
(
void
)
{
IDirectDrawSurface7
*
src_surface
,
*
dst_surface
;
RECT
rect
=
{
13
,
17
,
14
,
18
};
unsigned
int
offset
,
y
;
DDSURFACEDESC2
desc
;
unsigned
char
*
base
;
IDirectDraw7
*
ddraw
;
HWND
window
;
HRESULT
hr
;
window
=
CreateWindowA
(
"static"
,
"ddraw_test"
,
WS_OVERLAPPEDWINDOW
,
0
,
0
,
640
,
480
,
0
,
0
,
0
,
0
);
ddraw
=
create_ddraw
();
ok
(
!!
ddraw
,
"Failed to create a ddraw object.
\n
"
);
hr
=
IDirectDraw7_SetCooperativeLevel
(
ddraw
,
window
,
DDSCL_NORMAL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to set cooperative level, hr %#x.
\n
"
,
hr
);
if
(
!
(
src_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
skip
(
"Failed to create a YV12 overlay, skipping test.
\n
"
);
goto
done
;
}
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface7_Lock
(
src_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
ok
(
desc
.
dwFlags
==
(
DDSD_WIDTH
|
DDSD_HEIGHT
|
DDSD_PIXELFORMAT
|
DDSD_CAPS
|
DDSD_PITCH
),
"Got unexpected flags %#x.
\n
"
,
desc
.
dwFlags
);
ok
(
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
|
DDSCAPS_HWCODEC
)
||
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
),
"Got unexpected caps %#x.
\n
"
,
desc
.
ddsCaps
.
dwCaps
);
ok
(
desc
.
dwWidth
==
256
,
"Got unexpected width %u.
\n
"
,
desc
.
dwWidth
);
ok
(
desc
.
dwHeight
==
256
,
"Got unexpected height %u.
\n
"
,
desc
.
dwHeight
);
/* The overlay pitch seems to have 256 byte alignment. */
ok
(
!
(
U1
(
desc
).
lPitch
&
0xff
),
"Got unexpected pitch %u.
\n
"
,
U1
(
desc
).
lPitch
);
/* Fill the surface with some data for the blit test. */
base
=
desc
.
lpSurface
;
/* Luminance */
for
(
y
=
0
;
y
<
desc
.
dwHeight
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x10
,
desc
.
dwWidth
);
}
/* V */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
4
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x20
,
desc
.
dwWidth
);
}
/* U */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
2
;
++
y
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x30
,
desc
.
dwWidth
);
}
hr
=
IDirectDrawSurface7_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
/* YV12 uses 2x2 blocks with 6 bytes per block (4*Y, 1*U, 1*V). Unlike
* other block-based formats like DXT the entire Y channel is stored in
* one big chunk of memory, followed by the chroma channels. So partial
* locks do not really make sense. Show that they are allowed nevertheless
* and the offset points into the luminance data. */
hr
=
IDirectDrawSurface7_Lock
(
src_surface
,
&
rect
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
offset
=
((
const
unsigned
char
*
)
desc
.
lpSurface
-
base
);
ok
(
offset
==
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
"Got unexpected offset %u, expected %u.
\n
"
,
offset
,
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
);
hr
=
IDirectDrawSurface7_Unlock
(
src_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
if
(
!
(
dst_surface
=
create_overlay
(
ddraw
,
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
))))
{
/* Windows XP with a Radeon X1600 GPU refuses to create a second
* overlay surface, DDERR_NOOVERLAYHW, making the blit tests moot. */
skip
(
"Failed to create a second YV12 surface, skipping blit test.
\n
"
);
IDirectDrawSurface7_Release
(
src_surface
);
goto
done
;
}
hr
=
IDirectDrawSurface7_Blt
(
dst_surface
,
NULL
,
src_surface
,
NULL
,
DDBLT_WAIT
,
NULL
);
/* VMware rejects YV12 blits. This behavior has not been seen on real
* hardware yet, so mark it broken. */
ok
(
SUCCEEDED
(
hr
)
||
broken
(
hr
==
E_NOTIMPL
),
"Failed to blit, hr %#x.
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface7_Lock
(
dst_surface
,
NULL
,
&
desc
,
DDLOCK_WAIT
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to lock surface, hr %#x.
\n
"
,
hr
);
base
=
desc
.
lpSurface
;
ok
(
base
[
0
]
==
0x10
,
"Got unexpected Y data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x20
,
"Got unexpected V data 0x%02x.
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
/
4
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x30
,
"Got unexpected U data 0x%02x.
\n
"
,
base
[
0
]);
hr
=
IDirectDrawSurface7_Unlock
(
dst_surface
,
NULL
);
ok
(
SUCCEEDED
(
hr
),
"Failed to unlock surface, hr %#x.
\n
"
,
hr
);
}
IDirectDrawSurface7_Release
(
dst_surface
);
IDirectDrawSurface7_Release
(
src_surface
);
done:
IDirectDraw7_Release
(
ddraw
);
DestroyWindow
(
window
);
}
START_TEST
(
ddraw7
)
{
HMODULE
module
=
GetModuleHandleA
(
"ddraw.dll"
);
...
...
@@ -10859,4 +10992,5 @@ START_TEST(ddraw7)
test_range_colorkey
();
test_shademode
();
test_lockrect_invalid
();
test_yv12_overlay
();
}
dlls/ddraw/tests/overlay.c
View file @
b2b61094
...
...
@@ -191,106 +191,6 @@ static void offscreen_test(void) {
IDirectDrawSurface7_Release
(
overlay
);
}
static
void
yv12_test
(
void
)
{
HRESULT
hr
;
DDSURFACEDESC2
desc
;
IDirectDrawSurface7
*
surface
,
*
dst
;
char
*
base
;
RECT
rect
=
{
13
,
17
,
14
,
18
};
unsigned
int
offset
,
y
;
surface
=
create_overlay
(
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
));
if
(
!
surface
)
{
skip
(
"YV12 surfaces not available
\n
"
);
return
;
}
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface7_Lock
(
surface
,
NULL
,
&
desc
,
0
,
NULL
);
ok
(
hr
==
DD_OK
,
"IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK
\n
"
,
hr
);
ok
(
desc
.
dwFlags
==
(
DDSD_WIDTH
|
DDSD_HEIGHT
|
DDSD_PIXELFORMAT
|
DDSD_CAPS
|
DDSD_PITCH
),
"Unexpected desc.dwFlags 0x%08x
\n
"
,
desc
.
dwFlags
);
ok
(
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
)
||
desc
.
ddsCaps
.
dwCaps
==
(
DDSCAPS_OVERLAY
|
DDSCAPS_VIDEOMEMORY
|
DDSCAPS_LOCALVIDMEM
|
DDSCAPS_HWCODEC
),
"Unexpected desc.ddsCaps.dwCaps 0x%08x
\n
"
,
desc
.
ddsCaps
.
dwCaps
);
ok
(
desc
.
dwWidth
==
256
&&
desc
.
dwHeight
==
256
,
"Expected size 256x256, got %ux%u
\n
"
,
desc
.
dwWidth
,
desc
.
dwHeight
);
/* The overlay pitch seems to have 256 byte alignment */
ok
((
U1
(
desc
).
lPitch
&
0xff
)
==
0
,
"Expected 256 byte aligned pitch, got %u
\n
"
,
U1
(
desc
).
lPitch
);
/* Fill the surface with some data for the blit test */
base
=
desc
.
lpSurface
;
/* Luminance */
for
(
y
=
0
;
y
<
desc
.
dwHeight
;
y
++
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x10
,
desc
.
dwWidth
);
}
/* V */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
4
;
y
++
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x20
,
desc
.
dwWidth
);
}
/* U */
for
(;
y
<
desc
.
dwHeight
+
desc
.
dwHeight
/
2
;
y
++
)
{
memset
(
base
+
U1
(
desc
).
lPitch
*
y
,
0x30
,
desc
.
dwWidth
);
}
hr
=
IDirectDrawSurface7_Unlock
(
surface
,
NULL
);
ok
(
hr
==
DD_OK
,
"IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK
\n
"
,
hr
);
/* YV12 uses 2x2 blocks with 6 bytes per block(4*Y, 1*U, 1*V). Unlike other block-based formats like DXT
* the entire Y channel is stored in one big chunk of memory, followed by the chroma channels. So
* partial locks do not really make sense. Show that they are allowed nevertheless and the offset points
* into the luminance data */
hr
=
IDirectDrawSurface7_Lock
(
surface
,
&
rect
,
&
desc
,
0
,
NULL
);
ok
(
hr
==
DD_OK
,
"Partial lock of a YV12 surface returned 0x%08x, expected DD_OK
\n
"
,
hr
);
offset
=
((
const
char
*
)
desc
.
lpSurface
-
base
);
ok
(
offset
==
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
"Expected %u byte offset from partial lock, got %u
\n
"
,
rect
.
top
*
U1
(
desc
).
lPitch
+
rect
.
left
,
offset
);
hr
=
IDirectDrawSurface7_Unlock
(
surface
,
NULL
);
ok
(
hr
==
DD_OK
,
"IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK
\n
"
,
hr
);
dst
=
create_overlay
(
256
,
256
,
MAKEFOURCC
(
'Y'
,
'V'
,
'1'
,
'2'
));
if
(
!
dst
)
{
/* Windows XP with a Radeon X1600 GPU refuses to create a second overlay surface,
* DDERR_NOOVERLAYHW, making the blit tests moot */
skip
(
"Could not create a second YV12 surface, skipping blit test
\n
"
);
goto
cleanup
;
}
hr
=
IDirectDrawSurface7_Blt
(
dst
,
NULL
,
surface
,
NULL
,
0
,
NULL
);
/* VMware rejects YV12 blits. This behavior has not been seen on real hardware yet, so mark it broken */
ok
(
hr
==
DD_OK
||
broken
(
hr
==
E_NOTIMPL
),
"IDirectDrawSurface7_Blt returned 0x%08x, expected DD_OK
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
{
memset
(
&
desc
,
0
,
sizeof
(
desc
));
desc
.
dwSize
=
sizeof
(
desc
);
hr
=
IDirectDrawSurface7_Lock
(
dst
,
NULL
,
&
desc
,
0
,
NULL
);
ok
(
hr
==
DD_OK
,
"IDirectDrawSurface7_Lock returned 0x%08x, expected DD_OK
\n
"
,
hr
);
base
=
desc
.
lpSurface
;
ok
(
base
[
0
]
==
0x10
,
"Y data is 0x%02x, expected 0x10
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x20
,
"V data is 0x%02x, expected 0x20
\n
"
,
base
[
0
]);
base
+=
desc
.
dwHeight
/
4
*
U1
(
desc
).
lPitch
;
todo_wine
ok
(
base
[
0
]
==
0x30
,
"U data is 0x%02x, expected 0x30
\n
"
,
base
[
0
]);
hr
=
IDirectDrawSurface7_Unlock
(
dst
,
NULL
);
ok
(
hr
==
DD_OK
,
"IDirectDrawSurface7_Unlock returned 0x%08x, expected DD_OK
\n
"
,
hr
);
}
IDirectDrawSurface7_Release
(
dst
);
cleanup:
IDirectDrawSurface7_Release
(
surface
);
}
START_TEST
(
overlay
)
{
if
(
CreateDirectDraw
()
==
FALSE
)
{
...
...
@@ -300,7 +200,6 @@ START_TEST(overlay)
rectangle_settings
();
offscreen_test
();
yv12_test
();
if
(
primary
)
IDirectDrawSurface7_Release
(
primary
);
if
(
ddraw
)
IDirectDraw7_Release
(
ddraw
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment