[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