LibreOffice Module android (master) 1
SubTile.java
Go to the documentation of this file.
1/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6package org.mozilla.gecko.gfx;
7
8import android.graphics.Rect;
9import android.graphics.RectF;
10import android.graphics.Region;
11import android.graphics.RegionIterator;
12import android.opengl.GLES20;
13import android.util.Log;
14
16
17import java.nio.ByteBuffer;
18import java.nio.FloatBuffer;
19
20public class SubTile extends Layer {
21 private static String LOGTAG = SubTile.class.getSimpleName();
22 public final TileIdentifier id;
23
24 private final RectF mBounds;
25 private final RectF mTextureBounds;
26 private final RectF mViewport;
27 private final Rect mIntBounds;
28 private final Rect mSubRect;
29 private final RectF mSubRectF;
30 private final Region mMaskedBounds;
31 private final Rect mCropRect;
32 private final RectF mObjRectF;
33 private final float[] mCoords;
34
35 public boolean markedForRemoval = false;
36
38 private IntSize mSize;
39 private int[] mTextureIDs;
40 private boolean mDirtyTile;
41
43 super();
44 this.id = id;
45
46 mBounds = new RectF();
47 mTextureBounds = new RectF();
48 mViewport = new RectF();
49 mIntBounds = new Rect();
50 mSubRect = new Rect();
51 mSubRectF = new RectF();
52 mMaskedBounds = new Region();
53 mCropRect = new Rect();
54 mObjRectF = new RectF();
55 mCoords = new float[20];
56
57 mImage = null;
58 mTextureIDs = null;
59 mSize = new IntSize(0, 0);
60 mDirtyTile = false;
61 }
62
63 public void setImage(CairoImage image) {
64 if (image.getSize().isPositive()) {
65 this.mImage = image;
66 }
67 }
68
69 public void refreshTileMetrics() {
70 setPosition(id.getCSSRect());
71 }
72
73 public void markForRemoval() {
74 markedForRemoval = true;
75 }
76
77 protected int getTextureID() {
78 return mTextureIDs[0];
79 }
80
81 protected boolean initialized() {
82 return mTextureIDs != null;
83 }
84
85 @Override
86 protected void finalize() throws Throwable {
87 try {
90 } finally {
91 super.finalize();
92 }
93 }
94
95 private void cleanTexture() {
96 if (mTextureIDs != null) {
98 mTextureIDs = null;
100 }
101 }
102
103 public void destroy() {
104 try {
105 destroyImage();
106 cleanTexture();
107 } catch (Exception ex) {
108 Log.e(LOGTAG, "Error clearing buffers: ", ex);
109 }
110 }
111
112 public void destroyImage() {
113 if (mImage != null) {
114 mImage.destroy();
115 mImage = null;
116 }
117 }
118
123 public void invalidate() {
124 if (!inTransaction()) {
125 throw new RuntimeException("invalidate() is only valid inside a transaction");
126 }
127 if (mImage == null) {
128 return;
129 }
130 mDirtyTile = true;
131 }
132
136 private void validateTexture() {
137 IntSize textureSize = mImage.getSize().nextPowerOfTwo();
138
139 if (!textureSize.equals(mSize)) {
140 mSize = textureSize;
141 cleanTexture();
142 }
143 }
144
145 @Override
146 protected void performUpdates(RenderContext context) {
147 super.performUpdates(context);
148 if (mImage == null && !mDirtyTile) {
149 return;
150 }
153 mDirtyTile = false;
154 }
155
156 private void uploadNewTexture() {
157 ByteBuffer imageBuffer = mImage.getBuffer();
158 if (imageBuffer == null) {
159 return;
160 }
161
162 if (mTextureIDs == null) {
163 mTextureIDs = new int[1];
164 GLES20.glGenTextures(mTextureIDs.length, mTextureIDs, 0);
165 }
166
167 int cairoFormat = mImage.getFormat();
168 CairoGLInfo glInfo = new CairoGLInfo(cairoFormat);
169
171
172 IntSize bufferSize = mImage.getSize();
173
174 GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, glInfo.internalFormat,
175 mSize.width, mSize.height, 0, glInfo.format, glInfo.type, imageBuffer);
176
177 destroyImage();
178 }
179
180 private void bindAndSetGLParameters() {
181 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
182 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIDs[0]);
183
184 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
185 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
186 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
187 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
188 }
189
190 @Override
191 public void draw(RenderContext context) {
192 // mTextureIDs may be null here during startup if Layer.java's draw method
193 // failed to acquire the transaction lock and call performUpdates.
194 if (!initialized())
195 return;
196
197 mViewport.set(context.viewport);
198
199 mBounds.set(getBounds(context));
201
202 mBounds.roundOut(mIntBounds);
204
205 // XXX Possible optimisation here, form this array so we can draw it in
206 // a single call.
207 RegionIterator iterator = new RegionIterator(mMaskedBounds);
208 while (iterator.next(mSubRect)) {
209 // Compensate for rounding errors at the edge of the tile caused by
210 // the roundOut above
211 mSubRectF.set(Math.max(mBounds.left, (float) mSubRect.left),
212 Math.max(mBounds.top, (float) mSubRect.top),
213 Math.min(mBounds.right, (float) mSubRect.right),
214 Math.min(mBounds.bottom, (float) mSubRect.bottom));
215
216 // This is the left/top/right/bottom of the rect, relative to the
217 // bottom-left of the layer, to use for texture coordinates.
218 mCropRect.set(Math.round(mSubRectF.left - mBounds.left),
219 Math.round(mBounds.bottom - mSubRectF.top),
220 Math.round(mSubRectF.right - mBounds.left),
221 Math.round(mBounds.bottom - mSubRectF.bottom));
222
223 mObjRectF.set(mSubRectF.left - mViewport.left,
224 mViewport.bottom - mSubRectF.bottom,
225 mSubRectF.right - mViewport.left,
226 mViewport.bottom - mSubRectF.top);
227
229
230 FloatBuffer coordBuffer = context.coordBuffer;
231 int positionHandle = context.positionHandle;
232 int textureHandle = context.textureHandle;
233
234 GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
235 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTextureID());
236
237 // Make sure we are at position zero in the buffer
238 coordBuffer.position(0);
239 coordBuffer.put(mCoords);
240
241 // Unbind any the current array buffer so we can use client side buffers
242 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
243
244 // Vertex coordinates are x,y,z starting at position 0 into the buffer.
245 coordBuffer.position(0);
246 GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 20, coordBuffer);
247
248 // Texture coordinates are texture_x, texture_y starting at position 3 into the buffer.
249 coordBuffer.position(3);
250 GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 20, coordBuffer);
251 GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
252 }
253 }
254}
Identifies the tile by its position (x and y coordinate on the document), zoom and tile size (current...
Information needed to render Cairo bitmaps using OpenGL ES.
abstract ByteBuffer getBuffer()
boolean equals(IntSize size)
Definition: IntSize.java:35
static int nextPowerOfTwo(int value)
Definition: IntSize.java:52
boolean inTransaction()
Returns true if the layer is currently in a transaction and false otherwise.
Definition: Layer.java:104
final void fillRectCoordBuffer(float[] dest, RectF rect, float viewWidth, float viewHeight, Rect cropRect, float texWidth, float texHeight)
This function fills in the provided dest array with values to render a texture.
Definition: Layer.java:162
RectF getBounds(RenderContext context)
Given the intrinsic size of the layer, returns the pixel boundaries of the layer rect.
Definition: Layer.java:67
void setPosition(Rect newPosition)
Sets the position.
Definition: Layer.java:114
void setImage(CairoImage image)
Definition: SubTile.java:63
void performUpdates(RenderContext context)
Subclasses may override this method to perform custom layer updates.
Definition: SubTile.java:146
void validateTexture()
Remove the texture if the image is of different size than the current uploaded texture.
Definition: SubTile.java:136
void draw(RenderContext context)
Subclasses override this function to draw the layer.
Definition: SubTile.java:191
SubTile(TileIdentifier id)
Definition: SubTile.java:42
void invalidate()
Invalidates the entire buffer so that it will be uploaded again.
Definition: SubTile.java:123
final TileIdentifier id
Definition: SubTile.java:22
Manages a list of dead tiles, so we don't leak resources.
@ Exception