зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 0c1485b37ae9 (bug 1409871)
This commit is contained in:
Родитель
774b6c4844
Коммит
b4aa3847a7
|
@ -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()
|
||||
|
|
Загрузка…
Ссылка в новой задаче