1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/gfx/SingleTileLayer.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,153 @@ 1.4 +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +package org.mozilla.gecko.gfx; 1.10 + 1.11 +import android.graphics.Rect; 1.12 +import android.graphics.RectF; 1.13 +import android.graphics.Region; 1.14 +import android.graphics.RegionIterator; 1.15 +import android.opengl.GLES20; 1.16 + 1.17 +import java.nio.FloatBuffer; 1.18 + 1.19 +/** 1.20 + * Encapsulates the logic needed to draw a single textured tile. 1.21 + * 1.22 + * TODO: Repeating textures really should be their own type of layer. 1.23 + */ 1.24 +public class SingleTileLayer extends TileLayer { 1.25 + private static final String LOGTAG = "GeckoSingleTileLayer"; 1.26 + 1.27 + private Rect mMask; 1.28 + 1.29 + // To avoid excessive GC, declare some objects here that would otherwise 1.30 + // be created and destroyed frequently during draw(). 1.31 + private final RectF mBounds; 1.32 + private final RectF mTextureBounds; 1.33 + private final RectF mViewport; 1.34 + private final Rect mIntBounds; 1.35 + private final Rect mSubRect; 1.36 + private final RectF mSubRectF; 1.37 + private final Region mMaskedBounds; 1.38 + private final Rect mCropRect; 1.39 + private final RectF mObjRectF; 1.40 + private final float[] mCoords; 1.41 + 1.42 + public SingleTileLayer(CairoImage image) { 1.43 + this(false, image); 1.44 + } 1.45 + 1.46 + public SingleTileLayer(boolean repeat, CairoImage image) { 1.47 + this(image, repeat ? TileLayer.PaintMode.REPEAT : TileLayer.PaintMode.NORMAL); 1.48 + } 1.49 + 1.50 + public SingleTileLayer(CairoImage image, TileLayer.PaintMode paintMode) { 1.51 + super(image, paintMode); 1.52 + 1.53 + mBounds = new RectF(); 1.54 + mTextureBounds = new RectF(); 1.55 + mViewport = new RectF(); 1.56 + mIntBounds = new Rect(); 1.57 + mSubRect = new Rect(); 1.58 + mSubRectF = new RectF(); 1.59 + mMaskedBounds = new Region(); 1.60 + mCropRect = new Rect(); 1.61 + mObjRectF = new RectF(); 1.62 + mCoords = new float[20]; 1.63 + } 1.64 + 1.65 + /** 1.66 + * Set an area to mask out when rendering. 1.67 + */ 1.68 + public void setMask(Rect aMaskRect) { 1.69 + mMask = aMaskRect; 1.70 + } 1.71 + 1.72 + @Override 1.73 + public void draw(RenderContext context) { 1.74 + // mTextureIDs may be null here during startup if Layer.java's draw method 1.75 + // failed to acquire the transaction lock and call performUpdates. 1.76 + if (!initialized()) 1.77 + return; 1.78 + 1.79 + mViewport.set(context.viewport); 1.80 + 1.81 + if (repeats()) { 1.82 + // If we're repeating, we want to adjust the texture bounds so that 1.83 + // the texture repeats the correct number of times when drawn at 1.84 + // the size of the viewport. 1.85 + mBounds.set(getBounds(context)); 1.86 + mTextureBounds.set(0.0f, 0.0f, mBounds.width(), mBounds.height()); 1.87 + mBounds.set(0.0f, 0.0f, mViewport.width(), mViewport.height()); 1.88 + } else if (stretches()) { 1.89 + // If we're stretching, we just want the bounds and texture bounds 1.90 + // to fit to the page. 1.91 + mBounds.set(context.pageRect); 1.92 + mTextureBounds.set(mBounds); 1.93 + } else { 1.94 + mBounds.set(getBounds(context)); 1.95 + mTextureBounds.set(mBounds); 1.96 + } 1.97 + 1.98 + mBounds.roundOut(mIntBounds); 1.99 + mMaskedBounds.set(mIntBounds); 1.100 + if (mMask != null) { 1.101 + mMaskedBounds.op(mMask, Region.Op.DIFFERENCE); 1.102 + if (mMaskedBounds.isEmpty()) 1.103 + return; 1.104 + } 1.105 + 1.106 + // XXX Possible optimisation here, form this array so we can draw it in 1.107 + // a single call. 1.108 + RegionIterator i = new RegionIterator(mMaskedBounds); 1.109 + while (i.next(mSubRect)) { 1.110 + // Compensate for rounding errors at the edge of the tile caused by 1.111 + // the roundOut above 1.112 + mSubRectF.set(Math.max(mBounds.left, (float)mSubRect.left), 1.113 + Math.max(mBounds.top, (float)mSubRect.top), 1.114 + Math.min(mBounds.right, (float)mSubRect.right), 1.115 + Math.min(mBounds.bottom, (float)mSubRect.bottom)); 1.116 + 1.117 + // This is the left/top/right/bottom of the rect, relative to the 1.118 + // bottom-left of the layer, to use for texture coordinates. 1.119 + mCropRect.set(Math.round(mSubRectF.left - mBounds.left), 1.120 + Math.round(mBounds.bottom - mSubRectF.top), 1.121 + Math.round(mSubRectF.right - mBounds.left), 1.122 + Math.round(mBounds.bottom - mSubRectF.bottom)); 1.123 + 1.124 + mObjRectF.set(mSubRectF.left - mViewport.left, 1.125 + mViewport.bottom - mSubRectF.bottom, 1.126 + mSubRectF.right - mViewport.left, 1.127 + mViewport.bottom - mSubRectF.top); 1.128 + 1.129 + fillRectCoordBuffer(mCoords, mObjRectF, mViewport.width(), mViewport.height(), 1.130 + mCropRect, mTextureBounds.width(), mTextureBounds.height()); 1.131 + 1.132 + FloatBuffer coordBuffer = context.coordBuffer; 1.133 + int positionHandle = context.positionHandle; 1.134 + int textureHandle = context.textureHandle; 1.135 + 1.136 + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 1.137 + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID()); 1.138 + 1.139 + // Make sure we are at position zero in the buffer 1.140 + coordBuffer.position(0); 1.141 + coordBuffer.put(mCoords); 1.142 + 1.143 + // Unbind any the current array buffer so we can use client side buffers 1.144 + GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 1.145 + 1.146 + // Vertex coordinates are x,y,z starting at position 0 into the buffer. 1.147 + coordBuffer.position(0); 1.148 + GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer); 1.149 + 1.150 + // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer. 1.151 + coordBuffer.position(3); 1.152 + GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer); 1.153 + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); 1.154 + } 1.155 + } 1.156 +}