Bug 1089454: Prevent usage of incompatible graphics objects after device reset. r=jrmuizel

This commit is contained in:
Bas Schouten 2015-01-28 00:54:19 +00:00
parent 8e730610d5
commit e7a45f235f
7 changed files with 39 additions and 5 deletions

View File

@ -162,6 +162,7 @@ public:
virtual ~GradientStops() {}
virtual BackendType GetBackendType() const = 0;
virtual bool IsValid() const { return true; }
protected:
GradientStops() {}

View File

@ -1300,7 +1300,7 @@ DrawTargetD2D::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops, E
return nullptr;
}
return new GradientStopsD2D(stopCollection);
return new GradientStopsD2D(stopCollection, Factory::GetDirect3D11Device());
}
TemporaryRef<FilterNode>

View File

@ -725,7 +725,7 @@ DrawTargetD2D1::CreateGradientStops(GradientStop *rawStops, uint32_t aNumStops,
return nullptr;
}
return new GradientStopsD2D(stopCollection);
return new GradientStopsD2D(stopCollection, Factory::GetDirect3D11Device());
}
TemporaryRef<FilterNode>
@ -1228,6 +1228,12 @@ DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
D2D1::BrushProperties(aAlpha, D2DMatrix(pat->mMatrix)),
stops->mStopCollection,
byRef(gradBrush));
if (!gradBrush) {
gfxWarning() << "Couldn't create gradient brush.";
return CreateTransparentBlackBrush();
}
return gradBrush.forget();
}
if (aPattern.GetType() == PatternType::RADIAL_GRADIENT) {
@ -1251,6 +1257,11 @@ DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
stops->mStopCollection,
byRef(gradBrush));
if (!gradBrush) {
gfxWarning() << "Couldn't create gradient brush.";
return CreateTransparentBlackBrush();
}
return gradBrush.forget();
}
if (aPattern.GetType() == PatternType::SURFACE) {
@ -1279,6 +1290,8 @@ DrawTargetD2D1::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
Float(pat->mSurface->GetSize().height));
}
MOZ_ASSERT(pat->mSurface->IsValid());
RefPtr<ID2D1ImageBrush> imageBrush;
RefPtr<ID2D1Image> image = GetImageForSurface(pat->mSurface, mat, pat->mExtendMode, !pat->mSamplingRect.IsEmpty() ? &pat->mSamplingRect : nullptr);

View File

@ -17,17 +17,21 @@ class GradientStopsD2D : public GradientStops
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsD2D)
GradientStopsD2D(ID2D1GradientStopCollection *aStopCollection)
GradientStopsD2D(ID2D1GradientStopCollection *aStopCollection, ID3D11Device *aDevice)
: mStopCollection(aStopCollection)
, mDevice(aDevice)
{}
virtual BackendType GetBackendType() const { return BackendType::DIRECT2D; }
virtual bool IsValid() const MOZ_FINAL{ return mDevice == Factory::GetDirect3D11Device(); }
private:
friend class DrawTargetD2D;
friend class DrawTargetD2D1;
mutable RefPtr<ID2D1GradientStopCollection> mStopCollection;
RefPtr<ID3D11Device> mDevice;
};
}

View File

@ -185,7 +185,15 @@ gfxGradientCache::GetGradientStops(const DrawTarget *aDT, nsTArray<GradientStop>
}
GradientCacheData* cached =
gGradientCache->Lookup(aStops, aExtend, aDT->GetBackendType());
return cached ? cached->mStops : nullptr;
if (cached && cached->mStops) {
if (!cached->mStops->IsValid()) {
gGradientCache->NotifyExpired(cached);
} else {
return cached->mStops;
}
}
return nullptr;
}
GradientStops *

View File

@ -673,6 +673,8 @@ protected:
// Hardware vsync source. Only valid on parent process
nsRefPtr<mozilla::gfx::VsyncSource> mVsyncSource;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
private:
/**
* Start up Thebes.
@ -688,7 +690,6 @@ private:
virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
nsRefPtr<gfxASurface> mScreenReferenceSurface;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
nsTArray<uint32_t> mCJKPrefLangs;
nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
nsCOMPtr<nsIObserver> mFontPrefsObserver;

View File

@ -386,6 +386,7 @@ gfxWindowsPlatform::UpdateRenderMode()
/* Pick the default render mode for
* desktop.
*/
bool didReset = false;
if (DidRenderingDeviceReset()) {
mD3D11DeviceInitialized = false;
mD3D11Device = nullptr;
@ -395,6 +396,8 @@ gfxWindowsPlatform::UpdateRenderMode()
imgLoader::Singleton()->ClearCache(true);
imgLoader::Singleton()->ClearCache(false);
Factory::SetDirect3D11Device(nullptr);
didReset = true;
}
mRenderMode = RENDER_GDI;
@ -512,6 +515,10 @@ gfxWindowsPlatform::UpdateRenderMode()
contentMask |= BackendTypeBit(BackendType::SKIA);
InitBackendPrefs(canvasMask, defaultBackend,
contentMask, defaultBackend);
if (didReset) {
mScreenReferenceDrawTarget = CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8);
}
}
#ifdef CAIRO_HAS_D2D_SURFACE