Bug 708307 - Decouple texture size from tile size. r=pcwalton a=android-only

This removes the hard-coded limit of 1024x2048 tile sizes, and allows for
arbitrary tile-sizes. It will still only allocate texture sizes in powers of
two, however. It replaces the tile size with a buffered-area size, which can be
re-allocated as the screen dimensions change.
This commit is contained in:
Chris Lord 2011-12-14 19:41:37 +00:00
Родитель 4e929653f5
Коммит 660420952d
13 изменённых файлов: 171 добавлений и 98 удалений

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

@ -491,15 +491,6 @@ public class GeckoAppShell
/* /*
* The Gecko-side API: API methods that Gecko calls * The Gecko-side API: API methods that Gecko calls
*/ */
public static void scheduleRedraw() {
// Redraw everything
Rect rect = new Rect(0, 0, LayerController.TILE_WIDTH, LayerController.TILE_HEIGHT);
GeckoEvent event = new GeckoEvent(GeckoEvent.DRAW, rect);
event.mNativeWindow = 0;
sendEventToGecko(event);
}
public static void notifyIME(int type, int state) { public static void notifyIME(int type, int state) {
mInputConnection.notifyIME(type, state); mInputConnection.notifyIME(type, state);
} }

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

@ -46,21 +46,22 @@ import java.nio.ByteBuffer;
/** A Cairo image that simply saves a buffer of pixel data. */ /** A Cairo image that simply saves a buffer of pixel data. */
public class BufferedCairoImage extends CairoImage { public class BufferedCairoImage extends CairoImage {
private ByteBuffer mBuffer; private ByteBuffer mBuffer;
private int mWidth, mHeight, mFormat; private IntSize mSize;
private int mFormat;
private boolean mNeedToFreeBuffer = false; private boolean mNeedToFreeBuffer = false;
/** Creates a buffered Cairo image from a byte buffer. */ /** Creates a buffered Cairo image from a byte buffer. */
public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) { public BufferedCairoImage(ByteBuffer inBuffer, int inWidth, int inHeight, int inFormat) {
mBuffer = inBuffer; mWidth = inWidth; mHeight = inHeight; mFormat = inFormat; mBuffer = inBuffer; mSize = new IntSize(inWidth, inHeight); mFormat = inFormat;
} }
/** Creates a buffered Cairo image from an Android bitmap. */ /** Creates a buffered Cairo image from an Android bitmap. */
public BufferedCairoImage(Bitmap bitmap) { public BufferedCairoImage(Bitmap bitmap) {
mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig()); mFormat = CairoUtils.bitmapConfigToCairoFormat(bitmap.getConfig());
mWidth = bitmap.getWidth(); mSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
mHeight = bitmap.getHeight();
mNeedToFreeBuffer = true; mNeedToFreeBuffer = true;
mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 4); // XXX Why is this * 4? Shouldn't it depend on mFormat?
mBuffer = GeckoAppShell.allocateDirectBuffer(mSize.getArea() * 4);
bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer()); bitmap.copyPixelsToBuffer(mBuffer.asIntBuffer());
} }
@ -78,9 +79,7 @@ public class BufferedCairoImage extends CairoImage {
@Override @Override
public ByteBuffer getBuffer() { return mBuffer; } public ByteBuffer getBuffer() { return mBuffer; }
@Override @Override
public int getWidth() { return mWidth; } public IntSize getSize() { return mSize; }
@Override
public int getHeight() { return mHeight; }
@Override @Override
public int getFormat() { return mFormat; } public int getFormat() { return mFormat; }
} }

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

@ -45,8 +45,7 @@ import java.nio.ByteBuffer;
public abstract class CairoImage { public abstract class CairoImage {
public abstract ByteBuffer getBuffer(); public abstract ByteBuffer getBuffer();
public abstract int getWidth(); public abstract IntSize getSize();
public abstract int getHeight();
public abstract int getFormat(); public abstract int getFormat();
public static final int FORMAT_INVALID = -1; public static final int FORMAT_INVALID = -1;

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

@ -72,8 +72,9 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
private static final String LOGTAG = "GeckoSoftwareLayerClient"; private static final String LOGTAG = "GeckoSoftwareLayerClient";
private Context mContext; private Context mContext;
private int mWidth, mHeight, mFormat; private int mFormat;
private IntSize mScreenSize, mViewportSize; private IntSize mScreenSize, mViewportSize;
private IntSize mBufferSize;
private ByteBuffer mBuffer; private ByteBuffer mBuffer;
private final SingleTileLayer mTileLayer; private final SingleTileLayer mTileLayer;
@ -97,21 +98,15 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
public GeckoSoftwareLayerClient(Context context) { public GeckoSoftwareLayerClient(Context context) {
mContext = context; mContext = context;
mWidth = LayerController.TILE_WIDTH; mScreenSize = new IntSize(0, 0);
mHeight = LayerController.TILE_HEIGHT; mBufferSize = new IntSize(0, 0);
mFormat = CairoImage.FORMAT_RGB16_565; mFormat = CairoImage.FORMAT_RGB16_565;
mScreenSize = new IntSize(1, 1);
mBuffer = GeckoAppShell.allocateDirectBuffer(mWidth * mHeight * 2);
mCairoImage = new CairoImage() { mCairoImage = new CairoImage() {
@Override @Override
public ByteBuffer getBuffer() { return mBuffer; } public ByteBuffer getBuffer() { return mBuffer; }
@Override @Override
public int getWidth() { return mWidth; } public IntSize getSize() { return mBufferSize; }
@Override
public int getHeight() { return mHeight; }
@Override @Override
public int getFormat() { return mFormat; } public int getFormat() { return mFormat; }
}; };
@ -141,7 +136,6 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
layerController.notifyPanZoomControllerOfGeometryChange(false); layerController.notifyPanZoomControllerOfGeometryChange(false);
} }
geometryChanged();
GeckoAppShell.registerGeckoEventListener("Viewport:Update", this); GeckoAppShell.registerGeckoEventListener("Viewport:Update", this);
GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this); GeckoAppShell.registerGeckoEventListener("Viewport:UpdateLater", this);
} }
@ -209,7 +203,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
public Bitmap getBitmap() { public Bitmap getBitmap() {
try { try {
Bitmap b = Bitmap.createBitmap(mWidth, mHeight, Bitmap b = Bitmap.createBitmap(mBufferSize.width, mBufferSize.height,
CairoUtils.cairoFormatTobitmapConfig(mFormat)); CairoUtils.cairoFormatTobitmapConfig(mFormat));
b.copyPixelsFromBuffer(mBuffer.asIntBuffer()); b.copyPixelsFromBuffer(mBuffer.asIntBuffer());
return b; return b;
@ -241,9 +235,28 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
if (metrics.widthPixels != mScreenSize.width || if (metrics.widthPixels != mScreenSize.width ||
metrics.heightPixels != mScreenSize.height) { metrics.heightPixels != mScreenSize.height) {
mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels); mScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
int maxSize = getLayerController().getView().getMaxTextureSize();
// XXX Introduce tiling to solve this?
if (mScreenSize.width > maxSize || mScreenSize.height > maxSize)
throw new RuntimeException("Screen size of " + mScreenSize + " larger than maximum texture size of " + maxSize);
// Round to next power of two until we use NPOT texture support
mBufferSize = new IntSize(Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.width + LayerController.MIN_BUFFER.width)),
Math.min(maxSize, IntSize.nextPowerOfTwo(mScreenSize.height + LayerController.MIN_BUFFER.height)));
// Free the old buffer first, if it exists
if (mBuffer != null) {
GeckoAppShell.freeDirectBuffer(mBuffer);
mBuffer = null;
}
// * 2 because it's a 16-bit buffer (so 2 bytes per pixel).
mBuffer = GeckoAppShell.allocateDirectBuffer(mBufferSize.getArea() * 2);
Log.i(LOGTAG, "Screen-size changed to " + mScreenSize); Log.i(LOGTAG, "Screen-size changed to " + mScreenSize);
GeckoEvent event = new GeckoEvent(GeckoEvent.SIZE_CHANGED, GeckoEvent event = new GeckoEvent(GeckoEvent.SIZE_CHANGED,
LayerController.TILE_WIDTH, LayerController.TILE_HEIGHT, mBufferSize.width, mBufferSize.height,
metrics.widthPixels, metrics.heightPixels); metrics.widthPixels, metrics.heightPixels);
GeckoAppShell.sendEventToGecko(event); GeckoAppShell.sendEventToGecko(event);
} }
@ -289,7 +302,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
ViewportMetrics viewportMetrics = ViewportMetrics viewportMetrics =
new ViewportMetrics(getLayerController().getViewportMetrics()); new ViewportMetrics(getLayerController().getViewportMetrics());
PointF viewportOffset = viewportMetrics.getOptimumViewportOffset(); PointF viewportOffset = viewportMetrics.getOptimumViewportOffset(mBufferSize);
viewportMetrics.setViewportOffset(viewportOffset); viewportMetrics.setViewportOffset(viewportOffset);
viewportMetrics.setViewport(viewportMetrics.getClampedViewport()); viewportMetrics.setViewport(viewportMetrics.getClampedViewport());

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

@ -62,10 +62,18 @@ public class IntSize {
} }
} }
public int getArea() {
return width * height;
}
public boolean equals(IntSize size) { public boolean equals(IntSize size) {
return ((size.width == width) && (size.height == height)); return ((size.width == width) && (size.height == height));
} }
public boolean isPositive() {
return (width > 0 && height > 0);
}
@Override @Override
public String toString() { return "(" + width + "," + height + ")"; } public String toString() { return "(" + width + "," + height + ")"; }
@ -73,5 +81,23 @@ public class IntSize {
return new IntSize((int)Math.round(width * factor), return new IntSize((int)Math.round(width * factor),
(int)Math.round(height * factor)); (int)Math.round(height * factor));
} }
/* Returns the power of two that is greater than or equal to value */
public static int nextPowerOfTwo(int value) {
// code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
if (0 == value--) {
return 1;
}
value = (value >> 1) | value;
value = (value >> 2) | value;
value = (value >> 4) | value;
value = (value >> 8) | value;
value = (value >> 16) | value;
return value + 1;
}
public IntSize nextPowerOfTwo() {
return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height));
}
} }

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

@ -80,6 +80,9 @@ public abstract class Layer {
/** Subclasses override this function to draw the layer. */ /** Subclasses override this function to draw the layer. */
public abstract void draw(RenderContext context); public abstract void draw(RenderContext context);
/** Subclasses override this function to provide access to the size of the layer. */
public abstract IntSize getSize();
/** Given the intrinsic size of the layer, returns the pixel boundaries of the layer rect. */ /** Given the intrinsic size of the layer, returns the pixel boundaries of the layer rect. */
protected RectF getBounds(RenderContext context, FloatSize size) { protected RectF getBounds(RenderContext context, FloatSize size) {
float scaleFactor = context.zoomFactor / mResolution; float scaleFactor = context.zoomFactor / mResolution;
@ -168,20 +171,6 @@ public abstract class Layer {
} }
} }
/* Returns the power of two that is greater than or equal to value */
protected static int nextPowerOfTwo(int value) {
// code taken from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
if (0 == value--) {
return 1;
}
value = (value >> 1) | value;
value = (value >> 2) | value;
value = (value >> 4) | value;
value = (value >> 8) | value;
value = (value >> 16) | value;
return value + 1;
}
public static class RenderContext { public static class RenderContext {
public final RectF viewport; public final RectF viewport;
public final FloatSize pageSize; public final FloatSize pageSize;

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

@ -85,9 +85,11 @@ public class LayerController {
private boolean mForceRedraw; private boolean mForceRedraw;
/* NB: These must be powers of two due to the OpenGL ES 1.x restriction on NPOT textures. */ /* The extra area on the sides of the page that we want to buffer to help with
public static final int TILE_WIDTH = 1024; * smooth, asynchronous scrolling. Depending on a device's support for NPOT
public static final int TILE_HEIGHT = 2048; * textures, this may be rounded up to the nearest power of two.
*/
public static final IntSize MIN_BUFFER = new IntSize(512, 1024);
/* If the visible rect is within the danger zone (measured in pixels from each edge of a tile), /* If the visible rect is within the danger zone (measured in pixels from each edge of a tile),
* we start aggressively redrawing to minimize checkerboarding. */ * we start aggressively redrawing to minimize checkerboarding. */
@ -293,8 +295,12 @@ public class LayerController {
} }
private RectF getTileRect() { private RectF getTileRect() {
if (mRootLayer == null)
return new RectF();
float x = mRootLayer.getOrigin().x, y = mRootLayer.getOrigin().y; float x = mRootLayer.getOrigin().x, y = mRootLayer.getOrigin().y;
return new RectF(x, y, x + TILE_WIDTH, y + TILE_HEIGHT); IntSize layerSize = mRootLayer.getSize();
return new RectF(x, y, x + layerSize.width, y + layerSize.height);
} }
public RectF restrictToPageSize(RectF aRect) { public RectF restrictToPageSize(RectF aRect) {

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

@ -90,6 +90,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private final ScrollbarLayer mVertScrollLayer; private final ScrollbarLayer mVertScrollLayer;
private final FadeRunnable mFadeRunnable; private final FadeRunnable mFadeRunnable;
private RenderContext mLastPageContext; private RenderContext mLastPageContext;
private int mMaxTextureSize;
// Dropped frames display // Dropped frames display
private int[] mFrameTimings; private int[] mFrameTimings;
@ -122,12 +123,17 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
public void onSurfaceCreated(GL10 gl, EGLConfig config) { public void onSurfaceCreated(GL10 gl, EGLConfig config) {
checkFrameRateMonitorEnabled(); checkFrameRateMonitorEnabled();
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClearDepthf(1.0f); /* FIXME: Is this needed? */
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glShadeModel(GL10.GL_SMOOTH); /* FIXME: Is this needed? */
gl.glDisable(GL10.GL_DITHER); gl.glDisable(GL10.GL_DITHER);
gl.glEnable(GL10.GL_TEXTURE_2D); gl.glEnable(GL10.GL_TEXTURE_2D);
int maxTextureSizeResult[] = new int[1];
gl.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSizeResult, 0);
mMaxTextureSize = maxTextureSizeResult[0];
}
public int getMaxTextureSize() {
return mMaxTextureSize;
} }
/** /**

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

@ -167,5 +167,9 @@ public class LayerView extends GLSurfaceView {
return System.nanoTime() - mRenderTime; return System.nanoTime() - mRenderTime;
} }
} }
public int getMaxTextureSize() {
return mRenderer.getMaxTextureSize();
}
} }

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

@ -82,7 +82,8 @@ public class ScrollbarLayer extends TileLayer {
mVertical = vertical; mVertical = vertical;
mBuffer = buffer; mBuffer = buffer;
mBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888); IntSize size = image.getSize();
mBitmap = Bitmap.createBitmap(size.width, size.height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap); mCanvas = new Canvas(mBitmap);
} }
@ -100,7 +101,7 @@ public class ScrollbarLayer extends TileLayer {
public static ScrollbarLayer create(boolean vertical) { public static ScrollbarLayer create(boolean vertical) {
// just create an empty image for now, it will get drawn // just create an empty image for now, it will get drawn
// on demand anyway // on demand anyway
int imageSize = nextPowerOfTwo(BAR_SIZE); int imageSize = IntSize.nextPowerOfTwo(BAR_SIZE);
ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(imageSize * imageSize * 4); ByteBuffer buffer = GeckoAppShell.allocateDirectBuffer(imageSize * imageSize * 4);
CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize, CairoImage.FORMAT_ARGB32); CairoImage image = new BufferedCairoImage(buffer, imageSize, imageSize, CairoImage.FORMAT_ARGB32);
return new ScrollbarLayer(image, vertical, buffer); return new ScrollbarLayer(image, vertical, buffer);

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

@ -39,6 +39,7 @@ package org.mozilla.gecko.gfx;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.opengl.GLES20;
import android.util.Log; import android.util.Log;
import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11Ext; import javax.microedition.khronos.opengles.GL11Ext;
@ -58,27 +59,18 @@ public abstract class TileLayer extends Layer {
private final ArrayList<Rect> mDirtyRects; private final ArrayList<Rect> mDirtyRects;
private final CairoImage mImage; private final CairoImage mImage;
private final boolean mRepeat; private final boolean mRepeat;
private final IntSize mSize; private IntSize mSize;
private int[] mTextureIDs; private int[] mTextureIDs;
public TileLayer(boolean repeat, CairoImage image) { public TileLayer(boolean repeat, CairoImage image) {
mRepeat = repeat; mRepeat = repeat;
mImage = image; mImage = image;
mSize = new IntSize(image.getWidth(), image.getHeight()); mSize = new IntSize(0, 0);
mDirtyRects = new ArrayList<Rect>(); mDirtyRects = new ArrayList<Rect>();
/*
* Assert that the image has a power-of-two size. OpenGL ES < 2.0 doesn't support NPOT
* textures and OpenGL ES doesn't seem to let us efficiently slice up a NPOT bitmap.
*/
int width = mImage.getWidth(), height = mImage.getHeight();
if ((width & (width - 1)) != 0 || (height & (height - 1)) != 0) {
throw new RuntimeException("TileLayer: NPOT images are unsupported (dimensions are " +
width + "x" + height + ")");
}
} }
public IntSize getSize() { return mSize; } @Override
public IntSize getSize() { return mImage.getSize(); }
protected boolean repeats() { return mRepeat; } protected boolean repeats() { return mRepeat; }
protected int getTextureID() { return mTextureIDs[0]; } protected int getTextureID() { return mTextureIDs[0]; }
@ -101,13 +93,49 @@ public abstract class TileLayer extends Layer {
} }
public void invalidate() { public void invalidate() {
invalidate(new Rect(0, 0, mSize.width, mSize.height)); IntSize bufferSize = mImage.getSize();
invalidate(new Rect(0, 0, bufferSize.width, bufferSize.height));
}
private void validateTexture() {
/* Calculate the ideal texture size. This must be a power of two if
* the texture is repeated or OpenGL ES 2.0 isn't supported, as
* OpenGL ES 2.0 is required for NPOT texture support (without
* extensions), but doesn't support repeating NPOT textures.
*
* XXX Currently, we don't pick a GLES 2.0 context, so always round.
*/
IntSize bufferSize = mImage.getSize();
IntSize textureSize = bufferSize;
textureSize = bufferSize.nextPowerOfTwo();
if (!textureSize.equals(mSize)) {
mSize = textureSize;
// Delete the old texture
if (mTextureIDs != null) {
TextureReaper.get().add(mTextureIDs);
mTextureIDs = null;
// XXX This won't be freed until the next frame is drawn, so we
// temporarily have a larger-than-necessary memory requirement.
// Is this what we want?
}
}
} }
@Override @Override
protected void performUpdates(GL10 gl) { protected void performUpdates(GL10 gl) {
super.performUpdates(gl); super.performUpdates(gl);
// Reallocate the texture if the size has changed
validateTexture();
// Don't do any work if the image has an invalid size.
if (!mImage.getSize().isPositive())
return;
if (mTextureIDs == null) { if (mTextureIDs == null) {
uploadFullTexture(gl); uploadFullTexture(gl);
} else { } else {
@ -119,43 +147,58 @@ public abstract class TileLayer extends Layer {
} }
private void uploadFullTexture(GL10 gl) { private void uploadFullTexture(GL10 gl) {
mTextureIDs = new int[1]; IntSize bufferSize = mImage.getSize();
gl.glGenTextures(mTextureIDs.length, mTextureIDs, 0); uploadDirtyRect(gl, new Rect(0, 0, bufferSize.width, bufferSize.height));
int cairoFormat = mImage.getFormat();
CairoGLInfo glInfo = new CairoGLInfo(cairoFormat);
bindAndSetGLParameters(gl);
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, glInfo.internalFormat, mSize.width, mSize.height,
0, glInfo.format, glInfo.type, mImage.getBuffer());
} }
private void uploadDirtyRect(GL10 gl, Rect dirtyRect) { private void uploadDirtyRect(GL10 gl, Rect dirtyRect) {
if (mTextureIDs == null) boolean newlyCreated = false;
throw new RuntimeException("uploadDirtyRect() called with null texture ID!");
if (mTextureIDs == null) {
mTextureIDs = new int[1];
gl.glGenTextures(mTextureIDs.length, mTextureIDs, 0);
newlyCreated = true;
}
IntSize bufferSize = mImage.getSize();
Rect bufferRect = new Rect(0, 0, bufferSize.width, bufferSize.height);
int width = mSize.width;
int cairoFormat = mImage.getFormat(); int cairoFormat = mImage.getFormat();
CairoGLInfo glInfo = new CairoGLInfo(cairoFormat); CairoGLInfo glInfo = new CairoGLInfo(cairoFormat);
bindAndSetGLParameters(gl); bindAndSetGLParameters(gl);
if (newlyCreated || dirtyRect.equals(bufferRect)) {
if (mSize.equals(bufferSize)) {
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, glInfo.internalFormat, mSize.width, mSize.height,
0, glInfo.format, glInfo.type, mImage.getBuffer());
return;
} else {
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, glInfo.internalFormat, mSize.width, mSize.height,
0, glInfo.format, glInfo.type, null);
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, 0, bufferSize.width, bufferSize.height,
glInfo.format, glInfo.type, mImage.getBuffer());
return;
}
}
/* /*
* Upload the changed rect. We have to widen to the full width of the texture * Upload the changed rect. We have to widen to the full width of the texture
* because we can't count on the device having support for GL_EXT_unpack_subimage, * because we can't count on the device having support for GL_EXT_unpack_subimage,
* and going line-by-line is too slow. * and going line-by-line is too slow.
*
* XXX We should still use GL_EXT_unpack_subimage when available.
*/ */
Buffer viewBuffer = mImage.getBuffer().slice(); Buffer viewBuffer = mImage.getBuffer().slice();
int bpp = CairoUtils.bitsPerPixelForCairoFormat(cairoFormat) / 8; int bpp = CairoUtils.bitsPerPixelForCairoFormat(cairoFormat) / 8;
int position = dirtyRect.top * width * bpp; int position = dirtyRect.top * bufferSize.width * bpp;
if (position > viewBuffer.limit()) { if (position > viewBuffer.limit()) {
Log.e(LOGTAG, "### Position outside tile! " + dirtyRect.top); Log.e(LOGTAG, "### Position outside tile! " + dirtyRect.top);
return; return;
} }
viewBuffer.position(position); viewBuffer.position(position);
gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, dirtyRect.top, width, dirtyRect.height(), gl.glTexSubImage2D(gl.GL_TEXTURE_2D, 0, 0, dirtyRect.top, bufferSize.width, dirtyRect.height(),
glInfo.format, glInfo.type, viewBuffer); glInfo.format, glInfo.type, viewBuffer);
} }

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

@ -44,6 +44,7 @@ import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.FloatUtils;
import org.mozilla.gecko.gfx.FloatSize; import org.mozilla.gecko.gfx.FloatSize;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.LayerController; import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.RectUtils; import org.mozilla.gecko.gfx.RectUtils;
import org.json.JSONException; import org.json.JSONException;
@ -64,8 +65,7 @@ public class ViewportMetrics {
private float mZoomFactor; private float mZoomFactor;
public ViewportMetrics() { public ViewportMetrics() {
mPageSize = new FloatSize(LayerController.TILE_WIDTH, mPageSize = new FloatSize(1, 1);
LayerController.TILE_HEIGHT);
mViewportRect = new RectF(0, 0, 1, 1); mViewportRect = new RectF(0, 0, 1, 1);
mViewportOffset = new PointF(0, 0); mViewportOffset = new PointF(0, 0);
mZoomFactor = 1.0f; mZoomFactor = 1.0f;
@ -96,13 +96,13 @@ public class ViewportMetrics {
mZoomFactor = zoom; mZoomFactor = zoom;
} }
public PointF getOptimumViewportOffset() { public PointF getOptimumViewportOffset(IntSize displayportSize) {
// XXX We currently always position the viewport in the centre of the // XXX We currently always position the viewport in the centre of the
// displayport, but we might want to optimise this during panning // displayport, but we might want to optimise this during panning
// to minimise checkerboarding. // to minimise checkerboarding.
Point optimumOffset = Point optimumOffset =
new Point((int)Math.round((LayerController.TILE_WIDTH - mViewportRect.width()) / 2), new Point((int)Math.round((displayportSize.width - mViewportRect.width()) / 2),
(int)Math.round((LayerController.TILE_HEIGHT - mViewportRect.height()) / 2)); (int)Math.round((displayportSize.height - mViewportRect.height()) / 2));
/* XXX Until bug #524925 is fixed, changing the viewport origin will /* XXX Until bug #524925 is fixed, changing the viewport origin will
* probably cause things to be slower than just having a smaller usable * probably cause things to be slower than just having a smaller usable

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

@ -79,10 +79,6 @@ using mozilla::unused;
#include "nsStringGlue.h" #include "nsStringGlue.h"
// NB: Keep these in sync with LayerController.java in mobile/android/base and embedding/android/.
#define TILE_WIDTH 1024
#define TILE_HEIGHT 2048
using namespace mozilla; using namespace mozilla;
using namespace mozilla::widget; using namespace mozilla::widget;
@ -310,7 +306,7 @@ nsWindow::ConfigureChildren(const nsTArray<nsIWidget::Configuration>& config)
void void
nsWindow::RedrawAll() nsWindow::RedrawAll()
{ {
nsIntRect entireRect(0, 0, TILE_WIDTH, TILE_HEIGHT); nsIntRect entireRect(0, 0, gAndroidBounds.width, gAndroidBounds.height);
AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, entireRect); AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, entireRect);
nsAppShell::gAppShell->PostEvent(event); nsAppShell::gAppShell->PostEvent(event);
} }
@ -1018,7 +1014,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
if (coveringChildIndex == -1) { if (coveringChildIndex == -1) {
nsPaintEvent event(true, NS_PAINT, this); nsPaintEvent event(true, NS_PAINT, this);
nsIntRect tileRect(0, 0, TILE_WIDTH, TILE_HEIGHT); nsIntRect tileRect(0, 0, gAndroidBounds.width, gAndroidBounds.height);
event.region = boundsRect.Intersect(invalidRect).Intersect(tileRect); event.region = boundsRect.Intersect(invalidRect).Intersect(tileRect);
switch (GetLayerManager(nsnull)->GetBackendType()) { switch (GetLayerManager(nsnull)->GetBackendType()) {
@ -1112,7 +1108,7 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
unsigned char *bits = client.LockBufferBits(); unsigned char *bits = client.LockBufferBits();
nsRefPtr<gfxImageSurface> targetSurface = nsRefPtr<gfxImageSurface> targetSurface =
new gfxImageSurface(bits, gfxIntSize(TILE_WIDTH, TILE_HEIGHT), TILE_WIDTH * 2, new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2,
gfxASurface::ImageFormatRGB16_565); gfxASurface::ImageFormatRGB16_565);
if (targetSurface->CairoStatus()) { if (targetSurface->CairoStatus()) {
ALOG("### Failed to create a valid surface from the bitmap"); ALOG("### Failed to create a valid surface from the bitmap");