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