mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 809927: Add new blend modes and implement them for Direct2D. r=bas
This commit is contained in:
parent
2a37ad0196
commit
6b9a25d0b5
@ -1520,6 +1520,10 @@ DrawTargetD2D::GetRTForOperation(CompositionOp aOperator, const Pattern &aPatter
|
||||
|
||||
PopAllClips();
|
||||
|
||||
if (aOperator > OP_XOR) {
|
||||
mRT->Flush();
|
||||
}
|
||||
|
||||
if (mTempRT) {
|
||||
mTempRT->Clear(D2D1::ColorF(0, 0));
|
||||
return mTempRT;
|
||||
@ -1598,6 +1602,9 @@ DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aP
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
|
||||
RefPtr<ID3D10Texture2D> tmpTexture;
|
||||
RefPtr<ID3D10ShaderResourceView> mBckSRView;
|
||||
|
||||
mDevice->RSSetViewports(1, &viewport);
|
||||
mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(-1.0f, 1.0f, 2.0f, -2.0f));
|
||||
@ -1606,7 +1613,54 @@ DrawTargetD2D::FinalizeRTForOperation(CompositionOp aOperator, const Pattern &aP
|
||||
mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(mSRView);
|
||||
|
||||
// Handle the case where we blend with the backdrop
|
||||
if (aOperator > OP_XOR) {
|
||||
IntSize size = mSize;
|
||||
SurfaceFormat format = mFormat;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGIFormat(format), size.width, size.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
|
||||
HRESULT hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(tmpTexture));
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create temporary texture to hold surface data.";
|
||||
return;
|
||||
}
|
||||
|
||||
mDevice->CopyResource(tmpTexture, mTexture);
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
|
||||
return;
|
||||
}
|
||||
|
||||
DrawTargetD2D::Flush();
|
||||
|
||||
hr = mDevice->CreateShaderResourceView(tmpTexture, nullptr, byRef(mBckSRView));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << *this << "Failed to create shader resource view for temp texture. Code: " << hr;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int compop = (unsigned int)aOperator - (unsigned int)OP_XOR;
|
||||
mPrivateData->mEffect->GetVariableByName("bcktex")->AsShaderResource()->SetResource(mBckSRView);
|
||||
mPrivateData->mEffect->GetVariableByName("blendop")->AsScalar()->SetInt(compop);
|
||||
|
||||
if (aOperator > OP_EXCLUSION)
|
||||
mPrivateData->mEffect->GetTechniqueByName("SampleTextureForNonSeparableBlending")->
|
||||
GetPassByIndex(0)->Apply(0);
|
||||
else if (aOperator > OP_COLOR_DODGE)
|
||||
mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_2")->
|
||||
GetPassByIndex(0)->Apply(0);
|
||||
else
|
||||
mPrivateData->mEffect->GetTechniqueByName("SampleTextureForSeparableBlending_1")->
|
||||
GetPassByIndex(0)->Apply(0);
|
||||
}
|
||||
else {
|
||||
mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->GetPassByIndex(0)->Apply(0);
|
||||
}
|
||||
|
||||
} else if (aPattern.GetType() == PATTERN_RADIAL_GRADIENT) {
|
||||
const RadialGradientPattern *pat = static_cast<const RadialGradientPattern*>(&aPattern);
|
||||
|
||||
|
@ -58,7 +58,9 @@ struct PS_TEXT_OUTPUT
|
||||
};
|
||||
|
||||
Texture2D tex;
|
||||
Texture2D bcktex;
|
||||
Texture2D mask;
|
||||
uint blendop;
|
||||
|
||||
sampler sSampler = sampler_state {
|
||||
Filter = MIN_MAG_MIP_LINEAR;
|
||||
@ -67,6 +69,13 @@ sampler sSampler = sampler_state {
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
sampler sBckSampler = sampler_state {
|
||||
Filter = MIN_MAG_MIP_LINEAR;
|
||||
Texture = bcktex;
|
||||
AddressU = Clamp;
|
||||
AddressV = Clamp;
|
||||
};
|
||||
|
||||
sampler sWrapSampler = sampler_state {
|
||||
Filter = MIN_MAG_MIP_LINEAR;
|
||||
Texture = tex;
|
||||
@ -166,15 +175,262 @@ VS_RADIAL_OUTPUT SampleRadialVS(float3 pos : POSITION)
|
||||
return Output;
|
||||
}
|
||||
|
||||
float Screen(float a, float b)
|
||||
{
|
||||
return 1 - ((1 - a)*(1 - b));
|
||||
}
|
||||
|
||||
static float RedLuminance = 0.3f;
|
||||
static float GreenLuminance = 0.59f;
|
||||
static float BlueLuminance = 0.11f;
|
||||
|
||||
float Lum(float3 C)
|
||||
{
|
||||
return RedLuminance * C.r + GreenLuminance * C.g + BlueLuminance * C.b;
|
||||
}
|
||||
|
||||
float3 ClipColor(float3 C)
|
||||
{
|
||||
float L = Lum(C);
|
||||
float n = min(min(C.r, C.g), C.b);
|
||||
float x = max(max(C.r, C.g), C.b);
|
||||
|
||||
if(n < 0)
|
||||
C = L + (((C - L) * L) / (L - n));
|
||||
|
||||
if(x > 1)
|
||||
C = L + ((C - L) * (1 - L) / (x - L));
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
float3 SetLum(float3 C, float l)
|
||||
{
|
||||
float d = l - Lum(C);
|
||||
C = C + d;
|
||||
return ClipColor(C);
|
||||
}
|
||||
|
||||
float Sat(float3 C)
|
||||
{
|
||||
return max(C.r, max(C.g, C.b)) - min(C.r, min(C.g, C.b));
|
||||
}
|
||||
|
||||
void SetSatComponents(inout float minComp, inout float midComp, inout float maxComp, in float satVal)
|
||||
{
|
||||
midComp -= minComp;
|
||||
maxComp -= minComp;
|
||||
minComp = 0.0;
|
||||
if (maxComp > 0.0)
|
||||
{
|
||||
midComp *= satVal/maxComp;
|
||||
maxComp = satVal;
|
||||
}
|
||||
}
|
||||
|
||||
float3 SetSat(float3 color, in float satVal)
|
||||
{
|
||||
if (color.x <= color.y) {
|
||||
if (color.y <= color.z) {
|
||||
// x <= y <= z
|
||||
SetSatComponents(color.x, color.y, color.z, satVal);
|
||||
}
|
||||
else {
|
||||
if (color.x <= color.z) {
|
||||
// x <= z <= y
|
||||
SetSatComponents(color.x, color.z, color.y, satVal);
|
||||
}
|
||||
else {
|
||||
// z <= x <= y
|
||||
SetSatComponents(color.z, color.x, color.y, satVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (color.x <= color.z) {
|
||||
// y <= x <= z
|
||||
SetSatComponents(color.y, color.x, color.z, satVal);
|
||||
}
|
||||
else {
|
||||
if (color.y <= color.z) {
|
||||
// y <= z <= x
|
||||
SetSatComponents(color.y, color.z, color.x, satVal);
|
||||
}
|
||||
else {
|
||||
// z <= y <= x
|
||||
SetSatComponents(color.z, color.y, color.x, satVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float4 SampleBlendTextureSeparablePS_1( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
float4 output = tex.Sample(sSampler, In.TexCoord);
|
||||
float4 background = bcktex.Sample(sBckSampler, In.TexCoord);
|
||||
if((output.a == 0) || (background.a == 0))
|
||||
return output;
|
||||
|
||||
output.rgb /= output.a;
|
||||
background.rgb /= background.a;
|
||||
|
||||
float4 retval = output;
|
||||
|
||||
if(blendop == 1) { // multiply
|
||||
retval.rgb = output.rgb * background.rgb;
|
||||
} else if(blendop == 2) {
|
||||
retval.rgb = output.rgb + background.rgb - output.rgb * background.rgb;
|
||||
} else if(blendop == 3) {
|
||||
if(background.r <= 0.5)
|
||||
retval.r = 2*background.r * output.r;
|
||||
else
|
||||
retval.r = Screen(output.r, 2 * background.r - 1);
|
||||
if(background.g <= 0.5)
|
||||
retval.g = 2 * background.g * output.g;
|
||||
else
|
||||
retval.g = Screen(output.g, 2 * background.g - 1);
|
||||
if(background.b <= 0.5)
|
||||
retval.b = 2 * background.b * output.b;
|
||||
else
|
||||
retval.b = Screen(output.b, 2 * background.b - 1);
|
||||
} else if(blendop == 4) {
|
||||
retval.rgb = min(output.rgb, background.rgb);
|
||||
} else if(blendop == 5) {
|
||||
retval.rgb = max(output.rgb, background.rgb);
|
||||
} else {
|
||||
if(output.r > 0)
|
||||
retval.r = 1 - min(1, (1 - background.r) / output.r);
|
||||
else
|
||||
retval.r = background.r ? 1 : 0;
|
||||
if(output.g > 0)
|
||||
retval.g = 1 - min(1, (1 - background.g) / output.g);
|
||||
else
|
||||
retval.g = background.g ? 1 : 0;
|
||||
if(output.b > 0)
|
||||
retval.b = 1 - min(1, (1 - background.b) / output.b);
|
||||
else
|
||||
retval.b = background.b ? 1 : 0;
|
||||
}
|
||||
|
||||
output.rgb = ((1 - background.a) * output.rgb + background.a * retval.rgb) * output.a;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 SampleBlendTextureSeparablePS_2( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
float4 output = tex.Sample(sSampler, In.TexCoord);
|
||||
float4 background = bcktex.Sample(sBckSampler, In.TexCoord);
|
||||
if((output.a == 0) || (background.a == 0))
|
||||
return output;
|
||||
|
||||
output.rgb /= output.a;
|
||||
background.rgb /= background.a;
|
||||
|
||||
float4 retval = output;
|
||||
|
||||
if(blendop == 7) {
|
||||
if(output.r > 0)
|
||||
retval.r = 1 - min(1, (1 - background.r) / output.r);
|
||||
else
|
||||
retval.r = background.r ? 1 : 0;
|
||||
if(output.g > 0)
|
||||
retval.g = 1 - min(1, (1 - background.g) / output.g);
|
||||
else
|
||||
retval.g = background.g ? 1 : 0;
|
||||
if(output.b > 0)
|
||||
retval.b = 1 - min(1, (1 - background.b) / output.b);
|
||||
else
|
||||
retval.b = background.b ? 1 : 0;
|
||||
} else if(blendop == 8) {
|
||||
if(output.r <= 0.5)
|
||||
retval.r = 2 * output.r * background.r;
|
||||
else
|
||||
retval.r = Screen(background.r, 2 * output.r -1);
|
||||
if(output.g <= 0.5)
|
||||
retval.g = 2 * output.g * background.g;
|
||||
else
|
||||
retval.g = Screen(background.g, 2 * output.g -1);
|
||||
if(output.b <= 0.5)
|
||||
retval.b = 2 * output.b * background.b;
|
||||
else
|
||||
retval.b = Screen(background.b, 2 * output.b -1);
|
||||
} else if(blendop == 9){
|
||||
float D;
|
||||
if(background.r <= 0.25)
|
||||
D = ((16 * background.r - 12) * background.r + 4) * background.r;
|
||||
else
|
||||
D = sqrt(background.r);
|
||||
if(output.r <= 0.5)
|
||||
retval.r = background.r - (1 - 2 * output.r) * background.r * (1 - background.r);
|
||||
else
|
||||
retval.r = background.r + (2 * output.r - 1) * (D - background.r);
|
||||
|
||||
if(background.g <= 0.25)
|
||||
D = ((16 * background.g - 12) * background.g + 4) * background.g;
|
||||
else
|
||||
D = sqrt(background.g);
|
||||
if(output.g <= 0.5)
|
||||
retval.g = background.g - (1 - 2 * output.g) * background.g * (1 - background.g);
|
||||
else
|
||||
retval.g = background.g + (2 * output.g - 1) * (D - background.g);
|
||||
|
||||
if(background.b <= 0.25)
|
||||
D = ((16 * background.b - 12) * background.b + 4) * background.b;
|
||||
else
|
||||
D = sqrt(background.b);
|
||||
|
||||
if(output.b <= 0.5)
|
||||
retval.b = background.b - (1 - 2 * output.b) * background.b * (1 - background.b);
|
||||
else
|
||||
retval.b = background.b + (2 * output.b - 1) * (D - background.b);
|
||||
} else if(blendop == 10) {
|
||||
retval.rgb = abs(output.rgb - background.rgb);
|
||||
} else {
|
||||
retval.rgb = output.rgb + background.rgb - 2 * output.rgb * background.rgb;
|
||||
}
|
||||
|
||||
output.rgb = ((1 - background.a) * output.rgb + background.a * retval.rgb) * output.a;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 SampleBlendTextureNonSeparablePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
float4 output = tex.Sample(sSampler, In.TexCoord);
|
||||
float4 background = bcktex.Sample(sBckSampler, In.TexCoord);
|
||||
if((output.a == 0) || (background.a == 0))
|
||||
return output;
|
||||
|
||||
output.rgb /= output.a;
|
||||
background.rgb /= background.a;
|
||||
|
||||
float4 retval = output;
|
||||
|
||||
if(blendop == 12) {
|
||||
retval.rgb = SetLum(SetSat(output.rgb, Sat(background.rgb)), Lum(background.rgb));
|
||||
} else if(blendop == 13) {
|
||||
retval.rgb = SetLum(SetSat(background.rgb, Sat(output.rgb)), Lum(background.rgb));
|
||||
} else if(blendop == 14) {
|
||||
retval.rgb = SetLum(output.rgb, Lum(background.rgb));
|
||||
} else {
|
||||
retval.rgb = SetLum(background.rgb, Lum(output.rgb));
|
||||
}
|
||||
|
||||
output.rgb = ((1 - background.a) * output.rgb + background.a * retval.rgb) * output.a;
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
float4 SampleTexturePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
return tex.Sample(sSampler, In.TexCoord);
|
||||
};
|
||||
}
|
||||
|
||||
float4 SampleMaskTexturePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
return tex.Sample(sSampler, In.TexCoord) * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||
};
|
||||
}
|
||||
|
||||
float4 SampleRadialGradientPS(VS_RADIAL_OUTPUT In, uniform sampler aSampler) : SV_Target
|
||||
{
|
||||
@ -329,6 +585,39 @@ technique10 SampleTexture
|
||||
}
|
||||
}
|
||||
|
||||
technique10 SampleTextureForSeparableBlending_1
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState(TextureRast);
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleBlendTextureSeparablePS_1()));
|
||||
}
|
||||
}
|
||||
|
||||
technique10 SampleTextureForSeparableBlending_2
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState(TextureRast);
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleBlendTextureSeparablePS_2()));
|
||||
}
|
||||
}
|
||||
|
||||
technique10 SampleTextureForNonSeparableBlending
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState(TextureRast);
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleBlendTextureNonSeparablePS()));
|
||||
}
|
||||
}
|
||||
|
||||
technique10 SampleRadialGradient
|
||||
{
|
||||
pass APos
|
||||
|
15779
gfx/2d/ShadersD2D.h
15779
gfx/2d/ShadersD2D.h
File diff suppressed because it is too large
Load Diff
@ -84,7 +84,8 @@ enum FontStyle
|
||||
FONT_STYLE_BOLD_ITALIC
|
||||
};
|
||||
|
||||
enum CompositionOp { OP_OVER, OP_ADD, OP_ATOP, OP_OUT, OP_IN, OP_SOURCE, OP_DEST_IN, OP_DEST_OUT, OP_DEST_OVER, OP_DEST_ATOP, OP_XOR, OP_COUNT };
|
||||
enum CompositionOp { OP_OVER, OP_ADD, OP_ATOP, OP_OUT, OP_IN, OP_SOURCE, OP_DEST_IN, OP_DEST_OUT, OP_DEST_OVER, OP_DEST_ATOP, OP_XOR,
|
||||
OP_MULTIPLY, OP_SCREEN, OP_OVERLAY, OP_DARKEN, OP_LIGHTEN, OP_COLOR_DODGE, OP_COLOR_BURN, OP_HARD_LIGHT, OP_SOFT_LIGHT, OP_DIFFERENCE, OP_EXCLUSION, OP_HUE, OP_SATURATION, OP_COLOR, OP_LUMINOSITY, OP_COUNT };
|
||||
enum ExtendMode { EXTEND_CLAMP, EXTEND_REPEAT, EXTEND_REFLECT };
|
||||
enum FillRule { FILL_WINDING, FILL_EVEN_ODD };
|
||||
enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL, AA_DEFAULT };
|
||||
|
Loading…
Reference in New Issue
Block a user