зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1007821. Use image surfaces for transparent content on D3D9. r=bas
This gives us a 6% improvement on CART on WinXP.
This commit is contained in:
Родитель
e61f896f90
Коммит
83d2297b91
|
@ -402,6 +402,74 @@ OpaqueRenderer::End()
|
|||
mD3D9ThebesSurface = nullptr;
|
||||
|
||||
}
|
||||
class TransparentRenderer {
|
||||
public:
|
||||
TransparentRenderer(const nsIntRegion& aUpdateRegion) :
|
||||
mUpdateRegion(aUpdateRegion) {}
|
||||
~TransparentRenderer() { End(); }
|
||||
already_AddRefed<gfxImageSurface> Begin(LayerD3D9* aLayer);
|
||||
void End();
|
||||
IDirect3DTexture9* GetTexture() { return mTmpTexture; }
|
||||
|
||||
private:
|
||||
const nsIntRegion& mUpdateRegion;
|
||||
nsRefPtr<IDirect3DTexture9> mTmpTexture;
|
||||
nsRefPtr<gfxImageSurface> mD3D9ThebesSurface;
|
||||
};
|
||||
|
||||
already_AddRefed<gfxImageSurface>
|
||||
TransparentRenderer::Begin(LayerD3D9* aLayer)
|
||||
{
|
||||
nsIntRect bounds = mUpdateRegion.GetBounds();
|
||||
|
||||
HRESULT hr = aLayer->device()->
|
||||
CreateTexture(bounds.width, bounds.height, 1, 0, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(mTmpTexture), nullptr);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
aLayer->ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT r;
|
||||
hr = mTmpTexture->LockRect(0, &r, nullptr, 0);
|
||||
if (FAILED(hr)) {
|
||||
// Uh-oh, bail.
|
||||
NS_WARNING("Failed to lock the texture");
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<gfxImageSurface> result =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
bounds.Size(),
|
||||
r.Pitch,
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
if (!result || result->CairoStatus()) {
|
||||
NS_WARNING("Failed to d3d9 cairo surface.");
|
||||
return nullptr;
|
||||
}
|
||||
mD3D9ThebesSurface = result;
|
||||
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void
|
||||
TransparentRenderer::End()
|
||||
{
|
||||
// gfxImageSurface returned from ::Begin() should be released before the
|
||||
// texture is used. This will assert that this is the case
|
||||
#if 1
|
||||
if (mD3D9ThebesSurface) {
|
||||
mD3D9ThebesSurface->AddRef();
|
||||
nsrefcnt c = mD3D9ThebesSurface->Release();
|
||||
if (c != 1)
|
||||
NS_RUNTIMEABORT("Reference mD3D9ThebesSurface must be released by caller of Begin() before calling End()");
|
||||
}
|
||||
#endif
|
||||
mD3D9ThebesSurface = nullptr;
|
||||
if (mTmpTexture)
|
||||
mTmpTexture->UnlockRect(0);
|
||||
}
|
||||
|
||||
static void
|
||||
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
||||
|
@ -418,13 +486,13 @@ void
|
|||
ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
const nsTArray<ReadbackProcessor::Update>& aReadbackUpdates)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
OpaqueRenderer opaqueRenderer(aRegion);
|
||||
TransparentRenderer transparentRenderer(aRegion);
|
||||
OpaqueRenderer opaqueRendererOnWhite(aRegion);
|
||||
|
||||
switch (aMode)
|
||||
|
@ -434,25 +502,11 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
|||
break;
|
||||
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
|
||||
hr = device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
0, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), nullptr);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
ReportFailure(NS_LITERAL_CSTRING("Failed to create temporary texture in system memory."), hr);
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX - We may consider retaining a SYSTEMMEM texture texture the size
|
||||
// of our DEFAULT texture and then use UpdateTexture and add dirty rects
|
||||
// to update in a single call.
|
||||
nsRefPtr<gfxWindowsSurface> dest = new gfxWindowsSurface(
|
||||
gfxIntSize(bounds.width, bounds.height), gfxImageFormat::ARGB32);
|
||||
destinationSurface = transparentRenderer.Begin(this);
|
||||
// If the contents of this layer don't require component alpha in the
|
||||
// end of rendering, it's safe to enable Cleartype since all the Cleartype
|
||||
// glyphs must be over (or under) opaque pixels.
|
||||
dest->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
|
||||
destinationSurface = dest.forget();
|
||||
destinationSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -523,36 +577,13 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
|||
destTextures.AppendElement(mTexture);
|
||||
break;
|
||||
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA: {
|
||||
LockTextureRectD3D9 textureLock(tmpTexture);
|
||||
if (!textureLock.HasLock()) {
|
||||
NS_WARNING("Failed to lock ThebesLayer tmpTexture texture.");
|
||||
return;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT r = textureLock.GetLockRect();
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
bounds.Size(),
|
||||
r.Pitch,
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
if (destinationSurface) {
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
|
||||
context->SetSource(destinationSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
// Must release reference to dest surface before ending drawing
|
||||
case SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA:
|
||||
// Must release reference to dest surface before ending drawing
|
||||
destinationSurface = nullptr;
|
||||
imgSurface = nullptr;
|
||||
|
||||
srcTextures.AppendElement(tmpTexture);
|
||||
transparentRenderer.End();
|
||||
srcTextures.AppendElement(transparentRenderer.GetTexture());
|
||||
destTextures.AppendElement(mTexture);
|
||||
break;
|
||||
}
|
||||
|
||||
case SurfaceMode::SURFACE_COMPONENT_ALPHA: {
|
||||
// Must release reference to dest surface before ending drawing
|
||||
|
|
Загрузка…
Ссылка в новой задаче