wined3d: Add signed format conversion for glsl.
This commit is contained in:
parent
2755c92fc3
commit
10f25e0104
|
@ -969,6 +969,114 @@ static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected,
|
|||
}
|
||||
}
|
||||
|
||||
static void shader_glsl_add_color_correction(SHADER_OPCODE_ARG* arg, DWORD sampler_idx) {
|
||||
IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
|
||||
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) shader->baseShader.device;
|
||||
WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
|
||||
glsl_dst_param_t dst_param;
|
||||
glsl_dst_param_t dst_param2;
|
||||
WINED3DFORMAT fmt;
|
||||
IWineD3DBaseTextureImpl *texture;
|
||||
DWORD mask, mask_size;
|
||||
|
||||
texture = (IWineD3DBaseTextureImpl *) deviceImpl->stateBlock->textures[sampler_idx];
|
||||
if(texture) {
|
||||
fmt = texture->resource.format;
|
||||
} else {
|
||||
fmt = WINED3DFMT_UNKNOWN;
|
||||
}
|
||||
|
||||
switch(fmt) {
|
||||
case WINED3DFMT_V8U8:
|
||||
case WINED3DFMT_V16U16:
|
||||
if(GL_SUPPORT(NV_TEXTURE_SHADER) ||
|
||||
(GL_SUPPORT(ATI_ENVMAP_BUMPMAP) && fmt == WINED3DFMT_V8U8)) {
|
||||
/* The 3rd channel returns 1.0 in d3d, but 0.0 in gl. Fix this while we're at it :-) */
|
||||
mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_2, &dst_param);
|
||||
mask_size = shader_glsl_get_write_mask_size(mask);
|
||||
if(mask_size >= 3) {
|
||||
shader_addline(arg->buffer, "%s.%c = 1.0;\n", dst_param.reg_name, dst_param.mask_str[3]);
|
||||
}
|
||||
} else {
|
||||
/* Correct the sign, but leave the blue as it is - it was loaded correctly already */
|
||||
mask = shader_glsl_add_dst_param(arg, arg->dst,
|
||||
WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1,
|
||||
&dst_param);
|
||||
mask_size = shader_glsl_get_write_mask_size(mask);
|
||||
if(mask_size >= 2) {
|
||||
shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2],
|
||||
dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2]);
|
||||
} else if(mask_size == 1) {
|
||||
shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n", dst_param.reg_name, dst_param.mask_str[1],
|
||||
dst_param.reg_name, dst_param.mask_str[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DFMT_X8L8V8U8:
|
||||
if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
|
||||
/* Red and blue are the signed channels, fix them up; Blue(=L) is correct already,
|
||||
* and a(X) is always 1.0
|
||||
*/
|
||||
mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &dst_param);
|
||||
mask_size = shader_glsl_get_write_mask_size(mask);
|
||||
if(mask_size >= 2) {
|
||||
shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2],
|
||||
dst_param.reg_name, dst_param.mask_str[1], dst_param.mask_str[2]);
|
||||
} else if(mask_size == 1) {
|
||||
shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[1],
|
||||
dst_param.reg_name, dst_param.mask_str[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DFMT_L6V5U5:
|
||||
if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
|
||||
mask = shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &dst_param);
|
||||
mask_size = shader_glsl_get_write_mask_size(mask);
|
||||
shader_glsl_add_dst_param(arg, arg->dst, WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_2, &dst_param2);
|
||||
if(mask_size >= 3) {
|
||||
/* Swap y and z (U and L), and do a sign conversion on x and the new y(V and U) */
|
||||
shader_addline(arg->buffer, "tmp0.g = %s.%c;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[2]);
|
||||
shader_addline(arg->buffer, "%s.%c%c = %s.%c%c * 2.0 - 1.0;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[2], dst_param.mask_str[1],
|
||||
dst_param2.reg_name, dst_param.mask_str[1], dst_param.mask_str[3]);
|
||||
shader_addline(arg->buffer, "%s.%c = tmp0.g;\n", dst_param.reg_name,
|
||||
dst_param.mask_str[3]);
|
||||
} else if(mask_size == 2) {
|
||||
/* This is bad: We have VL, but we need VU */
|
||||
FIXME("2 components sampled from a converted L6V5U5 texture\n");
|
||||
} else {
|
||||
shader_addline(arg->buffer, "%s.%c = %s.%c * 2.0 - 1.0;\n",
|
||||
dst_param.reg_name, dst_param.mask_str[1],
|
||||
dst_param2.reg_name, dst_param.mask_str[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DFMT_Q8W8V8U8:
|
||||
if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
|
||||
/* Correct the sign in all channels. The writemask just applies as-is, no
|
||||
* need for checking the mask size
|
||||
*/
|
||||
shader_glsl_add_dst_param(arg, arg->dst,
|
||||
WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 |
|
||||
WINED3DSP_WRITEMASK_2 | WINED3DSP_WRITEMASK_3,
|
||||
&dst_param);
|
||||
shader_addline(arg->buffer, "%s%s = %s%s * 2.0 - 1.0;\n", dst_param.reg_name, dst_param.mask_str,
|
||||
dst_param.reg_name, dst_param.mask_str);
|
||||
}
|
||||
break;
|
||||
|
||||
/* stupid compiler */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
@ -1593,6 +1701,7 @@ void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) {
|
|||
********************************************/
|
||||
void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
|
||||
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
|
||||
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
|
||||
DWORD hex_version = This->baseShader.hex_version;
|
||||
char dst_swizzle[6];
|
||||
glsl_sample_function_t sample_function;
|
||||
|
@ -1607,7 +1716,6 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
|
|||
/* 1.0-1.4: Use destination register as sampler source.
|
||||
* 2.0+: Use provided sampler source. */
|
||||
if (hex_version < WINED3DPS_VERSION(1,4)) {
|
||||
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
|
||||
DWORD flags;
|
||||
|
||||
sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
|
||||
|
@ -1681,6 +1789,8 @@ void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
|
|||
sample_function.name, sampler_idx, coord_param.param_str, dst_swizzle);
|
||||
}
|
||||
}
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
void shader_glsl_texldl(SHADER_OPCODE_ARG* arg) {
|
||||
|
@ -1711,6 +1821,8 @@ void shader_glsl_texldl(SHADER_OPCODE_ARG* arg) {
|
|||
shader_addline(arg->buffer, "%sLod(Vsampler%u, %s, %s)%s);\n",
|
||||
sample_function.name, sampler_idx, coord_param.param_str, lod_param.param_str, dst_swizzle);
|
||||
}
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) {
|
||||
|
@ -1801,6 +1913,8 @@ void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) {
|
|||
default:
|
||||
FIXME("Unexpected mask bitcount %d\n", count_bits(sample_function.coord_mask));
|
||||
}
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXDP3 instruction in GLSL:
|
||||
|
@ -1923,6 +2037,8 @@ void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) {
|
|||
shader_addline(arg->buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
|
||||
|
||||
current_state->current_row = 0;
|
||||
|
||||
shader_glsl_add_color_correction(arg, reg);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXM3X3 instruction in GLSL
|
||||
|
@ -1975,6 +2091,8 @@ void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) {
|
|||
shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
|
||||
|
||||
current_state->current_row = 0;
|
||||
|
||||
shader_glsl_add_color_correction(arg, reg);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL
|
||||
|
@ -2009,6 +2127,8 @@ void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
|
|||
shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
|
||||
|
||||
current_state->current_row = 0;
|
||||
|
||||
shader_glsl_add_color_correction(arg, reg);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXBEM instruction in GLSL.
|
||||
|
@ -2067,6 +2187,8 @@ void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
|
|||
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat * %s, 0.0, 0.0)%s )%s);\n",
|
||||
sample_function.name, sampler_idx, sampler_idx, coord_mask, coord_param.param_str, coord_mask, dst_swizzle);
|
||||
}
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) {
|
||||
|
@ -2083,6 +2205,7 @@ void pshader_glsl_bem(SHADER_OPCODE_ARG* arg) {
|
|||
/** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
|
||||
* Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
|
||||
void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) {
|
||||
|
||||
glsl_src_param_t src0_param;
|
||||
DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
|
||||
char dst_mask[6];
|
||||
|
@ -2092,6 +2215,8 @@ void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) {
|
|||
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
|
||||
|
||||
shader_addline(arg->buffer, "texture2D(Psampler%u, %s.wx)%s);\n", sampler_idx, src0_param.reg_name, dst_mask);
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXREG2GB instruction in GLSL
|
||||
|
@ -2106,6 +2231,8 @@ void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg) {
|
|||
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
|
||||
|
||||
shader_addline(arg->buffer, "texture2D(Psampler%u, %s.yz)%s);\n", sampler_idx, src0_param.reg_name, dst_mask);
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL
|
||||
|
@ -2123,6 +2250,8 @@ void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg) {
|
|||
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &src0_param);
|
||||
|
||||
shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n", sample_function.name, sampler_idx, src0_param.param_str, dst_mask);
|
||||
|
||||
shader_glsl_add_color_correction(arg, sampler_idx);
|
||||
}
|
||||
|
||||
/** Process the WINED3DSIO_TEXKILL instruction in GLSL.
|
||||
|
|
|
@ -1504,8 +1504,8 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_
|
|||
} else {
|
||||
/* Not supported by GL_ATI_envmap_bumpmap */
|
||||
*format = GL_BGRA;
|
||||
*internal = GL_RGBA8;
|
||||
*type = GL_UNSIGNED_BYTE;
|
||||
*internal = GL_RGB8;
|
||||
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1523,8 +1523,8 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_
|
|||
if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
|
||||
*convert = CONVERT_V16U16;
|
||||
*format = GL_BGR;
|
||||
*internal = GL_RGB16;
|
||||
*type = GL_SHORT;
|
||||
*internal = GL_RGB16_EXT;
|
||||
*type = GL_UNSIGNED_SHORT;
|
||||
*target_bpp = 6;
|
||||
/* What should I do here about GL_ATI_envmap_bumpmap?
|
||||
* Convert it or allow data loss by loading it into a 8 bit / channel texture?
|
||||
|
@ -1733,6 +1733,25 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN
|
|||
break;
|
||||
}
|
||||
|
||||
case CONVERT_V16U16:
|
||||
{
|
||||
unsigned int x, y;
|
||||
DWORD *Source;
|
||||
unsigned short *Dest;
|
||||
for(y = 0; y < height; y++) {
|
||||
Source = (DWORD *) (src + y * pitch);
|
||||
Dest = (unsigned short *) (dst + y * outpitch);
|
||||
for (x = 0; x < width; x++ ) {
|
||||
DWORD color = (*Source++);
|
||||
/* B */ Dest[0] = 0xffff;
|
||||
/* G */ Dest[1] = (color >> 16) + 32768; /* V */
|
||||
/* R */ Dest[2] = (color ) + 32768; /* U */
|
||||
Dest += 3;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CONVERT_Q8W8V8U8:
|
||||
{
|
||||
unsigned int x, y;
|
||||
|
@ -1788,7 +1807,21 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN
|
|||
}
|
||||
}
|
||||
} else {
|
||||
FIXME("Add D3DFMT_L6V5U5 emulation using standard unsigned RGB and shaders\n");
|
||||
for(y = 0; y < height; y++) {
|
||||
unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch);
|
||||
Source = (WORD *) (src + y * pitch);
|
||||
for (x = 0; x < width; x++ ) {
|
||||
short color = (*Source++);
|
||||
unsigned char l = ((color >> 10) & 0xfc);
|
||||
short v = ((color >> 5) & 0x3e);
|
||||
short u = ((color ) & 0x1f);
|
||||
short v_conv = v + 16;
|
||||
short u_conv = u + 16;
|
||||
|
||||
*Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
|
||||
Dest_s += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1820,7 +1853,17 @@ HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UIN
|
|||
* shaders if the shader is adjusted. (There's no use for this format in gl's
|
||||
* standard fixed function pipeline anyway).
|
||||
*/
|
||||
FIXME("Implement CONVERT_X8L8V8U8 with standard unsigned GL_RGB\n");
|
||||
for(y = 0; y < height; y++) {
|
||||
Source = (DWORD *) (src + y * pitch);
|
||||
Dest = (unsigned char *) (dst + y * outpitch);
|
||||
for (x = 0; x < width; x++ ) {
|
||||
long color = (*Source++);
|
||||
/* B */ Dest[0] = ((color >> 16) & 0xff); /* L */
|
||||
/* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
|
||||
/* R */ Dest[2] = (color & 0xff) + 128; /* U */
|
||||
Dest += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue