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); 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->fClearColor(0.0, 0.0, 0.0, 0.0);
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT); mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
#endif
// Allow widget to render a custom background. // Allow widget to render a custom background.
mWidget->DrawWindowUnderlay(this, rect); mWidget->DrawWindowUnderlay(this, rect);

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

@ -100,6 +100,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private final FloatBuffer mCoordBuffer; private final FloatBuffer mCoordBuffer;
private RenderContext mLastPageContext; private RenderContext mLastPageContext;
private int mMaxTextureSize; private int mMaxTextureSize;
private int mBackgroundColor;
private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>(); private ArrayList<Layer> mExtraLayers = new ArrayList<Layer>();
@ -186,12 +187,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
public void resetCheckerboard() { public void resetCheckerboard() {
mCheckerboardLayer.reset(); mCheckerboardLayer.reset();
mCheckerboardLayer.beginTransaction();
try {
mCheckerboardLayer.invalidate();
} finally {
mCheckerboardLayer.endTransaction();
}
} }
public LayerRenderer(LayerView view) { public LayerRenderer(LayerView view) {
@ -423,20 +418,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
}).start(); }).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) * create a vertex shader type (GLES20.GL_VERTEX_SHADER)
* or a fragment shader type (GLES20.GL_FRAGMENT_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 if (rootLayer != null) mUpdated &= rootLayer.update(mPageContext); // called on compositor thread
mUpdated &= mBackgroundLayer.update(mScreenContext); // called on compositor thread mUpdated &= mBackgroundLayer.update(mScreenContext); // called on compositor thread
mUpdated &= mShadowLayer.update(mPageContext); // called on compositor thread mUpdated &= mShadowLayer.update(mPageContext); // called on compositor thread
updateCheckerboardImage();
mUpdated &= mCheckerboardLayer.update(mPageContext); // called on compositor thread mUpdated &= mCheckerboardLayer.update(mPageContext); // called on compositor thread
if (mFrameRateLayer != null) mUpdated &= mFrameRateLayer.update(mScreenContext); // called on compositor thread if (mFrameRateLayer != null) mUpdated &= mFrameRateLayer.update(mScreenContext); // called on compositor thread
mUpdated &= mVertScrollLayer.update(mPageContext); // 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) { if (mask.left <= 2) {
mask.left = -1; 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) { if (mask.bottom >= pageBottom - 2) {
mask.bottom = mPageRect.bottom + 1; mask.bottom = pageBottom + 1;
} }
return mask; return mask;
@ -611,6 +597,19 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/** This function is invoked via JNI; be careful when modifying signature. */ /** This function is invoked via JNI; be careful when modifying signature. */
public void drawBackground() { 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. */ /* Draw the background. */
mBackgroundLayer.setMask(mPageRect); mBackgroundLayer.setMask(mPageRect);
mBackgroundLayer.draw(mScreenContext); mBackgroundLayer.draw(mScreenContext);
@ -621,14 +620,21 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
if (!untransformedPageRect.contains(mView.getController().getViewport())) if (!untransformedPageRect.contains(mView.getController().getViewport()))
mShadowLayer.draw(mPageContext); mShadowLayer.draw(mPageContext);
/* Find the area the root layer will render into, to mask the checkerboard layer */ /* Draw the 'checkerboard'. We use gfx.show_checkerboard_pattern to
Rect rootMask = getMaskForLayer(mView.getController().getRoot()); * 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. */ /* Scissor around the page-rect, in case the page has shrunk
setScissorRect(); * since the screenshot layer was last updated.
mCheckerboardLayer.setMask(rootMask); */
mCheckerboardLayer.draw(mPageContext); setScissorRect();
GLES20.glDisable(GLES20.GL_SCISSOR_TEST); mCheckerboardLayer.draw(mPageContext);
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
}
} }
// Draws the layer the client added to us. // 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 // The size of the bitmap painted in the buffer
// (may be smaller than mBufferSize due to power of 2 padding) // (may be smaller than mBufferSize due to power of 2 padding)
private IntSize mImageSize; private IntSize mImageSize;
// Special case to show the page background color prior to painting a screenshot // Whether we have an up-to-date image to draw
private boolean mIsSingleColor = true; private boolean mHasImage;
// 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;
public static int getMaxNumPixels() { public static int getMaxNumPixels() {
return SCREENSHOT_SIZE_LIMIT; return SCREENSHOT_SIZE_LIMIT;
} }
public void reset() { public void reset() {
mIsSingleColor = true; mHasImage = false;
updateBackground(mForceSingleColor, Color.WHITE);
setPaintMode(TileLayer.PaintMode.STRETCH);
} }
void setBitmap(Bitmap bitmap) { void setBitmap(Bitmap bitmap) {
if (mForceSingleColor)
return;
mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight()); mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
int width = IntSize.nextPowerOfTwo(bitmap.getWidth()); int width = IntSize.nextPowerOfTwo(bitmap.getWidth());
int height = IntSize.nextPowerOfTwo(bitmap.getHeight()); int height = IntSize.nextPowerOfTwo(bitmap.getHeight());
mBufferSize = new IntSize(width, height); mBufferSize = new IntSize(width, height);
mImage.setBitmap(bitmap, width, height, CairoImage.FORMAT_RGB16_565); mImage.setBitmap(bitmap, width, height, CairoImage.FORMAT_RGB16_565);
mIsSingleColor = false; mHasImage = true;
setPaintMode(TileLayer.PaintMode.NORMAL);
} }
public void updateBitmap(Bitmap bitmap, float x, float y, float width, float height) { 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() { public static ScreenshotLayer create() {
// 3 x 3 min for the single color case. Less than 3x3 will blend return ScreenshotLayer.create(new IntSize(4, 4));
// the colors from outside this single color block when scaled
return ScreenshotLayer.create(new IntSize(3, 3));
} }
public static ScreenshotLayer create(IntSize size) { public static ScreenshotLayer create(IntSize size) {
@ -92,58 +80,20 @@ public class ScreenshotLayer extends SingleTileLayer {
} }
private ScreenshotLayer(ScreenshotImage image, IntSize size) { private ScreenshotLayer(ScreenshotImage image, IntSize size) {
super(image, TileLayer.PaintMode.STRETCH); super(image, TileLayer.PaintMode.NORMAL);
mBufferSize = size; mBufferSize = size;
mImage = image; mImage = image;
} }
public boolean updateBackground(boolean showChecks, int color) { @Override
if (!showChecks) { public void draw(RenderContext context) {
mIsSingleColor = true; if (mHasImage)
mForceSingleColor = true; super.draw(context);
} 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;
} }
/** A Cairo image that simply saves a buffer of pixel data. */ /** A Cairo image that simply saves a buffer of pixel data. */
static class ScreenshotImage extends CairoImage { static class ScreenshotImage extends CairoImage {
ByteBuffer mBuffer; private ByteBuffer mBuffer;
private IntSize mSize; private IntSize mSize;
private int mFormat; private int mFormat;