[PATCH] WineD3D: Support YUV formats with GL_APPLE_ycbcr_422=0A=
Stefan Doesinger
stefan at codeweavers.com
Tue Aug 19 10:55:42 CDT 2008
=0A=
This implements YUV formats for 3D texturing, but more=0A=
importantly for blitting for overlay emulation. This extension is=0A=
supported on all Macs(we use it to detect the Apple GL=0A=
implementation. On Linux, there's GL_MESA_ycbcr_texture, but I=0A=
don't know how widespread it is. (Not supported on the binary=0A=
drivers at least). So additionally to this codepath we need a=0A=
shader conversion at least for blits.=0A=
---=0A=
dlls/d3d9/tests/visual.c | 120 =
++++++++++++++++++++++++++++++++++++++++++++++=0A=
dlls/wined3d/directx.c | 8 ++-=0A=
dlls/wined3d/utils.c | 18 +++++--=0A=
3 files changed, 138 insertions(+), 8 deletions(-)=0A=
=0A=
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c=0A=
index 7d79db2..6c460b9 100644=0A=
--- a/dlls/d3d9/tests/visual.c=0A=
+++ b/dlls/d3d9/tests/visual.c=0A=
@@ -9179,6 +9179,125 @@ static void texop_test(IDirect3DDevice9 *device)=0A=
if (vertex_declaration) =
IDirect3DVertexDeclaration9_Release(vertex_declaration);=0A=
}=0A=
=0A=
+static void yuv_color_test(IDirect3DDevice9 *device) {=0A=
+ HRESULT hr;=0A=
+ IDirect3DSurface9 *surface =3D NULL, *target =3D NULL;=0A=
+ unsigned int fmt, i;=0A=
+ D3DFORMAT format;=0A=
+ const char *fmt_string;=0A=
+ D3DLOCKED_RECT lr;=0A=
+ IDirect3D9 *d3d;=0A=
+ HRESULT color;=0A=
+ DWORD ref_color_left, ref_color_right;=0A=
+=0A=
+ struct {=0A=
+ DWORD in; /* The input color */=0A=
+ DWORD uyvy_left; /* "in" interpreted as uyvy and transformed =
to RGB, pixel 1/1*/=0A=
+ DWORD uyvy_right; /* "in" interpreted as uyvy and transformed =
to RGB, pixel 2/1*/=0A=
+ DWORD yuy2_left; /* "in" interpreted as yuy2 and transformed =
to RGB, pixel 1/1 */=0A=
+ DWORD yuy2_right; /* "in" interpreted as yuy2 and transformed =
to RGB, pixel 2/1 */=0A=
+ } test_data[] =3D {=0A=
+ /* Originally I wanted to avoid being evil, and set Y1 =3D Y2 to =
avoid triggering troubles in shader converters,=0A=
+ * but the main difference between YUY2 and UYVY is the swapped =
ordering of the chroma and luminance=0A=
+ * values. However, handling the two Y's properly could have a big =
impact on image quality, so be picky about=0A=
+ * that=0A=
+ */=0A=
+ { 0x00000000, 0x00008700, 0x00008700, 0x00008700, 0x00008700 },=0A=
+ { 0xff000000, 0x00008700, 0x004bff1c, 0x00b30000, 0x00b30000 },=0A=
+ { 0x00ff0000, 0x00b30000, 0x00b30000, 0x00008700, 0x004bff1c },=0A=
+ { 0x0000ff00, 0x004bff1c, 0x00008700, 0x000030e1, 0x000030e1 },=0A=
+ { 0x000000ff, 0x000030e1, 0x000030e1, 0x004bff1c, 0x00008700 },=0A=
+ { 0xffff0000, 0x00b30000, 0x00ffd01c, 0x00b30000, 0x00ffd01c },=0A=
+ { 0xff00ff00, 0x004bff1c, 0x004bff1c, 0x00b300e1, 0x00b300e1 },=0A=
+ { 0xff0000ff, 0x000030e1, 0x004bffff, 0x00ffd01c, 0x00b30000 },=0A=
+ { 0x00ffff00, 0x00ffd01c, 0x00b30000, 0x000030e1, 0x004bffff },=0A=
+ { 0x00ff00ff, 0x00b300e1, 0x00b300e1, 0x004bff1c, 0x004bff1c },=0A=
+ { 0x0000ffff, 0x004bffff, 0x000030e1, 0x004bffff, 0x000030e1 },=0A=
+ { 0xffffff00, 0x00ffd01c, 0x00ffd01c, 0x00b300e1, 0x00ff79ff },=0A=
+ { 0xffff00ff, 0x00b300e1, 0x00ff79ff, 0x00ffd01c, 0x00ffd01c },=0A=
+ { 0xffffffff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff },=0A=
+=0A=
+ { 0x4cff4c54, 0x00ff0000, 0x00ff0000, 0x000b8b00, 0x00b6ffa3 },=0A=
+ { 0x00800080, 0x00000000, 0x00000000, 0x0000ff00, 0x0000ff00 },=0A=
+ { 0xFF80FF80, 0x00ffffff, 0x00ffffff, 0x00ff00ff, 0x00ff00ff },=0A=
+ { 0x1c6b1cff, 0x000000fd, 0x000000fd, 0x006dff45, 0x0000d500 },=0A=
+ };=0A=
+=0A=
+ hr =3D IDirect3DDevice9_GetDirect3D(device, &d3d);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr =3D =
%08x\n", hr);=0A=
+ hr =3D IDirect3DDevice9_GetRenderTarget(device, 0, &target);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr =
=3D %08x\n", hr);=0A=
+=0A=
+ IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DDevice9_SetFVF failed, hr =3D =
%08x\n", hr);=0A=
+=0A=
+ for(fmt =3D 0; fmt < 2; fmt++) {=0A=
+ if(fmt =3D=3D 0) {=0A=
+ format =3D D3DFMT_UYVY;=0A=
+ fmt_string =3D "D3DFMT_UYVY";=0A=
+ } else {=0A=
+ format =3D D3DFMT_YUY2;=0A=
+ fmt_string =3D "D3DFMT_YUY2";=0A=
+ }=0A=
+=0A=
+ /* Some(all?) Windows drivers do not support YUV 3D textures, =
only 2D surfaces in StretchRect. Thus use=0A=
+ * StretchRect to draw the YUV surface onto the =
screen instead of drawPrimitive=0A=
+ */=0A=
+ if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, =
D3DFMT_X8R8G8B8, 0,=0A=
+ D3DRTYPE_SURFACE, format) !=3D =
D3D_OK) {=0A=
+ skip("%s is not supported\n", fmt_string);=0A=
+ continue;=0A=
+ }=0A=
+=0A=
+ /* A pixel is effectively 16 bit large, but two pixels are =
stored together, so the minimum size is 2x1 */=0A=
+ hr =3D IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, =
1, format, D3DPOOL_DEFAULT, &surface, NULL);=0A=
+ ok(hr =3D=3D D3D_OK, =
"IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr =3D %08x\n", =
hr);=0A=
+=0A=
+ for(i =3D 0; i < (sizeof(test_data)/sizeof(test_data[0])); i++) =
{=0A=
+ if(fmt =3D=3D 0) {=0A=
+ ref_color_left =3D test_data[i].uyvy_left;=0A=
+ ref_color_right =3D test_data[i].uyvy_right;=0A=
+ } else {=0A=
+ ref_color_left =3D test_data[i].yuy2_left;=0A=
+ ref_color_right =3D test_data[i].yuy2_right;=0A=
+ }=0A=
+=0A=
+ memset(&lr, 0, sizeof(lr));=0A=
+ hr =3D IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DSurface9_LockRect failed, hr =
=3D %08x\n", hr);=0A=
+ *((DWORD *) lr.pBits) =3D test_data[i].in;=0A=
+ hr =3D IDirect3DSurface9_UnlockRect(surface);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DSurface9_UnlockRect failed, =
hr =3D %08x\n", hr);=0A=
+=0A=
+ hr =3D IDirect3DDevice9_Clear(device, 0, NULL, =
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DDevice9_Clear failed with =
0x%08x\n", hr);=0A=
+ hr =3D IDirect3DDevice9_StretchRect(device, surface, NULL, =
target, NULL, D3DTEXF_POINT);=0A=
+ ok(hr =3D=3D D3D_OK, "IDirect3DDevice9_StretchRect failed =
with 0x%08x\n", hr);=0A=
+ hr =3D IDirect3DDevice9_Present(device, NULL, NULL, NULL, =
NULL);=0A=
+ ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);=0A=
+=0A=
+ /* Native D3D can't resist filtering the YUY surface, even =
though we asked it not to do so above. To=0A=
+ * prevent running into precision problems, read a far left =
and far right pixel. In the future we may=0A=
+ * want to add tests for the filtered pixels as well.=0A=
+ *=0A=
+ * Unfortunately different implementations(Windows-NV and =
Mac-ATI tested) interpret some colors vastly=0A=
+ * differently, so we need a max diff of 16=0A=
+ */=0A=
+ color =3D getPixelColor(device, 40, 240);=0A=
+ ok(color_match(color, ref_color_left, 16),=0A=
+ "Input 0x%08x: Got color 0x%08x for pixel 1/1, expected =
0x%08x, format %s\n",=0A=
+ test_data[i].in, color, ref_color_left, fmt_string);=0A=
+ color =3D getPixelColor(device, 600, 240);=0A=
+ ok(color_match(color, ref_color_right, 16),=0A=
+ "Input 0x%08x: Got color 0x%08x for pixel 2/1, expected =
0x%08x, format %s\n",=0A=
+ test_data[i].in, color, ref_color_left, fmt_string);=0A=
+ }=0A=
+ IDirect3DSurface9_Release(surface);=0A=
+ }=0A=
+ IDirect3DSurface9_Release(target);=0A=
+ IDirect3D9_Release(d3d);=0A=
+}=0A=
+=0A=
START_TEST(visual)=0A=
{=0A=
IDirect3DDevice9 *device_ptr;=0A=
@@ -9274,6 +9393,7 @@ START_TEST(visual)=0A=
pointsize_test(device_ptr);=0A=
tssargtemp_test(device_ptr);=0A=
np2_stretch_rect_test(device_ptr);=0A=
+ yuv_color_test(device_ptr);=0A=
=0A=
if (caps.VertexShaderVersion >=3D D3DVS_VERSION(1, 1))=0A=
{=0A=
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c=0A=
index ebf7b40..b5bc44d 100644=0A=
--- a/dlls/wined3d/directx.c=0A=
+++ b/dlls/wined3d/directx.c=0A=
@@ -2325,10 +2325,14 @@ static BOOL CheckTextureCapability(UINT Adapter, =
WINED3DFORMAT CheckFormat)=0A=
TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented =
*/=0A=
return FALSE;=0A=
=0A=
- /* YUV formats, not supported for now */=0A=
+ /* YUV formats */=0A=
case WINED3DFMT_UYVY:=0A=
case WINED3DFMT_YUY2:=0A=
- TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented =
*/=0A=
+ if(GL_SUPPORT(APPLE_YCBCR_422)) {=0A=
+ TRACE_(d3d_caps)("[OK]\n");=0A=
+ return TRUE;=0A=
+ }=0A=
+ TRACE_(d3d_caps)("[FAILED]\n");=0A=
return FALSE;=0A=
=0A=
/* Not supported */=0A=
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c=0A=
index 98f7eef..cf8c3cd 100644=0A=
--- a/dlls/wined3d/utils.c=0A=
+++ b/dlls/wined3d/utils.c=0A=
@@ -42,8 +42,8 @@ static const StaticPixelFormatDesc formats[] =3D {=0A=
/*{WINED3DFORMAT ,alphamask ,redmask ,greenmask =
,bluemask ,bpp ,depth ,stencil, isFourcc*/=0A=
{WINED3DFMT_UNKNOWN ,0x0 ,0x0 ,0x0 ,0x0 =
,1 ,0 ,0 ,FALSE },=0A=
/* FourCC formats, kept here to have WINED3DFMT_R8G8B8(=3D20) at =
position 20 */=0A=
- {WINED3DFMT_UYVY ,0x0 ,0x0 ,0x0 ,0x0 =
,1/*?*/ ,0 ,0 ,TRUE },=0A=
- {WINED3DFMT_YUY2 ,0x0 ,0x0 ,0x0 ,0x0 =
,1/*?*/ ,0 ,0 ,TRUE },=0A=
+ {WINED3DFMT_UYVY ,0x0 ,0x0 ,0x0 ,0x0 =
,2 ,0 ,0 ,TRUE },=0A=
+ {WINED3DFMT_YUY2 ,0x0 ,0x0 ,0x0 ,0x0 =
,2 ,0 ,0 ,TRUE },=0A=
{WINED3DFMT_YV12 ,0x0 ,0x0 ,0x0 ,0x0 =
,1/*?*/ ,0 ,0 ,TRUE },=0A=
{WINED3DFMT_DXT1 ,0x0 ,0x0 ,0x0 ,0x0 =
,1 ,0 ,0 ,TRUE },=0A=
{WINED3DFMT_DXT2 ,0x0 ,0x0 ,0x0 ,0x0 =
,1 ,0 ,0 ,TRUE },=0A=
@@ -134,10 +134,16 @@ static const GlPixelFormatDescTemplate =
gl_formats_template[] =3D {=0A=
{WINED3DFMT_UNKNOWN ,0 ,0 =
, 0, 0 =
,0=0A=
,0 },=0A=
/* FourCC formats */=0A=
- {WINED3DFMT_UYVY ,0 ,0 =
, 0, 0 =
,0=0A=
- ,0 },=0A=
- {WINED3DFMT_YUY2 ,0 ,0 =
, 0, 0 =
,0=0A=
- ,0 },=0A=
+ /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is =
supported via the UNSIGNED_SHORT_8_8_REV_APPLE type=0A=
+ * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via =
UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The=0A=
+ * d3d9 test however shows that the opposite is true. Since the =
extension is from 2002, it predates the x86 based=0A=
+ * Macs, so probably the endianess differs. This could be tested as =
soon as we have a Windows and MacOS on a big=0A=
+ * endian machine=0A=
+ */=0A=
+ {WINED3DFMT_UYVY ,GL_RGB =
,GL_RGB , 0, =
GL_YCBCR_422_APPLE ,UNSIGNED_SHORT_8_8_APPLE=0A=
+ ,WINED3DFMT_FLAG_FILTERING },=0A=
+ {WINED3DFMT_YUY2 ,GL_RGB =
,GL_RGB , 0, =
GL_YCBCR_422_APPLE ,UNSIGNED_SHORT_8_8_REV_APPLE=0A=
+ ,WINED3DFMT_FLAG_FILTERING },=0A=
{WINED3DFMT_DXT1 ,GL_COMPRESSED_RGBA_S3TC_DXT1_EXT =
,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT , 0, GL_RGBA =
,GL_UNSIGNED_BYTE=0A=
,WINED3DFMT_FLAG_FILTERING },=0A=
{WINED3DFMT_DXT2 ,GL_COMPRESSED_RGBA_S3TC_DXT3_EXT =
,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT , 0, GL_RGBA =
,GL_UNSIGNED_BYTE=0A=
-- =0A=
1.5.4.5=0A=
=0A=
------=_NextPart_000_0025_01C901F1.ABC377B0--
More information about the wine-patches
mailing list