[PATCH] WineD3D: Implement YV12 support for emulated overlays=0A=

Stefan Doesinger stefan at codeweavers.com
Tue Aug 26 14:36:30 CDT 2008


=0A=
This is the prefered format of many codecs, and for some codecs=0A=
this is the only supported output format. As usual I try to=0A=
handle all the conversion in the GPU and keep the CPU involvement=0A=
minimal to gain the full performance of PBO transfers.=0A=
=0A=
Tests on Windows show that the pitch is equal to the width, so we=0A=
have to treat the surface as 8 bits per pixel. However, the=0A=
surface has 1.5 times the height due to the added U and V planes,=0A=
so we need a height(and memory size) scale factor.=0A=
---=0A=
 dlls/ddraw/utils.c                |    5 +=0A=
 dlls/wined3d/arb_program_shader.c |  342 =
++++++++++++++++++++++++++++---------=0A=
 dlls/wined3d/device.c             |    8 +-=0A=
 dlls/wined3d/surface.c            |    5 +=0A=
 dlls/wined3d/utils.c              |   14 ++-=0A=
 dlls/wined3d/wined3d_private.h    |    2 +-=0A=
 include/wine/wined3d_gl.h         |    1 +=0A=
 7 files changed, 291 insertions(+), 86 deletions(-)=0A=
=0A=
diff --git a/dlls/ddraw/utils.c b/dlls/ddraw/utils.c=0A=
index 5d96b36..937caa4 100644=0A=
--- a/dlls/ddraw/utils.c=0A=
+++ b/dlls/ddraw/utils.c=0A=
@@ -255,6 +255,11 @@ PixelFormat_WineD3DtoDD(DDPIXELFORMAT =
*DDPixelFormat,=0A=
             break;=0A=
 =0A=
         case WINED3DFMT_YV12:=0A=
+            DDPixelFormat->u1.dwYUVBitCount =3D 12;=0A=
+            DDPixelFormat->dwFlags =3D DDPF_FOURCC;=0A=
+            DDPixelFormat->dwFourCC =3D WineD3DFormat;=0A=
+            break;=0A=
+=0A=
         case WINED3DFMT_DXT1:=0A=
         case WINED3DFMT_DXT2:=0A=
         case WINED3DFMT_DXT3:=0A=
diff --git a/dlls/wined3d/arb_program_shader.c =
b/dlls/wined3d/arb_program_shader.c=0A=
index 2f18ddc..54c2a83 100644=0A=
--- a/dlls/wined3d/arb_program_shader.c=0A=
+++ b/dlls/wined3d/arb_program_shader.c=0A=
@@ -3142,6 +3142,7 @@ const struct fragment_pipeline =
arbfp_fragment_pipeline =3D {=0A=
 struct arbfp_blit_priv {=0A=
     GLenum yuy2_rect_shader, yuy2_2d_shader;=0A=
     GLenum uyvy_rect_shader, uyvy_2d_shader;=0A=
+    GLenum yv12_rect_shader, yv12_2d_shader;=0A=
 };=0A=
 =0A=
 static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) {=0A=
@@ -3162,23 +3163,23 @@ static void arbfp_blit_free(IWineD3DDevice =
*iface) {=0A=
     GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader));=0A=
     GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_rect_shader));=0A=
     GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader));=0A=
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader));=0A=
+    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader));=0A=
     checkGLcall("Delete yuv programs\n");=0A=
     LEAVE_GL();=0A=
 }=0A=
 =0A=
