Backed out changeset 0c1485b37ae9 (bug 1409871)

This commit is contained in:
Sebastian Hengst 2017-10-23 23:43:24 +02:00
Родитель 774b6c4844
Коммит b4aa3847a7
2 изменённых файлов: 123 добавлений и 154 удалений

Просмотреть файл

@ -278,128 +278,6 @@ RotatedBuffer::UpdateDestinationFrom(const RotatedBuffer& aSource,
}
}
static void
WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
{
if (*aRotationPoint < 0) {
*aRotationPoint += aSize;
} else if (*aRotationPoint >= aSize) {
*aRotationPoint -= aSize;
}
}
static IntRect
ComputeBufferRect(const IntRect& aRequestedRect)
{
IntRect rect(aRequestedRect);
// Set a minimum width to guarantee a minimum size of buffers we
// allocate (and work around problems on some platforms with smaller
// dimensions). 64 used to be the magic number needed to work around
// a rendering glitch on b2g (see bug 788411). Now that we don't support
// this device anymore we should be fine with 8 pixels as the minimum.
rect.SetWidth(std::max(aRequestedRect.Width(), 8));
return rect;
}
bool
RotatedBuffer::AdjustTo(const gfx::IntRect& aDestBufferRect,
const gfx::IntRect& aDrawBounds,
bool aCanHaveRotation,
bool aCanDrawRotated)
{
IntRect keepArea;
if (keepArea.IntersectRect(aDestBufferRect, mBufferRect)) {
// Set mBufferRotation so that the pixels currently in mDTBuffer
// will still be rendered in the right place when mBufferRect
// changes to aDestBufferRect.
IntPoint newRotation = mBufferRotation +
(aDestBufferRect.TopLeft() - mBufferRect.TopLeft());
WrapRotationAxis(&newRotation.x, mBufferRect.Width());
WrapRotationAxis(&newRotation.y, mBufferRect.Height());
NS_ASSERTION(gfx::IntRect(gfx::IntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
"newRotation out of bounds");
int32_t xBoundary = aDestBufferRect.XMost() - newRotation.x;
int32_t yBoundary = aDestBufferRect.YMost() - newRotation.y;
bool drawWrapsBuffer = (aDrawBounds.x < xBoundary && xBoundary < aDrawBounds.XMost()) ||
(aDrawBounds.y < yBoundary && yBoundary < aDrawBounds.YMost());
if ((drawWrapsBuffer && !aCanDrawRotated) ||
(newRotation != IntPoint(0,0) && !aCanHaveRotation)) {
// The stuff we need to redraw will wrap around an edge of the
// buffer (and the caller doesn't know how to support that), so
// move the pixels we can keep into a position that lets us
// redraw in just one quadrant.
RefPtr<gfx::DrawTarget> dtBuffer = GetDTBuffer();
RefPtr<gfx::DrawTarget> dtBufferOnWhite = GetDTBufferOnWhite();
if (mBufferRotation == IntPoint(0,0)) {
IntRect srcRect(IntPoint(0, 0), mBufferRect.Size());
IntPoint dest = mBufferRect.TopLeft() - aDestBufferRect.TopLeft();
MOZ_ASSERT(dtBuffer && dtBuffer->IsValid());
dtBuffer->CopyRect(srcRect, dest);
if (HaveBufferOnWhite()) {
MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid());
dtBufferOnWhite->CopyRect(srcRect, dest);
}
mDidSelfCopy = true;
mBufferRect = aDestBufferRect;
} else {
// With azure and a data surface perform an buffer unrotate
// (SelfCopy).
unsigned char* data;
IntSize size;
int32_t stride;
SurfaceFormat format;
if (dtBuffer->LockBits(&data, &size, &stride, &format)) {
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
dtBuffer->ReleaseBits(data);
if (HaveBufferOnWhite()) {
MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid());
dtBufferOnWhite->LockBits(&data, &size, &stride, &format);
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
dtBufferOnWhite->ReleaseBits(data);
}
// Buffer unrotate moves all the pixels
mDidSelfCopy = true;
mBufferRect = aDestBufferRect;
mBufferRotation = IntPoint(0, 0);
}
if (!mDidSelfCopy) {
// We couldn't unrotate the buffer, so we need to create a
// new one and start from scratch
return false;
}
}
} else {
mBufferRect = aDestBufferRect;
mBufferRotation = newRotation;
}
} else {
// No pixels are going to be kept. The whole visible region
// will be redrawn, so we don't need to copy anything, so we don't
// set destBuffer.
mBufferRect = aDestBufferRect;
mBufferRotation = IntPoint(0,0);
}
return true;
}
DrawTarget*
RotatedBuffer::BorrowDrawTargetForQuadrantUpdate(const IntRect& aBounds,
ContextSource aSource,
@ -652,6 +530,29 @@ RotatedContentBuffer::HaveBufferOnWhite() const
return mBufferProviderOnWhite || (mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
}
static void
WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
{
if (*aRotationPoint < 0) {
*aRotationPoint += aSize;
} else if (*aRotationPoint >= aSize) {
*aRotationPoint -= aSize;
}
}
static IntRect
ComputeBufferRect(const IntRect& aRequestedRect)
{
IntRect rect(aRequestedRect);
// Set a minimum width to guarantee a minimum size of buffers we
// allocate (and work around problems on some platforms with smaller
// dimensions). 64 used to be the magic number needed to work around
// a rendering glitch on b2g (see bug 788411). Now that we don't support
// this device anymore we should be fine with 8 pixels as the minimum.
rect.SetWidth(std::max(aRequestedRect.Width(), 8));
return rect;
}
void
RotatedContentBuffer::FlushBuffers()
{
@ -668,6 +569,12 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
uint32_t aFlags)
{
PaintState result;
// We need to disable rotation if we're going to be resampled when
// drawing, because we might sample across the rotation boundary.
// Also disable buffer rotation when using webrender.
bool canHaveRotation = gfxPlatform::BufferRotationEnabled() &&
!(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION)) &&
!(aLayer->Manager()->AsWebRenderLayerManager());
nsIntRegion validRegion = aLayer->GetValidRegion();
@ -796,14 +703,6 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
}
}
// We need to disable rotation if we're going to be resampled when
// drawing, because we might sample across the rotation boundary.
// Also disable buffer rotation when using webrender.
bool canHaveRotation = gfxPlatform::BufferRotationEnabled() &&
!(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION)) &&
!(aLayer->Manager()->AsWebRenderLayerManager());
bool canDrawRotated = aFlags & PAINT_CAN_DRAW_ROTATED;
IntRect drawBounds = result.mRegionToDraw.GetBounds();
RefPtr<DrawTarget> destDTBuffer;
RefPtr<DrawTarget> destDTBufferOnWhite;
@ -812,26 +711,106 @@ RotatedContentBuffer::BeginPaint(PaintedLayer* aLayer,
bufferFlags |= BUFFER_COMPONENT_ALPHA;
}
if (canReuseBuffer) {
if (!EnsureBuffer() ||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
if (!EnsureBuffer()) {
return result;
}
IntRect keepArea;
if (keepArea.IntersectRect(destBufferRect, mBufferRect)) {
// Set mBufferRotation so that the pixels currently in mDTBuffer
// will still be rendered in the right place when mBufferRect
// changes to destBufferRect.
IntPoint newRotation = mBufferRotation +
(destBufferRect.TopLeft() - mBufferRect.TopLeft());
WrapRotationAxis(&newRotation.x, mBufferRect.Width());
WrapRotationAxis(&newRotation.y, mBufferRect.Height());
NS_ASSERTION(gfx::IntRect(gfx::IntPoint(0,0), mBufferRect.Size()).Contains(newRotation),
"newRotation out of bounds");
int32_t xBoundary = destBufferRect.XMost() - newRotation.x;
int32_t yBoundary = destBufferRect.YMost() - newRotation.y;
bool drawWrapsBuffer = (drawBounds.x < xBoundary && xBoundary < drawBounds.XMost()) ||
(drawBounds.y < yBoundary && yBoundary < drawBounds.YMost());
if ((drawWrapsBuffer && !(aFlags & PAINT_CAN_DRAW_ROTATED)) ||
(newRotation != IntPoint(0,0) && !canHaveRotation)) {
// The stuff we need to redraw will wrap around an edge of the
// buffer (and the caller doesn't know how to support that), so
// move the pixels we can keep into a position that lets us
// redraw in just one quadrant.
if (mBufferRotation == IntPoint(0,0)) {
IntRect srcRect(IntPoint(0, 0), mBufferRect.Size());
IntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
MOZ_ASSERT(mDTBuffer && mDTBuffer->IsValid());
mDTBuffer->CopyRect(srcRect, dest);
if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
mDTBufferOnWhite->CopyRect(srcRect, dest);
}
mDidSelfCopy = true;
// Don't set destBuffer; we special-case self-copies, and
// just did the necessary work above.
mBufferRect = destBufferRect;
} else {
// With azure and a data surface perform an buffer unrotate
// (SelfCopy).
unsigned char* data;
IntSize size;
int32_t stride;
SurfaceFormat format;
if (!AdjustTo(destBufferRect,
drawBounds,
canHaveRotation,
canDrawRotated)) {
destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
CreateBuffer(result.mContentType, destBufferRect, bufferFlags,
&destDTBuffer, &destDTBufferOnWhite);
if (mDTBuffer->LockBits(&data, &size, &stride, &format)) {
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
mDTBuffer->ReleaseBits(data);
if (!destDTBuffer ||
(!destDTBufferOnWhite && (bufferFlags & BUFFER_COMPONENT_ALPHA))) {
if (Factory::ReasonableSurfaceSize(IntSize(destBufferRect.Width(), destBufferRect.Height()))) {
gfxCriticalNote << "Failed 1 buffer db=" << hexa(destDTBuffer.get()) << " dw=" << hexa(destDTBufferOnWhite.get()) << " for " << destBufferRect.x << ", " << destBufferRect.y << ", " << destBufferRect.Width() << ", " << destBufferRect.Height();
if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
if (!EnsureBufferOnWhite()) {
return result;
}
MOZ_ASSERT(mDTBufferOnWhite && mDTBufferOnWhite->IsValid());
mDTBufferOnWhite->LockBits(&data, &size, &stride, &format);
uint8_t bytesPerPixel = BytesPerPixel(format);
BufferUnrotate(data,
size.width * bytesPerPixel,
size.height, stride,
newRotation.x * bytesPerPixel, newRotation.y);
mDTBufferOnWhite->ReleaseBits(data);
}
// Buffer unrotate moves all the pixels, note that
// we self copied for SyncBackToFrontBuffer
mDidSelfCopy = true;
mBufferRect = destBufferRect;
mBufferRotation = IntPoint(0, 0);
}
if (!mDidSelfCopy) {
destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
CreateBuffer(result.mContentType, destBufferRect, bufferFlags,
&destDTBuffer, &destDTBufferOnWhite);
if (!destDTBuffer ||
(!destDTBufferOnWhite && (bufferFlags & BUFFER_COMPONENT_ALPHA))) {
if (Factory::ReasonableSurfaceSize(IntSize(destBufferRect.Width(), destBufferRect.Height()))) {
gfxCriticalNote << "Failed 1 buffer db=" << hexa(destDTBuffer.get()) << " dw=" << hexa(destDTBufferOnWhite.get()) << " for " << destBufferRect.x << ", " << destBufferRect.y << ", " << destBufferRect.Width() << ", " << destBufferRect.Height();
}
return result;
}
}
}
return result;
} else {
mBufferRect = destBufferRect;
mBufferRotation = newRotation;
}
} else {
// No pixels are going to be kept. The whole visible region
// will be redrawn, so we don't need to copy anything, so we don't
// set destBuffer.
mBufferRect = destBufferRect;
mBufferRotation = IntPoint(0,0);
}
} else {
// The buffer's not big enough, so allocate a new one

Просмотреть файл

@ -121,16 +121,6 @@ public:
void UpdateDestinationFrom(const RotatedBuffer& aSource,
const nsIntRegion& aUpdateRegion);
/**
* Adjusts the buffer to be centered on the destination buffer rect,
* and ready to draw the specified bounds. Returns whether a new buffer
* needs to be created.
*/
bool AdjustTo(const gfx::IntRect& aDestBufferRect,
const gfx::IntRect& aDrawBounds,
bool aCanHaveRotation,
bool aCanDrawRotated);
/**
* |BufferRect()| is the rect of device pixels that this
* RotatedBuffer covers. That is what DrawBufferWithRotation()