mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 705170 - Use OES_draw_texture to render textures to the screen. r=Cwiiis
This commit is contained in:
parent
c42843fef8
commit
747a4d7e3c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user