Bug 668801 - Part 3: Adjust dealing with clipped shadows to be accurate. r=jrmuizel

This commit is contained in:
Bas Schouten 2011-07-05 06:28:20 +00:00
parent 1234946c68
commit 951afc154e
4 changed files with 2768 additions and 1132 deletions

View File

@ -122,29 +122,7 @@ public:
gfxWarning() << "Failed to create shared bitmap for old surface.";
}
factory()->CreatePathGeometry(byRef(mClippedArea));
RefPtr<ID2D1GeometrySink> currentSink;
mClippedArea->Open(byRef(currentSink));
std::vector<DrawTargetD2D::PushedClip>::iterator iter = mDT->mPushedClips.begin();
iter->mPath->GetGeometry()->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
iter->mTransform, currentSink);
currentSink->Close();
iter++;
for (;iter != mDT->mPushedClips.end(); iter++) {
RefPtr<ID2D1PathGeometry> newGeom;
factory()->CreatePathGeometry(byRef(newGeom));
newGeom->Open(byRef(currentSink));
mClippedArea->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT,
iter->mTransform, currentSink);
currentSink->Close();
mClippedArea = newGeom;
}
mClippedArea = mDT->GetClippedGeometry();
}
ID2D1Factory *factory() { return mDT->factory(); }
@ -163,7 +141,9 @@ public:
mDT->mTransformDirty = true;
RefPtr<ID2D1RectangleGeometry> rectGeom;
factory()->CreateRectangleGeometry(D2D1::InfiniteRect(), byRef(rectGeom));
factory()->CreateRectangleGeometry(
D2D1::RectF(0, 0, float(mDT->mSize.width), float(mDT->mSize.height)),
byRef(rectGeom));
RefPtr<ID2D1PathGeometry> invClippedArea;
factory()->CreatePathGeometry(byRef(invClippedArea));
@ -188,7 +168,7 @@ private:
// with the old dest surface data.
RefPtr<ID2D1Bitmap> mOldSurfBitmap;
// This contains the area drawing is clipped to.
RefPtr<ID2D1PathGeometry> mClippedArea;
RefPtr<ID2D1Geometry> mClippedArea;
};
DrawTargetD2D::DrawTargetD2D()
@ -317,6 +297,12 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
Flush();
AutoSaveRestoreClippedOut restoreClippedOut(this);
if (!IsOperatorBoundByMask(aOperator)) {
restoreClippedOut.Save();
}
srView = static_cast<SourceSurfaceD2DTarget*>(aSurface)->GetSRView();
EnsureViews();
@ -331,35 +317,36 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
}
}
RefPtr<ID3D10RenderTargetView> destRTView = mRTView;
RefPtr<ID3D10Texture2D> destTexture;
HRESULT hr;
RefPtr<ID3D10Texture2D> maskTexture;
RefPtr<ID3D10ShaderResourceView> maskSRView;
if (mPushedClips.size()) {
// We need to take clips into account, draw into a temporary surface, which
// we then blend back with the proper clips set, using D2D.
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_A8_UNORM,
mSize.width, mSize.height,
1, 1);
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
hr = mDevice->CreateTexture2D(&desc, NULL, byRef(destTexture));
if (FAILED(hr)) {
gfxWarning() << "Failure to create temporary texture. Size: " << mSize << " Code: " << hr;
return;
}
hr = mDevice->CreateTexture2D(&desc, NULL, byRef(maskTexture));
hr = mDevice->CreateRenderTargetView(destTexture, NULL, byRef(destRTView));
if (FAILED(hr)) {
gfxWarning() << "Failure to create RenderTargetView. Code: " << hr;
return;
}
RefPtr<ID2D1RenderTarget> rt = CreateRTForTexture(maskTexture);
float color[4] = { 0, 0, 0, 0 };
mDevice->ClearRenderTargetView(destRTView, color);
RefPtr<ID2D1SolidColorBrush> brush;
rt->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), byRef(brush));
RefPtr<ID2D1Geometry> geometry = GetClippedGeometry();
rt->BeginDraw();
rt->Clear(D2D1::ColorF(0, 0));
rt->FillGeometry(geometry, brush);
rt->EndDraw();
mDevice->CreateShaderResourceView(maskTexture, NULL, byRef(maskSRView));
}
IntSize srcSurfSize;
ID3D10RenderTargetView *rtViews;
D3D10_VIEWPORT viewport;
@ -596,8 +583,18 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
SetFloatVector(ShaderConstantRectD3D10(-correctedOffset.x / Float(tmpSurfSize.width), -correctedOffset.y / Float(tmpSurfSize.height),
mSize.width / Float(tmpSurfSize.width) * dsFactorX,
mSize.height / Float(tmpSurfSize.height) * dsFactorY));
mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
GetPassByIndex(1)->Apply(0);
if (!mPushedClips.size()) {
mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
GetPassByIndex(1)->Apply(0);
} else {
mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(maskSRView);
mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
mPrivateData->mEffect->GetTechniqueByName("SampleTextureWithShadow")->
GetPassByIndex(2)->Apply(0);
}
mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), NULL, 0xffffffff);
mDevice->Draw(4, 0);
@ -607,39 +604,17 @@ DrawTargetD2D::DrawSurfaceWithShadow(SourceSurface *aSurface,
SetFloatVector(ShaderConstantRectD3D10(-aDest.x / aSurface->GetSize().width, -aDest.y / aSurface->GetSize().height,
Float(mSize.width) / aSurface->GetSize().width,
Float(mSize.height) / aSurface->GetSize().height));
mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
GetPassByIndex(0)->Apply(0);
if (!mPushedClips.size()) {
mPrivateData->mEffect->GetTechniqueByName("SampleTexture")->
GetPassByIndex(0)->Apply(0);
} else {
mPrivateData->mEffect->GetTechniqueByName("SampleMaskedTexture")->
GetPassByIndex(0)->Apply(0);
}
mDevice->OMSetBlendState(GetBlendStateForOperator(aOperator), NULL, 0xffffffff);
mDevice->Draw(4, 0);
if (mPushedClips.size()) {
// Assert destTexture
// Blend back using the proper clips.
PrepareForDrawing(mRT);
RefPtr<IDXGISurface> surf;
hr = destTexture->QueryInterface((IDXGISurface**) byRef(surf));
if (FAILED(hr)) {
gfxWarning() << "Failure to QI texture to surface. Code: " << hr;
return;
}
D2D1_BITMAP_PROPERTIES props =
D2D1::BitmapProperties(D2D1::PixelFormat(DXGIFormat(mFormat), AlphaMode(mFormat)));
RefPtr<ID2D1Bitmap> bitmap;
hr = mRT->CreateSharedBitmap(IID_IDXGISurface, surf,
&props, byRef(bitmap));
if (FAILED(hr)) {
gfxWarning() << "Failure to create shared bitmap for surface. Code: " << hr;
return;
}
mRT->DrawBitmap(bitmap);
}
}
void
@ -1415,6 +1390,38 @@ DrawTargetD2D::FinalizeRTForOperator(CompositionOp aOperator, const Rect &aBound
mDevice->Draw(4, 0);
}
TemporaryRef<ID2D1Geometry>
DrawTargetD2D::GetClippedGeometry()
{
RefPtr<ID2D1GeometrySink> currentSink;
RefPtr<ID2D1PathGeometry> clippedGeometry;
factory()->CreatePathGeometry(byRef(clippedGeometry));
clippedGeometry->Open(byRef(currentSink));
std::vector<DrawTargetD2D::PushedClip>::iterator iter = mPushedClips.begin();
iter->mPath->GetGeometry()->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES,
iter->mTransform, currentSink);
currentSink->Close();
iter++;
for (;iter != mPushedClips.end(); iter++) {
RefPtr<ID2D1PathGeometry> newGeom;
factory()->CreatePathGeometry(byRef(newGeom));
newGeom->Open(byRef(currentSink));
clippedGeometry->CombineWithGeometry(iter->mPath->GetGeometry(), D2D1_COMBINE_MODE_INTERSECT,
iter->mTransform, currentSink);
currentSink->Close();
clippedGeometry = newGeom;
}
return clippedGeometry;
}
TemporaryRef<ID2D1RenderTarget>
DrawTargetD2D::CreateRTForTexture(ID3D10Texture2D *aTexture)
{

View File

@ -160,6 +160,7 @@ private:
void PopAllClips();
TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture);
TemporaryRef<ID2D1Geometry> GetClippedGeometry();
TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);

