Bug 705170 - Use OES_draw_texture to render textures to the screen. r=Cwiiis

This commit is contained in:
Patrick Walton 2011-12-01 14:05:41 -08:00
parent c42843fef8
commit 747a4d7e3c
7 changed files with 225 additions and 287 deletions

View File

@ -39,6 +39,8 @@
package org.mozilla.gecko.gfx;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.Log;
import java.util.concurrent.locks.ReentrantLock;
import javax.microedition.khronos.opengles.GL10;
@ -74,19 +76,15 @@ public abstract class Layer {
}
}
/** Sets the transformation for the layer. */
public final void transform(GL10 gl) {
gl.glScalef(1.0f / mResolution, 1.0f / mResolution, 1.0f);
gl.glTranslatef(mOrigin.x, mOrigin.y, 0.0f);
}
/** Subclasses override this function to draw the layer. */
public abstract void draw(RenderContext context);
/** Draws the layer. Automatically applies the transformation. */
public final void draw(GL10 gl) {
gl.glPushMatrix();
onDraw(gl);
gl.glPopMatrix();
/** Given the intrinsic size of the layer, returns the pixel boundaries of the layer rect. */
protected RectF getBounds(RenderContext context, FloatSize size) {
float scaleFactor = context.zoomFactor / mResolution;
float x = mOrigin.x * scaleFactor, y = mOrigin.y * scaleFactor;
float width = size.width * scaleFactor, height = size.height * scaleFactor;
return new RectF(x, y, x + width, y + height);
}
/**
@ -153,13 +151,6 @@ public abstract class Layer {
mNewResolution = newResolution;
}
/**
* Subclasses implement this method to perform drawing.
*
* Invariant: The current matrix mode must be GL_MODELVIEW both before and after this call.
*/
protected abstract void onDraw(GL10 gl);
/**
* Subclasses may override this method to perform custom layer updates. This will be called
* with the transaction lock held. Subclass implementations of this method must call the
@ -170,7 +161,22 @@ public abstract class Layer {
mOrigin = mNewOrigin;
mNewOrigin = null;
}
mResolution = mNewResolution;
if (mNewResolution != 0.0f) {
mResolution = mNewResolution;
mNewResolution = 0.0f;
}
}
public static class RenderContext {
public final RectF viewport;
public final FloatSize pageSize;
public final float zoomFactor;
public RenderContext(RectF aViewport, FloatSize aPageSize, float aZoomFactor) {
viewport = aViewport;
pageSize = aPageSize;
zoomFactor = aZoomFactor;
}
}
}

View File

@ -40,6 +40,7 @@ package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.BufferedCairoImage;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.Layer.RenderContext;
import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.NinePatchTileLayer;
@ -68,12 +69,12 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private static final float BACKGROUND_COLOR_G = 0.81f;
private static final float BACKGROUND_COLOR_B = 0.81f;
private LayerView mView;
private SingleTileLayer mCheckerboardLayer;
private NinePatchTileLayer mShadowLayer;
private TextLayer mFPSLayer;
private ScrollbarLayer mHorizScrollLayer;
private ScrollbarLayer mVertScrollLayer;
private final LayerView mView;
private final SingleTileLayer mCheckerboardLayer;
private final NinePatchTileLayer mShadowLayer;
private final TextLayer mFPSLayer;
private final ScrollbarLayer mHorizScrollLayer;
private final ScrollbarLayer mVertScrollLayer;
// FPS display
private long mFrameCountTimestamp;
@ -83,15 +84,17 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
public LayerRenderer(LayerView view) {
mView = view;
/* FIXME: Layers should not be directly connected to the layer controller. */
LayerController controller = view.getController();
CairoImage checkerboardImage = new BufferedCairoImage(controller.getCheckerboardPattern());
mCheckerboardLayer = new SingleTileLayer(true, checkerboardImage);
CairoImage shadowImage = new BufferedCairoImage(controller.getShadowPattern());
mShadowLayer = new NinePatchTileLayer(controller, shadowImage);
mShadowLayer = new NinePatchTileLayer(shadowImage);
mFPSLayer = TextLayer.create(new IntSize(64, 32), "-- FPS");
mHorizScrollLayer = ScrollbarLayer.create();
mVertScrollLayer = ScrollbarLayer.create();
mHorizScrollLayer = ScrollbarLayer.create(false);
mVertScrollLayer = ScrollbarLayer.create(true);
mFrameCountTimestamp = System.currentTimeMillis();
mFrameCount = 0;
@ -106,14 +109,21 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
gl.glEnable(GL10.GL_TEXTURE_2D);
}
/**
* Called whenever a new frame is about to be drawn.
*
* FIXME: This is racy. Layers and page sizes can be modified by the pan/zoom controller while
* this is going on.
*/
public void onDrawFrame(GL10 gl) {
checkFPS();
TextureReaper.get().reap(gl);
LayerController controller = mView.getController();
Layer rootLayer = controller.getRoot();
RenderContext screenContext = createScreenContext(), pageContext = createPageContext();
/* Update layers */
/* Update layers. */
if (rootLayer != null) rootLayer.update(gl);
mShadowLayer.update(gl);
mCheckerboardLayer.update(gl);
@ -125,60 +135,61 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
/* Draw the drop shadow. */
setupPageTransform(gl, false);
mShadowLayer.draw(gl);
/* Draw the drop shadow, if we need to. */
Rect pageRect = getPageRect();
RectF untransformedPageRect = new RectF(0.0f, 0.0f, pageRect.width(), pageRect.height());
if (!untransformedPageRect.contains(controller.getViewport()))
mShadowLayer.draw(pageContext);
/* Draw the checkerboard. */
Rect pageRect = getPageRect();
Rect scissorRect = transformToScissorRect(pageRect);
gl.glEnable(GL10.GL_SCISSOR_TEST);
gl.glScissor(scissorRect.left, scissorRect.top,
scissorRect.width(), scissorRect.height());
gl.glLoadIdentity();
mCheckerboardLayer.draw(gl);
mCheckerboardLayer.draw(screenContext);
/* Draw the layer the client added to us. */
if (rootLayer != null) {
gl.glLoadIdentity();
setupPageTransform(gl, true);
rootLayer.transform(gl);
rootLayer.draw(gl);
}
if (rootLayer != null)
rootLayer.draw(pageContext);
gl.glDisable(GL10.GL_SCISSOR_TEST);
gl.glEnable(GL10.GL_BLEND);
/* Draw the vertical scrollbar */
/* Draw the vertical scrollbar. */
IntSize screenSize = new IntSize(controller.getViewportSize());
if (pageRect.height() > screenSize.height) {
mVertScrollLayer.drawVertical(gl, screenSize, pageRect);
}
if (pageRect.height() > screenSize.height)
mVertScrollLayer.draw(pageContext);
/* Draw the horizontal scrollbar */
if (pageRect.width() > screenSize.width) {
mHorizScrollLayer.drawHorizontal(gl, screenSize, pageRect);
}
/* Draw the horizontal scrollbar. */
if (pageRect.width() > screenSize.width)
mHorizScrollLayer.draw(pageContext);
/* Draw the FPS. */
gl.glLoadIdentity();
mFPSLayer.draw(gl);
gl.glDisable(GL10.GL_BLEND);
try {
gl.glEnable(GL10.GL_BLEND);
mFPSLayer.draw(screenContext);
} finally {
gl.glDisable(GL10.GL_BLEND);
}
}
private void setupPageTransform(GL10 gl, boolean scale) {
LayerController controller = mView.getController();
private RenderContext createScreenContext() {
LayerController layerController = mView.getController();
IntSize viewportSize = new IntSize(layerController.getViewportSize());
RectF viewport = new RectF(0.0f, 0.0f, viewportSize.width, viewportSize.height);
FloatSize pageSize = new FloatSize(layerController.getPageSize());
return new RenderContext(viewport, pageSize, 1.0f);
}
PointF origin = controller.getOrigin();
gl.glTranslatef(Math.round(-origin.x), Math.round(-origin.y), 0.0f);
private RenderContext createPageContext() {
LayerController layerController = mView.getController();
if (scale) {
float zoomFactor = controller.getZoomFactor();
gl.glScalef(zoomFactor, zoomFactor, 1.0f);
}
Rect viewport = new Rect();
layerController.getViewport().round(viewport);
FloatSize pageSize = new FloatSize(layerController.getPageSize());
float zoomFactor = layerController.getZoomFactor();
return new RenderContext(new RectF(viewport), pageSize, zoomFactor);
}
private Rect getPageRect() {
@ -208,11 +219,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
public void onSurfaceChanged(GL10 gl, final int width, final int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrthof(0.0f, (float)width, (float)height, 0.0f, -10.0f, 10.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// updating the state in the view/controller/client should be
// done on the main UI thread, not the GL renderer thread

View File

@ -38,6 +38,11 @@
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.FloatSize;
import android.graphics.PointF;
import android.graphics.RectF;
import android.opengl.GLES11;
import android.opengl.GLES11Ext;
import android.util.Log;
import javax.microedition.khronos.opengles.GL10;
import java.nio.FloatBuffer;
@ -48,131 +53,72 @@ import java.nio.FloatBuffer;
* http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
*/
public class NinePatchTileLayer extends TileLayer {
private FloatBuffer mSideTexCoordBuffer, mSideVertexBuffer;
private FloatBuffer mTopTexCoordBuffer, mTopVertexBuffer;
private LayerController mLayerController;
private FloatSize mPageSize;
private static final int PATCH_SIZE = 16;
private static final int TEXTURE_SIZE = 48;
/*
* We divide the nine-patch bitmap up into the "sides" and the "tops":
*
* Top
* |
* v
* +---+---+---+
* | | | |
* | +---+ |
* | |XXX| | <-- Side
* | +---+ |
* | | | |
* +---+---+---+
*/
private static final float[] SIDE_TEX_COORDS = {
0.0f, 0.0f,
0.25f, 0.0f,
0.0f, 0.25f,
0.25f, 0.25f,
0.0f, 0.50f,
0.25f, 0.50f,
0.0f, 0.75f,
0.25f, 0.75f,
};
private static final float[] TOP_TEX_COORDS = {
0.25f, 0.0f,
0.50f, 0.0f,
0.25f, 0.25f,
0.50f, 0.25f,
};
public NinePatchTileLayer(LayerController layerController, CairoImage image) {
public NinePatchTileLayer(CairoImage image) {
super(false, image);
mPageSize = new FloatSize(1.0f, 1.0f);
mLayerController = layerController;
mSideTexCoordBuffer = createBuffer(SIDE_TEX_COORDS);
mTopTexCoordBuffer = createBuffer(TOP_TEX_COORDS);
recreateVertexBuffers();
}
public void recreateVertexBuffers() {
float[] sideVertices = {
-PATCH_SIZE, -PATCH_SIZE, 0.0f,
0.0f, -PATCH_SIZE, 0.0f,
-PATCH_SIZE, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
-PATCH_SIZE, mPageSize.height, 0.0f,
0.0f, mPageSize.height, 0.0f,
-PATCH_SIZE, PATCH_SIZE + mPageSize.height, 0.0f,
0.0f, PATCH_SIZE + mPageSize.height, 0.0f
};
float[] topVertices = {
0.0f, -PATCH_SIZE, 0.0f,
mPageSize.width, -PATCH_SIZE, 0.0f,
0.0f, 0.0f, 0.0f,
mPageSize.width, 0.0f, 0.0f
};
mSideVertexBuffer = createBuffer(sideVertices);
mTopVertexBuffer = createBuffer(topVertices);
}
@Override
protected void onTileDraw(GL10 gl) {
FloatSize pageSize = mLayerController.getPageSize();
if (!pageSize.fuzzyEquals(mPageSize)) {
mPageSize = pageSize;
recreateVertexBuffers();
public void draw(RenderContext context) {
if (!initialized())
return;
GLES11.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
GLES11.glEnable(GL10.GL_BLEND);
try {
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, getTextureID());
drawPatches(context);
} finally {
GLES11.glDisable(GL10.GL_BLEND);
}
}
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_BLEND);
private void drawPatches(RenderContext context) {
/*
* We divide the nine-patch bitmap up as follows:
*
* +---+---+---+
* | 0 | 1 | 2 |
* +---+---+---+
* | 3 | | 4 |
* +---+---+---+
* | 5 | 6 | 7 |
* +---+---+---+
*/
gl.glBindTexture(GL10.GL_TEXTURE_2D, getTextureID());
FloatSize size = context.pageSize;
float width = size.width, height = size.height;
/* Left side */
drawTriangles(gl, mSideVertexBuffer, mSideTexCoordBuffer, 8);
drawPatch(context, 0, 0, /* 0 */
0.0f, 0.0f, PATCH_SIZE, PATCH_SIZE);
drawPatch(context, PATCH_SIZE, 0, /* 1 */
PATCH_SIZE, 0.0f, width, PATCH_SIZE);
drawPatch(context, PATCH_SIZE * 2, 0, /* 2 */
PATCH_SIZE + width, 0.0f, PATCH_SIZE, PATCH_SIZE);
drawPatch(context, 0, PATCH_SIZE, /* 3 */
0.0f, PATCH_SIZE, PATCH_SIZE, height);
drawPatch(context, PATCH_SIZE * 2, PATCH_SIZE, /* 4 */
PATCH_SIZE + width, PATCH_SIZE, PATCH_SIZE, height);
drawPatch(context, 0, PATCH_SIZE * 2, /* 5 */
0.0f, PATCH_SIZE + height, PATCH_SIZE, PATCH_SIZE);
drawPatch(context, PATCH_SIZE, PATCH_SIZE * 2, /* 6 */
PATCH_SIZE, PATCH_SIZE + height, width, PATCH_SIZE);
drawPatch(context, PATCH_SIZE * 2, PATCH_SIZE * 2, /* 7 */
PATCH_SIZE + width, PATCH_SIZE + height, PATCH_SIZE, PATCH_SIZE);
}
/* Top */
drawTriangles(gl, mTopVertexBuffer, mTopTexCoordBuffer, 4);
private void drawPatch(RenderContext context, int textureX, int textureY, float tileX,
float tileY, float tileWidth, float tileHeight) {
int[] cropRect = { textureX, textureY + PATCH_SIZE, PATCH_SIZE, -PATCH_SIZE };
GLES11.glTexParameteriv(GL10.GL_TEXTURE_2D, GLES11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect,
0);
/* Right side */
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glTranslatef(pageSize.width + PATCH_SIZE, 0.0f, 0.0f);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPushMatrix();
gl.glTranslatef(0.50f, 0.0f, 0.0f);
drawTriangles(gl, mSideVertexBuffer, mSideTexCoordBuffer, 8);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW); /* Not strictly necessary, but here for clarity. */
gl.glPopMatrix();
/* Bottom */
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPushMatrix();
gl.glTranslatef(0.0f, pageSize.height + PATCH_SIZE, 0.0f);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.50f, 0.0f);
drawTriangles(gl, mTopVertexBuffer, mTopTexCoordBuffer, 4);
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glPopMatrix();
gl.glDisable(GL10.GL_BLEND);
RectF viewport = context.viewport;
float viewportHeight = viewport.height();
float drawX = tileX - viewport.left - PATCH_SIZE;
float drawY = viewportHeight - (tileY + tileHeight - viewport.top - PATCH_SIZE);
GLES11Ext.glDrawTexfOES(drawX, drawY, 0.0f, tileWidth, tileHeight);
}
}

View File

@ -102,4 +102,8 @@ public final class RectUtils {
return new Rect(Math.round(rect.left), Math.round(rect.top),
Math.round(rect.right), Math.round(rect.bottom));
}
public static IntSize getSize(Rect rect) {
return new IntSize(rect.width(), rect.height());
}
}

View File

@ -37,55 +37,65 @@
package org.mozilla.gecko.gfx;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.PointF;
import android.graphics.RectF;
import android.opengl.GLES11;
import android.opengl.GLES11Ext;
import android.util.Log;
import java.nio.ByteBuffer;
import javax.microedition.khronos.opengles.GL10;
/**
* Draws a small rect. This is scaled to become a scrollbar.
*/
public class ScrollbarLayer extends SingleTileLayer {
public class ScrollbarLayer extends TileLayer {
private static final int BAR_SIZE = 8; // has to be power of 2
/*
* This awkward pattern is necessary due to Java's restrictions on when one can call superclass
* constructors.
*/
private ScrollbarLayer(CairoImage image) {
super(image);
private final boolean mVertical;
private ScrollbarLayer(CairoImage image, boolean vertical) {
super(false, image);
mVertical = vertical;
}
public static ScrollbarLayer create() {
Bitmap bitmap = Bitmap.createBitmap(BAR_SIZE, BAR_SIZE, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint painter = new Paint();
painter.setColor(Color.argb(127, 0, 0, 0));
canvas.drawRect(0.0f, 0.0f, BAR_SIZE, BAR_SIZE, painter);
return new ScrollbarLayer(new BufferedCairoImage(bitmap));
public static ScrollbarLayer create(boolean vertical) {
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
buffer.put(3, (byte)127); // Set A to 0.5; leave R/G/B at 0.
CairoImage image = new BufferedCairoImage(buffer, 1, 1, CairoImage.FORMAT_ARGB32);
return new ScrollbarLayer(image, vertical);
}
void drawVertical(GL10 gl, IntSize screenSize, Rect pageRect) {
float barStart = (float)screenSize.height * (float)(0 - pageRect.top) / pageRect.height();
float barEnd = (float)screenSize.height * (float)(screenSize.height - pageRect.top) / pageRect.height();
float scale = Math.max(1.0f, (barEnd - barStart) / BAR_SIZE);
gl.glLoadIdentity();
gl.glScalef(1.0f, scale, 1.0f);
gl.glTranslatef(screenSize.width - BAR_SIZE, barStart / scale, 0.0f);
draw(gl);
@Override
public void draw(RenderContext context) {
if (!initialized())
return;
try {
GLES11.glEnable(GL10.GL_BLEND);
RectF rect = mVertical ? getVerticalRect(context) : getHorizontalRect(context);
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, getTextureID());
float y = context.viewport.height() - rect.bottom;
GLES11Ext.glDrawTexfOES(rect.left, y, 0.0f, rect.width(), rect.height());
} finally {
GLES11.glDisable(GL10.GL_BLEND);
}
}
void drawHorizontal(GL10 gl, IntSize screenSize, Rect pageRect) {
float barStart = (float)screenSize.width * (float)(0 - pageRect.left) / pageRect.width();
float barEnd = (float)screenSize.width * (float)(screenSize.width - pageRect.left) / pageRect.width();
float scale = Math.max(1.0f, (barEnd - barStart) / BAR_SIZE);
gl.glLoadIdentity();
gl.glScalef(scale, 1.0f, 1.0f);
gl.glTranslatef(barStart / scale, screenSize.height - BAR_SIZE, 0.0f);
draw(gl);
private RectF getVerticalRect(RenderContext context) {
RectF viewport = context.viewport;
FloatSize pageSize = context.pageSize;
float barStart = viewport.height() * viewport.top / pageSize.height;
float barEnd = viewport.height() * viewport.bottom / pageSize.height;
return new RectF(viewport.width() - BAR_SIZE, barStart, viewport.width(), barEnd);
}
private RectF getHorizontalRect(RenderContext context) {
RectF viewport = context.viewport;
FloatSize pageSize = context.pageSize;
float barStart = viewport.width() * viewport.left / pageSize.width;
float barEnd = viewport.width() * viewport.right / pageSize.width;
return new RectF(barStart, viewport.height() - BAR_SIZE, barEnd, viewport.height());
}
}

View File

@ -42,6 +42,10 @@ import org.mozilla.gecko.gfx.CairoUtils;
import org.mozilla.gecko.gfx.IntSize;
import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.TileLayer;
import android.graphics.PointF;
import android.graphics.RectF;
import android.opengl.GLES11;
import android.opengl.GLES11Ext;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -50,58 +54,48 @@ import javax.microedition.khronos.opengles.GL10;
/**
* Encapsulates the logic needed to draw a single textured tile.
*
* TODO: Repeating textures really should be their own type of layer.
*/
public class SingleTileLayer extends TileLayer {
private FloatBuffer mTexCoordBuffer, mVertexBuffer;
private static final float[] VERTICES = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f
};
private static final float[] TEX_COORDS = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
public SingleTileLayer(CairoImage image) { this(false, image); }
public SingleTileLayer(boolean repeat, CairoImage image) {
super(repeat, image);
mVertexBuffer = createBuffer(VERTICES);
mTexCoordBuffer = createBuffer(TEX_COORDS);
}
@Override
protected void onTileDraw(GL10 gl) {
public void draw(RenderContext context) {
// mTextureIDs may be null here during startup if Layer.java's draw method
// failed to acquire the transaction lock and call performUpdates.
if (!initialized())
return;
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, getTextureID());
RectF bounds;
int[] cropRect;
IntSize size = getSize();
RectF viewport = context.viewport;
if (repeats()) {
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPushMatrix();
gl.glScalef(LayerController.TILE_WIDTH / size.width,
LayerController.TILE_HEIGHT / size.height,
1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glScalef(LayerController.TILE_WIDTH, LayerController.TILE_HEIGHT, 1.0f);
bounds = new RectF(0.0f, 0.0f, viewport.width(), viewport.height());
int width = (int)Math.round(viewport.width());
int height = (int)Math.round(-viewport.height());
cropRect = new int[] { 0, size.height, width, height };
} else {
gl.glScalef(size.width, size.height, 1.0f);
bounds = getBounds(context, new FloatSize(size));
cropRect = new int[] { 0, size.height, size.width, -size.height };
}
gl.glBindTexture(GL10.GL_TEXTURE_2D, getTextureID());
drawTriangles(gl, mVertexBuffer, mTexCoordBuffer, 4);
GLES11.glTexParameteriv(GL10.GL_TEXTURE_2D, GLES11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect,
0);
if (repeats()) {
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
float height = bounds.height();
float left = bounds.left - viewport.left;
float top = viewport.height() - (bounds.top + height - viewport.top);
GLES11Ext.glDrawTexfOES(left, top, 0.0f, bounds.width(), height);
}
}

View File

@ -38,8 +38,10 @@
package org.mozilla.gecko.gfx;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11Ext;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -80,6 +82,7 @@ public abstract class TileLayer extends Layer {
protected boolean repeats() { return mRepeat; }
protected int getTextureID() { return mTextureIDs[0]; }
protected boolean initialized() { return mImage != null && mTextureIDs != null; }
@Override
protected void finalize() throws Throwable {
@ -87,30 +90,6 @@ public abstract class TileLayer extends Layer {
TextureReaper.get().add(mTextureIDs);
}
/**
* Subclasses implement this method to perform tile drawing.
*
* Invariant: The current matrix mode must be GL_MODELVIEW both before and after this call.
*/
protected abstract void onTileDraw(GL10 gl);
@Override
protected void onDraw(GL10 gl) {
// mTextureIDs may be null here during startup if Layer.java's draw method
// failed to acquire the transaction lock and call performUpdates.
if (mImage == null || mTextureIDs == null)
return;
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glPushMatrix();
onTileDraw(gl);
gl.glPopMatrix();
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
/**
* Invalidates the given rect so that it will be uploaded again. Only valid inside a
* transaction.
@ -199,12 +178,5 @@ public abstract class TileLayer extends Layer {
floatBuffer.position(0);
return floatBuffer;
}
protected static void drawTriangles(GL10 gl, FloatBuffer vertexBuffer,
FloatBuffer texCoordBuffer, int count) {
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, count);
}
}