зеркало из https://github.com/mozilla/pjs.git
Bug 635373. If we need to resample a ThebesLayer texture, make sure we make all the pixels of the texture valid in case they get sampled. r=bas
This commit is contained in:
Родитель
722852cd8b
Коммит
95f536c14a
|
@ -54,6 +54,7 @@ namespace layers {
|
|||
ThebesLayerD3D10::ThebesLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ThebesLayer(aManager, NULL)
|
||||
, LayerD3D10(aManager)
|
||||
, mCurrentSurfaceMode(SURFACE_OPAQUE)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
@ -119,20 +120,24 @@ ThebesLayerD3D10::RenderLayer()
|
|||
return;
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
SetEffectTransformAndOpacity();
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
if (mTextureOnWhite) {
|
||||
switch (mCurrentSurfaceMode) {
|
||||
case SURFACE_COMPONENT_ALPHA:
|
||||
technique = effect()->GetTechniqueByName("RenderComponentAlphaLayer");
|
||||
} else if (CanUseOpaqueSurface()) {
|
||||
break;
|
||||
case SURFACE_OPAQUE:
|
||||
technique = effect()->GetTechniqueByName("RenderRGBLayerPremul");
|
||||
} else {
|
||||
break;
|
||||
case SURFACE_SINGLE_CHANNEL_ALPHA:
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown mode");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
nsIntRegionRectIterator iter(mVisibleRegion);
|
||||
|
||||
const nsIntRect *iterRect;
|
||||
|
@ -154,10 +159,10 @@ ThebesLayerD3D10::RenderLayer()
|
|||
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)(iterRect->x - visibleRect.x) / (float)visibleRect.width,
|
||||
(float)(iterRect->y - visibleRect.y) / (float)visibleRect.height,
|
||||
(float)iterRect->width / (float)visibleRect.width,
|
||||
(float)iterRect->height / (float)visibleRect.height)
|
||||
(float)(iterRect->x - mTextureRect.x) / (float)mTextureRect.width,
|
||||
(float)(iterRect->y - mTextureRect.y) / (float)mTextureRect.height,
|
||||
(float)iterRect->width / (float)mTextureRect.width,
|
||||
(float)iterRect->height / (float)mTextureRect.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
|
@ -176,11 +181,34 @@ ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
|||
return;
|
||||
}
|
||||
|
||||
nsIntRect newTextureRect = mVisibleRegion.GetBounds();
|
||||
|
||||
SurfaceMode mode = GetSurfaceMode();
|
||||
if (mode == SURFACE_COMPONENT_ALPHA &&
|
||||
(!mParent || !mParent->SupportsComponentAlphaChildren())) {
|
||||
mode = SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
// If we have a transform that requires resampling of our texture, then
|
||||
// we need to make sure we don't sample pixels that haven't been drawn.
|
||||
// We clamp sample coordinates to the texture rect, but when the visible region
|
||||
// doesn't fill the entire texture rect we need to make sure we draw all the
|
||||
// pixels in the texture rect anyway in case they get sampled.
|
||||
nsIntRegion neededRegion = mVisibleRegion;
|
||||
if (neededRegion.GetBounds() != newTextureRect ||
|
||||
neededRegion.GetNumRects() > 1) {
|
||||
gfxMatrix transform2d;
|
||||
if (!GetEffectiveTransform().Is2D(&transform2d) ||
|
||||
transform2d.HasNonIntegerTranslation()) {
|
||||
neededRegion = newTextureRect;
|
||||
if (mode == SURFACE_OPAQUE) {
|
||||
// We're going to paint outside the visible region, but layout hasn't
|
||||
// promised that it will paint opaquely there, so we'll have to
|
||||
// treat this layer as transparent.
|
||||
mode = SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
mCurrentSurfaceMode = mode;
|
||||
|
||||
VerifyContentType(mode);
|
||||
|
||||
|
@ -199,27 +227,22 @@ ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
|||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
if (mTexture) {
|
||||
if (!mTextureRegion.IsEqual(mVisibleRegion)) {
|
||||
if (mTextureRect != newTextureRect) {
|
||||
nsRefPtr<ID3D10Texture2D> oldTexture = mTexture;
|
||||
mTexture = nsnull;
|
||||
nsRefPtr<ID3D10Texture2D> oldTextureOnWhite = mTextureOnWhite;
|
||||
mTextureOnWhite = nsnull;
|
||||
|
||||
nsIntRegion retainRegion = mTextureRegion;
|
||||
nsIntRect oldBounds = mTextureRegion.GetBounds();
|
||||
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
||||
|
||||
CreateNewTextures(gfxIntSize(newBounds.width, newBounds.height), mode);
|
||||
|
||||
nsIntRegion retainRegion = mTextureRect;
|
||||
// Old visible region will become the region that is covered by both the
|
||||
// old and the new visible region.
|
||||
retainRegion.And(retainRegion, mVisibleRegion);
|
||||
// No point in retaining parts which were not valid.
|
||||
retainRegion.And(retainRegion, mValidRegion);
|
||||
|
||||
CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode);
|
||||
|
||||
nsIntRect largeRect = retainRegion.GetLargestRectangle();
|
||||
|
||||
// If we had no hardware texture before, have no retained area larger than
|
||||
|
@ -234,47 +257,41 @@ ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
|||
ResolutionChanged(xres, yres)) {
|
||||
mValidRegion.SetEmpty();
|
||||
} else {
|
||||
CopyRegion(oldTexture, oldBounds.TopLeft(),
|
||||
mTexture, newBounds.TopLeft(),
|
||||
CopyRegion(oldTexture, mTextureRect.TopLeft(),
|
||||
mTexture, newTextureRect.TopLeft(),
|
||||
retainRegion, &mValidRegion,
|
||||
xres, yres);
|
||||
if (oldTextureOnWhite) {
|
||||
CopyRegion(oldTextureOnWhite, oldBounds.TopLeft(),
|
||||
mTextureOnWhite, newBounds.TopLeft(),
|
||||
CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(),
|
||||
mTextureOnWhite, newTextureRect.TopLeft(),
|
||||
retainRegion, &mValidRegion,
|
||||
xres, yres);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mTextureRegion = mVisibleRegion;
|
||||
mTextureRect = newTextureRect;
|
||||
|
||||
if (!mTexture || (mode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite)) {
|
||||
CreateNewTextures(gfxIntSize(visibleRect.width, visibleRect.height), mode);
|
||||
CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode);
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
|
||||
if (!mValidRegion.IsEqual(mVisibleRegion)) {
|
||||
nsIntRegion drawRegion;
|
||||
drawRegion.Sub(neededRegion, mValidRegion);
|
||||
|
||||
if (!drawRegion.IsEmpty()) {
|
||||
LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
if (!cbInfo.Callback) {
|
||||
NS_ERROR("D3D10 should never need to update ThebesLayers in an empty transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
/* We use the bounds of the visible region because we draw the bounds of
|
||||
* this region when we draw this entire texture. We have to make sure that
|
||||
* the areas that aren't filled with content get their background drawn.
|
||||
* This is an issue for opaque surfaces, which otherwise won't get their
|
||||
* background painted.
|
||||
*/
|
||||
nsIntRegion region;
|
||||
region.Sub(mVisibleRegion, mValidRegion);
|
||||
|
||||
DrawRegion(region, mode);
|
||||
DrawRegion(drawRegion, mode);
|
||||
|
||||
if (readbackUpdates.Length() > 0) {
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
visibleRect.width, visibleRect.height,
|
||||
newTextureRect.width, newTextureRect.height,
|
||||
1, 1, 0, D3D10_USAGE_STAGING,
|
||||
D3D10_CPU_ACCESS_READ);
|
||||
|
||||
|
@ -285,11 +302,11 @@ ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
|||
for (int i = 0; i < readbackUpdates.Length(); i++) {
|
||||
mD3DManager->readbackManager()->PostTask(readbackTexture,
|
||||
&readbackUpdates[i],
|
||||
gfxPoint(visibleRect.x, visibleRect.y));
|
||||
gfxPoint(newTextureRect.x, newTextureRect.y));
|
||||
}
|
||||
}
|
||||
|
||||
mValidRegion = mVisibleRegion;
|
||||
mValidRegion = neededRegion;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,8 +75,11 @@ private:
|
|||
/* Shader resource view for our render-on-white texture */
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRViewOnWhite;
|
||||
|
||||
/* Visible region used when we drew the contents of the textures */
|
||||
nsIntRegion mTextureRegion;
|
||||
/* Area of layer currently stored in texture(s) */
|
||||
nsIntRect mTextureRect;
|
||||
|
||||
/* Last surface mode set in Validate() */
|
||||
SurfaceMode mCurrentSurfaceMode;
|
||||
|
||||
/* Checks if our D2D surface has the right content type */
|
||||
void VerifyContentType(SurfaceMode aMode);
|
||||
|
|
|
@ -208,11 +208,34 @@ ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
|
|||
return;
|
||||
}
|
||||
|
||||
nsIntRect newTextureRect = mVisibleRegion.GetBounds();
|
||||
|
||||
SurfaceMode mode = GetSurfaceMode();
|
||||
if (mode == SURFACE_COMPONENT_ALPHA &&
|
||||
(!mParent || !mParent->SupportsComponentAlphaChildren())) {
|
||||
mode = SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
// If we have a transform that requires resampling of our texture, then
|
||||
// we need to make sure we don't sample pixels that haven't been drawn.
|
||||
// We clamp sample coordinates to the texture rect, but when the visible region
|
||||
// doesn't fill the entire texture rect we need to make sure we draw all the
|
||||
// pixels in the texture rect anyway in case they get sampled.
|
||||
nsIntRegion neededRegion = mVisibleRegion;
|
||||
if (neededRegion.GetBounds() != newTextureRect ||
|
||||
neededRegion.GetNumRects() > 1) {
|
||||
gfxMatrix transform2d;
|
||||
if (!GetEffectiveTransform().Is2D(&transform2d) ||
|
||||
transform2d.HasNonIntegerTranslation()) {
|
||||
neededRegion = newTextureRect;
|
||||
if (mode == SURFACE_OPAQUE) {
|
||||
// We're going to paint outside the visible region, but layout hasn't
|
||||
// promised that it will paint opaquely there, so we'll have to
|
||||
// treat this layer as transparent.
|
||||
mode = SURFACE_SINGLE_CHANNEL_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerifyContentType(mode);
|
||||
UpdateTextures(mode);
|
||||
if (!HaveTextures(mode)) {
|
||||
|
@ -232,7 +255,7 @@ ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
|
|||
// Then the readback areas we need can be copied out of the temporary
|
||||
// destinationSurface in DrawRegion.
|
||||
nsIntRegion drawRegion;
|
||||
drawRegion.Sub(mVisibleRegion, mValidRegion);
|
||||
drawRegion.Sub(neededRegion, mValidRegion);
|
||||
drawRegion.Or(drawRegion, readbackRegion);
|
||||
// NS_ASSERTION(mVisibleRegion.Contains(region), "Bad readback region!");
|
||||
|
||||
|
@ -245,7 +268,7 @@ ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
|
|||
|
||||
DrawRegion(drawRegion, mode, readbackUpdates);
|
||||
|
||||
mValidRegion = mVisibleRegion;
|
||||
mValidRegion = neededRegion;
|
||||
}
|
||||
|
||||
SetShaderTransformAndOpacity();
|
||||
|
|
Загрузка…
Ссылка в новой задаче