View File

@ -13,6 +13,7 @@ cbuffer cb0
{
float4 QuadDesc;
float4 TexCoords;
float4 MaskTexCoords;
}
cbuffer cb1
@ -27,9 +28,11 @@ struct VS_OUTPUT
{
float4 Position : SV_Position;
float2 TexCoord : TEXCOORD0;
float2 MaskTexCoord : TEXCOORD1;
};
Texture2D tex;
Texture2D mask;
sampler sSampler = sampler_state {
Filter = MIN_MAG_MIP_LINEAR;
@ -38,6 +41,13 @@ sampler sSampler = sampler_state {
AddressV = Clamp;
};
sampler sMaskSampler = sampler_state {
Filter = MIN_MAG_MIP_LINEAR;
Texture = mask;
AddressU = Clamp;
AddressV = Clamp;
};
sampler sShadowSampler = sampler_state {
Filter = MIN_MAG_MIP_LINEAR;
Texture = tex;
@ -79,6 +89,8 @@ VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
Output.Position.z = 0;
Output.TexCoord.x = pos.x * TexCoords.z + TexCoords.x;
Output.TexCoord.y = pos.y * TexCoords.w + TexCoords.y;
Output.MaskTexCoord.x = pos.x * MaskTexCoords.z + MaskTexCoords.x;
Output.MaskTexCoord.y = pos.y * MaskTexCoords.w + MaskTexCoords.y;
return Output;
}
@ -87,6 +99,11 @@ 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 SampleShadowHPS( VS_OUTPUT In) : SV_Target
{
float outputStrength = 0;
@ -121,6 +138,23 @@ float4 SampleShadowVPS( VS_OUTPUT In) : SV_Target
return outputColor;
};
float4 SampleMaskShadowVPS( VS_OUTPUT In) : SV_Target
{
float4 outputColor = float4(0, 0, 0, 0);
outputColor += BlurWeights[0].x * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[0].x));
outputColor += BlurWeights[0].y * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[0].y));
outputColor += BlurWeights[0].z * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[0].z));
outputColor += BlurWeights[0].w * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[0].w));
outputColor += BlurWeights[1].x * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[1].x));
outputColor += BlurWeights[1].y * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[1].y));
outputColor += BlurWeights[1].z * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[1].z));
outputColor += BlurWeights[1].w * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[1].w));
outputColor += BlurWeights[2].x * tex.Sample(sShadowSampler, float2(In.TexCoord.x, In.TexCoord.y + BlurOffsetsV[2].x));
return outputColor * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
};
technique10 SampleTexture
{
pass P0
@ -132,6 +166,16 @@ technique10 SampleTexture
}
}
technique10 SampleMaskedTexture
{
pass P0
{
SetRasterizerState(TextureRast);
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleMaskTexturePS()));
}
}
technique10 SampleTextureWithShadow
{
@ -153,4 +197,13 @@ technique10 SampleTextureWithShadow
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleShadowVPS()));
}
}
// Vertical pass - used when using a mask
pass P2
{
SetRasterizerState(TextureRast);
SetBlendState(ShadowBlendV, float4(1.0f, 1.0f, 1.0f, 1.0f), 0xffffffff);
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleMaskShadowVPS()));
}
}

File diff suppressed because it is too large Load Diff