зеркало из https://github.com/mozilla/pjs.git
Bug 586683 - Part 3 - Add resolution handling to ThebesLayerD3D9. r=Bas a=blocking2.0
This commit is contained in:
Родитель
5f23a55e32
Коммит
9c3c36cf34
|
@ -76,7 +76,8 @@ ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
|
|||
void
|
||||
ThebesLayerD3D9::CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
|
||||
IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion)
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion,
|
||||
float aXRes, float aYRes)
|
||||
{
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface, dstSurface;
|
||||
aSrc->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
|
||||
|
@ -90,16 +91,17 @@ ThebesLayerD3D9::CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffse
|
|||
RECT oldRect, newRect;
|
||||
|
||||
// Calculate the retained rectangle's position on the old and the new
|
||||
// surface.
|
||||
oldRect.left = r->x - aSrcOffset.x;
|
||||
oldRect.top = r->y - aSrcOffset.y;
|
||||
oldRect.right = oldRect.left + r->width;
|
||||
oldRect.bottom = oldRect.top + r->height;
|
||||
// surface. We need to scale these rectangles since the visible
|
||||
// region is in unscaled units, and the texture size has been scaled.
|
||||
oldRect.left = UINT(floor((r->x - aSrcOffset.x) * aXRes));
|
||||
oldRect.top = UINT(floor((r->y - aSrcOffset.y) * aYRes));
|
||||
oldRect.right = oldRect.left + UINT(ceil(r->width * aXRes));
|
||||
oldRect.bottom = oldRect.top + UINT(ceil(r->height * aYRes));
|
||||
|
||||
newRect.left = r->x - aDestOffset.x;
|
||||
newRect.top = r->y - aDestOffset.y;
|
||||
newRect.right = newRect.left + r->width;
|
||||
newRect.bottom = newRect.top + r->height;
|
||||
newRect.left = UINT(floor((r->x - aDestOffset.x) * aXRes));
|
||||
newRect.top = UINT(floor((r->y - aDestOffset.y) * aYRes));
|
||||
newRect.right = newRect.left + UINT(ceil(r->width * aXRes));
|
||||
newRect.bottom = newRect.top + UINT(ceil(r->height * aYRes));
|
||||
|
||||
// Copy data from our old texture to the new one
|
||||
HRESULT hr = device()->
|
||||
|
@ -125,6 +127,15 @@ ThebesLayerD3D9::UpdateTextures(SurfaceMode aMode)
|
|||
{
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
float xres, yres;
|
||||
GetDesiredResolutions(xres, yres);
|
||||
|
||||
// If our resolution changed, we need new sized textures, delete the old ones.
|
||||
if (ResolutionChanged(xres, yres)) {
|
||||
mTexture = nsnull;
|
||||
mTextureOnWhite = nsnull;
|
||||
}
|
||||
|
||||
if (HaveTextures(aMode)) {
|
||||
if (mTextureRect != visibleRect) {
|
||||
nsRefPtr<IDirect3DTexture9> oldTexture = mTexture;
|
||||
|
@ -147,10 +158,10 @@ ThebesLayerD3D9::UpdateTextures(SurfaceMode aMode)
|
|||
mValidRegion.SetEmpty();
|
||||
} else {
|
||||
CopyRegion(oldTexture, mTextureRect.TopLeft(), mTexture, visibleRect.TopLeft(),
|
||||
retainRegion, &mValidRegion);
|
||||
retainRegion, &mValidRegion, xres, yres);
|
||||
if (aMode == SURFACE_COMPONENT_ALPHA) {
|
||||
CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(), mTextureOnWhite, visibleRect.TopLeft(),
|
||||
retainRegion, &mValidRegion);
|
||||
retainRegion, &mValidRegion, xres, yres);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +337,7 @@ public:
|
|||
OpaqueRenderer(const nsIntRegion& aUpdateRegion) :
|
||||
mUpdateRegion(aUpdateRegion), mDC(NULL) {}
|
||||
~OpaqueRenderer() { End(); }
|
||||
already_AddRefed<gfxWindowsSurface> Begin(LayerD3D9* aLayer);
|
||||
already_AddRefed<gfxWindowsSurface> Begin(LayerD3D9* aLayer, float aXRes, float aYRes);
|
||||
void End();
|
||||
IDirect3DTexture9* GetTexture() { return mTmpTexture; }
|
||||
|
||||
|
@ -338,12 +349,15 @@ private:
|
|||
};
|
||||
|
||||
already_AddRefed<gfxWindowsSurface>
|
||||
OpaqueRenderer::Begin(LayerD3D9* aLayer)
|
||||
OpaqueRenderer::Begin(LayerD3D9* aLayer, float aXRes, float aYRes)
|
||||
{
|
||||
nsIntRect bounds = mUpdateRegion.GetBounds();
|
||||
gfxIntSize scaledSize;
|
||||
scaledSize.width = PRInt32(ceil(bounds.width * aXRes));
|
||||
scaledSize.height = PRInt32(ceil(bounds.height * aYRes));
|
||||
|
||||
HRESULT hr = aLayer->device()->
|
||||
CreateTexture(bounds.width, bounds.height, 1, 0, D3DFMT_X8R8G8B8,
|
||||
CreateTexture(scaledSize.width, scaledSize.height, 1, 0, D3DFMT_X8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(mTmpTexture), NULL);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
|
@ -381,9 +395,11 @@ OpaqueRenderer::End()
|
|||
|
||||
static void
|
||||
FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
||||
const nsIntPoint& aOffset, const gfxRGBA& aColor)
|
||||
const nsIntPoint& aOffset, const gfxRGBA& aColor,
|
||||
float aXRes, float aYRes)
|
||||
{
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
||||
ctx->Scale(aXRes, aYRes);
|
||||
ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
|
||||
gfxUtils::ClipToRegion(ctx, aRegion);
|
||||
ctx->SetColor(aColor);
|
||||
|
@ -391,13 +407,18 @@ FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
|||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
||||
ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
float xres, yres;
|
||||
GetDesiredResolutions(xres, yres);
|
||||
|
||||
nsRefPtr<gfxASurface> destinationSurface;
|
||||
nsIntRect bounds = aRegion.GetBounds();
|
||||
gfxIntSize scaledSize;
|
||||
scaledSize.width = PRInt32(ceil(bounds.width * xres));
|
||||
scaledSize.height = PRInt32(ceil(bounds.height * yres));
|
||||
nsRefPtr<IDirect3DTexture9> tmpTexture;
|
||||
OpaqueRenderer opaqueRenderer(aRegion);
|
||||
OpaqueRenderer opaqueRendererOnWhite(aRegion);
|
||||
|
@ -405,11 +426,11 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
switch (aMode)
|
||||
{
|
||||
case SURFACE_OPAQUE:
|
||||
destinationSurface = opaqueRenderer.Begin(this);
|
||||
destinationSurface = opaqueRenderer.Begin(this, xres, yres);
|
||||
break;
|
||||
|
||||
case SURFACE_SINGLE_CHANNEL_ALPHA: {
|
||||
hr = device()->CreateTexture(bounds.width, bounds.height, 1,
|
||||
hr = device()->CreateTexture(scaledSize.width, scaledSize.height, 1,
|
||||
0, D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
|
||||
|
||||
|
@ -432,11 +453,11 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
}
|
||||
|
||||
case SURFACE_COMPONENT_ALPHA: {
|
||||
nsRefPtr<gfxWindowsSurface> onBlack = opaqueRenderer.Begin(this);
|
||||
nsRefPtr<gfxWindowsSurface> onWhite = opaqueRendererOnWhite.Begin(this);
|
||||
nsRefPtr<gfxWindowsSurface> onBlack = opaqueRenderer.Begin(this, xres, yres);
|
||||
nsRefPtr<gfxWindowsSurface> onWhite = opaqueRendererOnWhite.Begin(this, xres, yres);
|
||||
if (onBlack && onWhite) {
|
||||
FillSurface(onBlack, aRegion, bounds.TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0));
|
||||
FillSurface(onWhite, aRegion, bounds.TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0));
|
||||
FillSurface(onBlack, aRegion, bounds.TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0), xres, yres);
|
||||
FillSurface(onWhite, aRegion, bounds.TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0), xres, yres);
|
||||
gfxASurface* surfaces[2] = { onBlack.get(), onWhite.get() };
|
||||
destinationSurface = new gfxTeeSurface(surfaces, NS_ARRAY_LENGTH(surfaces));
|
||||
// Using this surface as a source will likely go horribly wrong, since
|
||||
|
@ -452,7 +473,10 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
return;
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(destinationSurface);
|
||||
// Draw content scaled at our current resolution.
|
||||
context->Scale(xres, yres);
|
||||
context->Translate(gfxPoint(-bounds.x, -bounds.y));
|
||||
aRegion.ExtendForScaling(xres, yres);
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
|
@ -472,8 +496,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface((unsigned char *)r.pBits,
|
||||
gfxIntSize(bounds.width,
|
||||
bounds.height),
|
||||
scaledSize,
|
||||
r.Pitch,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
|
@ -505,6 +528,8 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
}
|
||||
NS_ASSERTION(srcTextures.Length() == destTextures.Length(), "Mismatched lengths");
|
||||
|
||||
// Copy to the texture. We need to scale these rectangles since the visible
|
||||
// region is in unscaled units, and the texture sizes have been scaled.
|
||||
for (PRUint32 i = 0; i < srcTextures.Length(); ++i) {
|
||||
nsRefPtr<IDirect3DSurface9> srcSurface;
|
||||
nsRefPtr<IDirect3DSurface9> dstSurface;
|
||||
|
@ -516,13 +541,13 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
RECT rect;
|
||||
rect.left = iterRect->x - bounds.x;
|
||||
rect.top = iterRect->y - bounds.y;
|
||||
rect.right = rect.left + iterRect->width;
|
||||
rect.bottom = rect.top + iterRect->height;
|
||||
rect.left = UINT(floor((iterRect->x - bounds.x) * xres));
|
||||
rect.top = UINT(floor((iterRect->y - bounds.y) * yres));
|
||||
rect.right = rect.left + UINT(ceil(iterRect->width * xres));
|
||||
rect.bottom = rect.top + UINT(ceil(iterRect->height * yres));
|
||||
POINT point;
|
||||
point.x = iterRect->x - visibleRect.x;
|
||||
point.y = iterRect->y - visibleRect.y;
|
||||
point.x = UINT(floor((iterRect->x - visibleRect.x) * xres));
|
||||
point.y = UINT(floor((iterRect->y - visibleRect.y) * yres));
|
||||
device()->UpdateSurface(srcSurface, &rect, dstSurface, &point);
|
||||
}
|
||||
}
|
||||
|
@ -536,19 +561,53 @@ ThebesLayerD3D9::CreateNewTextures(const gfxIntSize &aSize,
|
|||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale the requested size (in unscaled units) to the actual
|
||||
// texture size we require.
|
||||
gfxIntSize scaledSize;
|
||||
float xres, yres;
|
||||
GetDesiredResolutions(xres, yres);
|
||||
scaledSize.width = PRInt32(ceil(aSize.width * xres));
|
||||
scaledSize.height = PRInt32(ceil(aSize.height * yres));
|
||||
|
||||
mTexture = nsnull;
|
||||
mTextureOnWhite = nsnull;
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
device()->CreateTexture(scaledSize.width, scaledSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
aMode != SURFACE_SINGLE_CHANNEL_ALPHA ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
|
||||
if (aMode == SURFACE_COMPONENT_ALPHA) {
|
||||
device()->CreateTexture(aSize.width, aSize.height, 1,
|
||||
device()->CreateTexture(scaledSize.width, scaledSize.height, 1,
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_X8R8G8B8,
|
||||
D3DPOOL_DEFAULT, getter_AddRefs(mTextureOnWhite), NULL);
|
||||
}
|
||||
|
||||
mXResolution = xres;
|
||||
mYResolution = yres;
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::GetDesiredResolutions(float& aXRes, float& aYRes)
|
||||
{
|
||||
const gfx3DMatrix& transform = GetLayer()->GetEffectiveTransform();
|
||||
gfxMatrix transform2d;
|
||||
if (transform.Is2D(&transform2d)) {
|
||||
//Scale factors are normalized to a power of 2 to reduce the number of resolution changes
|
||||
gfxSize scale = transform2d.ScaleFactors(PR_TRUE);
|
||||
aXRes = gfxUtils::ClampToScaleFactor(scale.width);
|
||||
aYRes = gfxUtils::ClampToScaleFactor(scale.height);
|
||||
} else {
|
||||
aXRes = 1.0;
|
||||
aYRes = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ThebesLayerD3D9::ResolutionChanged(float aXRes, float aYRes)
|
||||
{
|
||||
return aXRes != mXResolution ||
|
||||
aYRes != mYResolution;
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
|
|
|
@ -96,14 +96,25 @@ private:
|
|||
void RenderVisibleRegion();
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(const nsIntRegion &aRegion, SurfaceMode aMode);
|
||||
void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
|
||||
|
||||
void CopyRegion(IDirect3DTexture9* aSrc, const nsIntPoint &aSrcOffset,
|
||||
IDirect3DTexture9* aDest, const nsIntPoint &aDestOffset,
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion);
|
||||
const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion,
|
||||
float aXRes, float aYRes);
|
||||
|
||||
/**
|
||||
* Calculate the desired texture resolution based on
|
||||
* the layer managers resolution, and the current
|
||||
* transforms scale factor.
|
||||
*/
|
||||
void GetDesiredResolutions(float& aXRes, float& aYRes);
|
||||
|
||||
/* Check if the current texture resolution matches */
|
||||
bool ResolutionChanged(float aXRes, float aYRes);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
|
|
Загрузка…
Ссылка в новой задаче