Bug 749630 - Fix single-colour checkerboard and masking. r=kats

Bug 748718 tried to fix masking of the checkerboard layer, but incorrectly
calculated the values for the right and bottom sides of the page, causing
less masking to occur than should happen.

It also possibly broke single-colour layer drawing (though I'm not sure this
worked previously), which this fixes by clearing to the page colour instead of
generating and drawing a texture for it.
This commit is contained in:
Chris Lord 2012-04-27 12:54:18 -04:00
Родитель fd28c257d7
Коммит 6ec3beb9c7
3 изменённых файлов: 54 добавлений и 93 удалений

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

@ -817,8 +817,13 @@ LayerManagerOGL::Render()
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
// If the Java compositor is being used, this clear will be done in
// DrawWindowUnderlay. Make sure the bits used here match up with those used
// in mobile/android/base/gfx/LayerRenderer.java
#ifndef MOZ_JAVA_COMPOSITOR
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
#endif
// Allow widget to render a custom background.
mWidget->DrawWindowUnderlay(this, rect);

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

@ -100,6 +100,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private final FloatBuffer mCoordBuffer;
private RenderContext mLastPageContext;
private int mMaxTextureSize;
private int mBackgroundColor;
private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>();
@ -186,12 +187,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
public void resetCheckerboard() {
mCheckerboardLayer.reset();
mCheckerboardLayer.beginTransaction();
try {
mCheckerboardLayer.invalidate();
} finally {
mCheckerboardLayer.endTransaction();
}
}
public LayerRenderer(LayerView view) {
@ -423,20 +418,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
}).start();
}
private void updateCheckerboardImage() {
int checkerboardColor = mView.getController().getCheckerboardColor();
boolean showChecks = mView.getController().checkerboardShouldShowChecks();
mCheckerboardLayer.beginTransaction(); // called on compositor thread
try {
if (mCheckerboardLayer.updateBackground(showChecks, checkerboardColor))
mCheckerboardLayer.invalidate();
} finally {
mCheckerboardLayer.endTransaction();
}
}
/*
* create a vertex shader type (GLES20.GL_VERTEX_SHADER)
* or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
@ -564,7 +545,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
if (rootLayer != null) mUpdated &= rootLayer.update(mPageContext); // called on compositor thread
mUpdated &= mBackgroundLayer.update(mScreenContext); // called on compositor thread
mUpdated &= mShadowLayer.update(mPageContext); // called on compositor thread
updateCheckerboardImage();
mUpdated &= mCheckerboardLayer.update(mPageContext); // called on compositor thread
if (mFrameRateLayer != null) mUpdated &= mFrameRateLayer.update(mScreenContext); // called on compositor thread
mUpdated &= mVertScrollLayer.update(mPageContext); // called on compositor thread
@ -599,11 +579,17 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
if (mask.left <= 2) {
mask.left = -1;
}
if (mask.right >= mPageRect.right - 2) {
mask.right = mPageRect.right + 1;
// Because we're drawing relative to the page-rect, we only need to
// take into account its width and height (and not its origin)
int pageRight = mPageRect.width();
int pageBottom = mPageRect.height();
if (mask.right >= pageRight - 2) {
mask.right = pageRight + 1;
}
if (mask.bottom >= mPageRect.bottom - 2) {
mask.bottom = mPageRect.bottom + 1;
if (mask.bottom >= pageBottom - 2) {
mask.bottom = pageBottom + 1;
}
return mask;
@ -611,6 +597,19 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/** This function is invoked via JNI; be careful when modifying signature. */
public void drawBackground() {
/* Update background color. */
mBackgroundColor = mView.getController().getCheckerboardColor();
/* Clear to the page background colour. The bits set here need to
* match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp.
*/
GLES20.glClearColor(((mBackgroundColor>>16)&0xFF) / 255.0f,
((mBackgroundColor>>8)&0xFF) / 255.0f,
(mBackgroundColor&0xFF) / 255.0f,
0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |
GLES20.GL_DEPTH_BUFFER_BIT);
/* Draw the background. */
mBackgroundLayer.setMask(mPageRect);
mBackgroundLayer.draw(mScreenContext);
@ -621,14 +620,21 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
if (!untransformedPageRect.contains(mView.getController().getViewport()))
mShadowLayer.draw(mPageContext);
/* Find the area the root layer will render into, to mask the checkerboard layer */
Rect rootMask = getMaskForLayer(mView.getController().getRoot());
/* Draw the 'checkerboard'. We use gfx.show_checkerboard_pattern to
* determine whether to draw the screenshot layer.
*/
if (mView.getController().checkerboardShouldShowChecks()) {
/* Find the area the root layer will render into, to mask the checkerboard layer */
Rect rootMask = getMaskForLayer(mView.getController().getRoot());
mCheckerboardLayer.setMask(rootMask);
/* Draw the checkerboard. */
setScissorRect();
mCheckerboardLayer.setMask(rootMask);
mCheckerboardLayer.draw(mPageContext);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
/* Scissor around the page-rect, in case the page has shrunk
* since the screenshot layer was last updated.
*/
setScissorRect();
mCheckerboardLayer.draw(mPageContext);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
}
// Draws the layer the client added to us.

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

@ -33,34 +33,24 @@ public class ScreenshotLayer extends SingleTileLayer {
// The size of the bitmap painted in the buffer
// (may be smaller than mBufferSize due to power of 2 padding)
private IntSize mImageSize;
// Special case to show the page background color prior to painting a screenshot
private boolean mIsSingleColor = true;
// Force single color, needed for testing
private boolean mForceSingleColor = false;
// Cache the passed in background color to determine if we need to update
// initialized to 0 so it lets the code run to set it to white on init
private int mCurrentBackgroundColor = 0;
// Whether we have an up-to-date image to draw
private boolean mHasImage;
public static int getMaxNumPixels() {
return SCREENSHOT_SIZE_LIMIT;
}
public void reset() {
mIsSingleColor = true;
updateBackground(mForceSingleColor, Color.WHITE);
setPaintMode(TileLayer.PaintMode.STRETCH);
mHasImage = false;
}
void setBitmap(Bitmap bitmap) {
if (mForceSingleColor)
return;
mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
int width = IntSize.nextPowerOfTwo(bitmap.getWidth());
int height = IntSize.nextPowerOfTwo(bitmap.getHeight());
mBufferSize = new IntSize(width, height);
mImage.setBitmap(bitmap, width, height, CairoImage.FORMAT_RGB16_565);
mIsSingleColor = false;
setPaintMode(TileLayer.PaintMode.NORMAL);
mHasImage = true;
}
public void updateBitmap(Bitmap bitmap, float x, float y, float width, float height) {
@ -68,9 +58,7 @@ public class ScreenshotLayer extends SingleTileLayer {
}
public static ScreenshotLayer create() {
// 3 x 3 min for the single color case. Less than 3x3 will blend
// the colors from outside this single color block when scaled
return ScreenshotLayer.create(new IntSize(3, 3));
return ScreenshotLayer.create(new IntSize(4, 4));
}
public static ScreenshotLayer create(IntSize size) {
@ -92,58 +80,20 @@ public class ScreenshotLayer extends SingleTileLayer {
}
private ScreenshotLayer(ScreenshotImage image, IntSize size) {
super(image, TileLayer.PaintMode.STRETCH);
super(image, TileLayer.PaintMode.NORMAL);
mBufferSize = size;
mImage = image;
}
public boolean updateBackground(boolean showChecks, int color) {
if (!showChecks) {
mIsSingleColor = true;
mForceSingleColor = true;
} else {
mForceSingleColor = false;
}
if (!mIsSingleColor || color == mCurrentBackgroundColor)
return false;
mCurrentBackgroundColor = color;
/* mask each component of the 8888 color and bit shift to least
* sigificant. Then for red and blue multiply by (2^5 -1) and (2^6 - 1)
* for green. Finally, divide by (2^8 - 1) for all color values. This
* scales the 8 bit color values to 5 or 6 bits
*/
int red = ((color & 0x00FF0000 >> 16)* 31 / 255);
int green = ((color & 0x0000FF00 >> 8) * 63 / 255);
int blue = (color & 0x000000FF) * 31 / 255;
/* For the first byte left shift red by 3 positions such that it is the
* top 5 bits, right shift green by 3 so its 3 most significant are the
* 3 least significant. For the second byte, left shift green by 3 so
* its 3 least significant bits are the 3 most significant bits of the
* byte. Finally, set the 5 least significant bits to blue's value.
*/
byte byte1 = (byte)((red << 3 | green >> 3) & 0x0000FFFF);
byte byte2 = (byte)((green << 5 | blue) & 0x0000FFFF);
mImage.mBuffer.put(1, byte1);
mImage.mBuffer.put(0, byte2);
mImage.mBuffer.put(3, byte1);
mImage.mBuffer.put(2, byte2);
mImage.mBuffer.put(5, byte1);
mImage.mBuffer.put(4, byte2);
mImage.mBuffer.put(mImageSize.width + 1, byte1);
mImage.mBuffer.put(mImageSize.width + 0, byte2);
mImage.mBuffer.put(mImageSize.width + 3, byte1);
mImage.mBuffer.put(mImageSize.width + 2, byte2);
mImage.mBuffer.put(mImageSize.width + 5, byte1);
mImage.mBuffer.put(mImageSize.width + 4, byte2);
return true;
@Override
public void draw(RenderContext context) {
if (mHasImage)
super.draw(context);
}
/** A Cairo image that simply saves a buffer of pixel data. */
static class ScreenshotImage extends CairoImage {
ByteBuffer mBuffer;
private ByteBuffer mBuffer;
private IntSize mSize;
private int mFormat;