-GLenum gen_yuv_shader(IWineD3DDeviceImpl *device, WINED3DFORMAT fmt, =
GLenum textype) {=0A=
-    GLenum shader;=0A=
-    SHADER_BUFFER buffer;=0A=
+BOOL gen_planar_yuv_read(SHADER_BUFFER *buffer, WINED3DFORMAT fmt, =
GLenum textype, char *luminance) {=0A=
+    char chroma;=0A=
     const char *tex, *texinstr;=0A=
-    char chroma, luminance;=0A=
-    struct arbfp_blit_priv *priv =3D (struct arbfp_blit_priv *) =
device->blit_priv;=0A=
-=0A=
-    /* Shader header */=0A=
-    buffer.bsize =3D 0;=0A=
-    buffer.lineNo =3D 0;=0A=
-    buffer.newline =3D TRUE;=0A=
-    buffer.buffer =3D HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, =
SHADER_PGMSIZE);=0A=
 =0A=
+    if(fmt =3D=3D WINED3DFMT_UYVY) {=0A=
+        chroma =3D 'r';=0A=
+        *luminance =3D 'a';=0A=
+    } else {=0A=
+        chroma =3D 'a';=0A=
+        *luminance =3D 'r';=0A=
+    }=0A=
     switch(textype) {=0A=
         case GL_TEXTURE_2D:             tex =3D "2D";     texinstr =3D =
"TXP"; break;=0A=
         case GL_TEXTURE_RECTANGLE_ARB:  tex =3D "RECT";   texinstr =3D =
"TEX"; break;=0A=
@@ -3187,16 +3188,229 @@ GLenum gen_yuv_shader(IWineD3DDeviceImpl =
*device, WINED3DFORMAT fmt, GLenum text=0A=
              * properly in the texture to find the correct chroma values=0A=
              */=0A=
             FIXME("Implement yuv correction for non-2d, non-rect =
textures\n");=0A=
-            return 0;=0A=
+            return FALSE;=0A=
     }=0A=
 =0A=
-    if(fmt =3D=3D WINED3DFMT_UYVY) {=0A=
-        chroma =3D 'r';=0A=
-        luminance =3D 'a';=0A=
+    /* First we have to read the chroma values. This means we need at =
least two pixels(no filtering),=0A=
+     * or 4 pixels(with filtering). To get the unmodified chromas, we =
have to rid ourselves of the=0A=
+     * filtering when we sample the texture.=0A=
+     *=0A=
+     * These are the rules for reading the chroma:=0A=
+     *=0A=
+     * Even pixel: Cr=0A=
+     * Even pixel: U=0A=
+     * Odd pixel: V=0A=
+     *=0A=
+     * So we have to get the sampling x position in non-normalized =
coordinates in integers=0A=
+     */=0A=
+    if(textype !=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
+        shader_addline(buffer, "MUL texcrd.rg, fragment.texcoord[0], =
size.x;\n");=0A=
+        shader_addline(buffer, "MOV texcrd.a, size.x;\n");=0A=
     } else {=0A=
-        chroma =3D 'a';=0A=
-        luminance =3D 'r';=0A=
+        shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");=0A=
+    }=0A=
+    /* We must not allow filtering between pixel x and x+1, this would =
mix U and V=0A=
+     * Vertical filtering is ok. However, bear in mind that the pixel =
center is at=0A=
+     * 0.5, so add 0.5.=0A=
+     */=0A=
+    shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");=0A=
+    shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");=0A=
+=0A=
+    /* Divide the x coordinate by 0.5 and get the fraction. This gives =
0.25 and 0.75 for the=0A=
+     * even and odd pixels respectively=0A=
+     */=0A=
+    shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n");=0A=
+    shader_addline(buffer, "FRC texcrd2, texcrd2;\n");=0A=
+=0A=
+    /* Sample Pixel 1 */=0A=
+    shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", =
texinstr, tex);=0A=
+=0A=
+    /* Put the value into either of the chroma values */=0A=
+    shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");=0A=
+    shader_addline(buffer, "MUL chroma.r, luminance.%c, temp.x;\n", =
chroma);=0A=
+    shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");=0A=
+    shader_addline(buffer, "MUL chroma.g, luminance.%c, temp.x;\n", =
chroma);=0A=
+=0A=
+    /* Sample pixel 2. If we read an even pixel(SLT above returned 1), =
sample=0A=
+     * the pixel right to the current one. Otherwise, sample the left =
pixel.=0A=
+     * Bias and scale the SLT result to -1;1 and add it to the texcrd.x.=0A=
+     */=0A=
+    shader_addline(buffer, "MAD temp.x, temp.x, coef.z, -coef.x;\n");=0A=
+    shader_addline(buffer, "ADD texcrd.x, texcrd, temp.x;\n");=0A=
+    shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", =
texinstr, tex);=0A=
+=0A=
+    /* Put the value into the other chroma */=0A=
+    shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");=0A=
+    shader_addline(buffer, "MAD chroma.g, luminance.%c, temp.x, =
chroma.g;\n", chroma);=0A=
+    shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");=0A=
+    shader_addline(buffer, "MAD chroma.r, luminance.%c, temp.x, =
chroma.r;\n", chroma);=0A=
+=0A=
+    /* TODO: If filtering is enabled, sample a 2nd pair of pixels left =
or right of=0A=
+     * the current one and lerp the two U and V values=0A=
+     */=0A=
+=0A=
+    /* This gives the correctly filtered luminance value */=0A=
+    shader_addline(buffer, "TEX luminance, fragment.texcoord[0], =
texture[0], %s;\n", tex);=0A=
+=0A=
+    return TRUE;=0A=
+}=0A=
+=0A=
+BOOL gen_yv12_read(SHADER_BUFFER *buffer, WINED3DFORMAT fmt, GLenum =
textype, char *luminance) {=0A=
+    const char *tex;=0A=
+=0A=
+    switch(textype) {=0A=
+        case GL_TEXTURE_2D:             tex =3D "2D";     break;=0A=
+        case GL_TEXTURE_RECTANGLE_ARB:  tex =3D "RECT";   break;=0A=
+        default:=0A=
+            FIXME("Implement yv12 correction for non-2d, non-rect =
textures\n");=0A=
+            return FALSE;=0A=
+    }=0A=
+=0A=
+    /* YV12 surfaces contain a WxH sized luminance plane, followed by a =
(W/2)x(H/2)=0A=
+     * V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So the =
effective=0A=
+     * bitdepth is 12 bits per pixel. Since the U and V planes have =
only half the=0A=
+     * pitch of the luminance plane, the packing into the gl texture is =
a bit=0A=
+     * unfortunate. If the whole texture is interpreted as luminance =
data it looks=0A=
+     * approximately like this:=0A=
+     *=0A=
+     *        +----------------------------------+----=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        |                                  |   2=0A=
+     *        |            LUMINANCE             |   -=0A=
+     *        |                                  |   3=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        |                                  |=0A=
+     *        +----------------+-----------------+----=0A=
+     *        |                |                 |=0A=
+     *        |  U even rows   |  U odd rows     |=0A=
+     *        |                |                 |   1=0A=
+     *        +----------------+------------------   -=0A=
+     *        |                |                 |   3=0A=
+     *        |  V even rows   |  V odd rows     |=0A=
+     *        |                |                 |=0A=
+     *        +----------------+-----------------+----=0A=
+     *        |                |                 |=0A=
+     *        |     0.5        |       0.5       |=0A=
+     *=0A=
+     * So it appears as if there are 4 chroma images, but in fact the =
odd rows=0A=
+     * in the chroma images are in the same row as the even ones. So =
its is=0A=
+     * kinda tricky to read=0A=
+     *=0A=
+     * When reading from rectangle textures, keep in mind that the =
input y coordinates=0A=
+     * go from 0 to d3d_height, whereas the opengl texture height is =
1.5 * d3d_height=0A=
+     */=0A=
+    shader_addline(buffer, "PARAM yv12_coef =3D {%f, %f, %f, %f};\n",=0A=
+                   2.0 / 3.0, 1.0 / 6.0, (2.0 / 3.0) + (1.0 / 6.0), 1.0 =
/ 3.0);=0A=
+=0A=
+    shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");=0A=
+    /* the chroma planes have only half the width */=0A=
+    shader_addline(buffer, "MUL texcrd.x, texcrd.x, coef.y;\n");=0A=
+=0A=
+    /* The first value is between 2/3 and 5/6th of the texture's =
height, so scale+bias=0A=
+     * the coordinate. Also read the right side of the image when =
reading odd lines=0A=
+     *=0A=
+     * Don't forget to clamp the y values in into the range, otherwise =
we'll get filtering=0A=
+     * bleeding=0A=
+     */=0A=
+    if(textype =3D=3D GL_TEXTURE_2D) {=0A=
+=0A=
+        shader_addline(buffer, "RCP chroma.w, size.y;\n");=0A=
+=0A=
+        shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n");=0A=
+=0A=
+        shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n");=0A=
+        shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, =
yv12_coef.x;\n");=0A=
+=0A=
+        /* Read odd lines from the right side(add size * 0.5 to the x =
coordinate */=0A=
+        shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, =
yv12_coef.y;\n"); /* To avoid 0.5 =3D=3D 0.5 comparisons */=0A=
+        shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");=0A=
+        shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");=0A=
+        shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, =
texcrd.x;\n");=0A=
+=0A=
+        /* clamp, keep the half pixel origin in mind */=0A=
+        shader_addline(buffer, "MAD temp.y, coef.y, chroma.w, =
yv12_coef.x;\n");=0A=
+        shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");=0A=
+        shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, =
yv12_coef.z;\n");=0A=
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");=0A=
+    } else {=0A=
+        /* Read from [size - size+size/4] */=0A=
+        shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");=0A=
+        shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, =
size.y;\n");=0A=
+=0A=
+        /* Read odd lines from the right side(add size * 0.5 to the x =
coordinate */=0A=
+        shader_addline(buffer, "ADD texcrd2.x, texcrd.y, =
yv12_coef.y;\n"); /* To avoid 0.5 =3D=3D 0.5 comparisons */=0A=
+        shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");=0A=
+        shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");=0A=
+        shader_addline(buffer, "MUL texcrd2.x, texcrd2.x, size.x;\n");=0A=
+        shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, =
texcrd.x;\n");=0A=
+=0A=
+        /* Make sure to read exactly from the pixel center */=0A=
+        shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");=0A=
+        shader_addline(buffer, "ADD texcrd.y, texcrd.y, coef.y;\n");=0A=
+=0A=
+        /* Clamp */=0A=
+        shader_addline(buffer, "MAD temp.y, size.y, coef.w, size.y;\n");=0A=
+        shader_addline(buffer, "ADD temp.y, temp.y, -coef.y;\n");=0A=
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");=0A=
+        shader_addline(buffer, "ADD temp.y, size.y, -coef.y;\n");=0A=
+        shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");=0A=
+    }=0A=
+    /* Read the texture, put the result into the output register */=0A=
+    shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);=0A=
+    shader_addline(buffer, "MOV chroma.r, temp.a;\n");=0A=
+=0A=
+    /* The other chroma value is 1/6th of the texture lower, from 5/6th =
to 6/6th=0A=
+     * No need to clamp because we're just reusing the already clamped =
value from above=0A=
+     */=0A=
+    if(textype =3D=3D GL_TEXTURE_2D) {=0A=
+        shader_addline(buffer, "ADD texcrd.y, texcrd.y, =
yv12_coef.y;\n");=0A=
+    } else {=0A=
+        shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, =
texcrd.y;\n");=0A=
+    }=0A=
+    shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);=0A=
+    shader_addline(buffer, "MOV chroma.g, temp.a;\n");=0A=
+=0A=
+    /* Sample the luminance value. It is in the top 2/3rd of the =
texture, so scale the y coordinate.=0A=
+     * Clamp the y coordinate to prevent the chroma values from =
bleeding into the sampled luminance=0A=
+     * values due to filtering=0A=
+     */=0A=
+    shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");=0A=
+    if(textype =3D=3D GL_TEXTURE_2D) {=0A=
+        /* Multiply the y coordinate by 2/3 and clamp it */=0A=
+        shader_addline(buffer, "MUL texcrd.y, texcrd.y, =
yv12_coef.x;\n");=0A=
+        shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, =
yv12_coef.x;\n");=0A=
+        shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");=0A=
+        shader_addline(buffer, "TEX luminance, texcrd, texture[0], =
%s;\n", tex);=0A=
+    } else {=0A=
+        /* Reading from texture_rectangles is pretty streightforward, =
just use the unmodified=0A=
+         * texture coordinate. It is still a good idea to clamp it =
though, since the opengl texture=0A=
+         * is bigger=0A=
+         */=0A=
+        shader_addline(buffer, "ADD temp.x, size.y, -coef.y;\n");=0A=
+        shader_addline(buffer, "MIN texcrd.y, texcrd.y, size.x;\n");=0A=
+        shader_addline(buffer, "TEX luminance, texcrd, texture[0], =
%s;\n", tex);=0A=
     }=0A=
+    *luminance =3D 'a';=0A=
+=0A=
+    return TRUE;=0A=
+}=0A=
+=0A=
+GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, WINED3DFORMAT fmt, =
GLenum textype) {=0A=
+    GLenum shader;=0A=
+    SHADER_BUFFER buffer;=0A=
+    char luminance_component;=0A=
+    struct arbfp_blit_priv *priv =3D (struct arbfp_blit_priv *) =
device->blit_priv;=0A=
+=0A=
+    /* Shader header */=0A=
+    buffer.bsize =3D 0;=0A=
+    buffer.lineNo =3D 0;=0A=
+    buffer.newline =3D TRUE;=0A=
+    buffer.buffer =3D HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, =
SHADER_PGMSIZE);=0A=
 =0A=
     GL_EXTCALL(glGenProgramsARB(1, &shader));=0A=
     checkGLcall("GL_EXTCALL(glGenProgramsARB(1, &shader))");=0A=
@@ -3245,70 +3459,19 @@ GLenum gen_yuv_shader(IWineD3DDeviceImpl =
*device, WINED3DFORMAT fmt, GLenum text=0A=
     shader_addline(&buffer, "TEMP chroma;\n");=0A=
     shader_addline(&buffer, "TEMP texcrd;\n");=0A=
     shader_addline(&buffer, "TEMP texcrd2;\n");=0A=
-    shader_addline(&buffer, "PARAM coef =3D {1.0, 0.5, 2.0, 0.0};\n");=0A=
+    shader_addline(&buffer, "PARAM coef =3D {1.0, 0.5, 2.0, 0.25};\n");=0A=
     shader_addline(&buffer, "PARAM yuv_coef =3D {1.403, 0.344, 0.714, =
1.770};\n");=0A=
     shader_addline(&buffer, "PARAM size =3D program.local[0];\n");=0A=
 =0A=
-    /* First we have to read the chroma values. This means we need at =
least two pixels(no filtering),=0A=
-     * or 4 pixels(with filtering). To get the unmodified chromas, we =
have to rid ourselves of the=0A=
-     * filtering when we sample the texture.=0A=
-     *=0A=
-     * These are the rules for reading the chroma:=0A=
-     *=0A=
-     * Even pixel: Cr=0A=
-     * Even pixel: U=0A=
-     * Odd pixel: V=0A=
-     *=0A=
-     * So we have to get the sampling x position in non-normalized =
coordinates in integers=0A=
-     */=0A=
-    if(textype !=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
-        shader_addline(&buffer, "MUL texcrd.rg, fragment.texcoord[0], =
size.x;\n");=0A=
-        shader_addline(&buffer, "MOV texcrd.a, size.x;\n");=0A=
+    if(fmt =3D=3D WINED3DFMT_UYVY || fmt =3D=3DWINED3DFMT_YUY2) {=0A=
+        if(gen_planar_yuv_read(&buffer, fmt, textype, =
&luminance_component) =3D=3D FALSE) {=0A=
+            return 0;=0A=
+        }=0A=
     } else {=0A=
-        shader_addline(&buffer, "MOV texcrd, fragment.texcoord[0];\n");=0A=
+        if(gen_yv12_read(&buffer, fmt, textype, &luminance_component) =
=3D=3D FALSE) {=0A=
+            return 0;=0A=
+        }=0A=
     }=0A=
-    /* We must not allow filtering between pixel x and x+1, this would =
mix U and V=0A=
-     * Vertical filtering is ok. However, bear in mind that the pixel =
center is at=0A=
-     * 0.5, so add 0.5.=0A=
-     */=0A=
-    shader_addline(&buffer, "FLR texcrd.x, texcrd.x;\n");=0A=
-    shader_addline(&buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");=0A=
-=0A=
-    /* Divide the x coordinate by 0.5 and get the fraction. This gives =
0.25 and 0.75 for the=0A=
-     * even and odd pixels respectively=0A=
-     */=0A=
-    shader_addline(&buffer, "MUL texcrd2, texcrd, coef.y;\n");=0A=
-    shader_addline(&buffer, "FRC texcrd2, texcrd2;\n");=0A=
-=0A=
-    /* Sample Pixel 1 */=0A=
-    shader_addline(&buffer, "%s luminance, texcrd, texture[0], %s;\n", =
texinstr, tex);=0A=
-=0A=
-    /* Put the value into either of the chroma values */=0A=
-    shader_addline(&buffer, "SGE temp.x, texcrd2.x, coef.y;\n");=0A=
-    shader_addline(&buffer, "MUL chroma.r, luminance.%c, temp.x;\n", =
chroma);=0A=
-    shader_addline(&buffer, "SLT temp.x, texcrd2.x, coef.y;\n");=0A=
-    shader_addline(&buffer, "MUL chroma.g, luminance.%c, temp.x;\n", =
chroma);=0A=
-=0A=
-    /* Sample pixel 2. If we read an even pixel(SLT above returned 1), =
sample=0A=
-     * the pixel right to the current one. Otherwise, sample the left =
pixel.=0A=
-     * Bias and scale the SLT result to -1;1 and add it to the texcrd.x.=0A=
-     */=0A=
-    shader_addline(&buffer, "MAD temp.x, temp.x, coef.z, -coef.x;\n");=0A=
-    shader_addline(&buffer, "ADD texcrd.x, texcrd, temp.x;\n");=0A=
-    shader_addline(&buffer, "%s luminance, texcrd, texture[0], %s;\n", =
texinstr, tex);=0A=
-=0A=
-    /* Put the value into the other chroma */=0A=
-    shader_addline(&buffer, "SGE temp.x, texcrd2.x, coef.y;\n");=0A=
-    shader_addline(&buffer, "MAD chroma.g, luminance.%c, temp.x, =
chroma.g;\n", chroma);=0A=
-    shader_addline(&buffer, "SLT temp.x, texcrd2.x, coef.y;\n");=0A=
-    shader_addline(&buffer, "MAD chroma.r, luminance.%c, temp.x, =
chroma.r;\n", chroma);=0A=
-=0A=
-    /* TODO: If filtering is enabled, sample a 2nd pair of pixels left =
or right of=0A=
-     * the current one and lerp the two U and V values=0A=
-     */=0A=
-=0A=
-    /* This gives the correctly filtered luminance value */=0A=
-    shader_addline(&buffer, "TEX luminance, fragment.texcoord[0], =
texture[0], %s;\n", tex);=0A=
 =0A=
     /* Calculate the final result. Formula is taken from=0A=
      * http://www.fourcc.org/fccyvrgb.php. Note that the chroma=0A=
@@ -3316,10 +3479,10 @@ GLenum gen_yuv_shader(IWineD3DDeviceImpl =
*device, WINED3DFORMAT fmt, GLenum text=0A=
      */=0A=
     shader_addline(&buffer, "SUB chroma.rg, chroma, coef.y;\n");=0A=
 =0A=
-    shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, =
luminance.%c;\n", luminance);=0A=
-    shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, =
luminance.%c;\n", luminance);=0A=
+    shader_addline(&buffer, "MAD result.color.r, chroma.r, yuv_coef.x, =
luminance.%c;\n", luminance_component);=0A=
+    shader_addline(&buffer, "MAD temp.r, -chroma.g, yuv_coef.y, =
luminance.%c;\n", luminance_component);=0A=
     shader_addline(&buffer, "MAD result.color.g, -chroma.r, yuv_coef.z, =
temp.r;\n");=0A=
-    shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, =
luminance.%c;\n", luminance);=0A=
+    shader_addline(&buffer, "MAD result.color.b, chroma.g, yuv_coef.w, =
luminance.%c;\n", luminance_component);=0A=
     shader_addline(&buffer, "END\n");=0A=
 =0A=
     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, =
GL_PROGRAM_FORMAT_ASCII_ARB, strlen(buffer.buffer), buffer.buffer));=0A=
@@ -3337,12 +3500,18 @@ GLenum gen_yuv_shader(IWineD3DDeviceImpl =
*device, WINED3DFORMAT fmt, GLenum text=0A=
         } else {=0A=
             priv->yuy2_2d_shader =3D shader;=0A=
         }=0A=
-    } else {=0A=
+    } else if(fmt =3D=3D WINED3DFMT_UYVY) {=0A=
         if(textype =3D=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
             priv->uyvy_rect_shader =3D shader;=0A=
         } else {=0A=
             priv->uyvy_2d_shader =3D shader;=0A=
         }=0A=
+    } else {=0A=
+        if(textype =3D=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
+            priv->yv12_rect_shader =3D shader;=0A=
+        } else {=0A=
+            priv->yv12_2d_shader =3D shader;=0A=
+        }=0A=
     }=0A=
     return shader;=0A=
 }=0A=
@@ -3356,7 +3525,9 @@ static HRESULT arbfp_blit_set(IWineD3DDevice =
*iface, WINED3DFORMAT fmt, GLenum t=0A=
 =0A=
     getFormatDescEntry(fmt, &GLINFO_LOCATION, &glDesc);=0A=
 =0A=
-    if(glDesc->conversion_group !=3D WINED3DFMT_YUY2 && =
glDesc->conversion_group !=3D WINED3DFMT_UYVY) {=0A=
+    if(glDesc->conversion_group !=3D WINED3DFMT_YUY2 && =
glDesc->conversion_group !=3D WINED3DFMT_UYVY &&=0A=
+       glDesc->conversion_group !=3D WINED3DFMT_YV12) {=0A=
+        ERR("Format: %s\n", debug_d3dformat(glDesc->conversion_group));=0A=
         /* Don't bother setting up a shader for unconverted formats */=0A=
         glEnable(textype);=0A=
         checkGLcall("glEnable(textype)");=0A=
@@ -3369,12 +3540,18 @@ static HRESULT arbfp_blit_set(IWineD3DDevice =
*iface, WINED3DFORMAT fmt, GLenum t=0A=
         } else {=0A=
             shader =3D priv->yuy2_2d_shader;=0A=
         }=0A=
-    } else {=0A=
+    } else if(glDesc->conversion_group =3D=3D WINED3DFMT_UYVY) {=0A=
         if(textype =3D=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
             shader =3D priv->uyvy_rect_shader;=0A=
         } else {=0A=
             shader =3D priv->uyvy_2d_shader;=0A=
         }=0A=
+    } else {=0A=
+        if(textype =3D=3D GL_TEXTURE_RECTANGLE_ARB) {=0A=
+            shader =3D priv->yv12_rect_shader;=0A=
+        } else {=0A=
+            shader =3D priv->yv12_2d_shader;=0A=
+        }=0A=
     }=0A=
 =0A=
     if(!shader) {=0A=
@@ -3412,6 +3589,7 @@ static BOOL =
arbfp_blit_conv_supported(WINED3DFORMAT fmt) {=0A=
     switch(fmt) {=0A=
         case WINED3DFMT_YUY2:=0A=
         case WINED3DFMT_UYVY:=0A=
+        case WINED3DFMT_YV12:=0A=
             TRACE("[OK]\n");=0A=
             return TRUE;=0A=
         default:=0A=
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c=0A=
index e199ad1..73e4242 100644=0A=
--- a/dlls/wined3d/device.c=0A=
+++ b/dlls/wined3d/device.c=0A=
@@ -586,7 +586,8 @@ static HRESULT  WINAPI =
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U=0A=
     IWineD3DDeviceImpl  *This =3D (IWineD3DDeviceImpl *)iface;    =0A=
     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is =
a create function */=0A=
     unsigned int Size       =3D 1;=0A=
-    const StaticPixelFormatDesc *tableEntry =3D =
getFormatDescEntry(Format, NULL, NULL);=0A=
+    const GlPixelFormatDesc *glDesc;=0A=
+    const StaticPixelFormatDesc *tableEntry =3D =
getFormatDescEntry(Format, &GLINFO_LOCATION, &glDesc);=0A=
     TRACE("(%p) Create surface\n",This);=0A=
     =0A=
     /** FIXME: Check ranges on the inputs are valid =0A=
@@ -637,9 +638,11 @@ static HRESULT  WINAPI =
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U=0A=
     } else {=0A=
        /* The pitch is a multiple of 4 bytes */=0A=
         Size =3D ((Width * tableEntry->bpp) + This->surface_alignment - =
1) & ~(This->surface_alignment - 1);=0A=
-       Size *=3D Height;=0A=
+        Size *=3D Height;=0A=
     }=0A=
 =0A=
+    if(glDesc->heightscale !=3D 0.0) Size *=3D glDesc->heightscale;=0A=
+=0A=
     /** Create and initialise the surface resource **/=0A=
     =
D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, =
Size)=0A=
     /* "Standalone" surface */=0A=
@@ -650,6 +653,7 @@ static HRESULT  WINAPI =
IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U=0A=
     object->currentDesc.MultiSampleType    =3D MultiSample;=0A=
     object->currentDesc.MultiSampleQuality =3D MultisampleQuality;=0A=
     object->glDescription.level            =3D Level;=0A=
+    object->heightscale                    =3D glDesc->heightscale !=3D =
0.0 ? glDesc->heightscale : 1.0;=0A=
     list_init(&object->overlays);=0A=
 =0A=
     /* Flags */=0A=
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c=0A=
index a988121..7870d4b 100644=0A=
--- a/dlls/wined3d/surface.c=0A=
+++ b/dlls/wined3d/surface.c=0A=
@@ -231,6 +231,9 @@ static void =
surface_download_data(IWineD3DSurfaceImpl *This) {=0A=
 /* This call just uploads data, the caller is responsible for =
activating the=0A=
  * right context and binding the correct texture. */=0A=
 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum =
internal, GLsizei width, GLsizei height, GLenum format, GLenum type, =
const GLvoid *data) {=0A=
+=0A=
+    if(This->heightscale !=3D 1.0 && This->heightscale !=3D 0.0) height =
*=3D This->heightscale;=0A=
+=0A=
     if (This->resource.format =3D=3D WINED3DFMT_DXT1 ||=0A=
             This->resource.format =3D=3D WINED3DFMT_DXT2 || =
This->resource.format =3D=3D WINED3DFMT_DXT3 ||=0A=
             This->resource.format =3D=3D WINED3DFMT_DXT4 || =
This->resource.format =3D=3D WINED3DFMT_DXT5 ||=0A=
@@ -293,6 +296,8 @@ static void =
surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal,=0A=
     BOOL enable_client_storage =3D FALSE;=0A=
     BYTE *mem =3D NULL;=0A=
 =0A=
+    if(This->heightscale !=3D 1.0 && This->heightscale !=3D 0.0) height =
*=3D This->heightscale;=0A=
+=0A=
     TRACE("(%p) : Creating surface (target %#x)  level %d, d3d format =
%s, internal format %#x, width %d, height %d, gl format %#x, gl =
type=3D%#x\n", This,=0A=
             This->glDescription.target, This->glDescription.level, =
debug_d3dformat(This->resource.format), internal, width, height, format, =
type);=0A=
 =0A=
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c=0A=
index 31a1944..57e2b37 100644=0A=
--- a/dlls/wined3d/utils.c=0A=
+++ b/dlls/wined3d/utils.c=0A=
@@ -44,7 +44,7 @@ static const StaticPixelFormatDesc formats[] =3D {=0A=
     /* FourCC formats, kept here to have WINED3DFMT_R8G8B8(=3D20) at =
position 20 */=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    =
    ,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=
     {WINED3DFMT_DXT3        ,0x0        ,0x0        ,0x0        ,0x0    =
    ,1      ,0      ,0          ,TRUE  },=0A=
@@ -146,6 +146,8 @@ static const GlPixelFormatDescTemplate =
gl_formats_template[] =3D {=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_YV12           ,GL_ALPHA                         =
,GL_ALPHA                               , 0,           GL_ALPHA          =
        ,GL_UNSIGNED_BYTE=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=
@@ -273,6 +275,10 @@ static const GlPixelFormatDescTemplate =
gl_formats_template[] =3D {=0A=
         ,0 },=0A=
     /* Vendor-specific formats */=0A=
     {WINED3DFMT_ATI2N          ,0                                ,0     =
                                 , 0,           GL_LUMINANCE_ALPHA       =
 ,GL_UNSIGNED_BYTE=0A=
+        ,0 },=0A=
+    {WINED3DFMT_NVHU           ,0                                ,0     =
                                 , 0,           GL_LUMINANCE_ALPHA       =
 ,GL_UNSIGNED_BYTE=0A=
+        ,0 },=0A=
+    {WINED3DFMT_NVHS           ,0                                ,0     =
                                 , 0,           GL_LUMINANCE_ALPHA       =
 ,GL_UNSIGNED_BYTE=0A=
         ,0 }=0A=
 };=0A=
 =0A=
@@ -314,6 +320,7 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)=0A=
         gl_info->gl_formats[dst].glType          =3D =
gl_formats_template[src].glType;=0A=
         gl_info->gl_formats[dst].conversion_group=3D WINED3DFMT_UNKNOWN;=0A=
         gl_info->gl_formats[dst].Flags           =3D =
gl_formats_template[src].Flags;=0A=
+        gl_info->gl_formats[dst].heightscale     =3D 1.0;=0A=
 =0A=
         if(wined3d_settings.offscreen_rendering_mode =3D=3D ORM_FBO &&=0A=
            gl_formats_template[src].rtInternal !=3D 0) {=0A=
@@ -430,6 +437,11 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)=0A=
         gl_info->gl_formats[dst].glType =3D GL_UNSIGNED_BYTE;=0A=
         gl_info->gl_formats[dst].conversion_group =3D WINED3DFMT_UYVY;=0A=
     }=0A=
+=0A=
+    dst =3D getFmtIdx(WINED3DFMT_YV12);=0A=
+    gl_info->gl_formats[dst].heightscale =3D 1.5;=0A=
+    gl_info->gl_formats[dst].conversion_group =3D WINED3DFMT_YV12;=0A=
+=0A=
     return TRUE;=0A=
 }=0A=
 =0A=
diff --git a/dlls/wined3d/wined3d_private.h =
b/dlls/wined3d/wined3d_private.h=0A=
index f4b81f7..ebe0f7f 100644=0A=
--- a/dlls/wined3d/wined3d_private.h=0A=
+++ b/dlls/wined3d/wined3d_private.h=0A=
@@ -703,7 +703,6 @@ typedef struct WineD3D_PixelFormat=0A=
 } WineD3D_PixelFormat;=0A=
 =0A=
 /* The adapter structure */=0A=
-typedef struct GLPixelFormatDesc GLPixelFormatDesc;=0A=
 struct WineD3DAdapter=0A=
 {=0A=
     UINT                    num;=0A=
@@ -1312,6 +1311,7 @@ struct IWineD3DSurfaceImpl=0A=
 =0A=
     UINT                      pow2Width;=0A=
     UINT                      pow2Height;=0A=
+    float                     heightscale;=0A=
 =0A=
     /* A method to retrieve the drawable size. Not in the Vtable to =
make it changeable */=0A=
     void (*get_drawable_size)(IWineD3DSurfaceImpl *This, UINT *width, =
UINT *height);=0A=
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h=0A=
index 4c26c9b..3101c17 100644=0A=
--- a/include/wine/wined3d_gl.h=0A=
+++ b/include/wine/wined3d_gl.h=0A=
@@ -3813,6 +3813,7 @@ typedef struct {=0A=
     GLint                   glInternal, glGammaInternal, rtInternal, =
glFormat, glType;=0A=
     WINED3DFORMAT           conversion_group;=0A=
     unsigned int            Flags;=0A=
+    float                   heightscale;=0A=
 } GlPixelFormatDesc;=0A=
 =0A=
 typedef struct _WINED3DGLTYPE {=0A=
-- =0A=
1.5.6.4=0A=
=0A=

------=_NextPart_000_0001_01C909E0.B2FBA3D0--




More information about the wine-patches mailing list