зеркало из https://github.com/mozilla/pjs.git
Bug 577462: Use GetDC where possible for ThebesLayerD3D9 textures. r=jrmuizel
This commit is contained in:
Родитель
4b895ef379
Коммит
1c1caaf043
|
@ -38,9 +38,32 @@
|
||||||
#include "ThebesLayerD3D9.h"
|
#include "ThebesLayerD3D9.h"
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
|
|
||||||
|
#include "gfxWindowsPlatform.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
// Returns true if it's OK to save the contents of aLayer in an
|
||||||
|
// opaque surface (a surface without an alpha channel).
|
||||||
|
// If we can use a surface without an alpha channel, we should, because
|
||||||
|
// it will often make painting of antialiased text faster and higher
|
||||||
|
// quality.
|
||||||
|
static PRBool
|
||||||
|
UseOpaqueSurface(Layer* aLayer)
|
||||||
|
{
|
||||||
|
// If the visible content in the layer is opaque, there is no need
|
||||||
|
// for an alpha channel.
|
||||||
|
if (aLayer->IsOpaqueContent())
|
||||||
|
return PR_TRUE;
|
||||||
|
// Also, if this layer is the bottommost layer in a container which
|
||||||
|
// doesn't need an alpha channel, we can use an opaque surface for this
|
||||||
|
// layer too. Any transparent areas must be covered by something else
|
||||||
|
// in the container.
|
||||||
|
ContainerLayer* parent = aLayer->GetParent();
|
||||||
|
return parent && parent->GetFirstChild() == aLayer &&
|
||||||
|
UseOpaqueSurface(parent);
|
||||||
|
}
|
||||||
|
|
||||||
ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
|
ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
|
||||||
: ThebesLayer(aManager, NULL)
|
: ThebesLayer(aManager, NULL)
|
||||||
, LayerD3D9(aManager)
|
, LayerD3D9(aManager)
|
||||||
|
@ -67,16 +90,35 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||||
if (aRegion.IsEqual(mVisibleRegion)) {
|
if (aRegion.IsEqual(mVisibleRegion)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nsIntRegion oldVisibleRegion = mVisibleRegion;
|
|
||||||
nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
|
|
||||||
|
|
||||||
|
nsIntRegion oldVisibleRegion = mVisibleRegion;
|
||||||
ThebesLayer::SetVisibleRegion(aRegion);
|
ThebesLayer::SetVisibleRegion(aRegion);
|
||||||
|
|
||||||
|
if (!mTexture) {
|
||||||
|
// If we don't need to retain content initialize lazily. This is good also
|
||||||
|
// because we might get mIsOpaqueSurface set later than the first call to
|
||||||
|
// SetVisibleRegion.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||||
|
|
||||||
|
D3DSURFACE_DESC desc;
|
||||||
|
mTexture->GetLevelDesc(0, &desc);
|
||||||
|
|
||||||
|
if (fmt != desc.Format) {
|
||||||
|
// The new format isn't compatible with the old texture, toss out the old
|
||||||
|
// texture.
|
||||||
|
mTexture = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
|
||||||
|
|
||||||
nsIntRect oldBounds = oldVisibleRegion.GetBounds();
|
nsIntRect oldBounds = oldVisibleRegion.GetBounds();
|
||||||
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
||||||
|
|
||||||
device()->CreateTexture(newBounds.width, newBounds.height, 1,
|
device()->CreateTexture(newBounds.width, newBounds.height, 1,
|
||||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
D3DUSAGE_RENDERTARGET, fmt,
|
||||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||||
|
|
||||||
// Old visible region will become the region that is covered by both the
|
// Old visible region will become the region that is covered by both the
|
||||||
|
@ -149,11 +191,26 @@ ThebesLayerD3D9::RenderLayer()
|
||||||
if (mVisibleRegion.IsEmpty()) {
|
if (mVisibleRegion.IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||||
|
|
||||||
|
D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8;
|
||||||
|
if (mTexture) {
|
||||||
|
D3DSURFACE_DESC desc;
|
||||||
|
mTexture->GetLevelDesc(0, &desc);
|
||||||
|
|
||||||
|
if (fmt != desc.Format) {
|
||||||
|
// The new format isn't compatible with the old texture, toss out the old
|
||||||
|
// texture.
|
||||||
|
mTexture = nsnull;
|
||||||
|
mValidRegion.SetEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!mTexture) {
|
if (!mTexture) {
|
||||||
device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
device()->CreateTexture(visibleRect.width, visibleRect.height, 1,
|
||||||
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
|
D3DUSAGE_RENDERTARGET, fmt,
|
||||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||||
mValidRegion.SetEmpty();
|
mValidRegion.SetEmpty();
|
||||||
}
|
}
|
||||||
|
@ -163,48 +220,72 @@ ThebesLayerD3D9::RenderLayer()
|
||||||
region.Sub(mVisibleRegion, mValidRegion);
|
region.Sub(mVisibleRegion, mValidRegion);
|
||||||
nsIntRect bounds = region.GetBounds();
|
nsIntRect bounds = region.GetBounds();
|
||||||
|
|
||||||
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;;
|
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;
|
||||||
nsRefPtr<gfxASurface> destinationSurface;
|
nsRefPtr<gfxASurface> destinationSurface;
|
||||||
nsRefPtr<gfxContext> context;
|
nsRefPtr<gfxContext> context;
|
||||||
|
|
||||||
// XXX - Should optimize here to use IDirect3DSurface9::GetDC() for GDI
|
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||||
// rendering since we're always on windows. We may consider retaining a
|
device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||||
// SYSTEMMEM texture texture the size of our DEFAULT texture and then use
|
0, fmt,
|
||||||
// UpdateTexture and add dirty rects to update in a single call.
|
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||||
destinationSurface =
|
|
||||||
gfxPlatform::GetPlatform()->
|
nsRefPtr<IDirect3DSurface9> surf;
|
||||||
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
HDC dc;
|
||||||
bounds.height),
|
if (UseOpaqueSurface(this)) {
|
||||||
imageFormat);
|
hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf));
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
// Uh-oh, bail.
|
||||||
|
NS_WARNING("Failed to get texture surface level.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = surf->GetDC(&dc);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
NS_WARNING("Failed to get device context for texture surface.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinationSurface = new gfxWindowsSurface(dc);
|
||||||
|
} else {
|
||||||
|
// 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.
|
||||||
|
destinationSurface =
|
||||||
|
gfxPlatform::GetPlatform()->
|
||||||
|
CreateOffscreenSurface(gfxIntSize(bounds.width,
|
||||||
|
bounds.height),
|
||||||
|
imageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
context = new gfxContext(destinationSurface);
|
context = new gfxContext(destinationSurface);
|
||||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||||
cbInfo.Callback(this, context, region, nsIntRegion(), cbInfo.CallbackData);
|
cbInfo.Callback(this, context, region, nsIntRegion(), cbInfo.CallbackData);
|
||||||
|
|
||||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
if (UseOpaqueSurface(this)) {
|
||||||
device()->CreateTexture(bounds.width, bounds.height, 1,
|
surf->ReleaseDC(dc);
|
||||||
0, D3DFMT_A8R8G8B8,
|
} else {
|
||||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
D3DLOCKED_RECT r;
|
||||||
|
tmpTexture->LockRect(0, &r, NULL, 0);
|
||||||
|
|
||||||
D3DLOCKED_RECT r;
|
nsRefPtr<gfxImageSurface> imgSurface =
|
||||||
tmpTexture->LockRect(0, &r, NULL, 0);
|
new gfxImageSurface((unsigned char *)r.pBits,
|
||||||
|
gfxIntSize(bounds.width,
|
||||||
|
bounds.height),
|
||||||
|
r.Pitch,
|
||||||
|
imageFormat);
|
||||||
|
|
||||||
nsRefPtr<gfxImageSurface> imgSurface =
|
context = new gfxContext(imgSurface);
|
||||||
new gfxImageSurface((unsigned char *)r.pBits,
|
context->SetSource(destinationSurface);
|
||||||
gfxIntSize(bounds.width,
|
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||||
bounds.height),
|
context->Paint();
|
||||||
r.Pitch,
|
|
||||||
imageFormat);
|
|
||||||
|
|
||||||
context = new gfxContext(imgSurface);
|
imgSurface = NULL;
|
||||||
context->SetSource(destinationSurface);
|
|
||||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
|
||||||
context->Paint();
|
|
||||||
|
|
||||||
imgSurface = NULL;
|
tmpTexture->UnlockRect(0);
|
||||||
|
}
|
||||||
tmpTexture->UnlockRect(0);
|
|
||||||
|
|
||||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче